【问题标题】:Gradient in continuous regression using a neural network使用神经网络进行连续回归的梯度
【发布时间】:2012-10-26 16:23:20
【问题描述】:

我正在尝试实现具有 3 层(1 个输入层、1 个隐藏层和 1 个输出层,具有连续结果)的回归 NN。作为基础,我从coursera.org 类中提取了一个分类NN,但改变了成本函数和梯度计算以适应回归问题(而不是分类问题):

我的 nnCostFunction 现在是:

function [J grad] = nnCostFunctionLinear(nn_params, ...
                                   input_layer_size, ...
                                   hidden_layer_size, ...
                                   num_labels, ...
                                   X, y, lambda)

Theta1 = reshape(nn_params(1:hidden_layer_size * (input_layer_size + 1)), ...
                 hidden_layer_size, (input_layer_size + 1));

Theta2 = reshape(nn_params((1 + (hidden_layer_size * (input_layer_size + 1))):end), ...
                 num_labels, (hidden_layer_size + 1));

m = size(X, 1);

a1 = X;
a1 = [ones(m, 1) a1];
a2 = a1 * Theta1';
a2 = [ones(m, 1) a2];
a3 = a2 * Theta2';
Y = y;

J = 1/(2*m)*sum(sum((a3 - Y).^2))

th1 = Theta1;
th1(:,1) = 0; %set bias = 0 in reg. formula
th2 = Theta2;
th2(:,1) = 0;

t1 = th1.^2;
t2 = th2.^2;
th = sum(sum(t1)) + sum(sum(t2));
th = lambda * th / (2*m);
J = J + th; %regularization


del_3 = a3 - Y;
t1 = del_3'*a2;
Theta2_grad = 2*(t1)/m + lambda*th2/m;

t1 = del_3 * Theta2;
del_2 = t1 .*  a2;
del_2 = del_2(:,2:end);
t1 = del_2'*a1;
Theta1_grad = 2*(t1)/m + lambda*th1/m;

grad = [Theta1_grad(:) ; Theta2_grad(:)];
end

然后我在 fmincg 算法中使用这个函数,但在第一次迭代中 fmincg 结束它的工作。我认为我的渐变是错误的,但我找不到错误。

有人可以帮忙吗?

【问题讨论】:

  • 嗨 Mikhail,这是 1 年前的问题,但我想知道您是否已经解决了这个问题?实际上另一个人问了同样的问题,我在那里提供了我的代码,与 Andrew Ng 的 checkNNGradients(lambda) 相比,得到了 1e-4 的相对差异:stackoverflow.com/questions/20648422/… 如果你已经解决了这个问题并且得到的相对差异更小,请更新通过回答您自己的问题;否则希望我的代码有帮助。谢谢
  • 那是什么语言??它是 not octave/matlab(这是 Ng 教授所教的......)
  • @javadba,它是八度的

标签: machine-learning neural-network gradient regression


【解决方案1】:

根据线性系统神经网络的第 5 周讲义指南,您应该对初始代码进行以下更改:

  1. 删除 num_lables 或将其设为 1(在 reshape() 中也是如此)
  2. 无需将y转换为逻辑矩阵
  3. 对于 a2 - 将 sigmoid() 函数替换为 tanh()
  4. d2 计算中 - 将 sigmoidGradient(z2) 替换为 (1-tanh(z2).^2)
  5. 从输出层移除 sigmoid (a3 = z3)
  6. 将未正则化部分中的成本函数替换为线性一:J = (1/(2*m))*sum((a3-y).^2)
  7. 创建predictLinear():以predict()函数为基础,第一层假设用tanh()替换sigmoid,第二层去掉第二个sigmoid假设,去掉带有ma​​x()函数的行,使用隐藏层假设的输出作为预测结果
  8. 在讲义中的测试用例上验证您的 nnCostFunctionLinear()

