线性 curve_fit 总是产生 1 的斜率和 y 轴截距
Linear curve_fit always yields a slope and y-intercept of 1
我正在尝试对某些数据进行线性拟合,但我无法在 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 一个 "guess," 但是当我这样做时它给我一个溢出错误,我猜这是因为数字太大了。
通过使用 scipy basinhopping 而不是 curve_fit 进行大量迭代,我在 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 解的拟合比较。
确认正确的结果返回使用:
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]
然后撤销转换。
同样对于简单的线性近似,有一个简单的确定性方法。
不使用 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]
并生成以下图表:
我正在尝试对某些数据进行线性拟合,但我无法在 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 一个 "guess," 但是当我这样做时它给我一个溢出错误,我猜这是因为数字太大了。
通过使用 scipy basinhopping 而不是 curve_fit 进行大量迭代,我在 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 解的拟合比较。
确认正确的结果返回使用:
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]
然后撤销转换。
同样对于简单的线性近似,有一个简单的确定性方法。
不使用 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]
并生成以下图表: