スキップしてメイン コンテンツに移動

【番外編】AI(機械学習)やってみた。【第6回】乳がん診断AI その1

ソムリAI(ワインソムリエAI)で使った手法で乳がん診断AIを作ってみます。まずは決定木とニューラルネットワークの2つのモデルを試してみます。かなり高性能なモデルができました。名医誕生かもしれません 笑

ソムリAIで使った手法で乳がん診断AIを作る

ソムリAI(ワインの評価を当てるソムリエAI)では、いろいろな手法を試しましたが66%程度の精度しか出ませんでした。イマイチの精度しか出ず悔しかったので、ソムリAIで使った決定木やニューラルネットワーク・交差検証・多数決などの手法を使って、別のデータでAIを作ってみようと思います。

UCI(University of California, Irvine・カリフォルニア大学アーバイン校)が様々なビッグデータを提供しています。個人的には医療×AIがアツいと考えており、今回はウィスコンシンで収集された乳がんの診断データを使ってみようと思います。

乳がんデータのダウンロード

乳がんの診断データは以下のリンクからダウンロードできます。
https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wdbc.data

また、データの内容(項目の説明など)は以下のページに書かれています。
https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wdbc.names

早速Python(Jupyter Notebook)で読み込んでみます。
#入力データセットを読み込み
import pandas as pd #データハンドリング用ライブラリ呼び出し
data = pd.read_csv('BreastCancer.csv', encoding='SHIFT-JIS')
data.head() #先頭5つを表示して読み込まれていることを確認
各列の項目はUCIの解説を基に日本語にしています。患者のID・診断結果(Mはmalignantで悪性、Bはbenignで良性)に始まり、数値化した腫瘍データが並んでいます。数値化されたデータには腫瘍の半径・きめ・凹みの個数など10個のデータがあり、それぞれに対して平均・標準誤差・最大値の3つが用意されています。つまり、1患者当たり10×3で30個のデータがあります。腫瘍の画像データをそのまま使うのではなく、腫瘍の画像を数値化したデータを使うイメージなのです。

機械学習用のデータを準備

ダウンロードしたデータを機械学習用に加工します。腫瘍の悪性・良性を目的変数に、腫瘍の半径などのデータを説明変数にします。説明変数に重みづけなどを行って目的変数(悪性・良性)を当てようということです。

また、目的変数である診断結果がMとBというアルファベットであり、コンピュータでは扱いにくいため、悪性(M)を1・良性(B)を0とするように加工しています。コンピュータは数値データの方が扱いやすいのです。
from sklearn.preprocessing import LabelEncoder

#機械学習で求める解である「評価」以外の項目をdata_Xに、「評価」をdata_Yに格納
data_X = data.copy()
del data_X['ID']
del data_X['診断結果']
data_Y = data['診断結果']
 
#目的変数data_YはM(malignant:悪性)・B(benign:良性)で表現されており、
#コンピュータで扱いやすいように悪性=1・良性=0のように数値変換
labelencode = LabelEncoder()
data_Y = labelencode.fit_transform(data_Y)
labelencode.transform(['M', 'B'])
#返還結果を表示
print(data_Y)
0・1変換された目的変数(診断結果)が表示されました。

続いて、機械学習用のデータを機械学習のモデルを作る訓練データと、モデルの精度(汎化性能)を測る検証データに分割します。ソムリAI同様、全量の70%を訓練用・30%を検証用に分割します。
#入力データセットの70%を訓練データ・30%を検証データに分割
from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(data_X, data_Y,random_state=0, test_size=0.3)
#それぞれの件数を表示
print(len(X_train))
print(len(X_test))
ここまでで事前準備は完了です。ソムリAIで行ったデータの正規化(平均0・標準偏差が1になるように各データのモノサシを統一すること)は後程行います。

機械学習①:決定木

ベストな階層数の探索

まずは決定木を使った機械学習から。決定木は木の階層数が変数です。とりあえず3階層から10階層まで試してみます。
#決定木の機械学習
from sklearn.tree import DecisionTreeClassifier
from sklearn import metrics
 
