Main Content

lsqcurvefit または lsqnonlin の用のコード生成

この例では、非線形最小二乗用の C コードを生成する方法を示します。

最小二乗用のデータとモデル

この例では、ベクトル xdata が 100 個のデータ点を示し、ベクトル ydata が対応する測定値を示します。xdataydata のモデル化された関係は以下になります。

ydatai=a1+a2exp(a3xdatai)+εi.

問題のデータを生成します。

rng(5489,'twister') % For reproducibility
xdata = -2*log(rand(100,1));
ydata = (ones(100,1) + .1*randn(100,1)) + (3*ones(100,1)+...
    0.5*randn(100,1)).*exp((-(2*ones(100,1)+...
    0.5*randn(100,1))).*xdata);

このコードは、平均 2 の指数分布から 100 個の独立したサンプルによって xdata を生成します。コードは、a = [1;3;2] を使用して定義方程式から ydata を生成します。これには、標準偏差 [0.1;0.5;0.5] をもつ正規偏差を追加して摂動が与えられています。

lsqcurvefit 用のコード生成の解決

ソルバー アプローチ

ゴールは、データに最も合うモデルのパラメーター a^i、i = 1, 2, 3 を見つけることです。

lsqcurvefit を使用してパラメーターをデータに当てはめるには、近似関数を定義する必要があります。lsqcurvefit では、近似関数がパラメーター ベクトル a とデータ xdata を取得して応答の予測を返します。この予測は、ノイズのない完全なモデルを使用した ydata と一致する必要があります。無名関数として近似関数 predicted を定義します。

predicted = @(a,xdata) a(1)*ones(100,1)+a(2)*exp(-a(3)*xdata);

モデルをデータに当てはめるためにlsqcurvefit はパラメーターの初期推定 a0 を必要とします。

a0 = [2;2;2];

lsqcurvefit を呼び出して、最適適合パラメーター a^i を求めます。

[ahat,resnorm,residual,exitflag,output,lambda,jacobian] =...
   lsqcurvefit(predicted,a0,xdata,ydata);

コード生成アプローチ

コード生成を使用して同じ問題を解くには、次の手順を実行します。

  1. 以前のステップ (データの生成、近似関数の作成、初期点の作成、および lsqcurvefit の呼び出し) をすべて組み込んだ関数を記述します。

    function [x,res] = solvelsqcurve
    rng(5489,'twister') % For reproducibility
    xdata = -2*log(rand(100,1));
    ydata = (ones(100,1) + .1*randn(100,1)) + (3*ones(100,1)+...
        0.5*randn(100,1)).*exp((-(2*ones(100,1)+...
        0.5*randn(100,1))).*xdata);
    predicted = @(a,xdata) a(1)*ones(100,1)+a(2)*exp(-a(3)*xdata);
    options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt','Display','off');
    a0 = [2;2;2];
    lb = [];
    ub = [];
    [x,res] = lsqcurvefit(predicted,a0,xdata,ydata,lb,ub,options);
    end
  2. コード生成用の構成を作成します。この場合は、'mex' を使用します。

    cfg = coder.config('mex');
  3. 関数 solvelsqcurve 用のコードを生成します。

    codegen -config cfg solvelsqcurve
  4. solvelsqcurve_mex.mexw64 のような名前の生成されたファイルを実行して、生成されたコードをテストします。

    [x,res] = solvelsqcurve_mex
    x =
    
        1.0169
        3.1444
        2.1596
    
    
    res =
    
        7.4101

lsqnonlin 用のコード生成の解決

ソルバー アプローチ

ゴールは、データに最も合うモデルのパラメーター a^i、i = 1, 2, 3 を見つけることです。

lsqnonlin を使用してパラメーターをデータに当てはめるには、近似関数を定義する必要があります。lsqnonlin では、近似関数がパラメーター ベクトル a、データ xdata、およびデータ ydata を取得します。近似関数は、応答の予測とデータ ydata の差を返します。この差は、ノイズのない完全なモデルでは 0 になるはずです。無名関数として近似関数 predicted を定義します。

predicted = @(a)(a(1)*ones(100,1)+a(2)*exp(-a(3)*xdata) - ydata)

モデルをデータに当てはめるためにlsqnonlin はパラメーターの初期推定 a0 を必要とします。

a0 = [2;2;2];

lsqnonlin を呼び出して、最適適合パラメーター a^i を求めます。

[ahat,resnorm,residual,exitflag,output,lambda,jacobian] =...
   lsqnonlin(predicted,a0);

コード生成アプローチ

コード生成を使用して同じ問題を解くには、次の手順を実行します。

  1. 以前のステップ (データの生成、近似関数の作成、初期点の作成、および lsqnonlin の呼び出し) をすべて組み込んだ関数を記述します。

    function [x,res] = solvelsqnon
    rng(5489,'twister') % For reproducibility
    xdata = -2*log(rand(100,1));
    ydata = (ones(100,1) + .1*randn(100,1)) + (3*ones(100,1)+...
        0.5*randn(100,1)).*exp((-(2*ones(100,1)+...
        0.5*randn(100,1))).*xdata);
    predicted = @(a) (a(1)*ones(100,1)+a(2)*exp(-a(3)*xdata) - ydata);
    options = optimoptions('lsqnonlin','Algorithm','levenberg-marquardt','Display','off');
    a0 = [2;2;2];
    lb = [];
    ub = [];
    [x,res] = lsqnonlin(predicted,a0,lb,ub,options);
    end
  2. コード生成用の構成を作成します。この場合は、'mex' を使用します。

    cfg = coder.config('mex');
  3. 関数 solvelsqnon 用のコードを生成します。

    codegen -config cfg solvelsqnon
  4. solvelsqnon_mex.mexw64 のような名前の生成されたファイルを実行して、生成されたコードをテストします。

    [x,res] = solvelsqnon_mex
    x =
    
        1.0169
        3.1444
        2.1596
    
    
    res =
    
        7.4101

    解は solvelsqcurve_mex によって生成されるものと同じになります。これは、ソルバーの基礎となるアルゴリズムが同じだからです。そのため、都合の良い方のソルバーを使用できます。

参考

| | (MATLAB Coder) |

関連するトピック