我想为通用函数编写一个或多或少的通用拟合函数
$ f_i = \ sum_i a_i exp(-t / tau_i)$
我有一些数据。
以下是双指数函数的示例代码,但我希望能够以最小的代码适应性来拟合单指数或三指数函数。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
t = np.linspace(0, 10, 100)
a_1 = 1
a_2 = 1
tau_1 = 5
tau_2 = 1
data = 1*np.exp(-t/5) + 1*np.exp(-t/1)
data += 0.2 * np.random.normal(size=t.size)
def func(t, a_1, tau_1, a_2, tau_2): # plus more exponential functions
return a_1*np.exp(-t/tau_1)+a_2*np.exp(-t/tau_2)
popt, pcov = curve_fit(func, t, data)
print(popt)
plt.plot(t, data, label="data")
plt.plot(t, func(t, *popt), label="fit")
plt.legend()
plt.show()
原则上,我想将功能重新定义为一般形式
def func(t, a, tau): # with a and tau as a list
tmp = 0
tmp += a[i]*np.exp(-t/tau[i])
return tmp
,然后以列表或元组的形式将参数传递给curve_fit。但是我得到一个TypeError,如下所示。
TypeError: func() takes 4 positional arguments but 7 were given
无论如何,是否只能通过curve_fit的输入参数来重写代码,才能“确定”多指数函数的度?这样过去
a = (1)
在传递时会产生单指数函数
a = (1, 2, 3)
会产生三指数函数吗?
致谢
答案 0 :(得分:2)
是的,使用np.broadcasting
可以轻松完成:
def func(t, a, taus): # plus more exponential functions
a=np.array(a)[:,None]
taus=np.array(taus)[:,None]
return (a*np.exp(-t/taus)).sum(axis=0)
func
接受2个列表,将它们转换为2-dim np.array,计算具有所有指数的矩阵,然后对其求和。示例:
t=np.arange(100).astype(float)
out=func(t,[1,2],[0.3,4])
plt.plot(out)
请紧记a
和taus
的长度必须相同,因此请根据需要清理输入内容。或者,您也可以直接传递np.arrays而不是列表。