#決定木の深さを3階層から10階層の範囲で探索
for i in range(3,11):
    #モデル定義
    treeModel = DecisionTreeClassifier(max_depth=i, random_state=0)
    #機械学習実行
    treeModel.fit(X_train, Y_train)
    #精度表示
    Y_train_score = metrics.accuracy_score(Y_train, treeModel.predict(X_train))
    Y_test_score = metrics.accuracy_score(Y_test, treeModel.predict(X_test))
    print("%i階層 訓練精度: %0.4f 検証精度: %0.4f" % (i, Y_train_score, Y_test_score))
すごい!軒並み90%を超える精度です。訓練精度と検証精度のバランスを見ると、訓練精度99.75%・検証精度94.74%の6階層の決定木が一番バランスが良さそうです。

重要な変数の特定

次は決定木において、どのように条件分岐しているか(どの変数を重要とみなしているか)を見ていきます。まず6階層のモデルを作り直してから決定木における重要度を出力させます(3階層から10階層までループを回して探索しており、探索後最後のモデルは10階層で最適化されているモデルになっているので、6階層で再学習させる必要があります)。
#6階層で学習しなおし
treeModel = DecisionTreeClassifier(max_depth=6, random_state=0)
treeModel.fit(X_train, Y_train)
 
Y_train_score = metrics.accuracy_score(Y_train, treeModel.predict(X_train))
Y_test_score = metrics.accuracy_score(Y_test, treeModel.predict(X_test))
print("6階層 訓練精度: %0.4f 検証精度: %0.4f" % (Y_train_score, Y_test_score))

#モデルの決定係数を表示(入力データの各項目に対する重みを表示)
Importance=pd.DataFrame({'変数名':data_X.columns,'重要度':treeModel.feature_importances_})
#重要度を降順で表示
Importance.sort_values('重要度', ascending=False)
これを見ると「凹み個数」という変数の重要度が突出しています。続いて「面積」・「凹み度合い」が続きます。どうやら腫瘍の凹みに関連する情報が診断ポイントのようです。

決定木の可視化

最後に決定木を可視化してみます。日本語の項目名が文字化けしてしまいうまく表示出来なかったので、元の英語の項目名で可視化しました。
#決定木の可視化
from sklearn import tree
from graphviz import Source
from sklearn.externals.six import StringIO
import pydotplus as pdp

#決定木モデルの書き出し
dot_data = StringIO()
tree.export_graphviz(treeModel, out_file="tree.dot", feature_names=data_X.columns, filled=True, rounded=True)

6階層すべて表示するとかなり大きな図になるので部分的に切り抜いています。先ほど見た通り、決定木のモデルについても「凹み個数(concave points)」・「面積(area)」の順で条件分岐しているのが分かります。

機械学習②:ニューラルネットワーク

続いてニューラルネットワークで機械学習してみます。ニューラルネットワークは活性化関数・ソルバー・パーセプトロンの数と階層数がモデルの精度を決める主要なハイパーパラメータ(人間が手で決める機械学習の主要パラメータ)です。とりあえず適当に設定して精度を見てみます。活性化関数はReLU・ソルバーはLbfgs・パーセプトロンは500個ずつ3階層を指定してみます。
#ニューラルネットワークによる機械学習
from sklearn.neural_network import MLPClassifier
 
#モデル定義と機械学習実行
mlpModel = MLPClassifier(activation='relu',solver='lbfgs',
                         hidden_layer_sizes=(500,500,500), random_state=0)
mlpModel.fit(X_train, Y_train)
 
#精度を表示
Y_train_score = metrics.accuracy_score(Y_train, mlpModel.predict(X_train))
Y_test_score = metrics.accuracy_score(Y_test, mlpModel.predict(X_test))
print("訓練精度: %0.4f 検証精度: %0.4f" % (Y_train_score, Y_test_score))
訓練精度93.47%・検証精度95.32%です。いい感じなので、このパラメータをベースにベストなハイパーパラメータを探索します。

最適な活性化関数・ソルバーの探索

まずは、活性化関数とソルバーから。パーセプトロンの数と階層数を先ほどの500個ずつ3階層に固定して、活性化関数とソルバーを総当たりで試してみます。デフォルトで用意されている活性化関数4種類とソルバー3種類をグリッドサーチ関数(指定したハイパーパラメータを総当たりで試してベストなものを教えてくれる便利な関数)に放り込みます。結構時間かかるので所要時間も表示するようにしています。
#グリッドサーチ1回目(活性化関数・ソルバーの探索)
from sklearn.model_selection import GridSearchCV
import datetime
 
