【问题标题】:Matlab - Fit a Curve with Constrained ParametersMatlab - 用约束参数拟合曲线
【发布时间】:2018-02-17 02:54:50
【问题描述】:

对于 (x,y) 数据集,让由 abc... 等(例如 f='a*exp(b*x)+c')中的表达式给出的曲线进行拟合作为cfit=fit(x,y,f)

假设我们有一组约束,例如b>0c+b>a/2。在这种情况下我应该如何使用fit 命令?

【问题讨论】:

  • 虽然这听起来类似于this question,但我不相信它是重复的。该问题涉及拟合线的约束点,而该问题只是想将参数限制在一个范围内。
  • 是的,工具箱允许处理异常值,它在 xy 空间中,但我问的是参数空间。

标签: matlab curve-fitting


【解决方案1】:

虽然您可以设置下限来强制执行b>0,但我认为通过fit() 正确执行c+b>a/2 是不可能的。但最终每一个拟合问题也可以看成是一个“最小化曲线到数据的距离”的问题,所以可以使用fmincon()来实现你的目标:

%some sample x values
xdata = rand(1000,1);
%some parameters a,b,c
a = 2;
b = 3;
c = 4;
%resulting y values + some noise
ydata=a*exp(b*xdata)+c+rand(1000,1)*10-5;
plot(xdata,ydata,'o')

%function to minimize. It returns the sum of squared distances between the polynom and the data.
fun = @(coefs) sum((coefs(1)*exp(coefs(2).*xdata)+coefs(3)-ydata).^2);
%nonlinear constaint to enforce c+b>a/2, which is the same as -(c+b-a/2)<0
nonlcon = @(coefs)deal(-(coefs(3)+coefs(2)-coefs(1)/2), 0);
% lower bounds to enforce b>0
lb = [-inf 0 -inf];
%starting values
x0 = [1 1 1];
%finally find the coefficients (which should approximately be the values of a, b and c)
coefs = fmincon(fun,x0,[],[],[],[],lb,[],nonlcon)

【讨论】:

    【解决方案2】:

    对于只是数值的约束,例如b &gt; 0,您可以使用'Lower''Upper' 边界参数来指定它们。对于更复杂的关系,例如c+b&gt;a/2,您必须采用类似James suggests 的方法,将函数输出设置为像flintmax 这样的高值以产生较大的错误。例如,假设我这样定义我的函数:

    function y = my_fcn(a, b, c, x)
      if (c+b > a/2)
        y = a.*exp(b.*x)+c;
      else
        y = flintmax().*ones(size(x));
      end
    end
    

    我可以如下创建一组嘈杂的测试数据:

    a = 4;
    b = 2;
    c = 1;
    x = (0:0.01:2).';
    y = my_fcn(a, b, c, x) + 40.*(rand(size(x))-0.5);
    

    然后拟合曲线(注意您必须使用anonymous function,因为function handle 由于某种原因无法使用):

    params = fit(x, y, @(a, b, c, x) my_fcn(a, b, c, x), ...
                 'StartPoint', [1 1 1], ...  % Starting guesses for [a b c]
                 'Lower', [-Inf 0 -Inf]);    % Set bound for 'b'
    
    params = 
    
         General model:
         params(x) = my_fcn(a,b,c,x)
         Coefficients (with 95% confidence bounds):
           a =       4.297  (2.985, 5.609)
           b =       1.958  (1.802, 2.113)
           c =      0.1908  (-4.061, 4.442)
    

    请注意,拟合值与原始值接近,但由于存在噪声,并不完全匹配。我们可以像这样可视化拟合:

    plot(x, y);
    hold on;
    plot(x, my_fcn(params.a, params.b, params.c, x), 'r');
    

    【讨论】:

      【解决方案3】:

      一种简单的方法是让拟合函数返回一个非常大的值,如果参数值超出约束条件,则会产生非常大的误差。这种“砖墙”方法不是最优的,当拟合的参数值接近边界条件时会产生问题。值得一试,因为它可以快速实施并且可以在简单的情况下工作。注意从边界限制内的初始参数值开始。

      【讨论】:

      • 是的,我正在使用它,例如,将 0&lt;b&lt;1 替换为 atan(abs(b))/pi*2。但我相信应该有更好的选择。 Matlab 有一个非常完整的曲线拟合工具箱,却无法约束那些拟合?我很惊讶。
      • 虽然,我不确定如何在给定的情况下引入b~1 时的大错误。