使用 lmfit 绘制和建模数据 - 拟合与数据不匹配。我究竟做错了什么?

Plotting and modeling data with lmfit - Fit doesn't match data. What am I doing wrong?

我有一些数据正在尝试使用 lmfit 的模型进行建模。

具体来说,我正在测量超导电阻器。我正在尝试将实验数据(电阻与温度)拟合到一个包含临界温度 Tc(material 依赖)、低于 Tc 的电阻(通常为 0)和高于 Tc 的电阻(取决于结构)的模型.

这是我用来绘制数据的代码的简化版本(带有模拟数据)以及输出图。

我没有收到任何错误,但如您所见,我也没有找到与我的数据相匹配的数据。

我做错了什么?这是我第一次使用 lmfit 和模型,所以我可能犯了一个新手错误。我 以为 我在关注 the lmfit example 但是,正如我所说,我显然做错了什么。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from lmfit import Model


def main():
    x = np.linspace(0, 12, 50)
    x_ser = pd.Series(x)  # Simulated temperature data

    y1 = [0] * 20
    y2 = [10] * 30
    y1_ser = pd.Series(y1)  # Simulated resistance data below Tc
    y2_ser = pd.Series(y2)  # Simulated resistance data above Tc (
    y_ser = y1_ser.append(y2_ser, ignore_index=True)

    xcrit_model = Model(data_equation)
    params = xcrit_model.make_params(y1_guess=0, y2_guess=12, xcrit_guess=9)
    print('params: {}'.format(params))
    result = xcrit_model.fit(y_ser, params, x=x_ser)
    print(result.fit_report())

    plt.plot(x_ser, y_ser, 'bo', label='simulated data')
    plt.plot(x_ser, result.init_fit, 'k.', label='initial fit')
    plt.plot(x_ser, result.best_fit, 'r:', label='best fit')
    plt.legend()
    plt.show()


def data_equation(x, y1_guess, y2_guess, xcrit_guess):
    x_lt_xcrit = x[x < xcrit_guess]
    x_ge_xcrit = x[x >= xcrit_guess]
    y1 = [y1_guess] * x_lt_xcrit.size
    y1_ser = pd.Series(data=y1)
    y2 = [y2_guess] * x_ge_xcrit.size
    y2_ser = pd.Series(data=y2)

    y = y1_ser.append(y2_ser, ignore_index=True)

    return y

if __name__ == '__main__':
    main()

lmfit(以及基本上所有类似的求解器)使用 continuous 变量并研究它们如何通过对参数值进行微小更改并查看它们如何改变结果效果适合。

但是您的 xcrit_guess 参数仅用作离散变量。如果它的值从 9.0000 变为 9.00001,则拟合根本不会改变。

所以,基本上,不要这样做:

x_lt_xcrit = x[x < xcrit_guess]
x_ge_xcrit = x[x >= xcrit_guess]

相反,您应该使用更平滑的 S 形阶跃函数。事实上,lmfit 内置了其中之一。所以你可以尝试这样的事情(注意,将 numpy.arrays 转换为 pandas.Series 没有意义 - 代码只会将它们转回 numpy 数组):

import numpy as np
from lmfit.models import StepModel
import matplotlib.pyplot as plt

x = np.linspace(0, 12, 50)
y = 9.5*np.ones(len(x))
y[:26] = 0.0
y = y + np.random.normal(size=len(y), scale=0.0002)

xcrit_model = StepModel(form='erf')
params = xcrit_model.make_params(amplitude=4, center=5, sigma=1)

result = xcrit_model.fit(y, params, x=x)
print(result.fit_report())

plt.plot(x, y, 'bo', label='simulated data')
plt.plot(x, result.init_fit, 'k', label='initial fit')
plt.plot(x, result.best_fit, 'r:', label='best fit')
plt.legend()
plt.show()