如何绘制 fminsearch 遵循的轨迹?
How to plot the trajectory that fminsearch follows?
我正在尝试使用 fminsearch
优化 rosenbrock 函数,并在 rosenbrock 函数的二维等高线图上绘制给出最小值的点,点大小与每次迭代的迭代次数成正比,但这不是一个好主意。随着点的大小变大,很难看到其他点。相反,我想绘制 fminsearch
的轨迹,以便我可以清楚地看到路径。怎么做到的?
我找不到方法,因为您只能将一个点传递给 outputFcn
。
这是我的情节:
这是一个我希望它看起来像的例子(只是为了阐明我想要什么):
options = optimset('outputFcn', @out, 'Display', 'iter');
x = [3.5 2.5 0.5 0.5];
y = [0 -2 -2 0];
[x,fval,eflag,output] = fminsearch(@rosenbrock_wrapper, [x(4), y(4)], options)
title 'Rosenbrock solution via fminsearch'
%Rosenbrock Function
function val = rosenbrock(x, y)
% a = 1.5, b = -1
val = (1 - x + 1.5) .^ 2 + 100 * (y + 1 - (x - 1.5) .^ 2) .^ 2;
end
%Rosenbrock Wrapper
function val = rosenbrock_wrapper(X)
val = rosenbrock(X(:, 1), X(:, 2));
end
%Output Function
function stop = out(x, optimValue, state)
stop = false;
switch state
case 'init'
fcontour(@rosenbrock, [0 3 -3 3], 'MeshDensity',50, 'LineWidth', 2, 'LevelList', 1:5:300);
hold on;
case 'iter'
plot(x(1), x(2), '.', 'MarkerSize', optimValue.iteration + 1);
end
end
如果您想实时绘制优化问题的进度,可以使用 fminsearch
的 PlotFcn
选项(有关详细信息,请参阅 docs)。
options = optimset('PlotFcn', @myplotfnc, 'Display', 'iter');
x = [3.5 2.5 0.5 0.5];
y = [0 -2 -2 0];
[x,fval,eflag,output] = fminsearch(@rosenbrock_wrapper, [x(4), y(4)], options)
%Rosenbrock Function
function val = rosenbrock(x, y)
% a = 1.5, b = -1
val = (1 - x + 1.5) .^ 2 + 100 * (y + 1 - (x - 1.5) .^ 2) .^ 2;
end
%Rosenbrock Wrapper
function val = rosenbrock_wrapper(X)
val = rosenbrock(X(:, 1), X(:, 2));
end
% plot function
function stop = myplotfnc(x,optimValues,state)
persistent pline; % make handle to line peristent between function calls to add new data points
stop = false;
switch state
case 'init'
fcontour(@rosenbrock, [0 3 -3 3], 'MeshDensity',50, 'LineWidth', 2, 'LevelList', 1:5:300);
hold on;
pline = plot(x(1), x(2), '.-', 'linewidth', 2);
text(x(1), x(2), num2str(optimValues.iteration));
case 'iter'
% append data to line object
pline.XData(end+1) = x(1);
pline.YData(end+1) = x(2);
text(x(1), x(2), num2str(optimValues.iteration));
end
end
或者,您可以让输出函数在所有迭代后将 x,y 数据分配给基础工作区。然后你可以像你习惯的那样绘制它们。
%Output Function
function stop = out(x, optimValue, state)
persistent xy_data
stop = false;
switch state
case 'init'
xy_data(1,:) = [x(1), x(2)];
case 'iter'
xy_data(end+1,:) = [x(1), x(2)];
case 'done'
stop = xy_data; % get output when calling after simulation
end
end
而要获取优化后的数据,只需要做:
xy_data = out([],[],'done');
figure();
plot(xy_data(:,1), xy_data(:,2));
除了@rinkert 的绝妙回答,我还想 post 另一种方法,post 编辑了 对我在 MathWorks 上的问题的回答马特 J.
trajectory=doIt();
fcontour(@rosenbrock, [0 3 -3 3],'LineColor', '#00FFFF', 'MeshDensity',50,...
'LineWidth', 2, 'LevelList', 1:25:300);
hold on
plot(trajectory(1,:),trajectory(2,:),'ks-','MarkerFaceColor','k')
plot(trajectory(1,end),trajectory(2,end),'ro','MarkerSize',20)
hold off
title 'Rosenbrock solution via fminsearch'
function history=doIt
options = optimset('outputFcn', @out, 'Display', 'none');
x = [3.5 2.5 0.5 0.5];
y = [0 -2 -2 0];
history=[];
[x,fval,eflag,output] = fminsearch(@rosenbrock_wrapper, [x(4), y(4)], options);
%Output Function
function stop = out(x, optimValue, state)
stop = false;
switch state
case 'iter'
history=[history,x(:)];
end
end
end
%Rosenbrock Function
function val = rosenbrock(x, y)
% a = 1.5, b = -1
val = (1 - x + 1.5) .^ 2 + 100 * (y + 1 - (x - 1.5) .^ 2) .^ 2;
end
%Rosenbrock Wrapper
function val = rosenbrock_wrapper(X)
val = rosenbrock(X(:, 1), X(:, 2));
end
我正在尝试使用 fminsearch
优化 rosenbrock 函数,并在 rosenbrock 函数的二维等高线图上绘制给出最小值的点,点大小与每次迭代的迭代次数成正比,但这不是一个好主意。随着点的大小变大,很难看到其他点。相反,我想绘制 fminsearch
的轨迹,以便我可以清楚地看到路径。怎么做到的?
我找不到方法,因为您只能将一个点传递给 outputFcn
。
这是我的情节:
这是一个我希望它看起来像的例子(只是为了阐明我想要什么):
options = optimset('outputFcn', @out, 'Display', 'iter');
x = [3.5 2.5 0.5 0.5];
y = [0 -2 -2 0];
[x,fval,eflag,output] = fminsearch(@rosenbrock_wrapper, [x(4), y(4)], options)
title 'Rosenbrock solution via fminsearch'
%Rosenbrock Function
function val = rosenbrock(x, y)
% a = 1.5, b = -1
val = (1 - x + 1.5) .^ 2 + 100 * (y + 1 - (x - 1.5) .^ 2) .^ 2;
end
%Rosenbrock Wrapper
function val = rosenbrock_wrapper(X)
val = rosenbrock(X(:, 1), X(:, 2));
end
%Output Function
function stop = out(x, optimValue, state)
stop = false;
switch state
case 'init'
fcontour(@rosenbrock, [0 3 -3 3], 'MeshDensity',50, 'LineWidth', 2, 'LevelList', 1:5:300);
hold on;
case 'iter'
plot(x(1), x(2), '.', 'MarkerSize', optimValue.iteration + 1);
end
end
如果您想实时绘制优化问题的进度,可以使用 fminsearch
的 PlotFcn
选项(有关详细信息,请参阅 docs)。
options = optimset('PlotFcn', @myplotfnc, 'Display', 'iter');
x = [3.5 2.5 0.5 0.5];
y = [0 -2 -2 0];
[x,fval,eflag,output] = fminsearch(@rosenbrock_wrapper, [x(4), y(4)], options)
%Rosenbrock Function
function val = rosenbrock(x, y)
% a = 1.5, b = -1
val = (1 - x + 1.5) .^ 2 + 100 * (y + 1 - (x - 1.5) .^ 2) .^ 2;
end
%Rosenbrock Wrapper
function val = rosenbrock_wrapper(X)
val = rosenbrock(X(:, 1), X(:, 2));
end
% plot function
function stop = myplotfnc(x,optimValues,state)
persistent pline; % make handle to line peristent between function calls to add new data points
stop = false;
switch state
case 'init'
fcontour(@rosenbrock, [0 3 -3 3], 'MeshDensity',50, 'LineWidth', 2, 'LevelList', 1:5:300);
hold on;
pline = plot(x(1), x(2), '.-', 'linewidth', 2);
text(x(1), x(2), num2str(optimValues.iteration));
case 'iter'
% append data to line object
pline.XData(end+1) = x(1);
pline.YData(end+1) = x(2);
text(x(1), x(2), num2str(optimValues.iteration));
end
end
或者,您可以让输出函数在所有迭代后将 x,y 数据分配给基础工作区。然后你可以像你习惯的那样绘制它们。
%Output Function
function stop = out(x, optimValue, state)
persistent xy_data
stop = false;
switch state
case 'init'
xy_data(1,:) = [x(1), x(2)];
case 'iter'
xy_data(end+1,:) = [x(1), x(2)];
case 'done'
stop = xy_data; % get output when calling after simulation
end
end
而要获取优化后的数据,只需要做:
xy_data = out([],[],'done');
figure();
plot(xy_data(:,1), xy_data(:,2));
除了@rinkert 的绝妙回答,我还想 post 另一种方法,post 编辑了 对我在 MathWorks 上的问题的回答马特 J.
trajectory=doIt();
fcontour(@rosenbrock, [0 3 -3 3],'LineColor', '#00FFFF', 'MeshDensity',50,...
'LineWidth', 2, 'LevelList', 1:25:300);
hold on
plot(trajectory(1,:),trajectory(2,:),'ks-','MarkerFaceColor','k')
plot(trajectory(1,end),trajectory(2,end),'ro','MarkerSize',20)
hold off
title 'Rosenbrock solution via fminsearch'
function history=doIt
options = optimset('outputFcn', @out, 'Display', 'none');
x = [3.5 2.5 0.5 0.5];
y = [0 -2 -2 0];
history=[];
[x,fval,eflag,output] = fminsearch(@rosenbrock_wrapper, [x(4), y(4)], options);
%Output Function
function stop = out(x, optimValue, state)
stop = false;
switch state
case 'iter'
history=[history,x(:)];
end
end
end
%Rosenbrock Function
function val = rosenbrock(x, y)
% a = 1.5, b = -1
val = (1 - x + 1.5) .^ 2 + 100 * (y + 1 - (x - 1.5) .^ 2) .^ 2;
end
%Rosenbrock Wrapper
function val = rosenbrock_wrapper(X)
val = rosenbrock(X(:, 1), X(:, 2));
end