LoginSignup
29

More than 3 years have passed since last update.

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

Last updated at Posted at 2017-11-05

データハッカソンの勉強会で解読した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値
これらについて今後勉強していこうと思います。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29