机器学习 - 使用批量梯度下降的线性回归

Sri*_*jan 9 matlab gradient machine-learning linear-regression gradient-descent

我试图在具有单个特征和多个训练样例(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
Run Code Online (Sandbox Code Playgroud)

y是具有目标值的向量,X是一个矩阵,第一列中包含一列和第二列值(变量).

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

theta = theta - (alpha/m)*delta
Run Code Online (Sandbox Code Playgroud)

... delta是一个初始化为零的2元素列向量.

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

ray*_*ica 26

错误很简单.你的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
Run Code Online (Sandbox Code Playgroud)

关于适当矢量化的说明

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

在此输入图像描述

m对应于我们可用的训练样本的数量,并且x^{i}对应于第i 训练示例. y^{i}对应于我们与第i 训练样本相关的基础事实值. h是我们的假设,它给出如下:

在此输入图像描述

请注意,在2D中的线性回归的上下文中,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
Run Code Online (Sandbox Code Playgroud)

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

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

在此输入图像描述

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

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

在此输入图像描述

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

在此输入图像描述

我们想要一步一步地为学习的向量中的所有参数实现这一点,因此将它放入向量中会给我们:

在此输入图像描述

最后:

在此输入图像描述

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

theta = theta - (alpha/m)*X'*(X*theta - y);
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)