如何优化给定数据的对数模型曲线拟合效果?
优化指数拟合效果的解决方案
1. 修正numpy.polyfit的拟合逻辑
你当前的polyfit还原曲线时存在公式错误,导致拟合曲线偏离数据点。正确的推导逻辑是:
通过np.polyfit(y_value, np.log10(x_value), 1)得到的关系为log10(x) = b*y + a0(其中b=p[0],a0=p[1]),因此还原后的x值应为10^(b*y + a0),不需要额外添加np.min(y_value);同时你手动调整a值的操作会破坏拟合结果,应当删除。
修正后的polyfit代码:
import matplotlib.pyplot as plt import numpy as np from scipy.optimize import curve_fit x_value = np.array([30000,27850,25590,23900,22400,20470,19450,18120,17130,16180,15340,14620,13730,13400,12790,12460,12060,11760,11440,11200,10940,10780,10720,10530]) y_value = np.array([23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0]) # 正确的对数拟合与曲线还原 p = np.polyfit(y_value, np.log10(x_value), 1) b, a0 = p[0], p[1] x_fitted_polyfit = np.linspace(np.min(y_value), np.max(y_value), 100) y_fitted_polyfit = 10 ** (b * x_fitted_polyfit + a0) plt.scatter(y_value, x_value, label="zisk", color="blue", marker="x", s=30) plt.plot(x_fitted_polyfit, y_fitted_polyfit, 'r', label='polyfit - corrected') plt.xlabel('frekvence [Hz]') plt.ylabel('zisk [dBm]') plt.title('Corrected Polyfit Fit') plt.legend() plt.show()
2. 优化scipy.curve_fit的拟合效果
curve_fit需要合理的初始参数才能收敛到最优解,默认初始值[1,1]与你的数据差距过大,容易导致拟合失败。你可以根据数据范围手动估算初始参数:
a的初始值:当y=0时,x≈10530,因此设为10530b的初始值:取两个点估算,比如y=0时x=10530,y=23时x=30000,代入x=a*exp(b*y)得b = ln(30000/10530)/23 ≈ 0.045
另外不要手动调整拟合得到的a值,这会引入人为误差。
优化后的curve_fit代码:
# 定义指数模型 def exp_model(y, a, b): return a * np.exp(b * y) # 传入合理的初始参数 initial_guess = [10530, 0.045] popt, pcov = curve_fit(exp_model, y_value, x_value, p0=initial_guess) a_opt, b_opt = popt # 生成拟合曲线 x_fitted_curve_fit = np.linspace(np.min(y_value), np.max(y_value), 100) y_fitted_curve_fit = exp_model(x_fitted_curve_fit, a_opt, b_opt) plt.scatter(y_value, x_value, label="zisk", color="blue", marker="x", s=30) plt.plot(x_fitted_curve_fit, y_fitted_curve_fit, 'g', label='curve_fit - optimized') plt.xlabel('frekvence [Hz]') plt.ylabel('zisk [dBm]') plt.title('Optimized Curve Fit') plt.legend() plt.show()
3. 加权拟合提升精度
如果数据的测量误差随x值增大而增加,可以使用加权最小二乘拟合,给误差小的点更高权重。比如用1/x_value作为权重:
# 加权polyfit weights = 1 / x_value p_weighted = np.polyfit(y_value, np.log10(x_value), 1, w=weights) b_w, a0_w = p_weighted[0], p_weighted[1] y_fitted_weighted = 10 ** (b_w * x_fitted_polyfit + a0_w) plt.scatter(y_value, x_value, label="zisk", color="blue", marker="x", s=30) plt.plot(x_fitted_polyfit, y_fitted_weighted, 'purple', label='polyfit - weighted') plt.xlabel('frekvence [Hz]') plt.ylabel('zisk [dBm]') plt.title('Weighted Polyfit') plt.legend() plt.show()
4. 验证模型适用性
如果指数模型仍不能满足需求,可以尝试其他模型,比如双指数模型或幂律模型。例如幂律模型x = a*y^b + c,可以用curve_fit尝试拟合,看是否能提升拟合效果。
内容的提问来源于stack exchange,提问作者Ebrhvuv
相关产品推荐
相关产品推荐

