Python
初心者
機械学習
データ分析
Kaggle

機械学習初心者がkaggleのKernelを解読してみた(Medical Data, Keras)

データハッカソンの勉強会で解読したkaggleのKernelが非常にわかりやすく勉強になったので、こちらに残しておきます。なお初心者が初心者向けに書いていますので、細かい説明は省略します(というか書けない(苦笑))。もし間違った記載があればご指摘いただけると幸いです。

「kaggle」については以下の記事などをご覧ください。
- Kaggle事始め
- データサイエンティストを目指して勉強するなら、Kaggleからはじめよう

Dataset

今回は「Cervical Cancer Risk Classification(子宮頸がんのリスク分類)」のDatasetを使用します。
(後述しますが大変生々しいデータ内容となっております。ただ、こちらのデータは本物ではない(教育のため擬似的に作成したものだろう)と思われます。)

Kernel

今回解読するKernelは「For beginners: using Keras to build models」です。
Notebook形式で言語はPython、予測モデルにKeras(ニューラルネットワークライブラリ)を使用しています。
この記事の中でKernelを抜粋して転記していますが、ちゃんと解読する際は上記リンクから実際のKernelをご参照ください。

いざ解析

Kernelの大まかな流れは「データ内容の把握→データ前処理→モデルの構築・学習→モデルの精度を検証」となっています。1ステップずつみていきましょう。

Step 1 〜データ内容の把握〜

まずはデータを読み込み、表示してみます。(ライブラリのインポートについては割愛します。)

df_full = pd.read_csv('../input/kag_risk_factors_cervical_cancer.csv')
df_full

実際にやっていただくとわかりますが、かなりプライベートな内容が含まれていますね。
まずは「データの項目」「データの種類(離散データか連続データかなど)」「データの量」「欠損値」などを把握しましょう。info()でデータの概要を表示したり、isnull().sum()で欠損値をカウントしたりできます。

Step 2 〜データ前処理〜

データの内容を把握したら、次はデータを解析しやすい状態に整えていきます。
まずは全てのデータを数値型にします。

df = df_fullna
df = df.convert_objects(convert_numeric=True)

次に欠損値を埋める作業です。このKernelでは各項目のmedian(中央値)を採用していますね。

df['Number of sexual partners'] = df['Number of sexual partners'].fillna(df['Number of sexual partners'].median())
df['First sexual intercourse'] = df['First sexual intercourse'].fillna(df['First sexual intercourse'].median())
…

続いてカテゴリカルデータをダミー変数にします。カテゴリカルデータとは離散量のデータで、性別や職種、YES or NOなどの質的・定性的なデータです。これらのデータをダミー変数にするとは、例えばYESが1、NOが0となっている場合、YESは(1.0, 0.0)、NOは(0.0, 1.0)などとすることです(認識が合っているか怪しい・・・)。

df = pd.get_dummies(data=df, columns=['Smokes','Hormonal Contraceptives','IUD','STDs','Dx:Cancer','Dx:CIN','Dx:HPV','Dx','Hinselmann','Citology','Schiller'])

これで解析可能な形に整形できました。次はデータを学習データとテストデータに分けます。

np.random.seed(42)
df_data_shuffle = df_data.iloc[np.random.permutation(len(df_data))]
df_train = df_data_shuffle.iloc[1:686, :]
df_test = df_data_shuffle.iloc[686: , :]

特徴量とラベルを定義します。ここでは"Biopsy"(生検結果)をラベルにしています。

