C++ 我的神经网络学习sinx,但不学习cos

C++ 我的神经网络学习sinx,但不学习cos,c++,neural-network,trigonometry,backpropagation,feed-forward,C++,Neural Network,Trigonometry,Backpropagation,Feed Forward,我已经建立了自己的神经网络,我有一个奇怪的问题 该网络是一个具有反向传播学习的简单前馈1-N-1网络。Sigmoid用作激活函数 我的训练集是由[-PI,PI]及其[0,1]缩放正弦值之间的随机值生成的(这是因为“Sigmoid网络”只生成[0,1]之间的值,而未缩放正弦函数生成[-1,1]之间的值) 有了这个训练集,网络设置为1-10-1,学习率为0.5,一切都很好,网络学习到了它应该学习的sin函数。但是如果我对余弦函数的处理方法完全相同,网络就不会学习它。没有任何设置的隐藏层大小或学习率

我已经建立了自己的神经网络,我有一个奇怪的问题

该网络是一个具有反向传播学习的简单前馈1-N-1网络。Sigmoid用作激活函数

我的训练集是由[-PI,PI]及其[0,1]缩放正弦值之间的随机值生成的(这是因为“Sigmoid网络”只生成[0,1]之间的值,而未缩放正弦函数生成[-1,1]之间的值)

有了这个训练集,网络设置为1-10-1,学习率为0.5,一切都很好,网络学习到了它应该学习的sin函数。但是如果我对余弦函数的处理方法完全相同,网络就不会学习它。没有任何设置的隐藏层大小或学习率

有什么想法吗?我错过什么了吗


编辑:我的问题似乎与小程序类似。它似乎不会学习正弦函数,除非先教一些“更简单”的权重(比如1400个二次函数循环)。小程序中的所有其他设置可以保持最初的状态。因此,在正弦或余弦的情况下,在找到解决方案之前,似乎需要将权重提升到至少部分正确的方向。为什么会这样?

我正努力想知道这是怎么回事

据我所知,你有1个输入,1层中有N个节点,然后是1个输出。因此,网络隐藏层中的任何节点之间都没有区别。假设您有一个输入x和一组权重wi。然后,输出节点y将具有以下值:

y=
i
w\u i x

=x∑i
w_i

所以这总是线性的

为了使节点能够以不同的方式学习,它们必须以不同的方式连接和/或访问不同的输入。因此,您可以提供值的输入、值的平方根(提供一些缩放效果)等,并将不同的隐藏层节点连接到不同的输入,我猜想您至少还需要一个隐藏层

神经网络不是魔法。它为加权和生成一组特定权重。由于您可以导出一组权重来近似正弦或余弦函数,因此必须了解神经网络需要哪些输入才能获得成功

一个明确的例子:指数函数的最大值是:

exp(x) = 1 + x/1! + x^2/2! + x^3/3! + x^4/4! ...
因此,如果您提供了6个输入注释,其中包含1、x1、x2等,那么一个神经网络只接收到一个对应节点的每个输入,并将其乘以其权重,然后将所有这些输出馈送到输出节点,将能够对指数进行6项泰勒展开:

in     hid     out

1 ---- h0 -\
x   -- h1 --\
x^2 -- h2 ---\
x^3 -- h3 ----- y
x^4 -- h4 ---/
x^5 -- h5 --/
不太像神经网络,但你明白了


在Taylor级数的wikipedia页面上,有sin和cos的展开式,分别以x的奇数幂和偶数幂给出(想想看,sin是奇数,cos是偶数,是的,这很简单),所以,如果你提供x的所有幂,我猜,对于交替的零权重,sin和cos版本看起来非常相似。(sin:0,1,0,-1/6…,cos:1,0,-1/2…)

我想你可以先计算正弦,然后从外部计算余弦。我想你关心的是,为什么神经网络可以学习正弦函数,却不能学习余弦函数。假设这个工件不是因为你的代码;我建议如下:

  • 这显然是学习算法中的一个错误。可能是因为你的出发点。尝试从第一次输入正确结果的权重开始,然后向前推进
  • 检查你的学习中是否存在严重偏差-更多+ve而不是-ve
  • 因为余弦可以通过正弦90减去角度来计算,所以您可以找到权重,然后在1步中重新计算余弦的权重

  • 它能学到什么?这可能有助于我们猜测问题所在。我注意到sin(x+0.5*PI)(等于cos x)也不起作用。此外,幂函数(^2、^3等)似乎不起作用。线性函数确实有效。代码中可能存在一些问题,sin[-PI,PI]-函数的成功只是一个奇怪的副作用。发布一些代码可能会帮助我们帮助您。我还不太擅长NN,但我必须不同意。反向传播-学习方法调整网络的所有权重,以便将当前输入的某些“节点路径”调整为比其他路径更接近正确值。对多个样本执行此操作最终将导致一些隐藏节点更容易接受某些输入值,而对其他样本执行其他隐藏节点。假设隐藏层中有足够的节点,那么这些节点的总和+输出处的激活函数可以学习为任何输入的任意值(在act.func的范围内)。