曲线拟合求解传递函数参数L的方法
咱们先把已知条件理清楚,再一步步解决问题:
首先是你的数据和变量定义:
data = [ 0 0; 0.05 1.108646244630E-01; 0.10 2.217423074817E-01; 0.15 3.325947375398E-01; 0.20 4.434863433851E-01; 0.25 5.543595496420E-01; 0.30 6.652338361973E-01; 0.35 7.761094191116E-01; 0.40 8.869865144820E-01; 0.45 9.978653384221E-01; 0.50 1.108746107036E+00]; x = data(:,1); y = data(:,2);
你给出的拟合公式(我帮你补全了缺失的右括号,确保语法正确):
k = 3; y_model = cos(k*L).^2 - (0.8194*k*cos(k*L)*sin(k*L))*x;
需求是找到合适的L,让这个公式拟合数据,同时匹配传递函数的初始线性段。
第一步:先分析初始线性段的矛盾点
先看你的数据:x从0到0.5,y几乎是完美的线性增长,斜率大概是2.217,x=0时y=0。但代入公式看,x=0时y_model = cos²(3L),要和数据匹配的话必须cos²(3L)=0,也就是3L = π/2 + nπ(n是整数)。但这时候公式里的线性项系数-0.8194*k*cos(kL)*sin(kL)就变成了0,斜率为0,完全和数据的线性增长矛盾。
这说明你给出的公式大概率有输入错误——比如符号反了、括号位置错了,或者项的顺序颠倒了。不过没关系,咱们先给出通用的解决思路,再针对这个矛盾点说明。
第二步:用非线性最小二乘求解最优L
不管公式的矛盾,咱们可以直接用非线性最小二乘法找到L,让模型预测值和实际数据的误差平方和最小。这是拟合问题的标准解法,在Matlab里可以用lsqnonlin实现:
- 定义误差函数:输入L,输出模型预测值和实际y的误差向量
k = 3; error_fun = @(L) y - (cos(k*L).^2 - (0.8194*k*cos(k*L)*sin(k*L))*x);
- 选择初始估计值:
因为数据是线性的,咱们先拟合数据的线性斜率:
p = polyfit(x, y, 1); slope_data = p(1); % 算出来大概是2.2175
虽然按原公式推导斜率无解(因为正弦值范围是[-1,1]),但咱们可以选一个合理的初始值,比如L=0.1。
- 调用求解器:
L_initial = 0.1; L_opt = lsqnonlin(error_fun, L_initial);
- 验证拟合效果:
y_fit = cos(k*L_opt).^2 - (0.8194*k*cos(k*L_opt)*sin(k*L_opt))*x; plot(x, y, 'o', x, y_fit, '-'); legend('原始数据', '拟合曲线'); xlabel('x'); ylabel('y');
第三步:加入初始线性段的匹配约束
如果必须严格匹配初始线性段(比如x≤0.1的部分),咱们可以用fmincon加入约束条件,让模型在初始段的斜率和数据的斜率尽可能接近:
- 定义目标函数:误差平方和
obj_fun = @(L) sum((y - (cos(k*L).^2 - (0.8194*k*cos(k*L)*sin(k*L))*x)).^2);
- 定义斜率约束:
x_initial = x(x<=0.1); % 取初始段的x值 % 计算模型在初始段的斜率 slope_model = @(L) polyfit(x_initial, cos(k*L).^2 - (0.8194*k*cos(k*L)*sin(k*L))*x_initial, 1)(1); % 约束:模型斜率和数据斜率的差异绝对值小于0.01 constraints = struct('type', 'ineq', 'fun', @(L) 0.01 - abs(slope_model(L) - slope_data));
- 带约束求解:
L_opt_constrained = fmincon(obj_fun, L_initial, [], [], [], [], [], [], constraints);
重要提醒
按你给出的公式,完全匹配初始线性段是不可能的(因为推导出来斜率为0,和数据的线性增长矛盾),所以建议先检查公式的正确性:比如是不是把减号写成了加号?是不是括号位置错了?或者是不是y_model = (0.8194*k*cos(k*L)*sin(k*L))*x + cos(k*L).^2?修正公式后,上述方法就能完美解决你的问题。
内容的提问来源于stack exchange,提问作者Sumera Yamin

