2017年9月11日月曜日

ニューラルネットワークで直線にフィット

ニューラルネットワークを使って、直線のデータ\(y=x\)にノイズをのせた、\(y=x+n\) (\(n\)がノイズ)からサンプルしたデータにフィッティングをして、\(y=x\)を学習できるか試してみました。

Kerasを使って学習します。モデルは、

model = Sequential()
model.add(Dense(32, input_shape=(1,)))
model.add(Activation('tanh'))
model.add(Dense(32))
model.add(Activation('tanh'))
model.add(Dense(1))
としました。ただの直線フィッティングにしてはゴージャスな構成です。

学習データを[-10,10)の範囲で一様乱数で10000サンプルとって、100エポック学習したところ、学習できたモデルの出力は下図のようになりました。横軸が\(x\)、縦軸が\(y\)です。

学習データのある\(x\)が-10から10の範囲では目で見る限りにおいてノイズに惑わされず直線になっていますが、その範囲外は明らかに\(y=x\)ではありません。

学習用のコードは以下です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# This script trains a neural network model by using y=x with noise.
import keras, os
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Activation

TRAIN_EPOCH = 100

def approx_model():
    model = Sequential()
    model.add(Dense(32, input_shape=(1,)))
    model.add(Activation('tanh'))
    model.add(Dense(32))
    model.add(Activation('tanh'))
    model.add(Dense(1))
    print(model.summary())
    return model

if __name__ == '__main__':
    if not os.path.exists("models"):
        os.mkdir("models")

    # Make data for training and validation
    x_train = (np.random.rand(10000,)*20-10).reshape(10000, 1)
    y_train = np.array([x+np.random.normal(0, 1) for x in x_train]).reshape(10000, 1)
    x_val = (np.random.rand(10000,)*20-10).reshape(10000, 1)
    y_val = np.array([x+np.random.normal(0, 1) for x in x_val]).reshape(10000, 1)

    # Make a model
    model = approx_model()

    # Train the model
    opt = keras.optimizers.Adamax(lr=0.002, beta_1=0.9, beta_2=0.999,
                                  epsilon=1e-08, decay=1e-4)
    model.compile(optimizer=opt, loss='mean_squared_error', metrics=['mse'])
    hist = model.fit(x_train, y_train, validation_data=(x_val, y_val),
                     epochs=TRAIN_EPOCH, batch_size=32).history

    # Evaluate the last model by train and validation data
    score_train = model.evaluate(x_train, y_train, batch_size=32)
    score_val = model.evaluate(x_val, y_val, batch_size=32)
    model.save("models/linear.hdf5")

図の表示用のコードは、Jupyter notebook用のコードで、以下の通りです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
%matplotlib inline
import keras
import matplotlib.pyplot as plt
import numpy as np
x = np.array([v/10 for v in range(-300,300)])
model = keras.models.load_model('models/linear.hdf5')
y = model.predict(x)
plt.grid()
plt.scatter(x, y, s=1)
plt.show()

0 件のコメント :