Kerasでワイン分類


はじめに 

(注意 著者はこの分野をがっつり専門にしているわけではないので、説明の不足や誤りもあるかもしれません。)
scikit-learnで入手できるワインの種類(3種)とそれぞれの13の特徴量がまとめられたデータセットを機械学習で分類するためのプログラムです。Udemyの以下の講座ではChainer実装ですが、このページではKerasで実装してみました。
【キカガク流】現場で使えるChainerによるディープラーニング入門
https://www.udemy.com/course/kikagaku-chainer/learn/lecture/11004080#overview
プログラムをしっかり見直したわけではないので、少し変な部分があるかもしれません。その場合はご連絡いただけると幸いです。
今回やることの概略図を以下に示します。ニューラルネットワークは隠れ層一つです。

また、今回は最後に最適化関数を変えてみてどんな変化があるかもまとめました。

損失関数・最適化関数

損失値とはニューラルネットワークが予測した値と正解の誤差であり、その誤差を求める関数が損失関数です。プログラム中のloss='categorical_crossentropy'で損失関数を定義しています。前の記事では回帰だったのでloss='mean_squared_error'としていました。このように問題設定によって損失関数を変更します。

損失関数の値が減少するように重みを変化させるために最適化関数を用います。プログラム中ではopt = keras.optimizers.SGD(lr=0.08)で定義しています。損失関数同様、多数の種類があり、学習がうまくいかない場合には変更してみるといいです。

ニューラルネットの学習では損失値が小さくなるように重みを調整していきます。損失関数・最適化関数の説明については「はじめに」で述べた講座で詳しく解説されています。

プログラム

GitHubに載せます。
https://github.com/moriitkys/KerasWineClassify

KerasWineClassify.ipynb
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_wine
import pandas as pd
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout
import matplotlib.pyplot as plt

wine = load_wine()
df = pd.DataFrame(wine.data, columns=wine.feature_names)
dataset_mean = df.mean()
#pd.DataFrame(wine.target)

# Centering
df_c = df-df.mean()
# Normalizing
df_norm = (df_c - df_c.mean()) / (df_c.max() - df_c.min())

s = 13
nb_classes = 3

# Split data
from keras.utils import np_utils
train_X, test_X, train_Y, test_Y = train_test_split(df_norm, wine.target[:], test_size = 0.25)

train_Y1 = np_utils.to_categorical(train_Y,nb_classes)
test_Y1 = np_utils.to_categorical(test_Y,nb_classes)

# Build model
from keras.optimizers import Adam, RMSprop, SGD
model = Sequential()
model.add(Dense(128, input_shape=(s, ), use_bias=False, activation='relu'))
#model.add(Dense(128, activation='relu'))
#model.add(Dense(128, activation='relu'))
#model.add(Dense(128, activation='relu'))
model.add(Dense(nb_classes, activation='softmax'))
#opt = keras.optimizers.Adam(lr=0.08)
#opt = keras.optimizers.RMSprop(lr=0.08)
opt = keras.optimizers.SGD(lr=0.08)

model.compile(optimizer=opt,
      loss='categorical_crossentropy',
      metrics=['mae', 'acc'])

# Start training
history = model.fit(train_X, train_Y1, epochs=50, batch_size=20, verbose=1, validation_data=(test_X,test_Y1))

print(model.summary())
open("model", "w").write(model.to_json())
model.save_weights('param.hdf5')

weights = model.get_weights()

# plot val_loss 損失値の推移をプロット
plt.plot(history.history['val_loss'])
plt.plot(history.history['val_acc'])
plt.show()

結果

上記のグラフのように、val_accであるオレンジのグラフが1に近づいて行ったことから学習は成功したと思います。特にSGDが最も安定した曲線になっていると思います。