# polyfit
多项式曲线拟合
函数库: TyMath
# 语法
p,S,mu = polyfit(x,y,n)
p,S,mu = polyfit(x,y,n;normalize=true)
# 说明
p,S,mu = polyfit(x,y,n) 返回次数为 n 的多项式 p(x) 的系数,该阶数是 y 中数据的最佳拟合(基于最小二乘指标);还返回一个元组 S,可用作 polyval 的输入来获取误差估计值;同时还返回一个二元素向量 mu,包含中心化值和缩放值,mu[1] 是 mean(x),mu[2] 为 std(x)。p 中的系数按降幂排列,p 的长度为 n+1,其中: 示例
p,S,mu = polyfit(x,y,n;normalize=true) 指定关键字参数 normalize 为 true 来执行中心化和缩放以同时改善多项式和拟合算法的数值属性。关键字参数 normalize 的默认值为 false。polyfit 使用 mu 将 x 的中心置于零值处并缩放为具有单位标准差:示例
# 示例
将多项式与三角函数拟合
在区间 [0, 4*pi] 中沿正弦曲线生成 10 个等间距的点。
using TyMath
using TyPlot
x = LinRange(0,4*pi,10)
y = sin.(x)
使用 polyfit 将一个 7 次多项式与这些点拟合。
p, = polyfit(x,y,7)
在更精细的网格上计算多项式并绘制结果图。
x1 = LinRange(0,4*pi,100)
y1 = polyval(p,x1)
figure(1)
plot(x,y,"o")
hold("on")
plot(x1,y1)
hold("off")
将多项式与点集拟合
创建一个由区间 [0, 1] 中的 5 个等间距点组成的向量,并计算这些点处的
using TyMath
using TyPlot
x = LinRange(0,1,5)
y = 1 ./(1 .+x)
将 4 次多项式与 5 个点拟合。通常,对于 n 个点,可以拟合 n-1 次多项式以便完全通过这些点。
p, = polyfit(x,y,4)
在由0和2之间的点组成的更精细网格计算原始函数和多项式拟合。
x1 = LinRange(0,2,100)
y1=1 ./(1 .+x1)
f1 = polyval(p,x1)
在更大区间 [0, 2] 中绘制函数值和多项式拟合,其中包含用于获取以圆形突出显示的多项式拟合的点。多项式拟合在原始 [0, 1] 区间中的效果较好,但在该区间外部很快与拟合函数出现差异。
figure(1)
plot(x,y,"o")
hold("on")
plot(x1,y1)
plot(x1,f1,"r--")
legend(["y","y1","f1"])
hold("off")
对误差函数进行多项式拟合
首先生成 x 点的向量,在区间 [0, 2.5] 内等间距分布,然后计算这些点处的 erf(x)。
using TyMath
using TyBase
using TyPlot
x = 0:0.1:2.5
y = erf.(x)
确定6次逼近多项式的系数。
p, = polyfit(x,y,6)
p = 7-element Vector{Float64}:
0.008419371779225042
-0.09829957533670358
0.421736169817858
-0.7434628491295178
0.147104056632926
1.1064460446255027
0.0004411739619861183
为了查看拟合情况如何,在各数据点处计算多项式,并生成说明数据、拟合和误差的一个表。
f = polyval(p,x)
T = DataFrame(X=x,Y=y,Fit=f,FitError=y-f)
T = 26×4 DataFrame
Row │ X Y Fit FitError
│ Float64 Float64 Float64 Float64
────┼──────────────────────────────────────────────
1 │ 0.0 0.0 0.000441174 -0.000441174
2 │ 0.1 0.112463 0.111855 0.000608361
3 │ 0.2 0.222703 0.222311 0.000391886
4 │ 0.3 0.328627 0.328724 -9.74288e-5
5 │ 0.4 0.428392 0.428799 -0.000406608
6 │ 0.5 0.5205 0.520926 -0.000425678
7 │ 0.6 0.603856 0.604084 -0.000228242
8 │ 0.7 0.677801 0.677755 4.63827e-5
9 │ 0.8 0.742101 0.741831 0.000269919
10 │ 0.9 0.796908 0.796543 0.000365145
11 │ 1.0 0.842701 0.842384 0.000316401
12 │ 1.1 0.880205 0.880046 0.000159482
13 │ 1.2 0.910314 0.910354 -3.99194e-5
14 │ 1.3 0.934008 0.934219 -0.000210995
15 │ 1.4 0.952285 0.952584 -0.000299334
16 │ 1.5 0.966105 0.966386 -0.000280972
17 │ 1.6 0.976348 0.976515 -0.000167043
18 │ 1.7 0.98379 0.98379 8.33065e-7
19 │ 1.8 0.989091 0.988928 0.000162785
20 │ 1.9 0.99279 0.992533 0.000257909
21 │ 2.0 0.995322 0.995079 0.000243468
22 │ 2.1 0.997021 0.996907 0.000113098
23 │ 2.2 0.998137 0.998226 -8.85483e-5
24 │ 2.3 0.998857 0.999114 -0.000256727
25 │ 2.4 0.999311 0.999536 -0.000224508
26 │ 2.5 0.999593 0.999362 0.000231508
在该区间中,插值与实际值非常符合。创建一个绘图,以显示在该区间外,外插值与实际数值如何快速偏离。
x1 = 0:0.1:5
y1 = erf.(x1)
f1 = polyval(p,x1)
figure(1)
plot(x,y,"o")
hold("on")
plot(x1,y1,"-")
plot(x1,f1,"r--")
xlim([0, 5])
ylim([0, 2])
hold("off")
使用中心化和缩放改善数值属性
创建一个由 1750 - 2000 年的人口数据组成的表,并绘制数据点。
using TyMath
using TyBase
using TyPlot
year = 1750:25:2000
pop = 1e6*[791,856,978,1050,1262,1544,1650,2532,6122,8170,11560]
T = DataFrame(year = year,pop = pop)
T = 11×2 DataFrame
Row │ year pop
│ Int64 Float64
─────┼─────────────────
1 │ 1750 7.91e8
2 │ 1775 8.56e8
3 │ 1800 9.78e8
4 │ 1825 1.05e9
5 │ 1850 1.262e9
6 │ 1875 1.544e9
7 │ 1900 1.65e9
8 │ 1925 2.532e9
9 │ 1950 6.122e9
10 │ 1975 8.17e9
11 │ 2000 1.156e10
plot(year,pop,"o")
令关键字参数 normalize 为true,使用 polyfit 拟合一个使用中心化和缩放的 5 次多项式,这将改善问题的数值属性。polyfit 将 year 中的数据以 0 为进行中心化,并缩放为具有标准差 1,这可避免在拟合计算中出现病态的范德蒙矩阵。
p,sm_1,mu = polyfit(T.year, T.pop, 5; normalize=true)
使用带有四个输入的 polyval 来计算 p 与缩放的年份,(year-mu[1])/mu[2]。 根据原始年份绘制结果。
f = polyval(vec(p),year,[],mu)
hold("on")
plot(year,f)
hold("off")
简单线性回归
将一个简单线性回归模型与一组离散二维数据点拟合。创建几个由样本数据点 (x,y) 组成的向量,对数据进行一次多项式拟合。
using TyMath
using TyPlot
rng = MT19937ar(5489)
x = 1:50
y = vec(-0.3*x+2*randn(rng,50,1))
p, = polyfit(x,y,1)
计算在 x 中的点处拟合多项式 p,用这些数据绘制得到的线性回归模型。
f = polyval(p,x)
plot(x,y,"o",x,f,"-")
legend(["data","linear fit"])
误差估计的线性回归
将线性模型拟合到一组数据点并绘制结果,包括 95% 预测区间的估计值。
using TyMath
using TyPlot
rng = MT19937ar(5489)
x = 1:100
y = vec(-0.3*x+2*randn(rng,100))
p,S = polyfit(x,y,1)
在 x 中的点处评估 p 中的一次多项式拟合。 将误差估计结构指定为第三个输入,以便 polyval 计算标准误差的估计值。 标准误差估计值以 delta 形式返回。
y_fit,delta = polyval(vec(p),x,S)
绘制图像
plot(x,y,"bo")
hold("on")
plot(x,y_fit,"r-")
plot(x,y_fit .+ 2*delta,"m--",x,y_fit .- 2*delta,"m--")
title("Linear Fit of Data with 95% Prediction Interval")
legend(["Data","Linear Fit","95% Prediction Interval"])
# 输入参数
x - 查询点向量
查询点,指定为一个向量。x 中的点对应于 y 中包含的拟合函数值。
数据类型: Int64 | Int32 | Int16 | Int128 | Float64 | Float32 | Float16
复数支持: 是
y - 查询点位置的拟合向量
查询点位置的拟合值,指定为向量。y 中的值对应于 x 中包含的查询点。
数据类型: Int64 | Int32 | Int16 | Int128 | Float64 | Float32 | Float16
复数支持: 是
n - 多项式拟合的次数正整数标量
多项式拟合的次数,指定为正整数标量。n 指定 p 中最左侧系数的多项式幂。
normalize - 中心化并缩放指示false(默认) | true
中心化并缩放指示,指定为 false 或 true。当该项为 true 时,polyfit 执行中心化并缩放且在第三个输出参数中返回使用的中心化缩放参数。
# 输出参数
p - 最小二乘拟合多项式系数向量
最小二乘拟合多项式系数,以向量的形式返回。p 的长度为 n+1,包含按降幂排列的多项式系数,最高幂为 n。如果 x 或 y 包含 NaN 值且 n < length(x),则 p 的所有元素均为 NaN。使用 polyval 计算 p 在查询点处的解。
S - 误差估计元组元组
误差估计元组。此元组是 p,S,mu = polyfit(x,y,n) 中的第二个输出。指定 S 作为 polyval 的输入以获得误差估计值。S 包含以下字段:
| 字段 | 说明 |
|---|---|
| R | 范德蒙矩阵 x 的 QR 分解的三角 R 因子(可能经过置换) |
| df | 自由度 |
| normr | 残差的范数 |
如果 y 中的数据是随机的,则 p 的估计协方差矩阵是 (Rinv*Rinv')*normr^2/df,其中 Rinv 是 R 的逆矩阵。
mu - 中心化值和缩放值二元素向量
中心化值和缩放值,以二元素向量形式返回。mu[1] 为 mean(x),mu[2] 为 std(x)。这些值以单位标准差将 x 中的查询点的中心置于零值处。
使用 mu 作为 polyval 的第四个输入以计算 p 在缩放点 (x - mu[1])/mu[2] 处的解。