使用 fminunc 拟合次数>2 的多项式
Fitting polynomials with degree>2 using fminunc
我正在尝试使用 fminunc
查找 n
次多项式的系数。我知道 polyfit
但我必须使用 fminunc(或 lsqnonlin),因为我需要在以后扩展我的模型。无论如何,我的 objective 函数只是非线性最小二乘问题,我应用了与 polyfit
:
相同的居中和缩放方法
tmpx = (xdat-mean(xdat))./std(xdat) % centering/scaling
x0 = zeros(degree+1, 1); % initial point
objfctn = @(pars) mdl(pars, tmpx, ydat)
和
function [ sse, grad ] = mdl( pars, xdat, ydat )
est = polyval(pars, xdat)-ydat;
sse = sum(est.^2);
degree = length(pars)-1;
grad = [];
for d = 0:degree
grad = [sum(2*est.*(xdat.^d)); grad]; %#ok<AGROW>
end
end
然后我根据从我的目标测量数据集派生的一些启发式生成了一些测试数据:
degree = 2;
tpars = [ ... % true parameters
randraw('uniform', [-5e-20, 5e-20], 1), ...
randraw('uniform', [-10e-20, 10e-20], 1), ...
randraw('uniform', [-20e-9, 20e-9], 1), ...
randraw('uniform', [-50e-6, 50e-6], 1), ...
randraw('uniform', [0, 89e9], 1)];
tpars = tpars(end-degree:end);
xdat = sort(randi(1800e9, 100e3, 1));
yreal = polyval(tpars, xdat);
ydat = yreal + randraw('norm', [0, 100], length(xdat));
使用著名的 randraw
脚本 here。
到目前为止一切顺利,这适用于次数最多为 2 的多项式(即 length(pars) <= 3
)。有了上面的测试数据,它的准确率甚至打败了polyfit
。但是,一旦我尝试拟合阶数高于 2 的多项式,fminunc
在初始迭代后立即停止说
Optimization stopped because the objective function cannot be decreased in the current search direction. Either the predicted change in the objective function, or the line search interval is less than eps.
然而,polyfit
仍然能够拟合多项式,尽管误差越来越大。有谁知道如何用 fminunc
拟合高阶多项式吗?
我的感觉是一些数值问题阻止了 fminunc
的工作。也许梯度太高,我还需要一些 y 轴缩放?
看来我对 y 轴缩放的猜测是正确的,如果 SSE 太高,fminunc
似乎有一些数值问题。我通过简单地对 y 轴应用与对 x 轴所做的相同的缩放来解决了这个问题:
scaling_factor = std(ydat);
ydat_scaled = ydat / scaling_factor;
% fit the polynomial to ydat_scaled using fminunc or lsqnonlin
result = result * scaling_factor;
我用次数最多为 4 的多项式测试了这种方法,它非常有效。就生成的多项式与原始多项式的均方根偏差而言,fminunc
的性能比 polyfit 好得多。具体来说,我为每个度数 0-4 做了 100 运行s,每个 运行 有一组新的测试数据(见上面的问题)。 100 运行 的平均 RMSE 为:
- degree=0:
avgrmse_fminunc = 0.2608
和 avgrmse_polyfit=0.2608
- 度=1:
avgrmse_fminunc = 0.3810
和 avgrmse_polyfit=0.3809
- 度数=2:
avgrmse_fminunc = 2.5897
和 avgrmse_polyfit=53.3994
- 度数=3:
avgrmse_fminunc = 34.0733
和 avgrmse_polyfit=340.6380
- 度数=4:
avgrmse_fminunc = 5.2805e+13
和avgrmse_polyfit=2.9255e+14
这些结果表明,对于具有高 SSE 值和高精度要求的应用程序,"manual" 最小二乘法可能更可取。
我正在尝试使用 fminunc
查找 n
次多项式的系数。我知道 polyfit
但我必须使用 fminunc(或 lsqnonlin),因为我需要在以后扩展我的模型。无论如何,我的 objective 函数只是非线性最小二乘问题,我应用了与 polyfit
:
tmpx = (xdat-mean(xdat))./std(xdat) % centering/scaling
x0 = zeros(degree+1, 1); % initial point
objfctn = @(pars) mdl(pars, tmpx, ydat)
和
function [ sse, grad ] = mdl( pars, xdat, ydat )
est = polyval(pars, xdat)-ydat;
sse = sum(est.^2);
degree = length(pars)-1;
grad = [];
for d = 0:degree
grad = [sum(2*est.*(xdat.^d)); grad]; %#ok<AGROW>
end
end
然后我根据从我的目标测量数据集派生的一些启发式生成了一些测试数据:
degree = 2;
tpars = [ ... % true parameters
randraw('uniform', [-5e-20, 5e-20], 1), ...
randraw('uniform', [-10e-20, 10e-20], 1), ...
randraw('uniform', [-20e-9, 20e-9], 1), ...
randraw('uniform', [-50e-6, 50e-6], 1), ...
randraw('uniform', [0, 89e9], 1)];
tpars = tpars(end-degree:end);
xdat = sort(randi(1800e9, 100e3, 1));
yreal = polyval(tpars, xdat);
ydat = yreal + randraw('norm', [0, 100], length(xdat));
使用著名的 randraw
脚本 here。
到目前为止一切顺利,这适用于次数最多为 2 的多项式(即 length(pars) <= 3
)。有了上面的测试数据,它的准确率甚至打败了polyfit
。但是,一旦我尝试拟合阶数高于 2 的多项式,fminunc
在初始迭代后立即停止说
Optimization stopped because the objective function cannot be decreased in the current search direction. Either the predicted change in the objective function, or the line search interval is less than eps.
然而,polyfit
仍然能够拟合多项式,尽管误差越来越大。有谁知道如何用 fminunc
拟合高阶多项式吗?
我的感觉是一些数值问题阻止了 fminunc
的工作。也许梯度太高,我还需要一些 y 轴缩放?
看来我对 y 轴缩放的猜测是正确的,如果 SSE 太高,fminunc
似乎有一些数值问题。我通过简单地对 y 轴应用与对 x 轴所做的相同的缩放来解决了这个问题:
scaling_factor = std(ydat);
ydat_scaled = ydat / scaling_factor;
% fit the polynomial to ydat_scaled using fminunc or lsqnonlin
result = result * scaling_factor;
我用次数最多为 4 的多项式测试了这种方法,它非常有效。就生成的多项式与原始多项式的均方根偏差而言,fminunc
的性能比 polyfit 好得多。具体来说,我为每个度数 0-4 做了 100 运行s,每个 运行 有一组新的测试数据(见上面的问题)。 100 运行 的平均 RMSE 为:
- degree=0:
avgrmse_fminunc = 0.2608
和avgrmse_polyfit=0.2608
- 度=1:
avgrmse_fminunc = 0.3810
和avgrmse_polyfit=0.3809
- 度数=2:
avgrmse_fminunc = 2.5897
和avgrmse_polyfit=53.3994
- 度数=3:
avgrmse_fminunc = 34.0733
和avgrmse_polyfit=340.6380
- 度数=4:
avgrmse_fminunc = 5.2805e+13
和avgrmse_polyfit=2.9255e+14
这些结果表明,对于具有高 SSE 值和高精度要求的应用程序,"manual" 最小二乘法可能更可取。