【问题标题】:Machine learning - Linear regression using batch gradient descent机器学习 - 使用批量梯度下降的线性回归
【发布时间】:2015-11-23 07:37:05
【问题描述】:

我正在尝试在具有单个特征和多个训练示例的数据集上实现批量梯度下降 (m)。

当我尝试使用正规方程时,我得到了正确的答案,但下面这段代码在 MATLAB 中执行批量梯度下降时得到了错误的答案。

 function [theta] = gradientDescent(X, y, theta, alpha, iterations)
      m = length(y);
      delta=zeros(2,1);
      for iter =1:1:iterations
          for i=1:1:m
              delta(1,1)= delta(1,1)+( X(i,:)*theta - y(i,1))  ;
              delta(2,1)=delta(2,1)+ (( X(i,:)*theta - y(i,1))*X(i,2)) ;
          end
          theta= theta-( delta*(alpha/m) );
        computeCost(X,y,theta)
      end
end

y 是带有目标值的向量,X 是一个矩阵,第一列全是 1,第二列是值(变量)。

我已经使用矢量化实现了这一点,即

theta = theta - (alpha/m)*delta

... 其中 delta 是初始化为零的 2 元素列向量。

成本函数J(Theta)1/(2m)*(sum from i=1 to m [(h(theta)-y)^2])

【问题讨论】:

  • 考虑将标签batch-file改为batch-processing...
  • @aschipfl - 好建议。但是,这篇文章与批处理或任何与文件或数据相关的批处理无关。在这种情况下,它等同于机器学习中的一种技术,因此我删除了该标签,因为它不合适。可能是OP的错误标签。不过感谢您的评论!
  • 哎呀,我打字太快了,没有仔细阅读Q...感谢您的纠正!

标签: matlab machine-learning gradient linear-regression gradient-descent


【解决方案1】:

错误很简单。你的delta 声明应该在第一个for 循环内。每次累积训练样本和输出之间的加权差异时,都应该从头开始累积。

如果不这样做,您正在做的是累积错误来自上一次迭代,这会考虑到以前学习的theta 版本的错误,这是不正确的。您必须将其放在第一个 for 循环的开头。

此外,您似乎有一个无关的computeCost 电话。我假设这会在给定当前参数的情况下计算每次迭代的成本函数,因此我将创建一个名为 cost 的新输出数组,它会在每次迭代时向您显示这一点。我还要调用这个函数并将它分配给这个数组中的相应元素:

function [theta, costs] = gradientDescent(X, y, theta, alpha, iterations)
    m = length(y);
    costs = zeros(m,1); %// New
%    delta=zeros(2,1); %// Remove
    for iter =1:1:iterations
    delta=zeros(2,1); %// Place here
   for i=1:1:m
       delta(1,1)= delta(1,1)+( X(i,:)*theta - y(i,1))  ;
       delta(2,1)=delta(2,1)+ (( X(i,:)*theta - y(i,1))*X(i,2)) ;
   end
    theta= theta-( delta*(alpha/m) );
   costs(iter) = computeCost(X,y,theta); %// New
end
end

关于正确矢量化的说明

FWIW,我不认为此实现完全矢量化。您可以使用矢量化操作消除第二个for 循环。在我们这样做之前,让我介绍一些理论,以便我们在同一页上。您在这里使用线性回归的梯度下降。我们想要寻找最佳参数theta,它们是我们的线性回归系数,旨在最小化这个成本函数:

m 对应于我们可用的训练样本数,x^{i} 对应于第 ith 个训练样本。 y^{i} 对应于我们与第 ith 个训练样本相关联的真实值。 h 是我们的假设,给出如下:

请注意,在二维线性回归的上下文中,我们要计算的 theta 中只有两个值 - 截距项和斜率。

我们可以最小化成本函数J 以确定最佳回归系数,该系数可以为我们提供最佳预测,从而最小化训练集的误差。具体来说,从一些初始 theta 参数开始......通常是一个零向量,我们从 1 到我们认为合适的次数进行迭代,并且在每次迭代中,我们通过以下关系更新我们的 theta 参数:

