在Python lmfit包中计算参数协方差矩阵及相关参数统计量的方法
刚好对lmfit的参数统计分析这块比较熟悉,来帮你逐一解答问题:
1. 能否获取参数协方差矩阵而非相关系数矩阵?
完全可以!lmfit在拟合过程中默认就会计算协方差矩阵,只是默认展示的是标准化后的相关系数矩阵而已。你可以直接通过拟合结果对象的covar属性拿到原始的协方差矩阵。
举个实际使用的例子:
# 假设你已经完成拟合,得到了result对象 cov_matrix = result.covar
这个cov_matrix是一个二维数组,维度等于你拟合时的参数数量。其中对角线元素就是对应参数的方差(Var),非对角线元素则是两个参数之间的协方差(Cov)。而相关系数矩阵可以通过result.corr获取,它是协方差矩阵经过标准化(除以两个参数的标准差乘积)得到的。
2. 如何求得Var(E)和kref的标准差?
这两个统计量其实都可以从协方差矩阵或者参数对象本身直接获取,两种方式都很方便:
方式一:从协方差矩阵提取
假设你的参数名称是'E'和'kref',可以这样操作:
import numpy as np # 获取参数名称列表,找到对应索引 param_names = list(result.params.keys()) e_idx = param_names.index('E') kref_idx = param_names.index('kref') # 提取Var(E):协方差矩阵对角线对应位置的值 var_E = result.covar[e_idx, e_idx] # 提取kref的方差,再求平方根得到标准差 var_kref = result.covar[kref_idx, kref_idx] std_kref = np.sqrt(var_kref)
方式二:直接使用Parameter对象的属性
lmfit的Parameter对象本身就内置了标准差(stderr)属性,你可以直接调用:
# 获取kref的标准差 std_kref = result.params['kref'].stderr # Var(E)是E的标准差的平方 var_E = result.params['E'].stderr ** 2
两种方式得到的结果完全一致,第二种更简洁直观。
3. 关于重新参数化后的相关性验证
你推导的关系式Cov(ko,E)/k0 = Var(E)/RTref - Cov(Kref,E)/kref是正确的,现在你已经有了Cov(Kref,E)(从result.covar[e_idx, kref_idx]获取)、Var(E)、kref这些值,就可以计算出原参数化下的Cov(ko,E),进而算出相关系数对比:
# 代入已知的R和Tref(示例值,替换成你实际使用的数值) R = 8.314 Tref = 298.15 # 先获取k0的估计值(通过kref = ko*exp(-E/(R*Tref))反推) ko = result.params['kref'].value * np.exp(result.params['E'].value/(R*Tref)) # 计算Cov(ko,E) cov_ko_E = (var_E/(R*Tref) - result.covar[e_idx, kref_idx]/result.params['kref'].value) * ko # 计算原参数化下ko和E的相关系数 corr_ko_E = cov_ko_E / (result.params['E'].stderr * np.sqrt(cov_ko_E**2 / corr_ko_E**2 if corr_ko_E !=0 else var_E)) # 如果你有原参数化拟合的result,直接用result.corr里的对应值会更准确
之后对比重新参数化后E和kref的相关系数(result.corr[e_idx, kref_idx]),就能验证你的猜想——重新参数化是否降低了参数间的相关性。
补充个小技巧:如果想直观查看协方差矩阵,可以用numpy的格式化输出让它更易读,比如print(np.array2string(cov_matrix, precision=3))。
内容的提问来源于stack exchange,提问作者user14466123

