Scikit-learn乳がん診断データセットで深層ニューラルネットワークしてみる

機械学習

前回『【kaggle】いろんな果物を分類してみる』は教師なしの分類をk平均法でやりました。
今回は深層ニューラルネットワークをかじったので、早速、Scikit-learn乳がん診断データセット
でやってみようと思います。元日に。

各種ライブラリのインポートとかデータの確認とか準備とか

import numpy as np
import pandas as pd

from keras import models
from keras import layers
from keras.callbacks import EarlyStopping
from sklearn.model_selection import train_test_split

from sklearn.datasets import load_breast_cancer

グーグルコラボでやってますが、特別なことはせずとも、これでkerasからインポートできました。

datasets=load_breast_cancer()                               

例のごとく、”data”、”feature_names”、”target”に各々データとカラム名とターゲットが
入っているので、データフレームにしてどういうもんか見てみます。

df=pd.DataFrame(datasets.data,columns=datasets.feature_names)
df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 569 entries, 0 to 568
Data columns (total 30 columns):
 #   Column                   Non-Null Count  Dtype  
---  ------                   --------------  -----  
 0   mean radius              569 non-null    float64
 1   mean texture             569 non-null    float64
 2   mean perimeter           569 non-null    float64
 3   mean area                569 non-null    float64
 4   mean smoothness          569 non-null    float64
 5   mean compactness         569 non-null    float64
 6   mean concavity           569 non-null    float64
 7   mean concave points      569 non-null    float64
 8   mean symmetry            569 non-null    float64
 9   mean fractal dimension   569 non-null    float64
 10  radius error             569 non-null    float64
 11  texture error            569 non-null    float64
 12  perimeter error          569 non-null    float64
 13  area error               569 non-null    float64
 14  smoothness error         569 non-null    float64
 15  compactness error        569 non-null    float64
 16  concavity error          569 non-null    float64
 17  concave points error     569 non-null    float64
 18  symmetry error           569 non-null    float64
 19  fractal dimension error  569 non-null    float64
 20  worst radius             569 non-null    float64
 21  worst texture            569 non-null    float64
 22  worst perimeter          569 non-null    float64
 23  worst area               569 non-null    float64
 24  worst smoothness         569 non-null    float64
 25  worst compactness        569 non-null    float64
 26  worst concavity          569 non-null    float64
 27  worst concave points     569 non-null    float64
 28  worst symmetry           569 non-null    float64
 29  worst fractal dimension  569 non-null    float64

ということで、569人分の乳がん診断データで、30個の特徴量があります。
この特徴量、詳しくはこちらを参照されたしですが、腫瘍の検体(?)画像から計算した、画像にある細胞核の特徴を説明している特徴量だそうです。
そして、targetに、それが悪性(0)なのか良性(1)なのか、というデータが入っています。

欠損値なしのキレイな状態で用意されているので、このままやっていきます。

x_=datasets.data
t=datasets.target

標準化するので、

from sklearn.preprocessing import StandardScaler
scaler=StandardScaler()
x=scaler.fit_transform(x_)

で、これを学習、検証、テスト用のデータに分けますよ。

x_train,x_test,t_train,t_test=train_test_split(x,t,test_size=0.2,random_state=0)
x_train,x_train_val,t_train,t_train_val=train_test_split(x_train,t_train,test_size=0.2,random_state=0)
print(x_train.shape,x_train_val.shape,x_test.shape)
print(t_train.shape,t_train_val.shape,t_test.shape)
(364, 30) (91, 30) (114, 30)
(364,) (91,) (114,)

569個のデータを、
学習:364個
検証:91個
テスト:114個
に分けまして、データの準備完了です。

モデルの構築と学習

モデルの構築をやる訳ですが、例のごとく、まあ簡単に書けてしまうんです。
本当にありがたいことですね。

