机器学习 - 使用批量梯度下降的线性回归
Machine learning - Linear regression using batch 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
y
是具有目标值的向量,X
是一个矩阵,第一列为 1,第二列为值(变量)。
我已经使用矢量化实现了这个,即
theta = theta - (alpha/m)*delta
... 其中 delta 是初始化为零的 2 元素列向量。
代价函数J(Theta)
是1/(2m)*(sum from i=1 to m [(h(theta)-y)^2])
。
错误很简单。您的 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
当前状态下的梯度。如果你用微积分算出来,我们得到:
如果您不清楚这种推导是如何发生的,那么我建议您参考这个很好的数学堆栈交换 post 来讨论它:
现在...我们如何将其应用于当前的问题?具体来说,您可以非常轻松地一次性计算出 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)
上的操作可以在一条语句中完全向量化。您对 1, 2, ..., m
中的每个样本 i
所做的 theta^{T}*X^{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
我正在尝试在具有单个特征和多个训练示例 (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])
。
错误很简单。您的 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
当前状态下的梯度。如果你用微积分算出来,我们得到:
如果您不清楚这种推导是如何发生的,那么我建议您参考这个很好的数学堆栈交换 post 来讨论它:
现在...我们如何将其应用于当前的问题?具体来说,您可以非常轻松地一次性计算出 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)
上的操作可以在一条语句中完全向量化。您对 1, 2, ..., m
中的每个样本 i
所做的 theta^{T}*X^{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