对于我们要更新的每个参数,您需要确定成本函数相对于每个变量的梯度,并评估 theta 的当前状态。如果你使用微积分来解决这个问题,我们会得到:

如果您不清楚这种推导是如何发生的,那么我建议您参考这篇很好的数学堆栈交换帖子,其中讨论了它:

https://math.stackexchange.com/questions/70728/partial-derivative-in-gradient-descent-for-two-variables

现在...我们如何将其应用于当前问题?具体来说,您可以很容易地计算出delta 的条目,一口气分析所有样本。我的意思是你可以这样做:

function [theta, costs] = gradientDescent(X, y, theta, alpha, iterations)
    m = length(y);
    costs = zeros(m,1);
    for iter = 1 : iterations
        delta1 = theta(1) - (alpha/m)*(sum((theta(1)*X(:,1) + theta(2)*X(:,2) - y).*X(:,1)));
        delta2 = theta(2) - (alpha/m)*(sum((theta(1)*X(:,1) + theta(2)*X(:,2) - y).*X(:,2)));

        theta = [delta1; delta2];
        costs(iter) = computeCost(X,y,theta);
    end
end

delta(1)delta(2) 上的操作可以在一个语句中完全向量化。你在做什么theta^{T}*X^{i} 来自1, 2, ..., m 的每个样本i。您可以方便地将其放入单个 sum 语句中。

我们可以更进一步,用纯矩阵运算代替它。首先,您可以使用矩阵乘法非常快速地为每个输入样本 X^{i} 计算 theta^{T}*X^{i}。假设:

这里,X 是我们的数据矩阵,它由对应于m 训练样本的m 行和对应于n 特征的n 列组成。同样,theta 是我们从梯度下降中学习到的权重向量,其中 n+1 特征占截距项。

如果我们计算X*theta,我们得到:

正如您在此处看到的,我们已经计算了每个样本的假设并将每个样本放入一个向量中。该向量的每个元素都是第 ith 个训练样本的假设。现在,回忆一下梯度下降中每个参数的梯度项是什么:

我们希望为您学习的向量中的所有参数一次性实现这一切,因此将其放入向量中可以得到:

最后:

因此,我们知道y 已经是长度为m 的向量,因此我们可以非常紧凑地计算每次迭代的梯度下降:

theta = theta - (alpha/m)*X'*(X*theta - y);

....所以你的代码现在只是:

function [theta, costs] = gradientDescent(X, y, theta, alpha, iterations)
    m = length(y);
    costs = zeros(m, 1);
    for iter = 1 : iterations
        theta = theta - (alpha/m)*X'*(X*theta - y);
        costs(iter) = computeCost(X,y,theta);
    end
end

【讨论】:

  • 很好的收获!非常感谢......这让我很长时间了。
  • @SridharThiagarajan - 没问题 :) 请参阅我的编辑,了解如何使这项工作更加矢量化。
  • @IvanRodriguezTorres 在X 的转置中物理写出所有项以及假设和真实值之间的差向量。将此矩阵和向量相乘,您会发现表达式是等价的。
  • @BhoomtawathPlinsut 啊。嗯,这来自直觉。例如,请注意梯度项只是点积。梯度中的每一项都是假设与真实值之间的差向量的点积。此外,对于每个术语,我们可以看到我们将此差异向量与所有示例的每个特征之间的点积作为向量。我们可以通过转置训练示例矩阵X 并使用该差分向量对该矩阵的行执行点积来同时对所有特征执行此操作。它没有写。只是直觉。
  • @rayryeng 赞成。感谢您的澄清。
猜你喜欢
  • 1970-01-01
  • 2016-03-31
  • 1970-01-01
  • 2018-03-26
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 2015-07-15
  • 2013-11-22
相关资源
最近更新 更多