【问题标题】:Linear curve_fit always yields a slope and y-intercept of 1线性 curve_fit 总是产生 1 的斜率和 y 截距
【发布时间】:2017-09-13 15:17:30
【问题描述】:

我正在尝试对一些数据进行线性拟合,但我无法在 Python 中使用 curve_fit 来给我任何东西,但斜率和 y 截距为 1。这是我的代码示例:

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

def func(x, a, b):
    return a*x + b

# This is merely a sample of some of my actual data
x = [290., 300., 310.]
y = [1.87e+21, 2.07e+21, 2.29e+21]

popt, pcov = curve_fit(func, x, y)

print popt

我也尝试过给 curve_fit 一个“猜测”,但是当我这样做时,它会给我一个溢出错误,我猜这是因为数字太大。

【问题讨论】:

  • 当我将你的 y 值除以 1e21 时,我得到的拟合值不是 1。也许你可以拟合更小的 y 值,然后缩放结果
  • curve_fit() 的默认初始参数均为 1.0,因此当无法进行拟合时,只有初始参数估计可用 - 在本例中为所有 1.0。
  • ams,即使我将 1e21 分开,我的斜率仍然为 1。我可以看看你的代码吗?
  • @ams,即使我将 1e21 分开,我的斜率仍然为 1。我可以看看你的代码吗?
  • 一定要用curve_fit吗?

标签: python matplotlib curve-fitting


【解决方案1】:

不使用curve_fit 的另一种方法是使用numpy 的polyfit

import matplotlib.pyplot as plt
import numpy as np

# This is merely a sample of some of my actual data
x = [290., 300., 310.]
y = [1.87e+21, 2.07e+21, 2.29e+21]

xp = np.linspace(290, 310, 100)

z = np.polyfit(x, y, 1)
p = np.poly1d(z)
print (z)

fig, ax = plt.subplots()
ax.plot(x, y, '.')
ax.plot(xp, p(xp), '-')

plt.show()

这会将系数打印为[2.10000000e+19 -4.22333333e+21] 并生成以下图表:

【讨论】:

    【解决方案2】:

    使用以下命令返回确认正确的结果:

    x = [290., 300., 310.]
    y = [300., 301., 302.]
    

    我的猜测是 ≅ 10²¹ 的幅度太大,函数无法正常工作。

    你可以尝试做的是取两边的对数:

    def func(x, a, b):
        # might need to check if ≤ 0.0
        return math.log(a*x + b)
    
    # ... code omitted
    
    y = [48.9802253837, 49.0818355602, 49.1828387704]
    

    然后撤消转换。

    对于简单的线性近似,还有一个简单的确定性方法。

    【讨论】:

      【解决方案3】:

      通过使用 scipy 盆地跳跃而不是曲线拟合进行大量迭代,我得到了一些作为 Excel 线性拟合的东西。运行迭代需要一点时间,并且还需要一个误差函数,但它是在没有缩放原始数据的情况下完成的。 Basinhopping docs.

      import numpy as np
      import matplotlib.pyplot as plt
      from scipy.optimize import basinhopping
      
      def func( x0, x_data, y_data ):
      
          error = 0
          for x_val, y_val in zip(x_data, y_data): 
              error += (y_val - (x0[0]*x_val + x0[1]))**2
      
          return error
      
      x_data = [290., 300., 310.]
      y_data = [1.87e+21, 2.07e+21, 2.29e+21]
      a = 1
      b = 1
      x0 = [a, b]
      
      minimizer_kwargs = { 'method': 'TNC', 'args': (x_data, y_data) }
      
      res = basinhopping(func, x0, niter=1000000, minimizer_kwargs=minimizer_kwargs)
      
      print res
      

      这给出了 x: array([ 7.72723434e+18, -2.38554994e+20]) 但如果你再试一次,你会发现这有非唯一结果的问题,尽管它会给出类似的大概值。

      这是与 Excel 解决方案的拟合比较。

      【讨论】:

        猜你喜欢
        • 2014-02-15
        • 2018-02-28
        • 1970-01-01
        • 2015-09-09
        • 2018-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-23
        相关资源
        最近更新 更多