【发布时间】:2015-11-20 19:30:13
【问题描述】:
所以我编写了以下 MATLAB 代码作为 梯度下降 的练习。我显然选择了一个最小值为 (0,0) 的函数,但算法将我抛出到 (-3,3)。
我确实发现在xGrad 和yGrad 之间在线切换:[xGrad,yGrad] = gradient(f); 可以实现正确的收敛,尽管xGrad、yGrad 与预期的差不多2*X、2*Y .我想我在这里颠倒了一些东西,但我一直在试图弄清楚它是什么,但我不明白,所以我希望有人能注意到我的错误......
dx=.01;
dy=.01;
x=-3:dx:3;
y=-3:dy:3;
[X,Y]=meshgrid(x,y);
f=X.^2+Y.^2;
lr = .1; %learning rate
eps = 1e-10; %epsilon threshold
tooMuch = 1e5; %limit iterations
p = [.1 1]; %starting point
[~, idx] = min( abs(x-p(1)) ); %index of closest value
[~, idy] = min( abs(y-p(2)) ); %index of closest value
p = [x(idx) y(idy)]; %closest point to start
[xGrad,yGrad] = gradient(f); %partial derivatives of f
xGrad = xGrad/dx; %scale correction
yGrad = yGrad/dy; %scale correction
for i=1:tooMuch %prevents too many iterations
fGrad = [ xGrad(idx,idy) , yGrad(idx,idy) ]; %gradient's definition
pTMP = p(end,:) - lr*fGrad; %gradient descent's core
[~, idx] = min( abs(x-pTMP(1)) ); %index of closest value
[~, idy] = min( abs(y-pTMP(2)) ); %index of closest value
p = [p;x(idx) y(idy)]; %add the new point
if sqrt( sum( (p(end,:)-p(end-1,:)).^2 ) ) < eps %check conversion
break
end
end
感谢所有帮助的人
编辑:纠正错别字并使代码更清晰。它仍然做同样的事情并且有同样的问题
【问题讨论】:
-
切向评论:在这样的网格上预先计算梯度是不寻常的。我认为你不应该在网格上工作。它将大大简化代码,并且更正确并提供更好的结果。
-
我最终将它显示为箭头图(使用
quiver),但如果你能告诉我一种更准确地计算梯度的方法,我会很高兴(也许通过链接到它的一些文档) -
我认为这主要是出于学习目的。对于这样的问题,没有必要将所有内容都网格化。您可以在没有索引、网格等的情况下跟踪 x_val 和 y_val……并通过自己获取偏导数来计算梯度:
fGrad = [2*x_val, 2*y_val]。对于许多功能,您实际上可以使用自动微分自动计算梯度(有一些包)。 -
我需要它运行更多的功能,例如我稍后检查
-20*(X/2-X.^2-Y.^5)*exp(-X.^2-Y.^2)的收敛性。所以在我看来,一般功能会更好 -
如果你有符号数学工具箱,那么我建议使用
funstr='-20*(X/2-X^2-Y^5)*exp(-X^2-Y^2)'; syms X Y; mygrad=matlabFunction([diff(funstr,X) diff(funstr,Y)]);之类的东西来计算符号函数的梯度。请注意公式中缺少句点。