ニューラルネットワークを使って、正弦波のデータ\(y=\sin(fx)\)にノイズをのせた、\(y=\sin(fx)+n\) (\(n\)がノイズ)からサンプルしたデータにフィッティングをして、\(y=\sin(fx)\)を学習できるか試してみました。\(f\)は周波数の大小を表します。
モデルは、
直線フィッティングのときと同じです。
学習データを[-10,10)の範囲で一様乱数で10000サンプルとって、100エポック学習しました。
学習できたモデルの出力は\(f\)の値ごとに下図のようになりました。横軸がx、縦軸がyです。
薄い水色の線は、ノイズを加える前の学習データの生成に使った正弦波です。紺色の線が、学習したニューラルネットワークが生成した曲線です。
\(f=0.5\)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL56wgeXd5FWnqByZiGI8TyktKEShWxuQ98fFmJGlZXHhrqQT29NG8ikn1Jh7qon-7JclPOFm75W43OTzgCUj27hQMPGKG3fm9UDoDVCA-03BGA4m3pI9ShYEk226_JrXw7qNugg/s320/f0.5.png)
\(f=1\)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbsPI5Xwe8CBz1jtgT6caaz5_bSQlzLKParoEV43GqB_lPDAgtdkZje_T6iG412pveqBsUzGCFUtGJ0jwQ-PMgqMdR5iG4wJQnZ5oQzdNs-KRSOghS6Q_3L46lcXAZV2cTRhcSgQ/s320/f1.png)
\(f=2\)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj56ZP52w0kOTihntP4pyBBoz9ZbP3JHjDTR_bKXfAe_cxcwWJNwmHQNacnwsJYa-X0Rc36_OEYR950C5xHWYmGCiOwCJSdU_TeQyeEK9apLlWU-jIKzSxSXb0GQTG6KRpViW66DQ/s320/f2.png)
\(f=4\)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho2sSuXhgV9Z94P84cEOspuEV_2_e-iY6j3-23GHWc2613HmiTqLVpTnt0VaU8Xq0mXPsiVKnfN4bpaGi7ZPJNp4DbCVBb0Mo1lr2Jz80N2Wvr7wQEMRrnpWr2Ib5PcP0_qelTjA/s320/f4.png)
\(f=8\)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfNQkdk79YExEWvl86mlOUa_xIdEML6LQqpjMeo9WBRdr-I9pDJIenTl1JTf8JpsG4MFR5AIx55Wju7-70JpiA9XocGAHiAG3T90O-pd1ymglj-6Q12Y8J1_q5fGgJX6w0P1aE9g/s320/f8.png)
\(f=16\)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd6IRUZDhy2jUgcZ1Xa6kaCcHSCRo-owBoUU9Fcf1LI7thb92vfO2Mt5TNwxYjnVi6qGEVKDeG5jCpXaD8AGhidpB3aQzPXzf-UWrzjchLcr91Chcywt8tuQRHjAVAmEgGxmeU_A/s320/f16.png)
\(f=0.5\)や\(f=1\)はともかく、それ以降はフィットできていません。特に\(f=4\)以降は完全に崩れています。\(f=16\)では、そもそも周波数が高すぎて、図では元の正弦波がつぶれてしまっています。きちんとフィットさせるためにはニューラルネットワークをもう少し工夫する必要があることが分かりました。
\(f=4\)のときの学習データに使ったデータの生成と同じ条件で、ただし乱数違いで生成したデータをプロットしたものが下図です。横軸の範囲が異なることに注意してください。
\(f=4\) sampled with noise
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_6ZTApYi7wn2ONuVVrXwMO5QGNQxu6jZFbATyeqn1RwSghM7H5hvGUbrDLUYTjGygcueIxcqIoRNwSWzrc99AcbdnrYevcZIsO4jXeY4MIP9wdMKH9pTgM19yKcxrHZadHZX_qw/s320/f4-sampled.png)
まだ正弦波を見て取れるのですが、今回使ったニューラルネットワークでは難しいようです。
同様に、\(f=16\)のときの学習データに使ったデータの生成と同じ条件で、ただし乱数違いで生成したデータをプロットしたものが下図です。一応、正弦波の名残は残っていますが、元が正弦波とは言いがたいです。
\(f=16\) sampled with noise
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXR4jQp_d-bvZoRVApIuuAPJnd7d_WJeGHF-r2YmyZorqLCY8f4PK7U8KiE75ny-MSZ3_1Mmmt_R0QFSi0V2s-ThIQnPulBUbtciu0-cjUzBdj8yz3fEDC_hxeuohGbMFbOlKPew/s320/f16-sampled.png)
今回の実験のモデルの学習時に使ったコードは以下です。
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 件のコメント :
コメントを投稿