メインコンテンツ

制約付き非線形最小二乗の lsqnonlin と fmincon の比較

R2026b

この例では、制約付き最小二乗問題を解く際、一般的に lsqnonlin は fmincon よりも関数評価の回数が少ないことを示します。どちらのソルバーも、fmincon "interior-point" アルゴリズムを使用して問題を解きます。しかし、通常は lsqnonlin の方が少ない関数評価で問題を解きます。これは、lsqnonlin の方が処理する情報が多いためです。fmincon は ∑iFi2 として指定された二乗和を最小化します。ここで、F はベクトル関数です。これに対し、lsqnonlin はベクトル F 全体を処理するため、和のすべての成分にアクセスできます。言い換えれば、fmincon は和の値にのみアクセスできますが、lsqnonlin は各成分に個別にアクセスできます。

この例の最後にリストされている補助関数 runlsqfmincon は、1 から 50 までの N について、非線形制約のあるスケーリングされた Rosenbrock タイプの一連の問題を作成します。ここで、問題の変数の数は 2N です。Rosenbrock 関数の詳細については、制約付き非線形問題の解法、問題ベースを参照してください。また、この関数は結果をプロットして以下を表示します。

  • 反復回数

  • 関数カウント

  • 結果として得られる残差

このプロットは、有限差分導関数の推定値 (ラベル付き FD) と、自動微分を使用して計算された導関数の差を示します。自動微分の詳細については、自動微分の背景を参照してください。

runlsqfmincon;

Plot of iterations versus problem size N, showing fmincon requires about three times more iterations than lsqnonlin, with both increasing approximately linearly

Log-scaled plot of function count versus problem size N, showing finite-difference variants require significantly more function evaluations than automatic differentiation variants

Plot of residual versus problem size N, showing all four solver variants produce identical residuals that stabilize near 0.4

このプロットは以下の結果を示します。これらは一般的なものです。

  • 各 N について、fmincon の反復回数は lsqnonlin の 2 倍より多く、N に対してほぼ線形に増加します。

  • 反復回数は導関数の推定方法に依存しません。

  • 有限差分 (FD) 推定の関数カウントは、自動微分よりもはるかに多くなります。

  • 導関数の推定方法が同じである場合、lsqnonlin の関数カウントは fmincon よりも少なくなります。

  • 残差はすべての解法で一致します。これは、結果がソルバーや導関数の推定方法に依存しないことを意味します。

この結果は、反復回数と関数カウントの両方において lsqnonlin が fmincon よりも効率的であることを示しています。ただし、問題が異なれば結果も異なり、問題によっては fmincon が lsqnonlin よりも効率的なこともあります。

補助関数

次のコードは、runlsqfmincon 補助関数を作成します。

function [lsq,lsqfd,fmin,fminfd] = runlsqfmincon()
optslsq = optimoptions("lsqnonlin",Display="none",...
    MaxFunctionEvaluations=1e5,MaxIterations=1e4); % Allow for many iterations and Fevals
optsfmincon = optimoptions("fmincon",Display="none",...
    MaxFunctionEvaluations=1e5,MaxIterations=1e4);
% Create structures to hold results
z = zeros(1,50);
lsq = struct("Iterations",z,"Fcount",z,"Residual",z);
lsqfd = lsq;
fmin = lsq;
fminfd = lsq;
rng(1) % Reproducible initial points
x00 = -1/2 + randn(50,1);
y00 = 1/2 + randn(50,1);
for N = 1:50
    x = optimvar("x",N,LowerBound=-3,UpperBound=3);
    y = optimvar("y",N,LowerBound=0,UpperBound=9);
    prob = optimproblem("Objective",sum((10*(y - x.^2)).^2 + (1 - x).^2));
    x0.x = x00(1:N);
    x0.y = y00(1:N);
    % Include a set of nonlinear inequality constraints
    cons = optimconstr(N);
    for i = 1:N
        cons(i) = x(i)^2 + y(i)^2 <= 1/2 + 1/8*i;
    end
    prob.Constraints = cons;
    [sol,fval,exitflag,output] = solve(prob,x0,Options=optslsq);
    lsq.Iterations(N) = output.iterations;
    lsq.Fcount(N) = output.funcCount;
    lsq.Residual(N) = fval;

    [sol,fval,exitflag,output] = solve(prob,x0,Options=optslsq,...
        ObjectiveDerivative="finite-differences",ConstraintDerivative="finite-differences");
    lsqfd.Iterations(N) = output.iterations;
    lsqfd.Fcount(N) = output.funcCount;
    lsqfd.Residual(N) = fval;

    [sol,fval,exitflag,output] = solve(prob,x0,Options=optsfmincon,Solver="fmincon");
    fmin.Iterations(N) = output.iterations;
    fmin.Fcount(N) = output.funcCount;
    fmin.Residual(N) = fval;

    [sol,fval,exitflag,output] = solve(prob,x0,Options=optsfmincon,Solver="fmincon",...
        ObjectiveDerivative="finite-differences",ConstraintDerivative="finite-differences");
    fminfd.Iterations(N) = output.iterations;
    fminfd.Fcount(N) = output.funcCount;
    fminfd.Residual(N) = fval;
end

N = 1:50;    
plot(N,lsq.Iterations,"k",N,lsqfd.Iterations,"b--",N,fmin.Iterations,"g",N,fminfd.Iterations,"r--")
legend("lsqnonlin","lsqnonlin FD","fmincon","fmincon FD",Location="northwest")
xlabel("N")
ylabel("Iterations")
title("Iterations")

figure
semilogy(N,lsq.Fcount,"k",N,lsqfd.Fcount,"b--",N,fmin.Fcount,"g",N,fminfd.Fcount,"r--")
legend("lsqnonlin","lsqnonlin FD","fmincon","fmincon FD",Location="northwest")
xlabel("N")
ylabel("log(Function count)")
title("Function count, log-scaled")

figure
plot(N,lsq.Residual,"k",N,lsqfd.Residual,"b--",N,fmin.Residual,"g",N,fminfd.Residual,"r--")
legend("lsqnonlin","lsqnonlin FD","fmincon","fmincon FD",Location="southeast")
xlabel("N")
ylabel("Residual")
ylim([0,0.4])
title("Residual")

end

参考

| |

トピック