在Python中拟合指数

时间:2015-02-23 13:42:20

标签: python scipy curve-fitting

我试图在python中适应指数衰减。我尝试过使用scipy.optimize.curve_fit,但它完全失败了......

x
Out[18]: 
array([  1.06001000e+04,   1.18721000e+04,   1.32966000e+04,
         1.48926000e+04,   1.66801000e+04,   1.86816000e+04,
         2.09236000e+04,   2.34351000e+04,   2.62481000e+04,
         2.93981000e+04,   3.29261000e+04,   3.68781000e+04,
         4.13041000e+04,   4.62611000e+04,   5.18136000e+04,
         5.80321000e+04,   6.49966000e+04,   7.27971000e+04,
         8.15341000e+04,   9.13196000e+04,   1.02279100e+05,
         1.14554100e+05,   1.28302600e+05,   1.43701100e+05,
         1.60947600e+05,   1.80264100e+05,   2.01898600e+05,
         2.26129600e+05,   2.53268600e+05,   2.83664600e+05,
         3.17709100e+05,   3.55839100e+05,   3.98545100e+05,
         4.46377100e+05,   4.99949600e+05,   5.59951100e+05,
         6.27154100e+05,   7.02422600e+05,   7.86724100e+05,
         8.81143100e+05,   9.86894100e+05,   1.10533660e+06,
         1.23799410e+06,   1.38657310e+06,   1.55298310e+06,
         1.73936510e+06,   1.94811610e+06,   2.18192010e+06,
         2.44378460e+06,   2.73707660e+06,   3.06556810e+06,
         3.43348410e+06,   3.84555560e+06,   4.30708210e+06,
         4.82399910e+06,   5.40295410e+06,   6.05139210e+06,
         6.77765310e+06,   7.59107710e+06,   8.50212410e+06,
         9.52251060e+06,   1.06653596e+07,   1.19453686e+07,
         1.33789981e+07,   1.49846856e+07,   1.67830806e+07,
         1.87973106e+07,   2.10532796e+07,   2.35800001e+07,
         2.64099671e+07])

y
Out[19]: 
array([  7.21779435e-06,   6.88096911e-06,   6.44766520e-06,
         6.06220818e-06,   5.59156825e-06,   5.27746585e-06,
         4.90419458e-06,   4.57028098e-06,   4.19594740e-06,
         3.87213247e-06,   3.53253198e-06,   3.21746863e-06,
         2.96593379e-06,   2.69902818e-06,   2.45720479e-06,
         2.22894945e-06,   2.00554860e-06,   1.78755768e-06,
         1.60389345e-06,   1.43594942e-06,   1.27660849e-06,
         1.12632772e-06,   9.93404773e-07,   8.78887840e-07,
         7.68431386e-07,   6.69981141e-07,   5.88274963e-07,
         5.12602683e-07,   4.47113130e-07,   3.91898528e-07,
         3.42875999e-07,   3.00697454e-07,   2.63373855e-07,
         2.35082385e-07,   2.06185600e-07,   1.81771840e-07,
         1.60044617e-07,   1.42299315e-07,   1.26392523e-07,
         1.12661361e-07,   1.01275721e-07,   9.01458593e-08,
         8.09207343e-08,   7.38619000e-08,   6.76745276e-08,
         6.17079129e-08,   5.68279252e-08,   5.34049900e-08,
         5.05521909e-08,   4.76524243e-08,   4.36574532e-08,
         4.05941897e-08,   3.78241485e-08,   3.51867595e-08,
         3.34753821e-08,   3.13213498e-08,   2.96139649e-08,
         2.74616096e-08,   2.49946165e-08,   2.23428677e-08,
         2.04127328e-08,   1.84783950e-08,   1.65030587e-08,
         1.47845483e-08,   1.35851162e-08,   1.15353701e-08,
         9.18553778e-09,   7.01208306e-09,   5.04006337e-09,
                    nan])

def exp_func(x, a, b, c):
    ...:     return a * np.exp(-b * x) + c
    ...: 

curve_fit(exp_func, x, y)
Out[21]: (array([ 1.,  1.,  1.]), inf)

我知道参数的初始猜测非常重要,但我无法猜测它们(我只知道b接近1)。所以,如果有人能指出猜测参数的方法或者不需要猜测的方法,我将非常感激。 这是数据的loglog图:

More or less linear in log-log scale, and definitely with a linear part

修改

所以,实际上我意识到所有的问题都来自数据不是指数的,而是功率函数,所以使用幂函数而不是指数它可以合理地开箱即用。

1 个答案:

答案 0 :(得分:1)

您可能想要忽略nan

valid = np.logical_not(np.isnan(x + y))
optimize.curve_fit(exp_func, x[valid], y[valid])

为了避免数值不稳定,你应该以某种方式规范化输入数据,例如:将x1e6相乘。当然,您需要相应地更正结果参数。