神经网络玩具模型适合正弦函数失败,有什么不对?

时间:2017-10-28 22:43:36

标签: python machine-learning neural-network deep-learning keras

研究生,Keras的新手和神经网络试图将一个非常简单的前馈神经网络拟合到一维正弦

以下是我能得到的最佳配合的三个例子。在图上,您可以看到网络输出与基本事实

Neural network output vs Ground truth (run 3)

Neural network output vs Ground truth (run 1)
Neural network output vs Ground truth (run 2)

完整的代码,只需几行,在此处发布example Keras

我正在玩层数,不同的激活函数,不同的初始化,不同的损失函数,批量大小,训练样本数量。似乎没有一个能够改善上述例子之外的结果。

我将不胜感激任何意见和建议。对于神经网络来说,正弦函数是否很难?我怀疑答案不是,所以我一定做错了......

5年前有一个类似的问题here,但OP没有提供代码,仍然不清楚出了什么问题或者他是如何解决这个问题的。

2 个答案:

答案 0 :(得分:4)

为了使您的代码有效,您需要:

  • 缩放[-1,+ 1]范围内的输入值(神经网络不像大值)
  • 也会缩放输出值,因为tanh激活不能很好地接近+/- 1
  • 除最后一层外,使用relu激活而不是tanh(更快地收敛方式

通过这些修改,我能够使用10个和25个神经元的两个隐藏层来运行您的代码

答案 1 :(得分:4)

由于已经有一个答案提供了一种解决方法,我将专注于您的方法的问题。

输入数据比例

正如其他人所说,您的输入数据值范围从0到1000非常大。通过将输入数据缩放到零均值和单位方差(X = (X - X.mean())/X.std())可以轻松解决此问题,从而提高培训效果。对于tanh,这种改进可以通过饱和来解释:tanh映射到[-1; 1],因此对于几乎所有足够大的(> 3){{1}将返回-1或1 ,即它饱和。在饱和度中,x的梯度将接近于零,并且不会学习任何东西。当然,您也可以使用tanh来代替价值> 0,但是你会遇到类似的问题,因为现在渐变仅仅依赖于ReLU,因此后来的输入总是比早期的输入具有更高的影响(等等)。

虽然重新缩放或规范化可能是一种解决方案,但另一种解决方案是将输入视为分类输入并将离散值映射到单热编码向量,而不是

x

你会有

>>> X = np.arange(T)
>>> X.shape
(1000,)

当然,如果您想学习连续输入,这可能并不理想。

建模

您目前正在尝试建模从线性函数到非线性函数的映射:您将>>> X = np.eye(len(X)) >>> X.shape (1000, 1000) 映射到f(x) = x。虽然我知道这是一个玩具问题,但这种建模方式仅限于这一条曲线,因为g(x) = sin(x)f(x)没有任何关系。一旦您尝试对不同的曲线进行建模,同时说明g(x)sin(x),使用相同的网络,您的cos(x)就会出现问题,因为它们具有完全相同的值曲线。建模此问题的更好方法是预测曲线的下一个值,即代替

X

你想要

X = range(T)
Y = sin(x)

因此对于时间步骤2,您将获得时间步长1的X = sin(X)[:-1] Y = sin(X)[1:] 值作为输入,并且您的损失期望时间步长2的y值。这样您隐式地建模时间。