ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

目的関数の記述

目的関数の種類

多くの Optimization Toolbox™ ソルバーでは、多次元ベクトルのスカラー関数が最小になります。"目的" 関数とは、ソルバーで最小化する関数です。いくつかのソルバーはベクトル値をもつ目的関数を受け入れます。また、一部のソルバーでは、ベクトルや行列で指定した目的関数を使用します。

目的の種類ソルバー目的の記述方法
スカラー

fmincon

fminunc

fminbnd

fminsearch

fseminf

fzero

スカラー目的関数の記述
非線形最小二乗法

lsqcurvefit

lsqnonlin

ベクトルと行列の目的関数の記述
複数の変数をもつ方程式の解

fsolve

多目的

fgoalattain

fminimax

線形計画法

linprog

線形または二次の問題に対する目的関数の記述
混合整数線形計画法

intlinprog

線形最小二乗法

lsqlin

lsqnonneg

二次計画法

quadprog

スカラー目的関数の記述

関数ファイル

スカラー目的関数ファイルは、x などの 1 つの入力を受け入れ、f などの 1 つのスカラー出力を返します。入力 x には、スカラー、ベクトルまたは行列を指定できます。関数ファイルでは、より多くの出力を返すことができます (導関数を含めるを参照してください)。

たとえば、目的が次のような 3 つの変数 x、y、および z の関数だとします。

f(x) = 3*(x – y)4 + 4*(x + z)2 / (1 + x2 + y2 + z2) + cosh(x – 1) + tanh(y + z)

  1. この関数を、ベクトル xin = [x;y;z] を受け入れ、f を返すファイルとして記述します。

    function f = myObjective(xin)
    f = 3*(xin(1)-xin(2))^4 + 4*(xin(1)+xin(3))^2/(1+norm(xin)^2) ...
        + cosh(xin(1)-1) + tanh(xin(2)+xin(3));
  2. これを myObjective.m という名前のファイルとして、MATLAB® パス上のフォルダーに保存します。

  3. 関数が正しく評価されることをチェックします。

    myObjective([1;2;3])
    
    ans =
        9.2666

追加パラメーターを含める方法は 追加パラメーターの受け渡し を参照してください。さらに複雑な関数ファイルの例は、勾配およびヘッセ行列にスパース パターンを使った最小化または範囲制約および範囲付きの前提条件子を使った最小化を参照してください。

ローカル関数と入れ子関数-  関数は、他のファイルの内部に「ローカル関数」または「入れ子関数」として存在できます。ローカル関数や入れ子関数を使用すると、保存するファイルの数を減らせます。また、入れ子関数を使用すると、入れ子関数に示すように追加のパラメーターにアクセスできるようになります。

たとえば、関数ファイルに記述されている目的関数 myObjective.m を、非線形制約に記述されている ellipseparabola.m の制約に基づいて最小化するとします。この場合、2 つのファイル myObjective.mellipseparabola.m を作成する代わりに、両方の関数をローカル関数として含む 1 つのファイルを作成できます。

function [x fval] = callObjConstr(x0,options)
% Using a local function for just one file

if nargin < 2
    options = optimoptions('fmincon','Algorithm','interior-point');
end

[x fval] = fmincon(@myObjective,x0,[],[],[],[],[],[], ...
    @ellipseparabola,options);

function f = myObjective(xin)
f = 3*(xin(1)-xin(2))^4 + 4*(xin(1)+xin(3))^2/(1+sum(xin.^2)) ...
    + cosh(xin(1)-1) + tanh(xin(2)+xin(3));

function [c,ceq] = ellipseparabola(x)
c(1) = (x(1)^2)/9 + (x(2)^2)/4 - 1;
c(2) = x(1)^2 - x(2) - 1;
ceq = [];

[1;1;1] から開始して、制約付きの最小化を解きます。

[x fval] = callObjConstr(ones(3,1))

Local minimum found that satisfies the constraints.

Optimization completed because the objective function is 
non-decreasing in feasible directions, to within the default 
value of the function tolerance, and constraints are satisfied 
to within the default value of the constraint tolerance.

x =
    1.1835
    0.8345
   -1.6439

fval =
    0.5383

