错误非常简单。您的
delta
声明应该在第一个
for
循环内部。每次累积训练样本和输出之间的加权差异时,都应该从头开始累积。
这样做的问题是,您正在累积来自上一次迭代的错误,这将考虑到上一次学习版本的
theta
的错误,这是不正确的。您必须将其放在第一个
for
循环的开头。
此外,您似乎有一个多余的
computeCost
调用。我假设这会计算给定当前参数的每次迭代的成本函数,因此我将创建一个名为
cost
的新输出数组,以显示每次迭代中的成本。我还将调用此函数并将其分配给该数组中相应的元素。
function [theta, costs] = gradientDescent(X, y, theta, alpha, iterations)
m = length(y);
costs = zeros(m,1);
for iter =1:1:iterations
delta=zeros(2,1);
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);
end
end
关于正确向量化的说明
就个人而言,我不认为这个实现是完全向量化的。您可以通过使用向量化操作来消除第二个for
循环。在我们这样做之前,让我介绍一些理论,以便我们能够达成共识。您在这里使用梯度下降法进行线性回归。我们想要寻找最佳参数theta
,这些参数是我们的线性回归系数,旨在最小化此成本函数:
![enter image description here](https://istack.dev59.com/tPhVh.webp)
"
m
代表我们拥有的训练样本数量,x^{i}
对应第i个训练样本,y^{i}
对应第i个训练样本的真实值。h
是我们的假设,它被表示为:
"
![enter image description here](https://istack.dev59.com/f02I7.webp)
请注意,在二维线性回归的背景下,我们只需要计算两个值的θ来进行计算 - 截距项和斜率。
我们可以最小化代价函数J以确定最佳回归系数,从而给出最小化训练集误差的最佳预测。具体而言,从一些初始θ参数开始...通常是一个零向量,我们在迭代次数上迭代从1到我们认为适合的次数,并且在每次迭代时,我们通过以下关系更新我们的θ参数:
![enter image description here](https://istack.dev59.com/7cRbL.webp)
对于我们想要更新的每个参数,您需要确定成本函数相对于每个变量的梯度,并在当前状态下评估该值。如果使用微积分来计算,我们得到:
![enter image description here](https://istack.dev59.com/x5LFr.webp)
如果你不清楚这个推导是怎么得到的,我建议你看一下这篇很好的数学堆栈交换文章:
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)
的操作可以在单个语句中进行完全向量化。对于每个样本i从1, 2, ..., m
,你正在做theta^{T}*X^{i}
。您可以方便地将其放入单个sum
语句中。
我们甚至可以进一步用纯矩阵运算替换它。首先,您可以使用矩阵乘法非常快速地计算每个输入样本X^{i}
的theta^{T}*X^{i}
。假设如果:
![enter image description here](https://istack.dev59.com/XX1Hd.webp)
这里,
X
是我们的数据矩阵,由
m
行组成,对应于
m
个训练样本和
n
列对应于
n
个特征。同样地,
theta
是我们从梯度下降中学习到的权重向量,有
n+1
个特征,包括截距项。
如果我们计算
X*theta
,我们会得到:
![enter image description here](https://istack.dev59.com/Sf4UZ.webp)
您可以看到,我们已经为每个样本计算了假设,并将每个样本的假设放入向量中。该向量的每个元素是第i个训练样本的假设。现在,请回忆一下梯度下降中每个参数的梯度术语:
![enter image description here](https://istack.dev59.com/zg5SC.webp)
我们希望一次性实现您学习向量中所有参数的操作,将其放入向量中得到:
![enter image description here](https://istack.dev59.com/Uddxg.webp)
最终:
![enter image description here](https://istack.dev59.com/DGQgc.webp)
因此,我们知道
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