在下小白,只会用简单的curve fit中的polynomial和equation,这里简单介绍了一下用工具箱,poly fit函数拟合和计算相对误差的方法,模型建立如有不合理之处,纯属为了练手而建模。
鱼的质量与身长和腰围的关系
问题重述:
一垂钓俱乐部鼓励垂钓者将钓上的鱼放生,打算按照放生的鱼的重量给予奖励,俱乐部只准备了一把软尺用于测量,请你设计按照测量的长度估计鱼的重量的方法.假定鱼池中只有一种鲈鱼,并且得到8条鱼的如下数据(胸围指鱼身的最大周长):
身长(cm) |
36.8 |
31.8 |
43.8 |
36.8 |
32.1 |
45.1 |
35.9 |
32.1 |
重量(g) |
765 |
482 |
1162 |
737 |
482 |
1389 |
652 |
454 |
胸围(cm) |
24.8 |
21.3 |
27.9 |
24.8 |
21.6 |
31.8 |
22.9 |
21.6 |
先用机理分析建立模型,再用数据确定参数.
模型假设:
1. 模型一:假设鱼的质量只与身长有关,且假设质量与身长的一次方成正比
2. 模型二:假设鱼的质量与身长腰围同时相关且与质量与身长,腰围的平方,身长与腰围的乘积有关
3. 模型三:假设鱼的质量与身长乘腰围的平方成正比
4. 假设鱼没有四肢,可近似看作圆柱
5. 假设模型拟合效果可由各组数据的相对误差的平均值来衡量
建立模型
模型一:
只对身长进行一次拟合
方法一:
使用curvefit工具箱,得到如下系数
运行如下的脚本代码,计算拟合值与真实值的相对误差
x=[31.8,32.1,32.1,35.9,36.8,36.8,43.8,45.1]
z=[482,454,482,652,737,765,1162,1389]
y=[21.3,21.6,21.6,22.9,24.8,24.8,27.8,31.9];
p1 =65.29
p2 =-1637
z1= p1*x + p2
r=z1-z
re=r./z
res=strcat(num2str(mean(re)*100),'%')
得到平均相对误差res=' 4.779%'
方法二:
使用polyfit一次拟合
得到平均相对误差res= '4.7701%'
模型评价:
从以上两种方法中可以看出,误差在4.8%左右,还是比较符合实际情况的,poly fit拟合效果略好于curvefit工具箱的效果,但是相对误差还是较大
模型二:
假设鱼为圆柱体,没有四肢,因为圆柱体的体积为长乘π/4乘直径的平方,底面周长又等于直径乘π,则可认为鱼的质量与身长和腰围的平方的乘积成正比
这里令x为身长,y为腰围,z为质量,
选择polynomial拟合,设定质量和身长的一次方,腰围的二次方相关,得到拟合图形及系数如图
运行如下代码求出平均相对误差
x=[31.8,32.1,32.1,35.9,36.8,36.8,43.8,45.1]
z=[482,454,482,652,737,765,1162,1389]
y=[21.3,21.6,21.6,22.9,24.8,24.8,27.8,31.9];
p00 =-187.5
p10 =-6.198
p01 =-7.045
p11 =1.891
p02 =-0.6289
z1= p00 + p10*x + p01*y +p11*x.*y + p02*y.^2
plot3(x,y,z1)
r=z1-z% r为拟合值和实际值之差的数组
re=abs(r./z)% re为各组数据相对误差res=strcat(num2str(mean(re)*100),'%')
%res为各组相对误差的平均值,可大致反应拟合整体的相对误差
得到相对误差res =1.8121%'
模型评价:
平均相对误差在1.8%,能够很好地描述身长腰围质量之间的关系,
以上为多项式拟合,另外也可以使用定制拟合的方法,令公式为
z=p00 + p10*x + p01*y + p11*x.*y + p02*y.^2'
得到结果与多项式拟合完全相等
模型三:
上面讨论了使用多项式拟合的方法,但是只能按照公式z1= p00 + p10*x + p01*y + p11*x.*y + p02*y.^2拟合,由常识我们知道,鱼近似与圆柱体,圆柱体体积与长度乘截面周长的平方成正比,于是我们设想是否三者之间满足z=a*x*y^2+ b关系
在curvefit 中选择custom Equation,输入公式,得到如下结果
编写脚本文件计算误差
x=[31.8,32.1,32.1,35.9,36.8,36.8,43.8,45.1]
z=[482,454,482,652,737,765,1162,1389]
y=[21.3,21.6,21.6,22.9,24.8,24.8,27.8,31.9];
a =0.03056
b =46.46
z1=a*x.*y+b
r=abs(z1-z)
re=r./z
res=strcat(num2str(mean(re)*100),'%')
得到误差为'89.0792%'
可见实际情况并非与理论推导一致
总结:
鱼的质量与身长腰围大致满足z1= p00 + p10*x + p01*y + p11*x.*y + p02*y.^2关系,使用多项式拟合可以控制误差在1.8%,效果较好,而简单地认为鱼的质量与身长乘腰围的平方成正比的结果误差较大,认为只与身长的一次方有关的误差在4.8%左右。
使用poly fit计算误差
cla
x=[31.8,32.1,32.1,35.9,36.8,36.8,43.8,45.1];
y=[482,454,482,652,737,765,1162,1389];
plot(x,y,'bo');title('身长与质量一次拟合');hold on
a=polyfit(x,y,1)
b=polyval(a,x)
s=poly2sym(a);%系数矩阵转化成方程但是是分数
t=subs(s,x)%把x数组整体带入求值
y1=vpa(y1,8)%转化成小数并稍微控制一下位数
r=abs(y1-y)%平均误差记得用一下绝对值再加
re=r./y%相对误差,得到的是syms类型需要转化成double
res=strcat(num2str(mean(double(re))*100),'%')%平均相对误差并转化成百分数
从curvefit tool中导出
x=[31.8,32.1,32.1,35.9,36.8,36.8,43.8,45.1]
z=[482,454,482,652,737,765,1162,1389]
y=[21.3,21.6,21.6,22.9,24.8,24.8,27.8,31.9];
p=x.*y.^2
a=polyfit(p,z,1)
b=polyval(a,p)
s=poly2sym(a);%系数矩阵转化成方程但是是分数
t=subs(s,p)%把x数组整体带入求值
p1=vpa(p1,8)%转化成小数并稍微控制一下位数
r=abs(p1-p)%平均误差记得用一下绝对值再加
re=r./p%相对误差,得到的是syms类型需要转化成double
res=strcat(num2str(mean(double(re))*100),'%')%平均相对误差并转化成百分数