如何编写灵活的多重指数拟合

时间:2018-07-11 17:07:11

标签: scipy curve-fitting

我想为通用函数编写一个或多或少的通用拟合函数

$ 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)

会产生三指数函数吗?

致谢

1 个答案:

答案 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)

请紧记ataus的长度必须相同,因此请根据需要清理输入内容。或者,您也可以直接传递np.arrays而不是列表。