#時間表示(開始)
import datetime
start = datetime.datetime.now()
print("開始:",start)
 
#シミュレーションするパラメータを指定(活性化関数・ソルバーを指定)
parameters = {'activation': ['logistic', 'identity', 'relu', 'tanh'],
              'solver': ['lbfgs', 'sgd', 'adam']}
 
#グリッドサーチの実行
mlpModel2 = GridSearchCV(MLPClassifier(hidden_layer_sizes=(500,500,500),
                                       random_state=0, max_iter=500,
                                       early_stopping=True), parameters)
 
mlpModel2.fit(X_train, Y_train)
 
#ベストなパラメーターの表示
print(mlpModel2.best_params_)
 
#時間表示(終了)
end = datetime.datetime.now()
print("終了:",end)
CPUをマックスに使って15分くらいかかりました。最適な活性化関数はIdentityソルバーはLbfgsとのことです。このハイパーパラメータの精度を見てみます。
#1回目のグリッドサーチで得られたパラメータで機械学習
mlpModel = MLPClassifier(activation='identity',solver='lbfgs',
                         hidden_layer_sizes=(500,500,500), random_state=0,
                         max_iter=500, early_stopping=True)
mlpModel.fit(X_train, Y_train)
 
#精度を表示
Y_train_score = metrics.accuracy_score(Y_train, mlpModel.predict(X_train))
Y_test_score = metrics.accuracy_score(Y_test, mlpModel.predict(X_test))
print("訓練精度: %0.4f 検証精度: %0.4f" % (Y_train_score, Y_test_score))
訓練精度96.23%・検証精度95.32%と先ほどから改善された結果になりました。

最適な階層数の探索

続いて階層数の探索です。活性化関数とソルバー・パーセプトロン数を固定して階層数を変動させます。具体的には3階層・4階層・5階層で試してみました。
#グリッドサーチ2回目(階層数の探索)
 
#時間表示(開始)
start = datetime.datetime.now()
print("開始:",start)
 
#シミュレーションするパラメータを指定(階層数を変える)
parameters = {'hidden_layer_sizes': [(500,500,500),(500,500,500,500),(500,500,500,500,500)]}
 
#グリッドサーチの実行
mlpModel2 = GridSearchCV(MLPClassifier(activation='identity', solver='lbfgs',
                                       random_state=0, max_iter=500, early_stopping=True), parameters)
 
mlpModel2.fit(X_train, Y_train)
 
#ベストなパラメーターの表示
print(mlpModel2.best_params_)
 
#時間表示(終了)
end = datetime.datetime.now()
print("終了:",end)
階層を増やした方が精度が上がるかと思いきや、3階層がベストとのこと。

最適なパーセプトロン数の探索

最後に最適なパーセプトロン数の探索をしてみます。500個と1000個でグリッドサーチしてみます。
#グリッドサーチ3回目(パーセプトロン数の探索)
 
#時間表示(開始)
start = datetime.datetime.now()
print("開始:",start)
 
#シミュレーションするパラメータを指定(パーセプトロン数を変える)
parameters = {'hidden_layer_sizes': [(500,500,500),(1000,1000,1000)]}
 
#グリッドサーチの実行
mlpModel2 = GridSearchCV(MLPClassifier(activation='identity', solver='lbfgs',
                                       random_state=0, max_iter=500, early_stopping=True), parameters)
 
 
mlpModel2.fit(X_train, Y_train)
 
#ベストなパラメーターの表示
print(mlpModel2.best_params_)
 
#時間表示(終了)
end = datetime.datetime.now()
print("終了:",end)
1000個にした方が良いと思いきや、500個の方が良いとの結果に。人力ハイパーパラメータ探索の結果としては、活性化関数はIdentity・ソルバーはLbfgs・パーセプトロン数と階層は500個を3階層ということになりました。ニューラルネットワークの精度は訓練精度96.23%・検証精度95.32%

とりあえず今回はここまでで、次回は交差検証と多数決モデルを使って更なる精度向上にトライしようと思います。

