【问题标题】:Unable to train neural network properly无法正确训练神经网络
【发布时间】:2019-11-16 16:36:06
【问题描述】:

我正在尝试训练通过 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()

loss_plot_200_epoch

而最终的loss值大约是2.9,我觉得还不错。但是后来准确度图是这样的

accuracy_plot_200_epochs

所以当我检查神经网络对训练数据的预测时

plt.plot(model.predict(train_x))
plt.plot(train_x)
plt.show()

train_x_vs_predict_x

这些值刚刚偏移了一点,仅此而已。我尝试更改激活函数、神经元数量和层数,但结果仍然相同。我做错了什么?

---- 编辑----

使 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()

【问题讨论】:

    标签: python keras neural-network


    【解决方案1】:

    您正在构建的神经网络是一个简单的多层感知器,具有一个输入节点和一个输出节点。这意味着它本质上是一个接受一个实数并返回一个实数的函数——上下文没有传入,因此不能被考虑。表达式

    model.predict(train_x)
    

    不计算向量train_x 的向量到向量函数,但计算train_x 中每个数字的数字到数字函数,然后返回结果列表。这就是为什么您在 train_x_vs_predict_x 图中得到平坦段的原因:相同的输入数字每次都会产生相同的输出数字。

    鉴于此约束,近似值实际上相当不错。例如,网络已经看到 x 值为 150,许多 y 值为 150 和一些较低的值,但从未超过 150。因此,给定 x 为 150,它预测 y 值略低于 150。

    另一方面,您想要的函数是指先前的函数值,并且需要在其输入中提供有关此的信息。如果您要构建的是一个接受实数序列并返回实数序列的函数,那么您可以使用多对多循环网络来做到这一点(并且您将需要一个 很多比一个示例序列更多的训练数据),但是既然你可以直接计算函数,为什么还要麻烦神经网络呢?没有必要像黄油刀那样用电锯抽出。

    【讨论】:

    • 是的,现在我知道我哪里出错了。拥有一个输入维度为 2 且一个输入为 y(n-1) 而另一个为 x(n) 的 NN 使得模型几乎可以准确地沿着原始 train_y 曲线进行预测。
    【解决方案2】:

    如果我执行你的代码,我会得到下面的 X-Y 值图:

    如果我在这里没有遗漏一些重要的东西,而你真的把它输入你的神经网络,你可能无法期待更好的结果。原因是,神经网络只是一个函数,它只能为一个输入计算一个输出向量。在您的情况下,输出向量将仅包含一个元素(您的 y 值),但正如您在上图中看到的那样,对于 x=90,不只有一个输出。因此,您输入神经网络的内容并不能真正计算为函数,因此网络很可能会尝试计算点 ~(90, 145) 和 ~(150, 150) 之间的直线。我的意思是,图中的“上线”。

    【讨论】:

      猜你喜欢
      • 2018-11-26
      • 1970-01-01
      • 2019-07-17
      • 1970-01-01
      • 2011-04-07
      • 1970-01-01
      • 2015-06-11
      • 2017-06-19
      相关资源
      最近更新 更多