我创建了一个 Octave 脚本,用于使用反向传播训练具有 1 个隐藏层的神经网络,但它似乎不适合 XOR 函数。
x
输入 4x2 矩阵[0 0; 0 1; 1 0; 1 1]
y
输出 4x1 矩阵[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
所有四个输入 no无论我使用多少隐藏单元。
有谁知道我的错误在哪里?
最佳答案
初始化权重时从较大的范围开始,包括负值。您的代码很难在正权重和负权重之间“交叉”,您可能打算放置 * 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 ) );
乘数只是我在类(class)中得到的一些建议,我认为它得到了一篇比较几种不同方法的研究论文的支持。
此外,如果您运行基本的梯度下降,您可能需要很多 迭代来学习 XOR。我建议在宣布学习不起作用之前至少跑 10000 次。 fminunc
函数应该比这做得更好。
我用 2 个隐藏神经元、基本梯度下降和上述初始化运行了你的代码,它正确地学习了 XOR。我还尝试添加动量项,学习速度更快、更可靠,所以我建议您接下来看一下。
关于matlab - 神经网络不适合 XOR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27334215/