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

データハッカソンの勉強会で解読したkaggleのKernelが非常にわかりやすく勉強になったので、こちらに残しておきます。もし間違った記載があればご指摘いただけると幸いです。

「kaggle」については以下の記事などをご覧ください。
- [Kaggle事始め](https://qiita.com/taka4sato/items/802c494fdebeaa7f43b7)
- [データサイエンティストを目指して勉強するなら、Kaggleからはじめよう](https://qiita.com/KIKUYA-Takumi/items/13ac849582318f559271)

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

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

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

### Step 1　〜データ内容の把握〜
まずはデータを読み込み、表示してみます。（ライブラリのインポートについては割愛します。）

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

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

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

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

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

```python
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)などとすることです（認識が合っているか怪しい・・・）。

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

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

```python
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"（生検結果）をラベルにしています。

```python
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'])
```

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

```python
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　〜モデルの構築・学習〜
モデルを構築・学習しましょう！ここでは「入力層ー隠れ層１ー出力層」のニューラルネットワークとしています。

```python
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　〜モデルの精度を検証〜
モデルを動かしましょう。

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

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

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

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