如何为scipy的curve_fit添加权重优化左侧数据拟合效果?
为scipy curve_fit添加权重优化左侧拟合效果
使用scipy.optimize的curve_fit进行幂函数拟合时,若左侧数据点的拟合效果不佳,可以通过添加权重让拟合过程更重视左侧数据,从而让拟合线向左侧数据点靠拢。
核心思路
curve_fit的sigma参数可用于指定每个数据点的标准差,结合absolute_sigma=True,就能实现加权拟合:
- 给需要重点拟合的点(左侧小x值)设置更小的sigma(即更高的权重)
- 权重与sigma成反比:权重越高,sigma越小
修改后的代码示例
import pandas as pd import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit x = [ 57, 83, 124, 141, 196, 223, 275, 302, 341, 714, 895, 1034, 1117, 1207, 1248, 1416, 1494, 1563, 1708, 1785, 1863, 2015, 2139, 2238, 2312, 2412, 2442, 2520, 2596, 2658, 2706, 2777, 2846, 2966, 3106, 3241, 3276, 3424, 3568, 3647, 3831, 3961, 4091, 4248, 4430, 4478, 4644, 4833, 5052, 6041 ] y = [ 70, 81, 87, 91, 96, 106, 109, 114, 120, 129, 144, 162, 168, 175, 181, 184, 190, 195, 205, 213, 216, 219, 224, 226, 231, 236, 239, 247, 255, 260, 264, 269, 282, 292, 297, 304, 308, 313, 319, 322, 327, 333, 338, 341, 345, 354, 362, 364, 374, 391 ] plt.scatter(x,y,color='green') def func(x, a, b): return a * np.power(x,b) # 原始无权重拟合(蓝色线) popt, pcov = curve_fit(func, x, y) plt.plot(x, func(x, *popt), 'b-', label='无权重拟合: a=%5.3f, b=%5.3f' % tuple(popt)) # 生成权重:x越小,权重越高 # 方式1:基于x的倒数生成连续权重 weights = 1 / np.array(x) # 方式2:分段设置权重,给左侧小x点更高权重(可根据需求调整阈值和权重值) # weights = np.where(np.array(x) < 500, 5, 1) # 加权拟合(红色线) popt_weighted, pcov_weighted = curve_fit(func, x, y, sigma=1/weights, absolute_sigma=True) plt.plot(x, func(x, *popt_weighted), 'r-', label='加权拟合: a=%5.3f, b=%5.3f' % tuple(popt_weighted)) plt.semilogx() plt.legend() plt.show()
权重调整说明
- 若使用连续权重(如
1/x):x越小的点权重越大,拟合线会平滑地向左侧数据靠拢 - 若使用分段权重(如
np.where):可以针对性地给某一段x值的点设置固定高权重,适合需要重点强化特定区间的场景 - 可根据实际拟合效果调整权重的计算方式,比如用
1/x**2进一步提升左侧点的权重占比
内容的提问来源于stack exchange,提问作者Jiaming
相关产品推荐
相关产品推荐

