神经网络:估计正弦波频率

问题描述 投票:7回答:3

为了学习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的模型也没有学到任何有用的东西。

python tensorflow neural-network keras lstm
3个回答
4
投票

为什么不学习?

您认为训练RNN是一个简单的问题,但实际上您的设置对于网络来说并不容易:

  • 如前所述,缺乏重要的样本。你扔了太多的数据(300 * 2000点),但实际的目标(频率)只能由网络看到一次。即使网络确实学到了东西,它也很有可能会过度适应。
  • 数据不一致。请记住,RNN擅长捕获系列数据中的类似模式。例如,在NLP中,语料库中的所有句子都由相同的语言规则控制,并且更多句子帮助RNN更好地理解这些规则,即,更多数据有帮助。 在你的情况下,具有不同频率的系列不是很相似:将正弦与frequency=1frequency=100进行比较。数据的这种多样性使得学习变得更加困难,而不是更容易。这并不意味着RNN无法学习频率,这只意味着你不应该对像你这样的普通RNN有困难感到惊讶。
  • 数据规模。将频率从1改为300,将xy的比例改变两个数量级,这可能对任何神经网络都有问题。

由于你的目标是相当有教育意义,我只是通过将目标频率限制为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会增加分歧的变化。但即使它收敛,尽管拥有更多数据,但性能并没有提高,反而变得更糟,速度更快。


1
投票

样本数据项非常低,每个频率一个,

添加小噪音并使用更多数据,

将输出数据标准化为-1到1范围,然后再试一次


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

© www.soinside.com 2019 - 2024. All rights reserved.