我正尝试训练通过Keras实现的神经网络(NN),以实现以下功能。
y(n)= y(n-1)* 0.9 + x(n)* 0.1
因此,我们的想法是将信号作为train_x数据,并通过上述函数获取train_y数据,从而为我们提供(train_x,train_y)训练数据。
import numpy as np
from keras.models import Sequential
from keras.layers.core import Activation, Dense
from keras.callbacks import EarlyStopping
import matplotlib.pyplot as plt
train_x = np.concatenate((np.ones(100)*120,np.ones(150)*150,np.ones(150)*90,np.ones(100)*110), axis=None)
train_y = np.ones(train_x.size)*train_x[0]
alpha = 0.9
for i in range(train_x.size):
train_y[i] = train_y[i-1]*alpha + train_x[i]*(1 - alpha)
train_x data vs train_y data plot
问题y(n)下的函数是一个低通函数,使x(n)值不会突然变化,如图所示。
然后我制作一个NN,并使其适合(train_x,train_y)并绘制
model = Sequential()
model.add(Dense(128, kernel_initializer='normal', input_dim=1, activation='relu'))
model.add(Dense(256, kernel_initializer='normal', activation='relu'))
model.add(Dense(256, kernel_initializer='normal', activation='relu'))
model.add(Dense(256, kernel_initializer='normal', activation='relu'))
model.add(Dense(1, kernel_initializer='normal', activation='linear'))
model.compile(loss='mean_absolute_error',
optimizer='adam',
metrics=['accuracy'])
history = model.fit(train_x, train_y, epochs=200, verbose=0)
print(history.history['loss'][-1])
plt.plot(history.history['loss'])
plt.show()
最终损失值约为2.9,我认为还不错。但是随后的精度图就是这样
因此,当我根据数据对神经网络的预测进行检查时,
plt.plot(model.predict(train_x))
plt.plot(train_x)
plt.show()
这些值仅偏移了一点,仅此而已。我尝试更改激活功能,神经元和层数,但结果仍然相同。我在做什么错了?
----编辑----
使NN接受二维输入,并且可以按预期工作
import numpy as np
from keras.models import Sequential
from keras.layers.core import Activation, Dense
from keras.callbacks import EarlyStopping
import matplotlib.pyplot as plt
train_x = np.concatenate((np.ones(100)*120,np.ones(150)*150,np.ones(150)*90,np.ones(100)*110), axis=None)
train_y = np.ones(train_x.size)*train_x[0]
alpha = 0.9
for i in range(train_x.size):
train_y[i] = train_y[i-1]*alpha + train_x[i]*(1 - alpha)
train = np.empty((500,2))
for i in range(500):
train[i][0]=train_x[i]
train[i][1]=train_y[i]
model = Sequential()
model.add(Dense(128, kernel_initializer='normal', input_dim=2, activation='relu'))
model.add(Dense(256, kernel_initializer='normal', activation='relu'))
model.add(Dense(256, kernel_initializer='normal', activation='relu'))
model.add(Dense(256, kernel_initializer='normal', activation='relu'))
model.add(Dense(1, kernel_initializer='normal', activation='linear'))
model.compile(loss='mean_absolute_error',
optimizer='adam',
metrics=['accuracy'])
history = model.fit(train, train_y, epochs=100, verbose=0)
print(history.history['loss'][-1])
plt.plot(history.history['loss'])
plt.show()
答案 0 :(得分:2)
如果执行您的代码,则会得到以下X-Y值图:
如果我在这里没有错过任何重要的事情,而您确实将其馈入了神经网络,则可能无法期待更好的结果。原因是,神经网络只是一个功能,只能为一个输入计算一个输出向量。在您的情况下,输出向量将仅包含一个元素(您的y值),但是如您在上图中所见,对于x = 90,不仅只有一个输出。因此,您馈入神经网络的内容实际上无法作为函数进行计算,因此网络很可能会尝试计算点〜(90,145)和〜(150,150)之间的直线。我的意思是图中的“上线”。
答案 1 :(得分:1)
您要构建的神经网络是一个简单的多层感知器,具有一个输入节点和一个输出节点。这意味着它本质上是一个接受一个实数并返回一个实数的函数-上下文未传入,因此无法考虑。表达式
model.predict(train_x)
不评估向量train_x
的向量到向量函数,而是评估train_x
中每个数字的数字到数字函数,然后返回结果列表。这就是为什么在train_x_vs_predict_x图中获得平坦段的原因:相同的输入数字每次都会产生相同的输出数字。
鉴于此约束,近似值实际上非常好。例如,对于x值为150的网络,许多y值为150,而较低的y值却很少,但从150以上的值都没有。因此,给定x为150,它预测y值略低于150。
另一方面,您想要的函数引用了先前的函数值,并且在其输入中将需要有关此信息的信息。如果您要构建的函数是接受一个实数序列并返回一个实数序列的函数,则可以使用多对多的递归网络来做到这一点(并且您将需要很多训练数据),但是由于您可以直接计算该函数,因此为什么还要烦恼神经网络呢?没必要用油刀将电锯鞭打出来。