4

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

  • x输入4×2矩阵[0 0; 0 1; 1 0; 1 1]
  • y输出4X1矩阵[0; 1; 1; 0]
  • theta隐藏/输出层的权重
  • z加权和施加到加权和
  • m采样计数
  • a激活功能(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; 

反向传播

被初始化0
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

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

+0

请显示weight初始化('theta'的开始值)。猜测,这可能是你的问题。如果是的话,我会解释。 – 2014-12-06 18:43:02

+0

'epsilon_init = 0.12;' 'theta1 = rand(hiddenCount,inputCount + 1)* 2 * epsilon_init * epsilon_init;' 'theta2 = rand(outputCount,hiddenCount + 1)* 2 * epsilon_init * epsilon_init;'Do not知道如何在评论中正确地格式化它! – Torax 2014-12-06 19:31:13

+0

我的预感是错误的,但至少现在我可以看到我是否复制了结果 – 2014-12-06 19:44:35

回答

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)); 

乘数只是一些建议,我拿起一门课程,我认为这是一个研究论文相比已备份几种不同的方法。

此外,如果您运行基本梯度下降,您可能需要批次以了解XOR。我建议在宣布学习不起作用之前至少运行10000次。 fminunc函数应该比这更好。

我跑代码2层隐藏的神经元,基本梯度下降和上述initialisations,并正确获悉XOR。我也试着增加动量术语,学习速度更快,更可靠,所以我建议你接下来看看。

+0

哇,我没有意识到它会需要_that_许多迭代。感谢您的建议,我会接下来看看动力学条款! – Torax 2014-12-06 21:13:23

+0

我没有意识到这一点,我非常感谢你。 – 2015-08-23 13:43:43

1

您至少需要隐藏层中的3个神经元,并根据第一个答案的建议更正初始值。 如果sigmoidGradient(z2)表示a2。*(1-a2),那么所有其余的代码对我来说似乎都可以。

最好的reggards,

+0

异或将与2个隐藏的神经元一起工作。 – 2014-12-19 21:12:43