今回のまとめ

  • データに含まれる情報量が多いほど機械学習の精度が高くなるのかもしれない(ソムリAIで使ったワインデータは1データあたり11個の情報だったが、乳がん診断情報は1データあたり30個の情報)。
  • 決定木はニューラルネットワークなど他のモデルと比較すると精度が低いことが多いが、重要度の高い変数や条件分岐など機械学習の内部プロセスが目に見える点が優れている(医療など意思決定のプロセスが透明化されていなければならない領域にAIを適用する場合に有効だと思われる)。
  • ニューラルネットワークのハイパーパラメータ探索は探索を分割して絞り込んでいくのが良い(多くのパラメータを網羅的にグリッドサーチに掛けることも可能だが、計算量が雪だるま式に増えるためかなり時間がかかる。メモリがオーバーフローする可能性もある)。
  • 乳がん診断AIの性能はかなりいい感じ(決定木の検証精度は94.74%・ニューラルネットワークの検証精度は95.32%)。

関連情報

AI(機械学習)やってみた

AI(機械学習)関連書籍


ビッグデータ解析やってみた

ベストビュー(過去1カ月)

『九龍城探訪 魔窟で暮らす人々 - City of Darkness』 ☆4

魔窟とも言われた香港の九龍城の住人へのインタビューや、在りし日の写真集。香港の本土返還に伴い取り壊されてしまっているけど、その怪しさに妙に惹かれるのです。

【番外編】ボストン旅行記(UMASS Lowell卒業式編)【Day 4:卒業式】

UMASS Lowellの卒業式@Boston。4 日目は卒業式本番です。とても賑やかでアメリカンな式典でした。ただしあいにくの雨、僕曇り男なのに。。

【番外編】ボストン旅行記(UMASS Lowell卒業式編) 【Day2:晩餐会】

UMASS Lowellの卒業式@Boston。 2日目は午前中はボストン観光、夕方から Hooding ceremonyという卒業生(大学院生)向けの晩餐会です。卒業式で被るHoodをもらいました。

【番外編】ボストン旅行記(UMASS Lowell卒業式編) 【Day0:渡米前にやっておくこと】

UMASS Lowellの卒業式@Bostonについて、計画の立て方やら行く前にやっておくことやらをまとめておきます。

【番外編】ボストン旅行記(UMASS Lowell卒業式編) 【Day1:ボストンへ】

UMASS Lowellの卒業式@Boston。 1日目は移動だけで終わりました。

【番外編】ボストン旅行記(UMASS Lowell卒業式編) 【Day3:終日観光】

UMASS Lowellの卒業式@Boston。3 日目は終日フリーなので、ゆっくりボストンを観光しました。

【番外編】ボストン旅行記(UMASS Lowell卒業式編) 【Day5:帰国】

UMASS Lowellの卒業式@Boston。5 日目にして帰国なのです。

【番外編】AI(機械学習)やってみた。【第3回】ソムリAI ~ニューラルネットワーク編~

AI(機械学習)やってみた、第3弾です。「ニューラルネットワーク(Neural Network)」を使ったソムリAIを作ってみようと思います。”ニューラルネットワーク”、見るからにAIっぽい名前ですよね。

【番外編】AI(機械学習)やってみた。【第2回】ソムリAI ~ロジスティック回帰編~

AI(機械学習)やってみた、第2弾です。前回は決定木(Decision Tree)を使ったソムリAI(ワインソムリエAI)を作りました。今回は「ロジスティック回帰(Logistic Regression)」というモデルを使ったソムリAIを作ってみようと思います。

【番外編】AI(機械学習)やってみた。【第4回】ソムリAIの改良(正規化)

ソムリAI(ワインの評価を機械学習で当てる「ソムリエ+AI」)はもういいかなと思っていたのですが、機械学習の教科書的な本を読んでいるといくつか改良ポイントが見えてきたので、実際に適用してみようと思います。 まずは データの正規化 という手法を試してみました。結論から言うと、 あまり効果はなかった のです。。 ソムリAIの振り返り ワインの成分とランクのデータに対して、決定木・ロジスティック回帰・ニューラルネットワークの3通りのモデルを使って機械学習 を行い、モデルの精度を検証してきました。それぞれのソムリAIの性能はこんな感じでした。 どのモデルも概ね60%程度の精度 でした。 改良その1:正規化 正規化とは まずは 正規化 という手法を試してみます。標準化とも呼ばれます。正規化を行うことで 尺度の異なるデータを比べやすくする とともに、 はずれ値の影響を小さくする ことができます。正規化には 各データを平均0・標準偏差1に成形する手法 と、各データを 0から1の範囲に成形する手法 の2つがあります。 前者は標準偏差が出てくることからも分かるように、 データが正規分布に従うことを前提にした正規化手法 です。 元のデータが釣鐘型の分布になっている場合に有効 です。後者は単純に データの範囲を0から1の範囲に狭める手法 であり、 元のデータが一様分布の場合 (規則性が無くランダムなように見える場合) に有効 です。 どちらの手法でもデータの範囲を一定のレンジに狭めており、そうすることで異なる尺度のデータを比べやすくしつつ、はずれ値の影響を下げるのです。 正規化してみる 元データの分布を確認 前回同様のワインのデータを使って正規化してみます。まずはワインのデータを読み込んで表示してみます。ついでに機械学習で使うワインの成分と、ワインの評価にデータを分割しておきます。 【オリジナルのワインデータ】 UCI(University of California, Irvine:カリフォルニア大学アーバイン校) http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv #入力データセットを読み込み i

ベストビュー(全期間)

Malaysia Quarantine Premium Package 【番外編】Malaysia赴任記 隔離ホテル情報

Once entering Malaysia, we need to be quarantined for 14days. At the beginning of COVID-19 spread, the hotel for quarantine have been determined randomly. In these days, we can choose "premium quarantine stay package" in advance . This article is summary of premium packages which I asked each hotel. Note: Information in this article might be old. It's better to confirm the latest plan to the hotel. Note: Only Hotel Istana can be booked via its homepage so far. As the other hotels don't show their premium package plans on their homepage, you need to contact them through their reservation E-mail address or "Contact us". マレーシア入国とともに14日間ホテルで隔離されます。当初は滞在ホテルがランダムに割り振られていたようですが、より快適なプレミアムプランが追加されました。各ホテルにどんなプランがあるのか聞いてみたので、聞いた内容をまとめます。 ※情報が古い可能性があるので、念のため最新情報を各ホテルに確認したほうがよいかもしれません。

【番外編】AI(機械学習)やってみた。【第1回】ソムリAI ~決定木編~

最近ブームのAI(機械学習)に手を出しました。まずは、決定木(Decision Tree)というモデルを使って「ソムリAI(ワインソムリエAI)」を作ってみようと思います。

【番外編】ボストン旅行記(UMASS Lowell卒業式編) 【Day0:渡米前にやっておくこと】

UMASS Lowellの卒業式@Bostonについて、計画の立て方やら行く前にやっておくことやらをまとめておきます。

【番外編】AI(機械学習)やってみた。【第3回】ソムリAI ~ニューラルネットワーク編~

AI(機械学習)やってみた、第3弾です。「ニューラルネットワーク(Neural Network)」を使ったソムリAIを作ってみようと思います。”ニューラルネットワーク”、見るからにAIっぽい名前ですよね。

【番外編】ボストン旅行記(UMASS Lowell卒業式編) 【Day5:帰国】

UMASS Lowellの卒業式@Boston。5 日目にして帰国なのです。

【番外編】AI(機械学習)やってみた。【第2回】ソムリAI ~ロジスティック回帰編~

AI(機械学習)やってみた、第2弾です。前回は決定木(Decision Tree)を使ったソムリAI(ワインソムリエAI)を作りました。今回は「ロジスティック回帰(Logistic Regression)」というモデルを使ったソムリAIを作ってみようと思います。

【番外編】ボストン旅行記(UMASS Lowell卒業式編)【Day 4:卒業式】

UMASS Lowellの卒業式@Boston。4 日目は卒業式本番です。とても賑やかでアメリカンな式典でした。ただしあいにくの雨、僕曇り男なのに。。

【番外編】ボストン旅行記(UMASS Lowell卒業式編) 【Day2:晩餐会】

UMASS Lowellの卒業式@Boston。 2日目は午前中はボストン観光、夕方から Hooding ceremonyという卒業生(大学院生)向けの晩餐会です。卒業式で被るHoodをもらいました。

『深層学習教科書 ディープラーニング G検定(ジェネラリスト) 公式テキスト』 ☆5

一般社団法人日本ディープラーニング協会が実施している「Deep Learning for GENERAL (通称G検定 ) 」 の公式テキスト 。 ディープラーニングについて1冊で網羅的によくまとめられているので 、 ディープラーニングの入門書としてもおすすめです 。 ついでに勢いで資格も取ってしまいました 。 AI人材への第一歩なのです 笑