model=models.Sequential()
model.add(layers.Dense(200,activation="relu",input_dim=30))
model.add(layers.Dense(100,activation="relu"))
model.add(layers.Dense(1,activation="sigmoid"))

モデルとしては、これでおしまい。
に、ここではしてますが、行を足せばもっと多層にできます。
models.Sequential() こいつが、
データの線形結合➡活性化関数➡次のニューロンへ
をやってくれるアルゴリズムです。
で、順番に各層で何やるかを決めてるんですが、
model.add(layers.Dense(200,activation=”relu”,input_dim=30))
最初のこれが入力層、
・200個のニューロン
・活性化関数はRELU
・入力データの次元は30
だよって決めてます。
model.add(layers.Dense(100,activation=”relu”))
ほんでこれが、中間層で、
・100個のニューロン
・活性化関数はRELU
として、出力層として
model.add(layers.Dense(1,activation=”sigmoid”))
1個の出力を、シグモイド関数でだしてね、2値だから。
としているわけです。

model.summary()

これで、モデルの概要が見れて、

Model: "sequential_20"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_80 (Dense)            (None, 200)               6200      
                                                                 
 dense_81 (Dense)            (None, 100)               20100     
                                                                 
 dense_82 (Dense)            (None, 1)                 101       
                                                                 
=================================================================
Total params: 26,401
Trainable params: 26,401
Non-trainable params: 0
_________________________________________________________________

こんなですよと。
計26,401個のパラメータがあるよと、
各層でデータを線形結合する際の、各係数の数とその総和を教えてくれます。
モデルとしては、こうなんですが、
どうやって最適化していくの?とか、損失関数なんですか?とか、評価指標は何?
とうことを別途決めてあげないといけません。

model.compile(optimizer="adam",
              loss="binary_crossentropy",
              metrics=["accuracy"])

最適化アルゴリズムはadam,
2値分類問題なので、損失関数は、バイナリーの交差エントロピー、
同じく2値分類問題なので、評価指標は正解率、
としています。
最適化アルゴリズムについては、ここがわかりやすかったです。

callbacks=[EarlyStopping(monitor="val_accuracy",patience=3)]

ほんでもって、検証データの正解率が、3回向上しなかったら学習終わって、を定義しといて、

results=model.fit(x_train,
                  t_train,
                  epochs=50,
                  batch_size=100,
                  verbose=1,
                  callbacks=callbacks,
                  validation_data=(x_train_val,t_train_val))

こないして、学習です。
batch_size=100
これで、1回の学習で使うデータの数を、
epochs=50
これで学習の回数、を決めています。

Epoch 1/50 loss: 0.5555 - accuracy: 0.7308 - val_loss: 0.3488 - val_accuracy: 0.9121
Epoch 2/50 loss: 0.3072 - accuracy: 0.9396 - val_loss: 0.1997 - val_accuracy: 0.9560
Epoch 3/50 loss: 0.2033 - accuracy: 0.9505 - val_loss: 0.1311 - val_accuracy: 0.9670
Epoch 4/50 loss: 0.1512 - accuracy: 0.9560 - val_loss: 0.0952 - val_accuracy: 0.9890
Epoch 5/50 loss: 0.1225 - accuracy: 0.9670 - val_loss: 0.0751 - val_accuracy: 0.9890
Epoch 6/50 loss: 0.1031 - accuracy: 0.9698 - val_loss: 0.0640 - val_accuracy: 0.9890
Epoch 7/50 loss: 0.0906 - accuracy: 0.9725 - val_loss: 0.0591 - val_accuracy: 0.9890

ここで止まりました。どっちもすんごい正解率が出てますね。
では、テストではどうなのっと、

test_score=model.evaluate(x_test,t_test)
print(f"test_loss:{test_score[0]}",f"test_acc:{test_score[1]}")
test_loss:0.09619366377592087 test_acc:0.9473684430122375

114個中、6個間違えて、正解率94.7%。

適当なハイパーパラメータでこれですから、多分すごいんだと思います。