Main Content

lsqcurvefitlsqnonlin 生成代码

此示例显示如何生成非线性最小二乘的 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);

该代码基于 100 个独立样本(服从均值为 2 的指数分布)生成 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) |

相关主题