如何用Python在半对数图中绘制2σ误差带及拟合问题求助
我懂你这种卡在误差带上的烦恼!之前我也在半对数图里折腾过这个,其实核心是要搞清楚curve_fit给出的参数误差怎么转换成拟合曲线的误差,还有半对数图的特殊限制。下面给你一步步梳理解决方法:
解决半对数图中2σ误差带绘制问题
首先,咱们得先明确curve_fit返回的两个关键值:popt是最优拟合参数,pcov是参数的协方差矩阵。拟合曲线的标准差可以通过这个协方差矩阵推导出来,2σ就是这个标准差的两倍。
步骤1:计算拟合曲线的误差
假设你用的是半对数图常用的指数拟合函数(如果是其他函数,后面会给通用方法),先补全拟合逻辑:
# 假设你的样本y数据是y_data,先定义拟合函数 def fit_func(x, a, b): return a * np.exp(b * x) # 执行拟合 popt, pcov = curve_fit(fit_func, M, y_data)
接下来计算拟合曲线的误差,这里分两种方式:
方式1:手动推导误差传播(针对已知拟合函数)
适合简单函数,比如上面的指数函数:
# 生成更密集的x点,让拟合曲线和误差带更平滑 x_fit = np.linspace(min(M), max(M), 100) y_fit = fit_func(x_fit, *popt) # 获取参数的标准差 perr = np.sqrt(np.diag(pcov)) # 根据指数函数的误差传播公式计算每个x点的y误差 y_err = np.sqrt( (perr[0]*np.exp(popt[1]*x_fit))**2 + (perr[1]*popt[0]*x_fit*np.exp(popt[1]*x_fit))**2 ) # 计算2σ上下限 y_upper = y_fit + 2*y_err y_lower = y_fit - 2*y_err # 半对数图y轴不能为负,把下限裁剪到极小正数避免报错 y_lower = np.clip(y_lower, 1e-6, None)
方式2:蒙特卡洛方法(通用所有拟合函数)
不用手动推导误差公式,适合复杂拟合函数,省心又准确:
x_fit = np.linspace(min(M), max(M), 100) y_fit = fit_func(x_fit, *popt) # 生成1000组参数样本,基于协方差矩阵的分布 n_samples = 1000 params_samples = np.random.multivariate_normal(popt, pcov, n_samples) # 计算每组参数对应的拟合曲线 y_samples = np.array([fit_func(x_fit, *params) for params in params_samples]) # 取97.5%和2.5%分位数作为2σ上下限 y_upper = np.percentile(y_samples, 97.5, axis=0) y_lower = np.percentile(y_samples, 2.5, axis=0) # 同样处理y轴负数问题 y_lower = np.clip(y_lower, 1e-6, None)
步骤2:绘制半对数图和误差带
现在用semilogy绘制所有元素,误差带用灰色填充:
plt.figure(figsize=(8,6)) # 绘制原始样本点 plt.semilogy(M, y_data, 'o', label='Sample Data') # 绘制最优拟合曲线 plt.semilogy(x_fit, y_fit, 'r-', label='Best Fit') # 绘制2σ误差带,alpha设置透明度让曲线可见 plt.fill_between(x_fit, y_lower, y_upper, color='gray', alpha=0.3, label='2σ Error Band') plt.xlabel('M') plt.ylabel('Y (Log Scale)') plt.legend() plt.grid(True, which="both", ls="-") # 显示网格更清晰 plt.show()
关键踩坑点
- 半对数图的y轴限制:这是最容易出错的地方!半对数图y轴不能为0或负数,必须用
np.clip把误差带下限裁剪到极小正数,否则会报错或者显示异常。 - 误差计算的匹配性:如果你的拟合函数不是指数函数,手动推导误差的方法要对应修改,这时候蒙特卡洛方法就显得特别实用,不用管函数形式。
按照这个流程调整代码,应该就能正常显示灰色的2σ误差带了!
内容的提问来源于stack exchange,提问作者bhjghjh
相关产品推荐
相关产品推荐

