第8章: ニューラルネット
第6章で取り組んだニュース記事のカテゴリ分類を題材として,ニューラルネットワークでカテゴリ分類モデルを実装する.なお,この章ではPyTorch, TensorFlow, Chainerなどの機械学習プラットフォームを活用せよ.
ここでも、Google Colaboratoryを使用しています。
機械学習プラットフォームは、Karasを使用しています。
70. 単語ベクトルの和による特徴量
問題50で構築した学習データ,検証データ,評価データを行列・ベクトルに変換したい.例えば,学習データについて,すべての事例xiの特徴ベクトルxiを並べた行列Xと,正解ラベルを並べた行列(ベクトル)Yを作成したい.
・・・問題説明長いので省略・・・
問題50で作成したファイルを読み込みます。
Googleドライブ上に保存していたので、まずGoogleドライブをマウントします。
from google.colab import drive
drive.mount('/content/drive')
問題50で作成した学習データ・検証データ・評価データを読み込み
%cd "/content/drive/My Drive/NL100/data/"
import pandas as pd
trainDS = pd.read_csv("train.csv", sep='\t')
validDS = pd.read_csv("valid.csv", sep='\t')
testDS = pd.read_csv("test.csv", sep='\t')
trainDS.head()
<出力>
CATEGORY TITLE
0 b REFILE-UPDATE 1-European car sales up for sixt...
1 t Amazon Plans to Fight FTC Over Mobile-App Purc...
2 m Kids Still Get Codeine In Emergency Rooms Desp...
3 e What On Earth Happened Between Solange And Jay...
4 b NATO Missile Defense Is Flight Tested Over Hawaii
問題60で使用したGoogleの学習済み単語ベクトルを読み込み
from gensim.models import KeyedVectors
model = KeyedVectors.load_word2vec_format('/content/drive/My Drive/NL100/data/GoogleNews-vectors-negative300.bin.gz', binary=True)
文章から文章に含まれる単語ベクトルの総和の平均に変換する関数を定義
import string
import numpy as np
def transform_w2v(text):
table = str.maketrans(string.punctuation, ' '*len(string.punctuation))
words = text.translate(table).split() # 記号をスペースに置換後、スペースで分割してリスト化
vec = [model[word] for word in words if word in model] # 1語ずつベクトル化
return np.array(sum(vec) / len(vec)) # 平均ベクトルをndarray型に変換して出力
import pandas as pd
trainX = []
trainY = []
validX = []
validY = []
testX = []
testY = []
dictCat = {"b":0,"e":2,"t":1,"m":3} # 問題文どおりカテゴリを数値にマッピング
for index, row in trainDS.iterrows(): # データセットを1行ずつ処理
trainX.append(transform_w2v(row["TITLE"])) # TITLE列の文字列から単語ベクトル平均を求める。
trainY.append(dictCat[row["CATEGORY"]]) # カテゴリを数値に置換
for index, row in validDS.iterrows():
validX.append(transform_w2v(row["TITLE"]))
validY.append(dictCat[row["CATEGORY"]])
for index, row in testDS.iterrows():
testX.append(transform_w2v(row["TITLE"]))
testY.append(dictCat[row["CATEGORY"]])
df1 = pd.DataFrame(trainX)
df2 = pd.DataFrame(trainY)
df3 = pd.DataFrame(validX)
df4 = pd.DataFrame(validY)
df5 = pd.DataFrame(testX)
df6 = pd.DataFrame(testY)
# 作成データを保存
df1.to_csv("trainX.csv",index=False, header=False)
df2.to_csv("trainY.csv",index=False, header=False)
df3.to_csv("validX.csv",index=False, header=False)
df4.to_csv("validY.csv",index=False, header=False)
df5.to_csv("testX.csv",index=False, header=False)
df6.to_csv("testY.csv",index=False, header=False)
71. 単層ニューラルネットワークによる予測
問題70で保存した行列を読み込み,学習データについて以下の計算を実行せよ.
$$\hat{y_1}=softmax(x_1W),\quad\hat{Y}=softmax(X_{[1:4]}W)$$
ただし,$softmax$はソフトマックス関数,$X_{[1:4]}∈\mathbb{R}^{4×d}$は特徴ベクトル$x_1,x_2,x_3,x_4$を縦に並べた行列である.
$$X_{[1:4]} = \begin{pmatrix} x_1 \
x_2 \
x_3 \
x_4 \end{pmatrix} $$
行列$W∈\mathbb{R}^{d×L}$は単層ニューラルネットワークの重み行列で,ここではランダムな値で初期化すればよい(問題73以降で学習して求める).なお,$\hat{y_1}∈\mathbb{R}^L$は未学習の行列Wで事例$x_1$を分類したときに,各カテゴリに属する確率を表すベクトルである. 同様に,$Y^∈\mathbb{R}^{n×L}$は,学習データの事例$x_1,x_2,x_3,x_4$について,各カテゴリに属する確率を行列として表現している.
import pandas as pd
import numpy as np
from keras.models import Sequential
from keras.layers import Activation, Dense
from keras.utils.np_utils import to_categorical
# 訓練しないので、testデータだけ使用する。
dfXt = pd.read_csv("testX.csv", header=None)
dfYt = pd.read_csv("testY.csv", header=None)
testX = dfXt.values
testY = to_categorical(dfYt[0])
model = Sequential()
model.add(Dense(4,input_dim=300))
model.add(Activation("softmax"))
model.compile(optimizer="sgd", loss="categorical_crossentropy", metrics = ["accuracy"])
# yの予測値
print(model.predict(testX))
<出力>
[[0.24526535 0.24876732 0.26310366 0.24286367]
[0.25131112 0.2621907 0.2508219 0.23567624]
[0.26167753 0.21048622 0.25722775 0.27060854]
...
[0.2765127 0.2245721 0.26449034 0.23442486]
[0.24577916 0.2561649 0.24292147 0.2551344 ]
[0.24550672 0.2526844 0.24847303 0.2533358 ]]
未学習なので、各カテゴリに属する確率は同じように25%程度になっています。
72. 損失と勾配の計算
学習データの事例$x_1$と事例集合$x_1,x_2,x_3,x_4$に対して,クロスエントロピー損失と,行列$W$に対する勾配を計算せよ.なお,ある事例$x_i$に対して損失は次式で計算される.
$$l_i=−log[事例x_iがy_iに分類される確率]$$
ただし,事例集合に対するクロスエントロピー損失は,その集合に含まれる各事例の損失の平均とする.
Kerasで勾配を出力するのは難しいですが、以下のサイトを参考にさせていただきました。
TF2.0の組み込みKarasを使用してCNNヒートマップを生成する方法
TensorFlow 2.0 : 上級 Tutorials : カスタマイズ :- 自動微分と gradient tape
もし間違っていたらご指摘ください。
# 71のつづき
res = model.evaluate(testX, testY)
print("クロスエントロピー誤差:%f3" % res)
print("重み W:")
print(model.weights)
from tensorflow.keras import models
conv_layer = model.get_layer("dense_1")
heatmap_model = models.Model([model.inputs], [conv_layer.output, model.output])
with tf.GradientTape() as gtape:
conv_output, predictions = heatmap_model(testX)
loss = predictions[:, np.argmax(predictions[0])]
grads = gtape.gradient(loss, conv_output)
print("勾配:")
print(grads)
<出力>
42/42 [==============================] - 0s 1ms/step - loss: 1.4016
クロスエントロピー誤差:1.4015933
重み W:
[<tf.Variable 'dense_1/kernel:0' shape=(300, 4) dtype=float32, numpy=
array([[-0.12409324, 0.13879333, -0.04441376, -0.0361783 ],
[ 0.02392311, -0.04380204, -0.13000455, 0.07840692],
[ 0.13213696, -0.12254377, 0.10714729, 0.07443559],
...,
[-0.00052427, -0.02986155, -0.08738405, -0.12841251],
[ 0.11863591, -0.01194271, -0.09917359, 0.12955351],
[-0.01573159, 0.10756773, 0.04556297, 0.04842339]],
dtype=float32)>, <tf.Variable 'dense_1/bias:0' shape=(4,) dtype=float32, numpy=array([0., 0., 0., 0.], dtype=float32)>]
勾配:
tf.Tensor(
[[-0.07094043 -0.06413002 -0.06321437 0.19828482]
[-0.07565898 -0.05865274 -0.06319154 0.19750328]
[-0.05585048 -0.06545844 -0.07087792 0.19218685]
...
[-0.06880869 -0.06196056 -0.07107063 0.20183985]
[-0.06399511 -0.0693226 -0.06950014 0.20281786]
[-0.06372479 -0.07377882 -0.06278919 0.2002928 ]], shape=(1336, 4), dtype=float32)
73. 確率的勾配降下法による学習
確率的勾配降下法(SGD: Stochastic Gradient Descent)を用いて,行列Wを学習せよ.なお,学習は適当な基準で終了させればよい(例えば「100エポックで終了」など).
70で作成した訓練データを読み込ませ、先ほどのモデルでfit(訓練)します。
import pandas as pd
import numpy as np
from keras.models import Sequential
from keras.layers import Activation, Dense
from keras.utils.np_utils import to_categorical
dfX = pd.read_csv("trainX.csv", header=None)
dfY = pd.read_csv("trainY.csv", header=None)
dfXt = pd.read_csv("testX.csv", header=None)
dfYt = pd.read_csv("testY.csv", header=None)
trainX = dfX.values
trainY = to_categorical(dfY[0])
print(dfX.shape)
print(dfY.shape)
testX = dfXt.values
testY = to_categorical(dfYt[0])
model = Sequential()
model.add(Dense(4,input_dim=300))
model.add(Activation("softmax"))
model.compile(optimizer="sgd", loss="categorical_crossentropy", metrics="accuracy")
model.fit(trainX, trainY, batch_size=10, epochs=100)
<出力>
(10684, 300)
(10684, 1)
Epoch 1/100
1069/1069 [==============================] - 1s 749us/step - loss: 1.0467 - accuracy: 0.7080
Epoch 2/100
1069/1069 [==============================] - 1s 738us/step - loss: 0.8353 - accuracy: 0.7763
Epoch 3/100
1069/1069 [==============================] - 1s 752us/step - loss: 0.7427 - accuracy: 0.7794
Epoch 4/100
1069/1069 [==============================] - 1s 776us/step - loss: 0.6840 - accuracy: 0.7797
Epoch 5/100
1069/1069 [==============================] - 1s 764us/step - loss: 0.6420 - accuracy: 0.7802
・・・(省略)・・・
Epoch 95/100
1069/1069 [==============================] - 1s 783us/step - loss: 0.3002 - accuracy: 0.9010
Epoch 96/100
1069/1069 [==============================] - 1s 770us/step - loss: 0.2997 - accuracy: 0.9014
Epoch 97/100
1069/1069 [==============================] - 1s 740us/step - loss: 0.2991 - accuracy: 0.9018
Epoch 98/100
1069/1069 [==============================] - 1s 776us/step - loss: 0.2986 - accuracy: 0.9021
Epoch 99/100
1069/1069 [==============================] - 1s 766us/step - loss: 0.2981 - accuracy: 0.9023
Epoch 100/100
1069/1069 [==============================] - 1s 792us/step - loss: 0.2975 - accuracy: 0.9017
いい感じで正解率が上がっています。
74. 正解率の計測
問題73で求めた行列を用いて学習データおよび評価データの事例を分類したとき,その正解率をそれぞれ求めよ.
学習データに関しては73で約90.2%の正解率でした。
次は、テストデータを使って正解率を求めます。
model.evaluate(testX, testY)
<出力>
42/42 [==============================] - 0s 825us/step - loss: 0.3124 - accuracy: 0.8780
[0.31239748001098633, 0.8779940009117126]
87.8%でした。
学習データの結果からそんなに乖離はしていません。
75. 損失と正解率のプロット
問題73のコードを改変し,各エポックのパラメータ更新が完了するたびに,訓練データでの損失,正解率,検証データでの損失,正解率をグラフにプロットし,学習の進捗状況を確認できるようにせよ.
import pandas as pd
import numpy as np
from keras.models import Sequential
from keras.layers import Activation, Dense
from keras.utils.np_utils import to_categorical
import matplotlib.pyplot as plt
%matplotlib inline
dfX = pd.read_csv("trainX.csv", header=None)
dfY = pd.read_csv("trainY.csv", header=None)
dfXt = pd.read_csv("testX.csv", header=None)
dfYt = pd.read_csv("testY.csv", header=None)
dfXv = pd.read_csv("validX.csv", header=None)
dfYv = pd.read_csv("validY.csv", header=None)
trainX = dfX.values
trainY = to_categorical(dfY[0])
print(dfX.shape)
print(dfY.shape)
testX = dfXt.values
testY = to_categorical(dfYt[0])
validX = dfXv.values
validY = to_categorical(dfYv[0])
model = Sequential()
model.add(Dense(4,input_dim=300))
model.add(Activation("softmax"))
model.compile(optimizer="sgd", loss="categorical_crossentropy", metrics="accuracy")
history = model.fit(trainX, trainY, batch_size=10, epochs=100, validation_data=(validX, validY)) # validation_dataに検証用データセットを設定
plt.plot(history.history["accuracy"], label="train", ls="-", marker="o")
plt.plot(history.history["val_accuracy"], label="valid", ls="-", marker="x")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(loc="best")
plt.show()
<出力>
(10684, 300)
(10684, 1)
Epoch 1/100
1069/1069 [==============================] - 1s 1ms/step - loss: 1.0368 - accuracy: 0.7134 - val_loss: 0.8983 - val_accuracy: 0.7769
Epoch 2/100
1069/1069 [==============================] - 1s 974us/step - loss: 0.8351 - accuracy: 0.7731 - val_loss: 0.7811 - val_accuracy: 0.7844
Epoch 3/100
1069/1069 [==============================] - 1s 1ms/step - loss: 0.7447 - accuracy: 0.7777 - val_loss: 0.7114 - val_accuracy: 0.7837
Epoch 4/100
1069/1069 [==============================] - 1s 1ms/step - loss: 0.6862 - accuracy: 0.7785 - val_loss: 0.6636 - val_accuracy: 0.7859
Epoch 5/100
1069/1069 [==============================] - 1s 1ms/step - loss: 0.6440 - accuracy: 0.7807 - val_loss: 0.6277 - val_accuracy: 0.7874
・・・(省略)・・・
Epoch 95/100
1069/1069 [==============================] - 1s 971us/step - loss: 0.2998 - accuracy: 0.9011 - val_loss: 0.3256 - val_accuracy: 0.8952
Epoch 96/100
1069/1069 [==============================] - 1s 968us/step - loss: 0.2992 - accuracy: 0.9009 - val_loss: 0.3252 - val_accuracy: 0.8937
Epoch 97/100
1069/1069 [==============================] - 1s 956us/step - loss: 0.2987 - accuracy: 0.9013 - val_loss: 0.3248 - val_accuracy: 0.8960
Epoch 98/100
1069/1069 [==============================] - 1s 943us/step - loss: 0.2982 - accuracy: 0.9012 - val_loss: 0.3243 - val_accuracy: 0.8952
Epoch 99/100
1069/1069 [==============================] - 1s 970us/step - loss: 0.2976 - accuracy: 0.9016 - val_loss: 0.3240 - val_accuracy: 0.8960
Epoch 100/100
1069/1069 [==============================] - 1s 938us/step - loss: 0.2971 - accuracy: 0.9016 - val_loss: 0.3236 - val_accuracy: 0.8960
非常にシンプルなモデルであるが、100エポックで正解率90%で、検証データの精度ともそんなに違いがなく、良い状態であるといえます。
76. チェックポイント
問題75のコードを改変し,各エポックのパラメータ更新が完了するたびに,チェックポイント(学習途中のパラメータ(重み行列など)の値や最適化アルゴリズムの内部状態)をファイルに書き出せ.
Kerasには、訓練中にモデル内部の状態と統計量を可視化するために、コールバックが用意されています。
ここでは、TensorBordとModelCheckpointを使用します。
TensorBordは、訓練中に取得したログを、Webツールでグラフィカルに見られます。
TensorBordをGoogle Colaboratory上で使用する方法は、以下のサイトに書かれています。
簡単 3分 TensorBoard in Google Colab (TensorFlow 2.x 使用)
ModelCheckpointは、各エポックごとに指定した評価値を判定し、判定条件:Trueのときにモデルを保存します。(ex.誤差最小のときモデル保存)
以下のサイトの説明がわかりやすかったです。
最良のモデルを保存する(ModelCheckpointの使い方
from __future__ import absolute_import, division, print_function, unicode_literals
# Google ColaboratoryでTensorBoardを使用するための処理
try:
# %tensorflow_version only exists in Colab.
%tensorflow_version 2.x
except Exception:
pass
# Load the TensorBoard notebook extension
%load_ext tensorboard
前の問題のソースを改造します。
import pandas as pd
import numpy as np
from keras.models import Sequential
from keras.layers import Activation, Dense
from keras.utils.np_utils import to_categorical
import matplotlib.pyplot as plt
import keras
import os
%matplotlib inline
f_log = 'log' # ログ用フォルダ
f_model = 'model' # モデル用フォルダ
dfX = pd.read_csv("trainX.csv", header=None)
dfY = pd.read_csv("trainY.csv", header=None)
dfXt = pd.read_csv("testX.csv", header=None)
dfYt = pd.read_csv("testY.csv", header=None)
dfXv = pd.read_csv("validX.csv", header=None)
dfYv = pd.read_csv("validY.csv", header=None)
trainX = dfX.values
trainY = to_categorical(dfY[0])
print(dfX.shape)
print(dfY.shape)
testX = dfXt.values
testY = to_categorical(dfYt[0])
validX = dfXv.values
validY = to_categorical(dfYv[0])
model = Sequential()
model.add(Dense(4,input_dim=300))
model.add(Activation("softmax"))
model.compile(optimizer="sgd", loss="categorical_crossentropy", metrics="accuracy")
# TensorBoardを定義。出力フォルダを指定。histogram_freq=1 は毎エポックごとに出力
tb_cb = keras.callbacks.TensorBoard(log_dir=f_log, histogram_freq=1)
# ModelCheckpointを定義。出力フォルダとファイル名、評価する指標など定義している。
# ここでは、検証データ損失最小のときの重みを保存する。
cp_cb = keras.callbacks.ModelCheckpoint(filepath = os.path.join(f_model,'model{epoch:02d}-loss{loss:.2f}-acc{accuracy:.2f}-vloss{val_loss:.2f}-vacc{val_accuracy:.2f}.hdf5'), monitor='val_loss', verbose=1, save_best_only=True, mode='auto')
cbks = [tb_cb, cp_cb]
# 訓練時のパラメータにコールバックを渡す。
history = model.fit(trainX, trainY, batch_size=10, epochs=100, callbacks=cbks, validation_data=(validX, validY))
plt.plot(history.history["accuracy"], label="train", ls="-", marker="o")
plt.plot(history.history["val_accuracy"], label="valid", ls="-", marker="x")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(loc="best")
plt.show()
# 最終的なモデルと重みもファイルに残す。
strmodel = model.to_json()
with open("model.txt", "w") as f:
f.write(strmodel)
model.save_weights("param.hdf5")
# TensorBoardを起動
%tensorboard --logdir log
77. ミニバッチ化
問題76のコードを改変し,B事例ごとに損失・勾配を計算し,行列Wの値を更新せよ(ミニバッチ化).Bの値を1,2,4,8,…と変化させながら,1エポックの学習に要する時間を比較せよ.
エポックごとの処理時間を取得するため、以下のサイトを参考にTimeHistoryクラスを作成し、コールバックさせてみました。
model.fit()中にKerasの各エポックの計算時間を記録します
import pandas as pd
import numpy as np
from keras.models import Sequential
from keras.layers import Activation, Dense
from keras.utils.np_utils import to_categorical
import matplotlib.pyplot as plt
import keras
import os
import time
%matplotlib inline
class TimeHistory(keras.callbacks.Callback):
def __init__(self):
self.times = []
def on_epoch_begin(self, batch, logs={}):
self.Epoch_time_start = time.time()
def on_epoch_end(self, batch, logs={}):
self.times.append(time.time() - self.Epoch_time_start)
dfX = pd.read_csv("trainX.csv", header=None)
dfY = pd.read_csv("trainY.csv", header=None)
dfXt = pd.read_csv("testX.csv", header=None)
dfYt = pd.read_csv("testY.csv", header=None)
dfXv = pd.read_csv("validX.csv", header=None)
dfYv = pd.read_csv("validY.csv", header=None)
trainX = dfX.values
trainY = to_categorical(dfY[0])
print(dfX.shape)
print(dfY.shape)
testX = dfXt.values
testY = to_categorical(dfYt[0])
validX = dfXv.values
validY = to_categorical(dfYv[0])
markers = ["o","x",".","v","^","1"]
for i, batchNum in enumerate(np.arange(0,11,2)):
model = Sequential()
model.add(Dense(4,input_dim=300))
model.add(Activation("softmax"))
model.compile(optimizer="sgd", loss="categorical_crossentropy", metrics="accuracy")
time_callback = TimeHistory()
history = model.fit(trainX, trainY, batch_size=batchNum, epochs=100, callbacks=[time_callback], validation_data=(validX, validY), verbose=0)
print("train_acc:{:.3f} valid_acc:{:.3f}".format( np.average(history.history["accuracy"]), np.average(history.history["val_accuracy"])))
print(time_callback.times)
plt.plot( time_callback.times, label="batch size:%d" % batchNum, ls="-", marker=markers[i])
plt.ylabel("time")
plt.xlabel("epoch")
plt.legend(loc="best")
plt.show()
<出力>
batch_size=0 のときは、デフォルト値の32で実行されるので、1エポック当たり0.3秒未満で実行されています。
バッチサイズを大きくすることにより、処理時間が短くなることがわかる。
78. GPU上での学習
問題77のコードを改変し,GPU上で学習を実行せよ.
Google Colaboratoryでは、「ランタイム」メニューの「ランタイムのタイプを変更」で実行環境を
・ None (GPUなし)
・ GPU (GPUを使用)
・ TPU (Googleが開発したテンソル計算に特化したGPUを使用)
の3つから選択できます。
問題77はNone設定(GPUなし)で実行していましたが、このとき、1エポック当たりの実行時間は0.25~0.3秒くらいでした。
ランタイムをGPUに切り替えて、バッチサイズ0(デフォルト32)で実行してみました。
1エポック当たり0.5秒!なぜかNoneのときより時間かかってます。
次にランタイムをTPUに切り替えて実行
1エポック当たり0.2秒くらいです。
GPUがCPUより遅い理由はよくわかりません。サーバーの混雑状況?
79. 多層ニューラルネットワーク
問題78のコードを改変し,バイアス項の導入や多層化など,ニューラルネットワークの形状を変更しながら,高性能なカテゴリ分類器を構築せよ.
以下、中間層を増やし、カスタマイズしました。
import pandas as pd
import numpy as np
from keras.models import Sequential
from keras.layers import Activation, Dense, Dropout, BatchNormalization
from keras.utils.np_utils import to_categorical
import matplotlib.pyplot as plt
import keras
import os
%matplotlib inline
f_log = 'log' # ログ用フォルダ
f_model = 'model' # モデル用フォルダ
dfX = pd.read_csv("trainX.csv", header=None)
dfY = pd.read_csv("trainY.csv", header=None)
dfXt = pd.read_csv("testX.csv", header=None)
dfYt = pd.read_csv("testY.csv", header=None)
dfXv = pd.read_csv("validX.csv", header=None)
dfYv = pd.read_csv("validY.csv", header=None)
trainX = dfX.values
trainY = to_categorical(dfY[0])
print(dfX.shape)
print(dfY.shape)
testX = dfXt.values
testY = to_categorical(dfYt[0])
validX = dfXv.values
validY = to_categorical(dfYv[0])
model = Sequential()
model.add(Dense(256,input_dim=300))
model.add(BatchNormalization()) # バッチ正規化をいれた。
model.add(Activation("relu")) # 活性化関数はRelu関数
model.add(Dense(128))
model.add(BatchNormalization())
model.add(Activation("relu"))
model.add(Dense(64))
model.add(BatchNormalization())
model.add(Activation("relu"))
model.add(Dense(32))
model.add(BatchNormalization())
model.add(Activation("relu"))
model.add(Dropout(rate=0.5)) # 過学習防止のためのDropout
model.add(Dense(4))
model.add(Activation("softmax"))
model.compile(optimizer="Adam", loss="categorical_crossentropy", metrics="accuracy")
tb_cb = keras.callbacks.TensorBoard(log_dir=f_log, histogram_freq=1)
cp_cb = keras.callbacks.ModelCheckpoint(filepath = os.path.join(f_model,'model{epoch:02d}-loss{loss:.2f}-acc{accuracy:.2f}-vloss{val_loss:.2f}-vacc{val_accuracy:.2f}.hdf5'), monitor='val_loss', verbose=1, save_best_only=True, mode='auto')
cbks = [tb_cb, cp_cb]
print(model.summary())
history = model.fit(trainX, trainY, batch_size=10, epochs=100, callbacks=cbks, validation_data=(validX, validY))
model.evaluate(testX, testY)
plt.plot(history.history["accuracy"], label="train", ls="-", marker="o")
plt.plot(history.history["val_accuracy"], label="valid", ls="-", marker="x")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(loc="best")
plt.show()
strmodel = model.to_json()
with open("model.txt", "w") as f:
f.write(strmodel)
model.save_weights("param.hdf5")
#print(model.predict(testX))
#res = model.evaluate(testX, testY)
%tensorboard --logdir log
<出力>
(10684, 300)
(10684, 1)
Model: "sequential_4"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_17 (Dense) (None, 256) 77056
_________________________________________________________________
batch_normalization_14 (Batc (None, 256) 1024
_________________________________________________________________
activation_17 (Activation) (None, 256) 0
_________________________________________________________________
dense_18 (Dense) (None, 128) 32896
_________________________________________________________________
batch_normalization_15 (Batc (None, 128) 512
_________________________________________________________________
activation_18 (Activation) (None, 128) 0
_________________________________________________________________
dense_19 (Dense) (None, 64) 8256
_________________________________________________________________
batch_normalization_16 (Batc (None, 64) 256
_________________________________________________________________
activation_19 (Activation) (None, 64) 0
_________________________________________________________________
dense_20 (Dense) (None, 32) 2080
_________________________________________________________________
batch_normalization_17 (Batc (None, 32) 128
_________________________________________________________________
activation_20 (Activation) (None, 32) 0
_________________________________________________________________
dropout_3 (Dropout) (None, 32) 0
_________________________________________________________________
dense_21 (Dense) (None, 4) 132
_________________________________________________________________
activation_21 (Activation) (None, 4) 0
=================================================================
Total params: 122,340
Trainable params: 121,380
Non-trainable params: 960
_________________________________________________________________
None
Epoch 1/100
2/1069 [..............................] - ETA: 1:32 - loss: 2.6207 - accuracy: 0.0500WARNING:tensorflow:Callbacks method `on_train_batch_end` is slow compared to the batch time (batch time: 0.0078s vs `on_train_batch_end` time: 0.1656s). Check your callbacks.
1059/1069 [============================>.] - ETA: 0s - loss: 0.6205 - accuracy: 0.7751
Epoch 00001: val_loss improved from inf to 0.35474, saving model to model/model01-loss0.62-acc0.78-vloss0.35-vacc0.88.hdf5
1069/1069 [==============================] - 3s 3ms/step - loss: 0.6189 - accuracy: 0.7756 - val_loss: 0.3547 - val_accuracy: 0.8772
Epoch 2/100
1050/1069 [============================>.] - ETA: 0s - loss: 0.4454 - accuracy: 0.8546
Epoch 00002: val_loss improved from 0.35474 to 0.34267, saving model to model/model02-loss0.44-acc0.86-vloss0.34-vacc0.89.hdf5
1069/1069 [==============================] - 3s 3ms/step - loss: 0.4446 - accuracy: 0.8551 - val_loss: 0.3427 - val_accuracy: 0.8900
Epoch 3/100
1058/1069 [============================>.] - ETA: 0s - loss: 0.4085 - accuracy: 0.8646
Epoch 00003: val_loss improved from 0.34267 to 0.32080, saving model to model/model03-loss0.41-acc0.86-vloss0.32-vacc0.89.hdf5
1069/1069 [==============================] - 3s 3ms/step - loss: 0.4096 - accuracy: 0.8646 - val_loss: 0.3208 - val_accuracy: 0.8945
Epoch 4/100
1054/1069 [============================>.] - ETA: 0s - loss: 0.3747 - accuracy: 0.8770
Epoch 00004: val_loss did not improve from 0.32080
1069/1069 [==============================] - 3s 3ms/step - loss: 0.3749 - accuracy: 0.8774 - val_loss: 0.3381 - val_accuracy: 0.8982
・・・(省略)・・・
Epoch 00098: val_loss did not improve from 0.31329
1069/1069 [==============================] - 3s 3ms/step - loss: 0.0434 - accuracy: 0.9874 - val_loss: 0.6189 - val_accuracy: 0.9049
Epoch 99/100
1068/1069 [============================>.] - ETA: 0s - loss: 0.0502 - accuracy: 0.9866
Epoch 00099: val_loss did not improve from 0.31329
1069/1069 [==============================] - 3s 3ms/step - loss: 0.0502 - accuracy: 0.9866 - val_loss: 0.6550 - val_accuracy: 0.9004
Epoch 100/100
1050/1069 [============================>.] - ETA: 0s - loss: 0.0446 - accuracy: 0.9863
Epoch 00100: val_loss did not improve from 0.31329
1069/1069 [==============================] - 3s 3ms/step - loss: 0.0472 - accuracy: 0.9864 - val_loss: 0.6239 - val_accuracy: 0.9004
42/42 [==============================] - 0s 1ms/step - loss: 0.3928 - accuracy: 0.9244
訓練データの誤差は小さくなり、正解率は98%以上まで上がりました。
しかし、検証データの正解率は90%前後のままで、かつ、エポックが進むほど誤差が大きくなっているようです。
過学習対策にドロップアウトやバッチ正規化を入れてみましたが、なかなかテスト誤差が改善できませんでした。
テストデータをもっと増やすことが必要なのだと思います。