ニューラルネットワークを使って、正弦波のデータ\(y=\sin(fx)\)にノイズをのせた、\(y=\sin(fx)+n\) (\(n\)がノイズ)からサンプルしたデータにフィッティングをして、\(y=\sin(fx)\)を学習できるか試してみました。\(f\)は周波数の大小を表します。
モデルは、
直線フィッティングのときと同じです。
学習データを[-10,10)の範囲で一様乱数で10000サンプルとって、100エポック学習しました。
学習できたモデルの出力は\(f\)の値ごとに下図のようになりました。横軸がx、縦軸がyです。
薄い水色の線は、ノイズを加える前の学習データの生成に使った正弦波です。紺色の線が、学習したニューラルネットワークが生成した曲線です。
\(f=0.5\)
\(f=1\)
\(f=2\)
\(f=4\)
\(f=8\)
\(f=16\)
\(f=0.5\)や\(f=1\)はともかく、それ以降はフィットできていません。特に\(f=4\)以降は完全に崩れています。\(f=16\)では、そもそも周波数が高すぎて、図では元の正弦波がつぶれてしまっています。きちんとフィットさせるためにはニューラルネットワークをもう少し工夫する必要があることが分かりました。
\(f=4\)のときの学習データに使ったデータの生成と同じ条件で、ただし乱数違いで生成したデータをプロットしたものが下図です。横軸の範囲が異なることに注意してください。
\(f=4\) sampled with noise
まだ正弦波を見て取れるのですが、今回使ったニューラルネットワークでは難しいようです。
同様に、\(f=16\)のときの学習データに使ったデータの生成と同じ条件で、ただし乱数違いで生成したデータをプロットしたものが下図です。一応、正弦波の名残は残っていますが、元が正弦波とは言いがたいです。
\(f=16\) sampled with noise
今回の実験のモデルの学習時に使ったコードは以下です。
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
43
44 | # This script trains a neural network model using MNIST.
import keras, os, math
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
def sine_dist(freq):
xd = np.random.rand(10000,)*20-10
yd = [math.sin(x*freq)+np.random.normal(0, 1) for x in xd]
return xd, yd
if __name__ == '__main__':
if not os.path.exists("models"):
os.mkdir("models")
# Make a model
model = approx_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')
model.save_weights("initial-weights.hdf5")
for freq in [0.5, 1, 2, 4, 8, 16]:
# Make data for training and validation
x_train, y_train = sine_dist(freq)
x_val, y_val = sine_dist(freq)
# Train and save a model
model.load_weights("initial-weights.hdf5")
model.fit(x_train, y_train, validation_data=(x_val, y_val),
epochs=TRAIN_EPOCH, batch_size=32)
model.save("models/sine-{0}.hdf5".format(freq))
|
グラフの描画に使ったコードは以下です(\(f=1\)の場合)。
1
2
3
4
5
6
7
8
9
10
11
12 | %matplotlib inline
import keras, math
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(-30, 30, 0.001)
model = keras.models.load_model('models/sine-1.hdf5')
y = model.predict(x)
yc = np.array([math.sin(xi*1) for xi in x])
plt.grid()
plt.plot(x, yc, color='lightblue')
plt.plot(x, y, color='midnightblue')
plt.show()
|
0 件のコメント :
コメントを投稿