Tensorflow Keras: 2値分類 実装例

Tensorflow Keras を利用した深層学習(Deep Learning)2値分類モデルの単純な実装例について,常に参照できるように備忘録として示す。モデル構築の実装例を可能な限りシンプルに示すため,入力データの前処理やハイパーパラメータ調整については特別扱わない。

開発環境

  • keras: 2.10.0
  • matplotlib: 3.5.3
  • python: 3.10.4
  • tensorflow-gpu: 2.4.0

ソースコード

import numpy as np
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, Input
from tensorflow.keras.datasets import boston_housing
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import confusion_matrix, classification_report
from matplotlib import pyplot as plt

# データセット作成
# データの読み込み
boston = boston_housing
(X_train, y_train), (X_test, y_test) = boston.load_data()
# 平均値より小さいターゲットを0に,平均値以上のターゲットを1に変更して2クラス分類課題にする
threshold = y_train.mean()
y_train, y_test = np.where(y_train < threshold, 0, 1), np.where(y_test < threshold, 0, 1)
# 特徴量を正規化する
scaler = MinMaxScaler().fit(X_train)
X_train, X_test = scaler.transform(X_train), scaler.transform(X_test)

# モデル作成
# 入力層/中間層/出力層 各1層
model = Sequential()
# 入力層
model.add(Input(shape=(X_train.shape[1],)))
# 中間層
model.add(Dense(64, activation='relu'))
# 出力層
model.add(Dense(1))
# モデルコンパイル
model.compile(loss='binary_crossentropy', optimizer='adam', metrics='accuracy')
# モデル内容の確認
model.summary()

# 学習
history = model.fit(X_train, y_train, epochs=50, validation_split=0.2)

# 学習過程の可視化
fig, ax = plt.subplots(1, 2)
# Loss変動の可視化
ax[0].plot(history.history['loss'], label='Train')
ax[0].plot(history.history['val_loss'], label='Test')
ax[0].set_title('Model loss')
ax[0].set_ylabel('Loss')
ax[0].set_xlabel('Epoch')
ax[0].legend()
# Accuracy変動の可視化
ax[1].plot(history.history['accuracy'], label='Train')
ax[1].plot(history.history['val_accuracy'], label='Test')
ax[1].set_title('Model accuracy')
ax[1].set_ylabel('Accuracy')
ax[1].set_xlabel('Epoch')
ax[1].legend()
plt.tight_layout()
plt.show()

# 予測値を計算
pred = (model.predict(X_test) > 0.5).astype('int32')

# 予測値精度
print('混合行列\n', confusion_matrix(y_test, pred))
print('各種制度指標\n', classification_report(y_test, pred))

パッケージのインポート

「matplotlib」は学習・予測結果の可視化に,「scikit-learn」は前処理及ぼ予測精度の評価に用いる。

import numpy as np
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, Input
from tensorflow.keras.datasets import boston_housing
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import confusion_matrix, classification_report
from matplotlib import pyplot as plt

データセット作成

keras で用意されているboston_housingデータセットを用いる。学習データ(X_train)は404行13列,テストデータ(X_test)は102行13列のデータ。

boston_housingデータセットのターゲットは連続値なので,平均値を以上の値はクラス1,平均値より小さい値はクラス0に置き換えることで,2値分類データセットに変換している。

# データの読み込み
boston = boston_housing
(X_train, y_train), (X_test, y_test) = boston.load_data()
# 平均値より小さいターゲットを0に,平均値以上のターゲットを1に変更して2クラス分類課題にする
threshold = y_train.mean()
y_train, y_test = np.where(y_train < threshold, 0, 1), np.where(y_test < threshold, 0, 1)
# 特徴量を正規化する
scaler = MinMaxScaler().fit(X_train)
X_train, X_test = scaler.transform(X_train), scaler.transform(X_test)

モデル作成

シンプルな実装例として,各1層の入力層/中間層/出力層で構成される回帰モデルを定義する。下記の例において中間層は64個のユニットを持つ。出力は値が平均値以上か否か [0 or 1] に対応するn行1列の形状になるので,ユニット数は1を指定する。2値分類が目的なので,損失は’binary_crossentropy’を指定。

# 入力層/中間層/出力層 各1層
model = Sequential()
# 入力層
model.add(Input(shape=(X_train.shape[1],)))
# 中間層
model.add(Dense(64, activation='relu'))
# 出力層
model.add(Dense(1))
# モデルコンパイル
model.compile(loss='binary_crossentropy', optimizer='adam', metrics='accuracy')
# モデル内容の確認
model.summary()
# コード実行時の出力

Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 64)                896       
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 65        
=================================================================
Total params: 961
Trainable params: 961
Non-trainable params: 0
_________________________________________________________________

学習

定義した回帰モデルについて,事前に用意しておいた学習データ(X_train)と正答データ(y_test)を与え,fitメソッドを利用して学習を行う。下記の例では訓練回数は50回(epochs=50),バリデーションデータ割合は20%(validation_split=0.2)に指定している。

history = model.fit(X_train, y_train, epochs=50, validation_split=0.2)
# コード実行時の出力

Epoch 1/50
11/11 [==============================] - 2s 113ms/step - loss: 4.7995 - accuracy: 0.5715 - val_loss: 1.3066 - val_accuracy: 0.5062
Epoch 2/50
11/11 [==============================] - 0s 12ms/step - loss: 0.9818 - accuracy: 0.5124 - val_loss: 0.8908 - val_accuracy: 0.3951
.
.
.
Epoch 49/50
11/11 [==============================] - 0s 11ms/step - loss: 0.3037 - accuracy: 0.9043 - val_loss: 0.6630 - val_accuracy: 0.8395
Epoch 50/50
11/11 [==============================] - 0s 11ms/step - loss: 0.2590 - accuracy: 0.9342 - val_loss: 0.6693 - val_accuracy: 0.8395

学習過程の可視化

history変数内に保存されている学習過程の情報を用いて,学習データ/バリデーションデータに対する損失(loss)および正答率(accuracy)の変動を可視化する。

# 学習過程の可視化
fig, ax = plt.subplots(1, 2)
# Loss変動の可視化
ax[0].plot(history.history['loss'], label='Train')
ax[0].plot(history.history['val_loss'], label='Test')
ax[0].set_title('Model loss')
ax[0].set_ylabel('Loss')
ax[0].set_xlabel('Epoch')
ax[0].legend()
# Accuracy変動の可視化
ax[1].plot(history.history['accuracy'], label='Train')
ax[1].plot(history.history['val_accuracy'], label='Test')
ax[1].set_title('Model accuracy')
ax[1].set_ylabel('Accuracy')
ax[1].set_xlabel('Epoch')
ax[1].legend()
plt.tight_layout()
plt.show()

予測値を計算

学習済みモデルの predictメソッドを用いてテストデータ(X_test)について予測値を求める。一応,predict_classesメソッドを利用することもできるが,UserWarningが表示されるので,警告内容の記載に従って以下の書き方をしている。

pred = (model.predict(X_test) > 0.5).astype('int32')

予測精度

テストデータ(X_test)についての予測の正しさを可視化するため,混合行列および各種評価指標を出力する。

print('混合行列\n', confusion_matrix(y_test, pred))
print('各種制度指標\n', classification_report(y_test, pred))
# コード実行時の出力

混合行列
 [[44 10]
 [11 37]]

各種制度指標
               precision    recall  f1-score   support

           0       0.80      0.81      0.81        54
           1       0.79      0.77      0.78        48

    accuracy                           0.79       102
   macro avg       0.79      0.79      0.79       102
weighted avg       0.79      0.79      0.79       102

コメント