神经网络无法拟合异或函数

我创建了一个Octave脚本,用于训练具有一个隐藏层的使用反向传播的神经网络,但它似乎无法拟合异或函数。

  • x 输入 4×2 矩阵 [0 0; 0 1; 1 0; 1 1]
  • y 输出 4×1 矩阵 [0; 1; 1; 0]
  • theta 隐藏层/输出层权重
  • z 加权和
  • a 对加权和应用的激活函数
  • m 样本数量(这里是4

我的权重初始化如下

epsilon_init = 0.12;theta1 = rand(hiddenCount, inputCount + 1) * 2 * epsilon_init * epsilon_init;theta2 = rand(outputCount, hiddenCount + 1) * 2 * epsilon_init * epsilon_init;

前馈

a1 = x;a1_with_bias = [ones(m, 1) a1];z2 = a1_with_bias * theta1';a2 = sigmoid(z2);a2_with_bias = [ones(size(a2, 1), 1) a2];z3 = a2_with_bias * theta2';a3 = sigmoid(z3);

然后我计算逻辑成本函数

j = -sum((y .* log(a3) + (1 - y) .* log(1 - a3))(:)) / m;

反向传播

delta2 = (a3 - y);gradient2 = delta2' * a2_with_bias / m;delta1 = (delta2 * theta2(:, 2:end)) .* sigmoidGradient(z2);gradient1 = delta1' * a1_with_bias / m;

通过梯度检查验证了梯度是正确的。

然后我使用这些梯度通过梯度下降法找到theta的最优值,尽管使用Octave的fminunc函数得到相同的结果。成本函数收敛到ln(2)(或对于平方误差成本函数是0.5),因为无论我使用多少隐藏单元,网络对所有四个输入的输出都是0.5

有谁知道我的错误在哪里吗?


回答:

在初始化权重时,从更大的范围开始,包括负值。对于你的代码来说,很难在正权重和负权重之间“跨越”,而且你可能原本打算写* 2 * epsilon_init - epsilon_init;,但却写成了* 2 * epsilon_init * epsilon_init;。修正这个错误可能会解决你的问题。

作为经验法则,我会这样做:

theta1 = ( 0.5 * sqrt ( 6 / ( inputCount + hiddenCount) ) *     randn( hiddenCount, inputCount + 1 ) );theta2 = ( 0.5 * sqrt ( 6 / ( hiddenCount + outputCount ) ) *     randn( outputCount, hiddenCount + 1 ) );

这个乘数只是我在课程中学到的一些建议,我认为它有研究论文的支持,比较了几种不同的方法。

此外,如果你运行基本的梯度下降法来学习异或函数,你可能需要进行大量的迭代。我建议在宣布学习无效之前至少运行10000次。fminunc函数应该能做得更好。

我使用2个隐藏神经元、基本的梯度下降法和上述初始化运行了你的代码,它正确地学习了异或函数。我还尝试添加了动量项,学习速度更快且更可靠,所以我建议你接下来看看这个。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注