回帰問題
これまで,Kerasを用いて分類問題を扱ってきましたが,Kerasを使ってニューラルネットワークを構築し,回帰問題を解くことも可能です.すなわち,入力データに対して何らかのクラスを出力するのではなく,連続値を出力します.
入力画像から別の画像を生成するような高度な回帰問題(高解像度化や自動着色)もCNNを使えば可能ですが,まずはより簡単な,複数の特徴量から1つの数値を予測するような回帰問題をやってみたいと思います.
データセット
今回は,機械学習の回帰問題でよく用いられるデータセットである,boston_housingを用いて,ボストンの住宅価格の推定を行ってみたいと思います.これは,Kerasのなかにも標準で入っているデータセットです.このデータセットには,犯罪発生数や住居の平均部屋数など,14個の特徴量を有するデータが506件入っています.これらの特徴量を用いて住宅価格の回帰を行います.今回は,データセットの80%を学習に用い,残りの20%を評価に用います.
サンプルコード
以下,サンプルコードです.
1 2 |
import keras from keras.datasets import boston_housing |
まずはKerasのインポートです.
そして,boston_housingのデータセットもインポートします.
1 |
(X_train, y_train), (X_test, y_test) = boston_housing.load_data() |
そして,boston_housingのデータをトレーニングデータとテストデータに分割します.元から4:1に分けられているので,データセットの80%が学習に用いられます.
X_で始まるのが各特徴量を有するデータで,y_で始まるのが対応する住宅価格です.
1 2 3 4 5 6 7 8 9 10 |
#トレーニングデータの正規化 X_train_mean = X_train.mean(axis=0) X_train_std = X_train.std(axis=0) X_train -= X_train_mean X_train /= X_train_std y_train_mean = y_train.mean() y_train_std = y_train.std() y_train -= y_train_mean y_train /= y_train_std |
次に各データを正規化しています.これは,各データの属性がそれぞれ異なるためです.属性がそれぞれ異なると,計算するときにこれらのスケールの違いに結果が引っ張られてしまう恐れがあるので,これを防ぐために,同じ尺度に調整します.具体的な内容としては,各変数ごとに平均値を引いて,これを標準偏差で割ります.
1 2 3 4 5 |
#テストデータの正規化 X_test -= X_train_mean X_test /= X_train_std y_test -= y_train_mean y_test /= y_train_std |
また,テストデータに対しても,トレーニングデータの平均と標準偏差を用いて正規化します.これは,テストデータとトレーニングデータを同じ尺度で正規化するためです.でないと,精度が一気に低下してしまうので気をつけましょう.
さて,データの準備が一通り終わったのでニューラルネットワークモデルを構築します.
1 2 3 4 5 6 7 |
from keras.models import Sequential from keras.layers import Dense model = Sequential() model.add(Dense(64, activation='relu', input_shape=(X_train.shape[1],))) model.add(Dense(64, activation='relu')) model.add(Dense(1)) |
今回の回帰では,画像処理をしたりするわけではないので,畳み込み層などは特に設けず,全結合層のみで構成しています.また,今回は最終的に住宅価格を出力したいので,最後の全結合層のニューロンは1つだけになっています.
1 2 3 |
model.compile(optimizer='adam', loss='mse', metrics=['mae']) |
今回は最適化アルゴリズムにAdamを用いました.また,分類問題では損失関数にcategorical crossentropyを使っていましたが,今回はmse(平均二乗誤差)を使っています.これは回帰でよく用いられる損失関数で,なめらかな関数を学習によって計算します.評価関数は学習に直接関わってきませんが,今回はmae(平均絶対誤差)を用いています.
それでは,これまでに構築したモデルを用いて学習を開始します.
1 2 3 4 5 |
history = model.fit(X_train, y_train, #トレーニングデータ batch_size=1, #バッチサイズの指定 epochs=100, #エポック数の指定 verbose=1, #ログ出力の指定. validation_data=(X_test, y_test)) #テストデータ |
今回の場合はバッチサイズ1でエポック100として学習を行います.
結果は以下のようになりました.
Train on 404 samples, validate on 102 samples
Epoch 1/100
404/404 [==============================] – 3s 7ms/step – loss: 0.3963 – mean_absolute_error: 0.4105 – val_loss: 0.2950 – val_mean_absolute_error: 0.3866
~(省略)~
Epoch 100/100
404/404 [==============================] – 2s 5ms/step – loss: 0.0176 – mean_absolute_error: 0.0905 – val_loss: 0.1393 – val_mean_absolute_error: 0.2480
エポックが進む毎に少しずつ誤差が低下していることが確認できると思います.