首页 > 解决方案 > 通过使用 lmfit 优化变量以同时对两条曲线进行最佳拟合

问题描述

假设我们有两条具有相同变量的不同曲线。如何优化变量以同时对两条曲线进行最佳拟合?我可以分别优化每条曲线,但获得的值不一定能为另一条曲线提供最佳拟合。

import numpy as np
from scipy.optimize import minimize
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from lmfit import Model, Parameters


def f(wdata, a, b, c, d):
    return (  a+b*wdata + c*d*wdata  )

def g(wdata, a, b, c, d):
    return (  a**2*(wdata)**2/a*b*wdata*(c)**2  )

wdata = (1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100)
wdata= np.asarray(wdata)

ydata1 = f(wdata, -19, -60, 9, 100)
ydata2 = g(wdata, -19, -60, 9, 100)

fmodel = Model(f)
gmodel = Model(g)

params = Parameters()
params.add('a', value=-19, max = 0, vary=False)
params.add('b', value=-60, vary=True)
params.add('c', value=9, min = 0, vary=True)
params.add('xangle', value=0.05, vary=True, min=-np.pi/2, max=np.pi/2)
params.add('d', expr='(c*a/b)*sin(xangle)')


resultf = fmodel.fit(ydata1, params, wdata=wdata, method='leastsq')
print(resultf.fit_report())
plt.plot(wdata, ydata1, 'bo')
plt.plot(wdata, resultf.init_fit, 'k--')
plt.plot(wdata, resultf.best_fit, 'r-')


resultg = gmodel.fit(ydata2, params, wdata=wdata, method='leastsq')
print(resultg.fit_report())
plt.plot(wdata, ydata2, 'bo')
plt.plot(wdata, resultg.init_fit, 'k--')
plt.plot(wdata, resultg.best_fit, 'r-')


plt.show()

标签: pythonoptimizationcurve-fittinglmfit

解决方案


我认为您想要做的是创建一个模型函数,该函数对数组和数据的连接进行建模。也许是这样的:fg

def f_and_g(wdata, a, b, c, d):
    fmodel = f(wdata, a, b, c, d)
    gmodel = g(wdata, a, b, c, d)
    return np.concatenate((fmodel, gmodel))

# turn that into a model
fg_model = Model(f_and_g)

# same parameters as before:
params = Parameters()
params.add('a', value=-19, max = 0, vary=False)
params.add('b', value=-60, vary=True)
params.add('c', value=9, min = 0, vary=True)
params.add('xangle', value=0.05, vary=True, min=-np.pi/2, max=np.pi/2)
params.add('d', expr='(c*a/b)*sin(xangle)')

# concatenate data to build a 1D array to be modeled:
fdata = f(wdata, -19, -60, 9, 100) + np.normal(scale=0.1, size=len(wdata))
gdata = g(wdata, -19, -60, 9, 100) + np.normal(scale=0.1, size=len(wdata))

fg_data = np.concatenate((fdata, gdata))

# now fit the concatenated data to the concatenated model  
result = fg_model.fit(fg_data, params, wdata=wdata, method='leastsq')
print(result.fit_report())

# to plot individual results, you'll have to untangle the concatenated data:
plt.plot(wdata, fdata, 'bo', label='f data')
plt.plot(wdata, result.best_fit[:len(wdata)], 'b--', label='f fit')

plt.plot(wdata, rgdata, 'ro', label='g data')
plt.plot(wdata, result.best_fit[len(wdata):], 'r--', label='g fit')
plt.legend()
plt.show()

这里假设的一件事是f数据和g数据是同等规模和重要的。情况并非总是如此。如果不是这种情况,您可能需要为模型添加权重(请参阅 lmfit 文档和示例)。通常,这种加权将反映每个数据点的不确定性变化(即,数据中的标准误差在哪里)weight=1./stderrstderr但是对于多数据集拟合,您可能需要更改它,以便比其他部分更强调一个数据集(甚至一个数据集的一部分)。


推荐阅读