df_train_feature = df_train[['Age', 'Number of sexual partners', 'First sexual intercourse','Num of pregnancies', 'Smokes (years)', 'Smokes (packs/year)','Hormonal Contraceptives (years)', 'IUD (years)', 'STDs (number)','STDs:condylomatosis', 'STDs:cervical condylomatosis','STDs:vaginal condylomatosis', 'STDs:vulvo-perineal condylomatosis','STDs:syphilis', 'STDs:pelvic inflammatory disease','STDs:genital herpes', 'STDs:molluscum contagiosum', 'STDs:AIDS','STDs:HIV', 'STDs:Hepatitis B', 'STDs:HPV', 'STDs: Number of diagnosis','STDs: Time since first diagnosis', 'STDs: Time since last diagnosis','Smokes_0.0', 'Smokes_1.0','Hormonal Contraceptives_0.0', 'Hormonal Contraceptives_1.0', 'IUD_0.0','IUD_1.0', 'STDs_0.0', 'STDs_1.0', 'Dx:Cancer_0', 'Dx:Cancer_1','Dx:CIN_0', 'Dx:CIN_1', 'Dx:HPV_0', 'Dx:HPV_1', 'Dx_0', 'Dx_1','Hinselmann_0', 'Hinselmann_1', 'Citology_0', 'Citology_1','Schiller_0','Schiller_1']]
train_label = np.array(df_train['Biopsy'])
df_test_feature = df_test[['Age', 'Number of sexual partners', 'First sexual intercourse','Num of pregnancies', 'Smokes (years)', 'Smokes (packs/year)','Hormonal Contraceptives (years)', 'IUD (years)', 'STDs (number)','STDs:condylomatosis', 'STDs:cervical condylomatosis','STDs:vaginal condylomatosis', 'STDs:vulvo-perineal condylomatosis','STDs:syphilis', 'STDs:pelvic inflammatory disease','STDs:genital herpes', 'STDs:molluscum contagiosum', 'STDs:AIDS','STDs:HIV', 'STDs:Hepatitis B', 'STDs:HPV', 'STDs: Number of diagnosis','STDs: Time since first diagnosis', 'STDs: Time since last diagnosis','Smokes_0.0', 'Smokes_1.0','Hormonal Contraceptives_0.0', 'Hormonal Contraceptives_1.0', 'IUD_0.0','IUD_1.0', 'STDs_0.0', 'STDs_1.0', 'Dx:Cancer_0', 'Dx:Cancer_1','Dx:CIN_0', 'Dx:CIN_1', 'Dx:HPV_0','Dx:HPV_1', 'Dx_0', 'Dx_1','Hinselmann_0', 'Hinselmann_1', 'Citology_0','Citology_1','Schiller_0','Schiller_1']]
test_label = np.array(df_test['Biopsy'])

データを標準化します。ざっくり言うと、各データのスケールを調整します。(今後ちゃんと勉強しなければならない点その①…)

minmax_scale = preprocessing.MinMaxScaler(feature_range=(0, 1))
train_feature = minmax_scale.fit_transform(df_train_feature)
test_feature = minmax_scale.fit_transform(df_test_feature)

Step 3 〜モデルの構築・学習〜

モデルを構築・学習しましょう!ここでは「入力層ー隠れ層1ー出力層」のニューラルネットワークとしています。

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
model = Sequential()

#Input layer
model.add(Dense(units=500,input_dim=46,kernel_initializer='uniform',activation='relu'))
model.add(Dropout(0.5))

#Hidden layer 1
model.add(Dense(units=200,kernel_initializer='uniform',activation='relu'))
model.add(Dropout(0.5))

#Output layer
model.add(Dense(units=1,kernel_initializer='uniform',activation='sigmoid'))
print(model.summary()) \#for showing the structure and parameters

# Defining how to measure performance
model.compile(loss='binary_crossentropy',optimizer='adam', metrics=['accuracy'])

# Train the model
# Verbose=2, showing loss and accuracy change timely
train_history = model.fit(x=train_feature, y=train_label,validation_split=0.2, epochs=20,batch_size=200, verbose=2) 

#visualize the loss and accuracy after each epoch
show_train_history(train_history,'acc','val_acc')
show_train_history(train_history,'loss','val_loss')

Step 4 〜モデルの精度を検証〜

モデルを動かしましょう。

scores = model.evaluate(test_feature, test_label)
print('\n')
print('accuracy=',scores[1])

約94.8%の精度が出ています。なかなかの精度ですね!ただ先述した通り、教育のため擬似的に作成したデータと思われるので、実際のデータに比べて精度が出やすいかもしれません。

モデルの検証です。ここでは「Confusion matrix(混同行列)」を用いて評価をおこなっています。(今後ちゃんと勉強しなければならない点その②…)
ということでここは今後書き足そうと思います。

今後の課題

今回のKernel解読を通して、自分が勉強しなければと思ったキーワード。(上述していないものも含む)
- ダミー変数
- データの標準化
- 欠損値
- グリッドサーチ
- 混同行列
- F値
これらについて今後勉強していこうと思います。