post Image
機械学習初心者が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値

これらについて今後勉強していこうと思います。


『 Python 』Article List