为了学习Keras LSTM和RNN,我想创造一个简单的问题:给定一个正弦波,我们能预测它的频率吗?
鉴于时间概念在这里很重要,我不希望简单的神经网络能够预测频率。然而,即使使用LSTM,我也无法了解频率;我能够学习一个微不足道的零作为估计的频率(即使是火车样本)。
这是创建火车组的代码。
import numpy as np
import matplotlib.pyplot as plt
def create_sine(frequency):
return np.sin(frequency*np.linspace(0, 2*np.pi, 2000))
train_x = np.array([create_sine(x) for x in range(1, 300)])
train_y = list(range(1, 300))
现在,这个例子是一个简单的神经网络。
from keras.models import Model
from keras.layers import Dense, Input, LSTM
input_series = Input(shape=(2000,),name='Input')
dense_1 = Dense(100)(input_series)
pred = Dense(1, activation='relu')(dense_1)
model = Model(input_series, pred)
model.compile('adam','mean_absolute_error')
model.fit(train_x[:100], train_y[:100], epochs=100)
正如所料,这个NN没有学到任何有用的东西。接下来,我尝试了一个简单的LSTM示例。
input_series = Input(shape=(2000,1),name='Input')
lstm = LSTM(100)(input_series)
pred = Dense(1, activation='relu')(lstm)
model = Model(input_series, pred)
model.compile('adam','mean_absolute_error')
model.fit(train_x[:100].reshape(100, 2000, 1), train_y[:100], epochs=100)
但是,这个基于LSTM的模型也没有学到任何有用的东西。
答案 0 :(得分:4)
您认为训练RNN是一个简单的问题,但实际上您的设置对于网络来说并不容易:
如前所述,缺少重要样本。你扔了太多的数据(300 * 2000点),但实际的目标(频率)只能由网络看到一次。即使网络确实学到了东西,它也很有可能会过度适应。
数据不一致。请记住,RNN擅长捕获系列数据中的类似模式。例如,在NLP中,语料库中的所有句子都由相同的语言规则控制,并且更多句子帮助RNN更好地理解这些规则,即,更多数据有帮助。
在您的情况下,具有不同频率的系列非常相似:将正弦与frequency=1
和frequency=100
进行比较。数据的这种多样性使得学习变得更加困难,而不是更容易。这并不意味着RNN无法学习这个频率,这只是意味着你不应该对像你这样的普通RNN有困难感到惊讶。
数据比例。将频率从1更改为300,会将x
和y
的比例更改两个数量级,这对任何神经网络都可能存在问题。
由于您的目标相当有教育意义,我只是将目标频率限制为10来解决第二和第三项问题,因此缩放和分布多样性不是问题(欢迎您在这里尝试不同的值:你应该看到将这一个参数增加到比如50会使任务变得更加复杂。)
第一项是通过给RNN 10个每个频率的例子而不是一个频率来解决的。我还添加了一个隐藏层以增加网络灵活性,另外还添加了一个简单的规范化器(Dropout
层)。
完整的代码:
import numpy as np
from keras.models import Model
from keras.layers import Input, Dense, Dropout, LSTM
max_freq = 10
time_steps = 100
def create_sine(frequency, offset):
return np.sin(frequency * np.linspace(offset, 2 * np.pi + offset, time_steps))
train_y = list(range(1, max_freq)) * 10
train_x = np.array([create_sine(freq, np.random.uniform(0,1)) for freq in train_y])
train_y = np.array(train_y)
input_series = Input(shape=(time_steps, 1), name='Input')
lstm = LSTM(units=100)(input_series)
hidden = Dense(units=100, activation='relu')(lstm)
dropout = Dropout(rate=0.1)(hidden)
output = Dense(units=1, activation='relu')(dropout)
model = Model(input_series, output)
model.compile('adam', 'mean_squared_error')
model.fit(train_x.reshape(-1, time_steps, 1), train_y, epochs=200)
# Trying the network on the same data
test_x = train_x.reshape(-1, time_steps, 1)
test_y = train_y
predicted = model.predict(test_x).reshape([-1])
print()
print((predicted - train_y)[:12])
print(np.mean(np.abs(predicted - train_y)))
输出:
<强> max_freq = 10 强>
[-0.05612183 -0.01982236 -0.03744316 -0.02568841 -0.11959982 -0.0770483
0.04643679 0.12057972 -0.00625324 -0.00724655 -0.16919005 -0.04512954]
0.0503574344847
max_freq = 20 (其他一切都相同)
[ 0.51365542 0.09269333 -0.009691 0.0619092 0.09852839 0.04378462
0.01430321 -0.01953268 0.00722599 0.02558327 -0.04520988 -0.0614748 ]
0.146024380232
max_freq = 30 (其他一切都相同)
[-0.28205156 -0.28922796 -0.00569081 -0.21314907 0.1068716 0.23497915
0.23975039 0.25955486 0.26333141 0.24235058 0.08320332 -0.03686047]
0.406703719805
请注意,结果是随机的,实际上增加max_freq
会增加 divergence 的变化。但即使它收敛,尽管拥有更多数据,但性能并没有提高,反而变得更糟,速度更快。
答案 1 :(得分:1)
示例数据项非常低,每个频率一个,
添加小噪音并使用更多数据,
将输出数据标准化-1到1范围 然后再试一次
答案 2 :(得分:1)
正如你所说,你想预测频率。您还想使用LSTM。首先,我们生成足够的数据进行训练,然后我们构建网络。对不起我的例子不在keras
,我使用tflearn
。
import numpy as np
import tflearn
from random import shuffle
# parameters
n_input=100
n_train=2000
n_test = 500
# generate data
xs=[]
ys=[]
frequencies = np.linspace(1,50,n_train+n_test)
shuffle(frequencies)
t=np.linspace(0,2*np.pi,n_input)
for freq in frequencies:
xs.append(np.sin(t*freq))
ys.append(freq)
xs_train=np.array(xs[:n_train]).reshape(n_train,n_input,1)
xs_test=np.array(xs[n_train:]).reshape(n_test,n_input,1)
ys_train = np.array(ys[:n_train]).reshape(-1,1)
ys_test = np.array(ys[n_train:]).reshape(-1,1)
# LSTM network prediction
net = tflearn.input_data(shape=[None, n_input, 1])
net = tflearn.lstm(net, 10)
net = tflearn.fully_connected(net, 100, activation="relu")
net = tflearn.fully_connected(net, 1)
net = tflearn.regression(net, optimizer='adam', loss='mean_square')
model = tflearn.DNN(net)
model.fit(xs_train, ys_train, n_epoch=100)
print(np.hstack((model.predict(xs_test),ys_test))[:10])
# [[ 13.08494568 12.76470588]
# [ 22.23135376 21.98039216]
# [ 39.0812912 37.58823529]
# [ 15.77548409 15.66666667]
# [ 26.57996941 25.58823529]
# [ 26.57759476 25.11764706]
# [ 16.42217445 15.8627451 ]
# [ 32.55020905 30.80392157]
# [ 44.16622925 43.01960784]
# [ 26.18071365 25.45098039]]
如果您拥有该订单中的数据,您实际上并不需要LSTM,您可以使用深度神经网络轻松替换LSTM部件:
# Deep network instead of LSTM
net = tflearn.input_data(shape=[None, n_input])
net = tflearn.fully_connected(net, 100)
net = tflearn.fully_connected(net, 100)
net = tflearn.fully_connected(net, 1)
net = tflearn.regression(net, optimizer='adam',loss='mean_square')
model = tflearn.DNN(net)
model.fit(xs_train, ys_train)
print(np.hstack((model.predict(xs_test),ys_test))[:10])
两个代码都将为您提供频率的预测值。我还用程序创建了gist。