無名関数の目的関数

無名関数は、単純な目的関数の記述に使用します。無名関数の詳細は、『MATLAB プログラミングの基礎』ドキュメンテーションの「無名関数とは」を参照してください。Rosenbrock 関数はシンプルな関数であり、無名関数として記述するのに適しています。

anonrosen = @(x)(100*(x(2) - x(1)^2)^2 + (1-x(1))^2);
anonrosen[-1 2] の点で正しく評価されることをチェックします。
anonrosen([-1 2])

ans =
   104
anonrosenfminunc で最小化すると以下の結果になります。
options = optimoptions(@fminunc,'Algorithm','quasi-newton');
[x fval] = fminunc(anonrosen,[-1;2],options)

Local minimum found.

Optimization completed because the size of the gradient
is less than the default value of the function tolerance.

x =
    1.0000
    1.0000

fval =
  1.2262e-10

導関数を含める

fminconfminunc に対しては、目的関数に勾配を含めることができます。また、アルゴリズムによっては、ヘッセ行列を含めることもできます。ヘッセ行列は、Hi,j(x) = ∂2f/∂xi∂xj です。

以下の表に、どのアルゴリズムで勾配とヘッセ行列を使用できるかを示します。

ソルバーアルゴリズム勾配ヘッセ行列
fminconactive-setオプションなし
interior-pointオプションオプションの個別の関数 (ヘッセ行列を参照)
sqpオプションなし
trust-region-reflective必須オプション
fminunctrust-region必須オプション
quasi-newtonオプションなし

導関数を含める利点-  勾配を指定しない場合は、ソルバーで有限差分によって勾配が推定されます。勾配を指定すると、ソルバーでこの有限差分の推定を行う必要がないため、時間を節約でき、より正確になります。また、ソルバーでは近似ヘッセ行列が使用され、真のヘッセ行列とは大きく異なる場合があります。ヘッセ行列を指定すると、少ない反復数で解が得られます。

制約問題の場合は、勾配を与えることで別の利点があります。ソルバーは、x が実行可能な点 x に到達できますが、この x に対し、x の周囲の有限差分は常に実行不可能な点を導きます。また、目的関数は実行不可能な点において、複素数出力、InfNaN、またはエラーを返すとします。この場合、ソルバーは失敗するか途中で停止する可能性があります。勾配を与えることで、ソルバーは続行できます。この利点を得るには、さらに非線形制約関数の勾配を含め、GradConstr オプションを 'on' に設定しなければならない場合があります。非線形制約を参照してください。

内点法 fmincon に対する入力ヘッセ行列の選択-  fmincon interior-point アルゴリズムには、入力ヘッセ行列を選択する場合に多くのオプションがあります。構文の詳細は、ヘッセ行列 を参照してください。次の表にオプションと各オプション間の相対的な特性をまとめます。

ヘッセ行列相対的なメモリ使用量相対的な効率性
'bfgs' (既定の設定)高 (大規模問題の場合)
'lbfgs'低から中
'fin-diff-grads'
'user-supplied''HessMult'低 (コードにより変化の可能性)
'user-supplied''HessFcn'? (コードによる)高 (コードによる)

以下の場合を除き、既定の 'bfgs' ヘッセ行列を使用します。

'lbfgs' に中程度の効率性しかないのは、2 つの理由があります。1 つの原因は、Sherman-Morrison の更新に比較的多くのリソースが使用さるためです。また、その結果として生じる反復ステップは 'lbfgs' のメモリが限られているためにやや不正確になります。

'fin-diff-grads'HessMult に中程度の効率性しかないのは、共役勾配のアプローチを使用するためです。目的関数のヘッセ行列は正確に推定されますが、最も正確な反復ステップが生成されるわけではありません。詳細は、fmincon の内点法アルゴリズムと、式 6-52 を解決する LDL アプローチと共役勾配アプローチについての説明を参照してください。

