Main Content

优化求解器输出函数

什么是输出函数?

输出函数是优化函数在算法的每次迭代过程中调用的函数。通常,使用输出函数生成图输出,记录算法生成的数据的历史信息,或者根据当前迭代的数据暂停算法。可以按函数文件、局部函数或嵌套函数的形式创建输出函数。

OutputFcn 选项可以与下列 MATLAB® 优化函数配合使用:

创建和使用输出函数

下面给出了输出函数的一个简单示例,该输出函数绘制优化函数生成的点。

function stop = outfun(x, optimValues, state)
stop = false;
hold on;
plot(x(1),x(2),'.');
drawnow

在解算以下优化问题时,可以使用此输出函数绘制 fminsearch 生成的点

minxf(x)=minxex1(4x12+2x22+x1x2+2x2).

为此,

  1. 创建一个包含前述代码的文件,并将其作为 outfun.m 保存在 MATLAB 路径的文件夹中。

  2. options 结构体的 Outputfcn 字段的值设置为 outfun 的函数句柄。

    options = optimset('OutputFcn', @outfun);
  3. 输入以下命令:

    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 生成的点的绘图:

    Plot of x(1) vs. x(2).

输出函数的结构体

输出函数的函数定义行采用以下格式:

stop = outfun(x, optimValues, state)

其中

  • stop 是一个标志,根据优化例程是停止还是继续,该标志为 truefalse。请参阅 Stop 标签

  • x 是算法在当前迭代中计算的点。

  • optimValues 是包含当前迭代中的数据的结构体。optimValues 中的字段详细介绍了此结构体。

  • state 是算法的当前状态。算法的状态列出了可能的值。

优化函数在每次迭代中将输入参数的值传递给 outfun

嵌套输出函数的示例

创建和使用输出函数中的示例不需要输出函数在每次迭代后保留数据。如果不需要保存各次迭代之间的数据,可以将输出函数编写为函数文件,并从命令行直接调用优化函数。但是,要使输出函数在每次迭代后记录数据,请编写一个用于实现以下目的的文件:

  • 以嵌套函数的形式包括输出函数 - 有关详细信息,请参阅 MATLAB 编程基础中的嵌套函数

  • 调用优化函数。

在以下示例中,函数文件还包含目标函数作为局部函数。您也可以将目标函数编写为单独的文件或匿名函数。

嵌套函数可以访问其所在的文件中的变量。因此,此方法使输出函数能够在每次迭代后保留变量。

以下示例使用输出函数记录以下求解中的 fminsearch 迭代:

minxf(x)=minxex1(4x12+2x22+x1x2+2x2).

输出函数以矩阵(称为 history)的形式返回点序列。

要运行此示例,请执行下列步骤:

  1. 使用 MATLAB 编辑器打开一个新文件。

  2. 将以下代码复制并粘贴到此文件。

    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
  3. 将文件作为 myproblem.m 保存到 MATLAB 路径上的某个文件夹中。

  4. 在 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 中的字段

下表列出了由优化函数 fminbndfminsearchfzero 提供的 optimValues 结构体的字段。

表的“命令行显示标题”列中列出了将 optionsDisplay 参数设置为 'iter' 时显示的标题。

optimValues 字段 (optimValues.field)

描述

命令行显示标题

funccount

函数计算的累积数目

Func-count

fval

当前点的函数值

min f(x)

iteration

迭代序号 - 从 0 开始

Iteration

procedure

步骤信息

Procedure

算法的状态

下表列出了 state 的可能值:

状态

描述

'init'

算法在第一次迭代前处于初始状态。

'interrupt'

算法正在执行迭代。在此状态下,输出函数可停止优化的当前迭代。您可能为了提高计算效率而让输出函数停止迭代。state 设置为 'interrupt' 后,xoptimValues 的值与最后一次调用输出函数时的值相同,在最后一次调用中,state 设置为 'iter'

'iter'

算法位于迭代末尾。

'done'

算法在最后一次迭代后处于最终状态。

下面的代码演示输出函数如何使用 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 标签

输出参数 stoptruefalse 的标签。此标志通知优化函数优化是停止 (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 存储在名为 hObjecthandles 结构体的 optimstop 字段中,而该结构体又存储在 appdata 中。

function stop = myoutput(x, optimValues, state)
stop = false;
% Check if user has requested to stop the optimization.
stop = getappdata(hObject,'optimstop');

相关主题