【问题标题】:scipy.optimize.curve_fit doesn't fitscipy.optimize.curve_fit 不适合
【发布时间】:2022-01-20 04:34:06
【问题描述】:

我想用curve_fit做指数回归,这样我就可以计算出我数据的年增长率了。

x 是年份,y 是资产。如果合适,增长率应该是exp(b) - 1。但它返回 (1.0, 1.0, 1.0) 作为 popt。

import pandas as pd
import numpy as np
import scipy.stats as stats
from datetime import datetime
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt

df = pd.DataFrame([
    [2011, 255],
    [2012, 349],
    [2013, 449],
    [2014, 554],
    [2015, 658]
], columns=['x', 'y'])

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

popt, pcov = curve_fit(func, df['x'], df['y'])
print('popt', popt)

df['y1'] = func(df['x'], *popt)
print('df\n', df)

plt.plot(df['x'], df['y'])
plt.plot(df['x'], df['y1'], 'g--',
            label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt))
plt.xlabel('x')
plt.xlabel('y')
plt.legend()
plt.show()

输出:

popt [1.0 1.0 1.0]
df
       x    y   y1
0  2011  255  inf
1  2012  349  inf
2  2013  449  inf
3  2014  554  inf
4  2015  658  inf

如果我将 x 更改为 [1, 2, 3, 4, 5],它可能适合。

【问题讨论】:

    标签: python scipy scipy-optimize


    【解决方案1】:

    您遇到了溢出,因为您的 x 值太大而无法将 np.exp(x) 放入 64 位浮点数,请参阅 np.exp(2015)。处理此问题的一种方法是改为拟合函数 g(x) = func(x-2011):

    import numpy as np
    from scipy.optimize import curve_fit
    import matplotlib.pyplot as plt
    
    x = np.array([2011, 2012, 2013, 2014, 2015])
    y = np.array([255, 349, 449, 554, 658])
    
    def func(x, a, b, c):
        return a * np.exp(b * x + c)
    
    def g(x, a, b, c): 
        return func(x-2011, a, b, c)
    
    popt, pcov = curve_fit(g, x, y)
    plt.plot(x, g(x, *popt))
    plt.show()
    

    【讨论】:

    • 我还是不明白原因。你能试试这个吗? np.array([1, 2012, 2013, 2014, 2015])x-2000x-2011,结果完全不同。选择减法的原理是什么?
    • 基本上,这个想法是为 x = [0, 1, 2, 3, 4] 拟合函数 g,然后将其向右移动 x = 2011。但是,只有当您的所有 x 值都处于同一数量级时,这才能正常工作。在您的示例中,您还将遇到自 np.exp(1-2000)=np.exp(-1999)=np.exp(1999)**(-1) 以来的溢出。或者,您可以进行 log-fit,即您适合 np.log(x)。
    • 但似乎x-2011 有效。 np.exp(2010) 应该比 np.exp(1999) 大,对吧?
    • 不,它更小。
    • np.exp(2010) 也会溢出。但似乎x-2011 有效。实际上,func 使用的是np.exp(b*2010),而不是直接使用np.exp(2010)
    猜你喜欢
    • 1970-01-01
    • 2013-03-15
    • 2018-06-27
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多