環境
python2.7, ubuntu14.04上。Kerasを使用して、入力はベクトルを想定。
モデルの定義
print(autoencoder.summary())
とすればモデルに含まれるパラメータ数を出力してくれます。
今回は入力のベクトルをPolynomialFeatures
でわざと増やしています。
ようはx*y
の多項式の特徴をつくるため一気に次元数が増えます。
from keras.layers import Input, Dense from keras.models import Model from sklearn.preprocessing import PolynomialFeatures poly = PolynomialFeatures(2).fit(train_X) train_pX, test_pX = poly.transform(train_X), poly.transform(test_X) encoding_dim = 32 input_v = Input(shape=(train_pX.shape[1],)) encoded = Dense(encoding_dim, activation='relu')(input_v) decoded = Dense(train_pX.shape[1], activation='sigmoid')(encoded) autoencoder = Model(input=input_v, output=decoded) autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy') print(autoencoder.summary())
出力
____________________________________________________________________________________________________ Layer (type) Output Shape Param # Connected to ==================================================================================================== input_2 (InputLayer) (None, 253) 0 ____________________________________________________________________________________________________ dense_3 (Dense) (None, 32) 8128 input_2[0][0] ____________________________________________________________________________________________________ dense_4 (Dense) (None, 253) 8349 dense_3[0][0] ==================================================================================================== Total params: 16477 ____________________________________________________________________________________________________ None
モデルの訓練
誤差の減少過程を出力するためにコールバックを新しくインポート。
verbose=2
は訓練中の出力のオプション。
from keras.callbacks import Callback class LossHistory(Callback): def on_train_begin(self, logs={}): self.losses = [] def on_batch_end(self, batch, logs={}): self.losses.append(logs.get('loss')) plotdata = LossHistory() autoencoder.fit(train_pX, train_pX, nb_epoch=50, batch_size=100, shuffle=True, validation_data=(test_pX, test_pX), verbose=2, callbacks=[plotdata])
誤差の減少具合
plt.plot(plotdata.losses) plt.xlabel('train step') plt.ylabel('binary_crossentropy')
このモデルでは、もうこれ以上は誤差が減りそうにありません。 もう少し複雑なモデルを試してみます。
オートエンコーダーのモデルを複雑に
層の数を増やして、層の次元数を 1000 -> 500 -> 250 といった具合に半分はんぶんになっていくように定義し直します。
encoding_dim = 50 dimension = train_pX.shape[1] input_v = Input(shape=(dimension,)) encoded2 = Dense(encoding_dim, activation='relu')(input_v) encoded2 = Dense(int(dimension/2), activation='relu')(encoded2) encoded2 = Dense(int(dimension/4), activation='relu')(encoded2) decoded2 = Dense(int(dimension/4), activation='relu')(encoded2) decoded2 = Dense(int(dimension/2), activation='relu')(decoded2) decoded2 = Dense(dimension, activation='sigmoid')(encoded2) autoencoder2 = Model(input=input_v, output=decoded2) autoencoder2.compile(optimizer='adadelta', loss='binary_crossentropy') print(autoencoder.summary()) print(autoencoder.summary())
____________________________________________________________________________________________________ Layer (type) Output Shape Param # Connected to ==================================================================================================== input_3 (InputLayer) (None, 253) 0 ____________________________________________________________________________________________________ dense_5 (Dense) (None, 50) 12700 input_3[0][0] ____________________________________________________________________________________________________ dense_6 (Dense) (None, 126) 6426 dense_5[0][0] ____________________________________________________________________________________________________ dense_7 (Dense) (None, 63) 8001 dense_6[0][0] ____________________________________________________________________________________________________ dense_10 (Dense) (None, 253) 16192 dense_7[0][0] ==================================================================================================== Total params: 43319 ____________________________________________________________________________________________________ None
パラメータ数はさっきの五倍近くになりました。
二つのモデルの比較
新しいオートエンコーダーをエポック数、バッチサイズを同条件にして訓練。 そのあと損失関数の減少具合を比較してみます。
plotdata2 = LossHistory() autoencoder2.fit(train_pX, train_pX, nb_epoch=50, batch_size=100, shuffle=True, validation_data=(test_pX, test_pX), verbose=2, callbacks=[plotdata2]) plt.plot(plotdata.losses, label='simple model') plt.plot(plotdata2.losses, label='complex model', alpha=.5) plt.xlabel('train step') plt.ylabel('binary_crossentropy') plt.legend()
青色が複雑にしたモデルの結果です。 わずかに精度改善しただけなので、モデルの層を増やすのではなくバッチサイズなどの他パラメータが原因で精度が止まっている可能性があることがわかりました。