【问题标题】:How to fix this fitting routine (2 independent variable) using lmfit?如何使用 lmfit 修复此拟合程序(2 个自变量)?
【发布时间】:2019-08-26 16:08:11
【问题描述】:

我目前正在尝试使用 lmfit 实现曲线拟合例程,尽管我的编码技能有限,而且我之前使用 curve_fit 的经验也无济于事。另外,我一直在浏览https://lmfit.github.io/lmfit-py/model.html 上的文档,但我仍然无法修复它。

正如您在下面看到的,我试图拟合以下等式:R2avg*(np.sin(thetas))**2 + ((np.sin(thetas))**2)*(phi_ex*k_ex/(k_ex**2 + omega_eff**2)),它有 2 个自变量(omega_effthetas),而我想拟合其余三个参数。

import lmfit as lf
from lmfit import Model, Parameters
import numpy as np
import matplotlib.pyplot as plt
from math import atan

def on_res(omega_eff, thetas, R2avg=5, k_ex=0.1, phi_ex=500):
    return R2avg*(np.sin(thetas))**2 + ((np.sin(thetas))**2)*(phi_ex*k_ex/(k_ex**2 + omega_eff**2))

model = Model(on_res,independent_vars=['omega_eff','thetas'])

model.set_param_hint('R2avg',value=5)
model.set_param_hint('k_ex',value=0.1)
model.set_param_hint('phi_ex',value=500)

carrier = 6146.53
O_1 = 5846
spin_locks = (1000, 2000, 3000, 4000, 5000) 
delta_omega = (O_1 - carrier)

omega_eff1 = ((delta_omega**2) + (spin_locks[0]**2))**0.5
omega_eff2 = ((delta_omega**2) + (spin_locks[1]**2))**0.5
omega_eff3 = ((delta_omega**2) + (spin_locks[2]**2))**0.5
omega_eff4 = ((delta_omega**2) + (spin_locks[3]**2))**0.5
omega_eff5 = ((delta_omega**2) + (spin_locks[4]**2))**0.5

theta_rad1 = atan(spin_locks[0]/delta_omega)
theta_rad2 = atan(spin_locks[1]/delta_omega)
theta_rad3 = atan(spin_locks[2]/delta_omega)
theta_rad4 = atan(spin_locks[3]/delta_omega)
theta_rad5 = atan(spin_locks[4]/delta_omega)

x = (omega_eff1/1000, omega_eff2/1000, omega_eff3/1000, omega_eff4/1000, omega_eff5/1000)# , omega_eff6/1000)# , omega_eff7/1000)
theta = (theta_rad1, theta_rad2, theta_rad3, theta_rad4, theta_rad5)
R1rho_vals = (7.9328, 6.2642, 6.0005, 5.9972, 6.1988)
e = (0.33, 0.31, 0.32, 0.33, 0.5)

new_x = np.linspace(0, 6, 1000)
omega_eff = np.array(x, dtype=float)
thetas = np.array(theta, dtype=float)
R1rho_vals = np.array(R1rho_vals, dtype=float)

result = model.fit(R2avg, k_ex, phi_ex, thetas=thetas, omega_eff=omega_eff)

plt.errorbar(x, R1rho_vals, yerr = e, fmt = ".k", markersize = 8, capsize = 3)
# plt.plot(new_x, result.best_fit, label="Two sites fast exchange")
# plt.show()
print(model.param_names)
print(model.independent_vars)

如果我按照我发布的方式运行脚本,我会得到:

result = model.fit(R2avg, k_ex, phi_ex, thetas=thetas, omega_eff=omega_eff)
NameError: name 'R2avg' is not defined

我不太明白。 我做了一些故障排除,并通过检查:

print(model.param_names)print(model.independent_vars)

似乎一切都被恰当地定义了。

非常欢迎任何帮助!

【问题讨论】:

  • 您的代码中没有名为 R2avg 的变量。所以python在写model.fit(R2avg, ...)的时候不知道你想做什么。
  • @ImportanceOfBeingErnest 谢谢!那我该怎么定义呢?只需定义一个空列表,例如R2avg = []?
  • .fit 的第一个参数应该是你想要拟合的数据。
  • 从你代码中的名字来看omega_eff是独立数据。但是这些 omega 的相关数据(y 值)是什么?
  • 剩下的参数应该是你的函数的输入值。

标签: python matplotlib lmfit


【解决方案1】:

您使用lmfit.Model 定义独立参数看起来没问题。您没有做的是定义一组要在拟合中使用的参数。

你这样做:

model = Model(on_res,independent_vars=['omega_eff','thetas'])

model.set_param_hint('R2avg',value=5)
model.set_param_hint('k_ex',value=0.1)
model.set_param_hint('phi_ex',value=500)

set_param_hint 告诉模型如何制作参数,但它不制作。你必须明确地这样做。在我看来,这样做会更好

model = Model(on_res,independent_vars=['omega_eff','thetas'])

params = model.make_params(R2avg=5, k_ex=0.1, phi_ex=500)

部分是因为a)您需要一个Parameters对象以使其适合工作,并且b)这些值并不是您模型的真正一部分(参数或约束表达式的界限可能是,但是值很少)。

然后要适合独立的(y)数据,你想做的事

result = model.fit(data, params, thetas=thetas, omega_eff=omega_eff)

或者(如果您真的坚持不创建参数)您可以明确声明每个参数的起始值:

result = model.fit(data, R2avg=5, k_ex=0.1, phi_ex=500, 
                  thetas=thetas, omega_eff=omega_eff)

但不是

result = model.fit(param1, param2, ..., thetas=thetas, omega_eff=omega_eff) # NO!

一般来说,明确地使用参数对象是首选。

看起来(但我不确定)R1rho_vals 是要拟合的数据,所以这意味着您想要这样做:

result = model.fit(R1rho_vals, params, thetas=thetas, omega_eff=omega_eff)

要包括不确定性(您的e),您可以这样做:

result = model.fit(R1rho_vals, params, weights=1.0/e, 
                   thetas=thetas, omega_eff=omega_eff)

然后你可以打印和绘制结果:

print(result.fit_report())

plt.errorbar(x, R1rho_vals, yerr = e, fmt = ".k", markersize = 8, capsize = 3)
plt.plot(new_x, result.best_fit, label="Two sites fast exchange")  
plt.show()

【讨论】:

  • 首先:谢谢!我肯定在这里遗漏了一些关键概念。现在拟合有效(print(result.fit_report()) 提供了合理的数据),但我在绘制图表时仍然遇到一些问题。在一种情况下,包括weights=1.0/e,我收到错误消息TypeError: unsupported operand type(s) for /: 'int' and 'tuple'。有什么办法可以绕过这个吗?看起来不想要除法运算符...其次,由于与new_x = np.linspace 的形状不匹配,即使去掉weightsplt.plot 也无法正常工作。有什么建议吗?
  • 您好!我解决了weights 问题。处理plt.plot 问题!
  • 是的,使用 lmfit 拟合时,所有序列数据最好使用 numpy ndarrays 而不是元组或列表。
  • 你有任何关于如何显示与plt.plot() 的合身的cmets 吗?使用 new_x 我得到一个不匹配的形状错误,而使用 x 我得到一个非常粗糙的轮廓(正如预期的那样,因为我只有 5 个实验点)。
猜你喜欢
  • 1970-01-01
  • 2021-02-25
  • 1970-01-01
  • 2022-10-12
  • 1970-01-01
  • 1970-01-01
  • 2014-06-18
  • 2021-02-23
  • 1970-01-01
相关资源
最近更新 更多