优化求解器输出函数
什么是输出函数?
输出函数是优化函数在算法的每次迭代过程中调用的函数。通常,使用输出函数生成图输出,记录算法生成的数据的历史信息,或者根据当前迭代的数据暂停算法。可以按函数文件、局部函数或嵌套函数的形式创建输出函数。
outputfcn
选项可以与下列 matlab® 优化函数配合使用:
创建和使用输出函数
下面给出了输出函数的一个简单示例,该输出函数绘制优化函数生成的点。
function stop = outfun(x, optimvalues, state) stop = false; hold on; plot(x(1),x(2),'.'); drawnow
在解算以下优化问题时,可以使用此输出函数绘制 fminsearch
生成的点
为此,
创建一个包含前述代码的文件,并将其作为
outfun.m
保存在 matlab 路径的文件夹中。将
options
结构体的outputfcn
字段的值设置为outfun
的函数句柄。options = optimset('outputfcn', @outfun);
输入以下命令:
hold on objfun=@(x) exp(x(1))*(4*x(1)^2 2*x(2)^2 x(1)*x(2) 2*x(2)); [x fval] = fminsearch(objfun, [-1 1], options) hold off
这些命令返回解
x = 0.1290 -0.5323 fval = -0.5689
并显示以下关于
fminsearch
生成的点的绘图:
输出函数的结构体
输出函数的函数定义行采用以下格式:
stop = outfun(x, optimvalues, state)
其中
stop
是一个标志,根据优化例程是停止还是继续,该标志为true
或false
。请参阅 。x
是算法在当前迭代中计算的点。optimvalues
是包含当前迭代中的数据的结构体。详细介绍了此结构体。state
是算法的当前状态。列出了可能的值。
优化函数在每次迭代中将输入参数的值传递给 outfun
。
嵌套输出函数的示例
中的示例不需要输出函数在每次迭代后保留数据。如果不需要保存各次迭代之间的数据,可以将输出函数编写为函数文件,并从命令行直接调用优化函数。但是,要使输出函数在每次迭代后记录数据,请编写一个用于实现以下目的的文件:
以嵌套函数的形式包括输出函数 - 有关详细信息,请参阅 matlab 编程基础中的。
调用优化函数。
在以下示例中,函数文件还包含目标函数作为局部函数。您也可以将目标函数编写为单独的文件或匿名函数。
嵌套函数可以访问其所在的文件中的变量。因此,此方法使输出函数能够在每次迭代后保留变量。
以下示例使用输出函数记录以下求解中的 fminsearch
迭代:
输出函数以矩阵(称为 history
)的形式返回点序列。
要运行此示例,请执行下列步骤:
使用 matlab 编辑器打开一个新文件。
将以下代码复制并粘贴到此文件。
function [x fval history] = myproblem(x0) history = []; options = optimset('outputfcn', @myoutput); [x fval] = fminsearch(@objfun, x0,options); function stop = myoutput(x,optimvalues,state); stop = false; if isequal(state,'iter') history = [history; x]; end end function z = objfun(x) z = exp(x(1))*(4*x(1)^2 2*x(2)^2 x(1)*x(2) 2*x(2)); end end
将文件作为
myproblem.m
保存到 matlab 路径上的某个文件夹中。在 matlab 提示符下,输入
[x fval history] = myproblem([-1 1]);
函数 fminsearch
返回最佳点 x
及 x 处的目标函数值 fval
。
x,fval
x = 0.1290 -0.5323 fval = -0.5689
此外,输出函数 myoutput
向 matlab 工作区返回矩阵 history
,该矩阵包含算法在每次迭代中生成的点。history
的前四行为
history(1:4,:)
ans = -1.0000 1.0000 -1.0000 1.0000 -1.0750 0.9000 -1.0125 0.8500
history
最后一行的点与最佳点 x
相同。
history(end,:)
ans = 0.1290 -0.5323
objfun(history(end,:))
ans = -0.5689
optimvalues 中的字段
下表列出了由优化函数 、 和 提供的 optimvalues
结构体的字段。
表的“命令行显示标题”列中列出了将 options
的 display
参数设置为 'iter'
时显示的标题。
optimvalues 字段 (optimvalues.field) | 描述 | 命令行显示标题 |
---|---|---|
| 函数计算的累积数目 |
|
| 当前点的函数值 |
|
| 迭代编号 - 从 |
|
| 步骤信息 |
|
算法的状态
下表列出了 state
的可能值:
状态 | 描述 |
---|---|
| 算法在第一次迭代前处于初始状态。 |
| 算法正在执行迭代。在此状态下,输出函数可停止优化的当前迭代。您可能为了提高计算效率而让输出函数停止迭代。state 设置为 |
| 算法位于迭代末尾。 |
| 算法在最后一次迭代后处于最终状态。 |
下面的代码演示输出函数如何使用 state
的值来确定要在当前迭代中执行的任务。
switch state case 'init' % setup for plots or dialog boxes case 'iter' % make updates to plots or dialog boxes as needed case 'interrupt' % check conditions to see whether optimization % should quit case 'done' % cleanup of plots, dialog boxes, or final plot end
stop 标签
输出参数 stop
是 true
或 false
的标签。此标志通知优化函数优化是停止 (true
) 还是继续 (false
)。下面的示例演示了使用 stop
标签的典型方法。
根据 optimvalues 中的数据停止优化
输出函数可以根据 optimvalues
中的当前数据在任何迭代中停止优化。例如,下面的代码在目标函数值小于 5
时将 stop
设置为 true
:
function stop = myoutput(x, optimvalues, state) stop = false; % check if objective function is less than 5. if optimvalues.fval < 5 stop = true; end
基于对话框输入停止优化
在设计 ui 来执行优化时,可以采用控件(例如停止按钮)使输出函数停止优化。以下代码显示如何执行此回调。代码假定停止按钮回调将值 true
存储在名为 hobject
的 handles
结构体的 optimstop
字段中,而该结构体又存储在 appdata
中。
function stop = myoutput(x, optimvalues, state) stop = false; % check if user has requested to stop the optimization. stop = getappdata(hobject,'optimstop');