Matlab - 用受限参数拟合曲线

4
对于一个(xy)数据集,假设有一个曲线由表达式 f='a*exp(b*x)+c' 给出,其中 abc 等等需要拟合为 cfit=fit(x,y,f)
假设我们有一组约束条件,如 b>0c+b>a/2。在这种情况下,应该如何使用 fit 命令?

1
虽然听起来与此问题相似,但我并不认为它是重复的。那个问题涉及到限制拟合线的点,而这个问题只想将参数限制在一个范围内。 - gnovice
是的,工具箱可以处理xy空间中的异常值,但我正在询问参数空间。 - Brethlosze
3个回答

4

虽然你可以设置下限来强制 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)

3

对于仅为数值的约束条件,例如 b > 0,您可以使用'Lower''Upper'边界参数来指定它们。对于更复杂的关系,例如 c+b>a/2,您需要采用类似James建议的方法,将函数输出设置为高值,例如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);

接下来拟合一个曲线(请注意,您必须使用匿名函数,因为某些原因函数句柄不起作用):

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');

enter image description here


2

一种简单的方法是,如果参数值超出约束条件,则使适配函数返回一个非常大的值,从而产生非常大的误差。这种“墙壁”方法并不是最优的,当拟合参数值接近边界条件时会导致问题。尽管这种方法很快,可以在简单的情况下工作,但需要注意的是,要从边界限制内的初始参数值开始。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接