6

我有数据应该使用必须属于以下类型的函数进行插值:

f(x) = ax4 + bx2 + c

和。a > 0_ b ≤ 0不幸的是,MATLABpolyfit不允许对多项式的系数进行任何约束。有人知道是否有 MATLAB 函数可以做到这一点吗?否则,我该如何实施?

非常感谢您,

伊丽莎白

4

3 回答 3

11

您可以尝试使用fminsearchfminunc手动定义您的目标函数。

或者,您可以稍微不同地定义您的问题:

f(x) = a2x4 - b2x2 + c

现在,新的ab可以无限制地优化,同时确保最终的ab你正在寻找的都是积极的(分别是消极的)。

于 2013-07-01T14:46:57.917 回答
7

没有约束,这个问题可以写成一个简单的线性系统并解决:

% Your design matrix ([4 2 0] are the powers of the polynomial)
A = bsxfun(@power, your_X_data(:), [4 2 0]);

% Best estimate for the coefficients, [a b c], found by 
% solving A*[a b c]' = y in a least-squares sense
abc = A\your_Y_data(:)

如果该约束模型确实是您的数据的基础,那么这些约束当然会自动得到满足。例如,

% some example factors
a = +23.9;
b = -15.75;
c = 4;

% Your model
f = @(x, F) F(1)*x.^4 + F(2)*x.^2 + F(3);

% generate some noisy XY data
x = -1:0.01:1;
y = f(x, [a b c]) + randn(size(x));

% Best unconstrained estimate a, b and c from the data
A = bsxfun(@power, x(:), [4 2 0]);
abc = A\y(:);

% Plot results
plot(x,y, 'b'), hold on
plot(x, f(x, abc), 'r')
xlabel('x (nodes)'), ylabel('y (data)')

在此处输入图像描述

但是,如果您对该约束模型未准确描述的数据施加约束,则可能会出错:

% Note: same data, but flipped signs 
a = -23.9;
b = +15.75;
c = 4;

f = @(x, F) F(1)*x.^4 + F(2)*x.^2 + F(3);

% generate some noisy XY data
x = -1:0.01:1;
y = f(x, [a b c]) + randn(size(x));

% Estimate a, b and c from the data, Forcing a>0 and b<0
abc = fmincon(@(Y) sum((f(x,Y)-y).^2), [0 0 0], [-1 0 0; 0 +1 0; 0 0 0], zeros(3,1));

% Plot results
plot(x,y, 'b'), hold on
plot(x, f(x, abc), 'r')
xlabel('x (nodes)'), ylabel('y (data)')

在此处输入图像描述

(此解决方案有a == 0,表示模型选择不正确)。

如果 的 完全相等a == 0是一个问题:如果你设置 . 当然没有区别a == eps(0)。从数值上讲,这对于真实世界的数据来说并不明显,但它仍然是非零的。

无论如何,我怀疑您的模型选择不当,并且约束是使一切正常工作的“修复”,或者您的数据实际上应该在尝试进行任何拟合之前是无偏见/重新调整的,或者适用一些类似的先决条件(我经常看到人们做这种事情,所以是的,我在这方面有点偏见:)。

那么......这些限制背后的真正原因是什么?

于 2013-07-01T14:58:10.563 回答
3

如果您有曲线拟合工具箱,那么fit确实允许使用“上”和“下”选项设置约束。你会想要类似的东西。

M=fit(x, f, 'poly4', 'upper', [-inf, 0, -inf, 0, -inf], 'lower', [0, 0, 0, 0, -inf]);

注意使用 -inf 将特定系数设置为不受约束。

这将给出一个具有相关系数的 cfit 对象。您可以使用例如 M.p1 访问这些 x^4 术语。或者,您可以使用feval在您想要的任何点评估函数。

我认为您也可以在优化工具箱中使用 lsqcurvefit 做类似的事情。

于 2015-01-15T10:54:06.983 回答