Python中使用ODR(正交距离回归)进行一维高斯拟合出错排查
问题分析与修正方案
你的ODR高斯拟合结果不符合预期,主要是数据传入错误和初始参数设置不合理导致的,具体问题及修正如下:
1. Data类自变量传入错误
你将x放在列表中传给Data([x], y),但单自变量场景下,直接传入一维数组x即可。原写法会让func中的x变成包含数组的列表,虽然numpy广播不会报错,但不符合ODR的参数传递逻辑,容易引发计算偏差。
2. 初始参数设置偏离真实值
拟合算法的初始值会极大影响收敛结果:
- 峰值
height:你的数据峰值约为4.66e12,但初始值设为1e12,与真实值差距过大,算法难以收敛到正确值; - 宽度
width:数据半高宽明显大于2,初始值设为2太小,容易让算法陷入局部最优。
修正后的代码
import numpy as np import matplotlib.pyplot as plt from scipy.odr import ODR, Model, Data x = np.arange(0,19,1) y = np.array([5.64998480e+09, 3.03653479e+10, 2.18927521e+11, 6.22541771e+11, 1.24917901e+12, 2.05145638e+12, 2.92904416e+12, 3.74656109e+12, 4.36310058e+12, 4.66564452e+12, 4.59701326e+12, 4.17028923e+12, 3.46549578e+12, 2.60950760e+12, 1.74504950e+12, 9.97650569e+11, 4.49637554e+11, 1.27693929e+11, 6.10512095e+09]) def func(beta, x): height, center_x, width = beta return height * np.exp(-(((center_x - x)/width)**2 / 2)) # 修正Data的自变量传入方式 data = Data(x, y) # 若x无测量误差,明确设置x方向误差为0 data.xerr = 0 model = Model(func) # 调整初始参数:峰值接近数据最大值,中心对应峰值位置x=9,宽度设为4 odr = ODR(data, model, [4.7e12, 9, 4]) res = odr.run() plt.figure() plt.plot(x, y, label='原始数据') plt.plot(x, func(res.beta, x), '-o', label='ODR拟合结果') plt.legend() plt.show() # 打印拟合参数 print("拟合参数(峰值, 中心位置, 宽度):", res.beta)
修正说明
- 调整
Data的传入参数为Data(x, y),让func直接接收一维数组x,符合计算逻辑; - 初始参数设置为更接近真实值的数值,帮助拟合算法快速收敛到全局最优;
- 添加
data.xerr = 0明确x无误差,让ODR拟合更贴合数据实际情况。
内容的提问来源于stack exchange,提问作者Chris Lin
相关产品推荐
相关产品推荐

