在Octave/Matlab中实现神经网络

我正在尝试构建一个由三层组成的简单神经网络,以解决二元分类问题。前两层各有八个神经元(加上偏置单元)。我使用的是fminunc。这是我的成本函数:

1    function [jVal, gradient] = cost2(thetaVec, X, y)2      Theta1 = reshape(thetaVec(1:72),8, 9); % my weights used for 3      Theta2 = reshape(thetaVec(73:81),1, 9); %forward propagation4      Delta1 = 0; %Delta is divided in Delta1 and Delta2 for simplicity but 5      Delta2 = 0; %they're combined to eventually calculate the gradient6      jVal   = 0; %the value of the costfunction7      m = length(y);8      for i = 1:m9        a1 = X(i, :); %X size: 3x9, a1 size: 1x910        z2 = Theta1 * a1';11        a2 = 1 ./(1 + exp(-z2)); %a2 size: 8x112        a2 = [ones(columns(a2), 1) a2']; % bias unit added to a2: a2 size: 1x913        z3 = Theta2 * a2';14        a3 = 1 ./(1 + exp(-z3)); %a3 = h(x(i)) size: 1x115        jVal   += (-1/m) * (y(i) * log(a3) + (1 - y(i)) * log(1 - a3));16        delta3 = a3 - y(i); %delta3 size: 1x117        delta2 = Theta2' * delta3 .* a2 .* (1 - a2); %delta2 size: 9x918        Delta2 += delta3 * a2'; %I use Delta1 and Delta2 as accumulators19        Delta1 += delta2 * a1'; %size Delta2: 9x1, size Delta1: 9x120      endfor21      jVal = jVal/m; %avarage of jVal22      Delta = [Delta1;Delta2]; %Deltas are combined. Size Delta: 18x123      gradient = (1/m) * Delta;% size gradient: 18x124    endfunction

我的主程序如下:

    %the values of the vector from which I derive my weights are chosen randomly    INIT_EPSILON = 0.1; %between thi interval    Theta1 = rand(8, 9) * (2*INIT_EPSILON) - INIT_EPSILON;    Theta2 = rand(1, 9) * (2*INIT_EPSILON) - INIT_EPSILON;    thetaVec = [ Theta1(:); Theta2(:)];    options = optimset('GradObj', 'on', 'MaxIter', 10000);    [optTheta, functionVal, exitFlag] = fminunc(@(t) cost2(t, X, y), thetaVec, options)

梯度应该是一个9×9的矩阵,但实际上它是一个18×1的矩阵,所以我无法使用fminunc。实际上,我尝试了多次修改成本函数中的反向传播部分以获得9×9的梯度(特别是修改了delta2)。然而,这从未奏效,输出结果是:

optTheta = %a vector of various valuesfunctionVal =  0.71681 %or a similar valueexitFlag =  1

所以,即使exitflag为1,它也没有收敛。我哪里做错了?


回答:

你当前的代码如下:

delta3  = a3 - y(i);                            % (1×1)delta2  = Theta2' * delta3 .* a2 .* (1 - a2);   % (9×1).*(1×9) = (9×9)Delta2 += delta3 * a2';                         % (9×9)* (9×1) = (9×1)Delta1 += delta2 * a1';                         % (9×9)* (n×1) = (9×1)

我认为应该改成这样:

delta3  = a3 - y(i);                           % (1×1)delta2  = Theta2 * delta3 .* a2 .* (1 - a2);   % (1×9).*(1×9) = (1×9)Delta2 += delta3 * a2';                        % (9×9)* (9×1) = (9×1)Delta1 += delta2.' * a1;                       % (9×1)* (1×9) = (9×9)

然后在每一步中丢弃Delta1中偏置的梯度,最终得到一个(8×9)的矩阵作为你的Delta1组件。(你可能需要先转置Delta1,我没有仔细跟踪你的转置操作)。

最后,在末尾的垂直拼接步骤的整个目的是将你的矩阵“压缩”回单列长向量形式,以便它们遵循与输入“thetaVec”相同的“规格”,因此你需要将你的(8×9)和(1×9)的Delta1和Delta2对象“压缩”,即:

[Delta1(:) ; Delta2(:)]

更新

继续在上面的评论中讨论。

考虑Delta1和Delta2是什么。这是对应于Theta1和Theta2中元素的总误差(在所有观测值上)。换句话说,Delta1应该与Theta1大小相同,Delta2应该与Theta2大小相同。现在你已经在代码中包含了矩阵大小,你可以立即看到这不是这种情况。

此外,由于每次迭代都会添加到这些矩阵中,每次迭代的结果应该是正确大小的Delta1和Delta2,以便你可以添加每次迭代贡献的误差,以获得所有迭代的总误差(每个参数)。

另外,考虑delta2和delta3是什么。这些也是误差,但它们不是指参数中的误差,而是指节点中的误差。换句话说,它们显示了每一层中每个节点对最终误差的贡献/责任。因此,它们的大小需要是一个与相应层中节点数量相同的向量。你已经可以看到delta2的大小为9×9是没有意义的!

所以算法的逻辑是这样的。获取节点对误差的贡献,并将其反向传播到前面的节点和它们之间的参数。

例如,将每个delta3(在这种情况下只有一个节点)与第二层中的每个节点相乘,以找出错误是如何在Theta2的每个参数元素上分布的。

同样,为了获得delta2,我们考虑了delta3中的误差,并通过参数乘法向后分配到第二层中的每个节点。然后在此基础上,我们乘以梯度(因为这定义了该误差将向前传播的程度/速率)。

现在我们已经处理了第三层及其与第二层的交互,我们继续处理第二层及其与第一层的交互。因此,同样,将每个delta2(第二层有9个节点,因此delta2应该有9个元素)与第一层中的每个节点相乘。这给出了一个9×9的矩阵,反映了第一层中的每个节点通过参数Theta1如何导致第二层中每个节点的错误。然而,因为我们不关心对第二层“偏置”节点的贡献,我们从Delta1中删除这部分,这使我们得到一个8×9的矩阵,与Theta1的大小完全相同。

理论上你也可以反向传播delta2以找到delta1,但由于我们不需要它,我们跳过了这一步。毕竟,我们真正关心的是参数中的误差,而不是节点中的误差。(即我们只关心每一步中节点的误差,因为我们需要它们来从前一层获取参数中的误差)。

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

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