【讨论】:

    【解决方案2】:

    尝试包含 sigmoid 函数来计算第二层(隐藏层)值,并避免在计算目标(输出)值时使用 sigmoid。

    function [J grad] = nnCostFunction1(nnParams, ...
                                       inputLayerSize, ...
                                       hiddenLayerSize, ...
                                       numLabels, ...
                                       X, y, lambda)
    
    Theta1 = reshape(nnParams(1:hiddenLayerSize * (inputLayerSize + 1)), ...
                     hiddenLayerSize, (inputLayerSize + 1));
    
    Theta2 = reshape(nnParams((1 + (hiddenLayerSize * (inputLayerSize + 1))):end), ...
                     numLabels, (hiddenLayerSize + 1));
    
    Theta1Grad = zeros(size(Theta1));
    Theta2Grad = zeros(size(Theta2));
    
    m = size(X,1);
    
    a1 = [ones(m, 1) X]';
    z2 = Theta1 * a1;
    a2 = sigmoid(z2);
    a2 = [ones(1, m); a2];
    z3 = Theta2 * a2;
    a3 = z3;
    
    Y = y';
    
    r1 = lambda / (2 * m) * sum(sum(Theta1(:, 2:end) .* Theta1(:, 2:end)));
    r2 = lambda / (2 * m) * sum(sum(Theta2(:, 2:end) .* Theta2(:, 2:end)));
    
    J = 1 / ( 2 * m ) * (a3 - Y) * (a3 - Y)' + r1 + r2;
    
    delta3 = a3 - Y;
    delta2 = (Theta2' * delta3) .* sigmoidGradient([ones(1, m); z2]);
    delta2 = delta2(2:end, :);
    
    Theta2Grad = 1 / m * (delta3 * a2');
    Theta2Grad(:, 2:end) = Theta2Grad(:, 2:end) + lambda / m * Theta2(:, 2:end);
    Theta1Grad = 1 / m * (delta2 * a1');
    Theta1Grad(:, 2:end) = Theta1Grad(:, 2:end) + lambda / m * Theta1(:, 2:end);
    
    grad = [Theta1Grad(:) ; Theta2Grad(:)];
    
    end
    

    在将输入传递到 nnCostFunction 之前对其进行标准化。

    【讨论】:

      【解决方案3】:

      Mikhaill,我也一直在使用 NN 进行连续回归,并且在某些时候遇到过类似的问题。最好的办法是在运行模型之前针对数值计算测试梯度计算。如果这不正确,fmincg 将无法训练模型。 (顺便说一句,我不鼓励你使用数值梯度,因为所涉及的时间要长得多)。

      考虑到您从 Ng 的 Coursera 课程中获得了这个想法,我将为您实施一个可能的解决方案,以尝试对 Octave 使用相同的符号。

          % Cost function without regularization.
          J = 1/2/m^2*sum((a3-Y).^2); 
      
          % In case it´s needed, regularization term is added (i.e. for Training).
          if (reg==true);
       J=J+lambda/2/m*(sum(sum(Theta1(:,2:end).^2))+sum(sum(Theta2(:,2:end).^2)));
          endif;
      
          % Derivatives are computed for layer 2 and 3.
          d3=(a3.-Y);
          d2=d3*Theta2(:,2:end);
      
          % Theta grad is computed without regularization.
          Theta1_grad=(d2'*a1)./m;
          Theta2_grad=(d3'*a2)./m;
      
          % Regularization is added to grad computation.
          Theta1_grad(:,2:end)=Theta1_grad(:,2:end)+(lambda/m).*Theta1(:,2:end);
          Theta2_grad(:,2:end)=Theta2_grad(:,2:end)+(lambda/m).*Theta2(:,2:end);
      
          % Unroll gradients.
          grad = [Theta1_grad(:) ; Theta2_grad(:)];
      

      请注意,由于您已取出所有 sigmoid 激活,因此导数计算非常简单,并且会简化原始代码。

      接下来的步骤: 1. 检查此代码以了解它是否对您的问题有意义。 2.使用梯度检查来测试梯度计算。 3. 最后,使用 fmincg 并检查你得到不同的结果。

      【讨论】:

        【解决方案4】:

        如果我理解正确,您的第一段代码(如下所示)-

        m = size(X, 1);
        
        a1 = X;
        a1 = [ones(m, 1) a1];
        a2 = a1 * Theta1';
        a2 = [ones(m, 1) a2];
        a3 = a2 * Theta2';
        Y = y;
        

        是在输出层得到输出a(3)

        Ng 关于 NN 的幻灯片具有以下配置来计算 a(3)。它与您的代码呈现的不同。

        • 在中间/输出层,您没有执行激活函数g,例如sigmoid 函数。

        就没有正则化项的成本函数J而言,Ng的幻灯片有以下公式:

        我不明白你为什么可以使用:

        J = 1/(2*m)*sum(sum((a3 - Y).^2))
        

        因为您根本不包括 log 函数。

        【讨论】:

        • log() 和 sigmoid() - 逻辑回归 NN 的方法。在 coursera 示例中,它是癌症检测,但我想要房屋成本预测
        猜你喜欢
        • 2017-09-16
        • 2013-05-28
        • 2018-10-15
        • 2016-06-15
        • 2017-04-18
        • 1970-01-01
        • 1970-01-01
        • 2019-01-27
        • 1970-01-01
        相关资源
        最近更新 更多