導関数を含める方法-  

  1. 以下の出力を返すコードを記述します。

    • 最初の出力として目的関数 (スカラー)

    • 2 番目の出力として勾配 (ベクトル)

    • オプションで、3 番目の出力としてヘッセ (行列)

  2. optimoptionsGradObj オプションを 'on' に設定します。

  3. オプションで、Hessian オプションを 'on' または 'user-supplied' に設定します。

    fmincon interior-point ソルバーでは、Hessian オプションを 'user-supplied' に、'HessFcn' オプションを @hessianfcn に設定します。ここで hessianfcn はラグランジュ関数のヘッセ行列を計算する関数です。詳細は、ヘッセ行列を参照してください。たとえば、解析的ヘッセ行列を使用した fmincon の内点法アルゴリズムを参照してください。

  4. オプションで、勾配関数が有限差分近似と一致するかどうかを確認します。勾配またはヤコビ行列の有効性を確認を参照してください。

    ヒント:   最大の柔軟性を得るには、"条件付き" コードを記述します。条件付きとは、以下の例に示すように、関数出力の数が異なることを意味します。条件付きコードでは、GradObj オプションや Hessian オプションの値によってエラーが発生することはありません。条件なしのコードでは、これらのオプションを適切に設定しなければなりません。

たとえば、次の Rosenbrock 関数について考察します。

f(x)=100(x2x12)2+(1x1)2,

この関数は、制約付き非線形問題の解法で詳細が述べられています。f(x) の勾配は、次のようになります。

f(x)=[400(x2x12)x12(1x1)200(x2x12)],

また、ヘッセ行列 H(x) は次のようになります。

H(x)=[1200x12400x2+2400x1400x1200].

rosenthree は条件なしの関数で、勾配とヘッセ行列とともに Rosenbrock 関数を返します。

function [f g H] = rosenthree(x)
% Calculate objective f, gradient g, Hessian H
f = 100*(x(2) - x(1)^2)^2 + (1-x(1))^2;
g = [-400*(x(2)-x(1)^2)*x(1)-2*(1-x(1));
        200*(x(2)-x(1)^2)];
H = [1200*x(1)^2-400*x(2)+2, -400*x(1);
            -400*x(1), 200];

rosenboth は条件付き関数で、ソルバーで必要なものを返します。

function [f g H] = rosenboth(x)
% Calculate objective f
f = 100*(x(2) - x(1)^2)^2 + (1-x(1))^2;

if nargout > 1 % gradient required
    g = [-400*(x(2)-x(1)^2)*x(1)-2*(1-x(1));
        200*(x(2)-x(1)^2)];
    
    if nargout > 2 % Hessian required
        H = [1200*x(1)^2-400*x(2)+2, -400*x(1);
            -400*x(1), 200];  
    end

end

nargout は呼び出し関数が指定する引数の数をチェックします。『MATLAB プログラミングの基礎』ドキュメンテーションの「関数の引数の数の確認」を参照してください。

制約なしの最適化のために設計された fminunc ソルバーは Rosenbrock 関数を最小化します。options を設定して、fminunc が勾配とヘッセ行列を使用するようにします。

options = optimoptions(@fminunc,'Algorithm','trust-region',...
    'GradObj','on','Hessian','on');

fminunc[-1;2] から開始して起動します。

[x fval] = fminunc(@rosenboth,[-1;2],options)
Local minimum found.

Optimization completed because the size of the gradient
is less than the default value of the function tolerance.

x =
    1.0000
    1.0000

fval =
  1.9310e-017

Symbolic Math Toolbox™ のライセンスをおもちの場合は、勾配とヘッセ行列を自動的に計算することができます (Symbolic Math Toolbox による勾配とヘッセ行列の計算を参照)。

ベクトルと行列の目的関数の記述

fsolvelsqcurvefit などいくつかのソルバーは、ベクトルまたは行列の目的関数をもつことができます。これらの種類の目的関数とスカラーの目的関数の使用法で異なる主な点は、微分係数の記述方法です。ベクトル値または行列値関数の 1 次の偏導関数はヤコビ行列と呼ばれます。スカラー関数の 1 次の偏導関数は勾配と呼ばれます。

ベクトル関数のヤコビ行列

x が独立変数のベクトルで F(x) がベクトル関数の場合、ヤコビ行列 J(x) は次のように定義されます。

Jij(x)=Fi(x)xj.

F が m 個の成分をもち、x が k 個の成分をもつ場合、J は m 行 k 列の行列です。

たとえば、

F(x)=[x12+x2x3sin(x1+2x23x3)],

の場合、J(x) は以下になります。

J(x)=[2x1x3x2cos(x1+2x23x3)2cos(x1+2x23x3)3cos(x1+2x23x3)].

この例に関連付けられる関数ファイルは次のようになります。

function [F jacF] = vectorObjective(x)
F = [x(1)^2 + x(2)*x(3);
    sin(x(1) + 2*x(2) - 3*x(3))];
if nargout > 1 % need Jacobian
    jacF = [2*x(1),x(3),x(2);
        cos(x(1)+2*x(2)-3*x(3)),2*cos(x(1)+2*x(2)-3*x(3)), ...
        -3*cos(x(1)+2*x(2)-3*x(3))];
end

行列関数のヤコビ行列

行列 F(x) のヤコビ行列は列ごとに行列をベクトルへ変更することで定義されます。たとえば、行列

F=[F11F12F21F22F31F32]

をベクトル f として書き直します。

f=[F11F21F31F12F22F32].

F のヤコビ行列は f のヤコビ行列です。

Jij=fixj.

F が m 行 n 列の行列であり、x が k 成分ベクトルの場合、ヤコビ行列は mn 行 k 列の行列となります。

たとえば次の場合、

F(x)=[x1x2x13+3x225x2x14x2/x14x22x13x24],

F のヤコビ行列は次のようになります。

J(x)=[x2x14x13502x23x126x2x2/x121/x13x124x23].

行列値の独立変数をもつヤコビ行列

x が行列の場合は、列ごとに x をベクトルに変更して F(x) のヤコビ行列を定義します。たとえば、次の場合

X=[x11x12x21x22],

勾配は以下のベクトルの形式で定義されます。

x=[x11x21x12x22].

F=[F11F12F21F22F31F32],

で、f は上記のように F のベクトルの形式で与えられているとき、F(X) のヤコビ行列は f(x) のヤコビ行列

Jij=fixj.

として定義されます。

したがって、たとえば、次のようになります。

J(3,2)=f(3)x(2)=F31X21, and J(5,4)=f(5)x(4)=F22X22.

F が m 行 n 列の行列であり、x が j 行 k 列の行列の場合、ヤコビ行列は mn 行 jk 列の行列になります。

線形または二次の問題に対する目的関数の記述

次のソルバーは、線形目的関数または二次目的関数を処理します。

  • linprog および intlinprog: 次を最小化します。

    f'x = f(1)*x(1) + f(2)*x(2) +...+ f(n)*x(n).

    目的にベクトル f を入力します。「線形計画法と混合整数線形計画法」の例を参照してください。

  • lsqlin および lsqnonneg: 次を最小化します。

    Cx - d∥.

    目的に行列 C とベクトル d を入力します。範囲制約を課した線形最小二乗法を参照してください。

  • quadprog: 次を最小化します。

    1/2 * x'Hx + f'x
    = 1/2 * (x(1)*H(1,1)*x(1) + 2*x(1)*H(1,2)*x(2) +...
    + x(n)*H(n,n)*x(n)) + f(1)*x(1) + f(2)*x(2) +...+ f(n)*x(n)

    目的にベクトル f と対称行列 H の両方を入力します。「二次計画法」を参照してください。

目的関数の最大化

すべてのソルバーでは、目的関数の最小化が試みられます。最大化問題を扱う場合、問題の形式

maxxf(x),

を g(x) = –f(x) に定義しなおし、g を最小化します。

たとえば、x = 5 の近くの tan(cos(x)) の最大値を見つけるには以下を計算します。

[x fval] = fminunc(@(x)-tan(cos(x)),5)
Local minimum found.

Optimization completed because the size of the gradient is less than
the default value of the function tolerance.

x =
    6.2832

fval =
   -1.5574
最大値は x = 6.2832 のとき 1.5574 (fval の出力の負の値) になります。この回答は 5 桁まで正しい結果です。最大値は tan(1) = 1.5574 で、x = 2π = 6.2832 のときに発生します。

この情報は役に立ちましたか?