SciPy curve_fit with np.log returns 立即 with popt = p0, pcov = inf
SciPy curve_fit with np.log returns immediately with popt = p0, pcov = inf
我正在尝试使用 scipy.optimize.curve_fit
优化对数据集的对数拟合。在实际数据集上尝试之前,我在虚拟数据集上编写代码 运行。
def do_fitting():
x = np.linspace(0, 4, 100)
y = func(x, 1.1, .4, 5)
y2 = y + 0.2 * np.random.normal(size=len(x))
popt, pcov = curve_fit(func, x, y2, p0=np.array([2, 0.5, 1]))
plt.figure()
plt.plot(x, y, 'bo', label="Clean Data")
plt.plot(x, y2, 'ko', label="Fuzzed Data")
plt.plot(x, func(x, *popt), 'r-', label="Fitted Curve")
plt.legend()
plt.show()
当然,do_fitting()
依赖于 func()
,它传递给 curve_fit
。这就是问题所在。当我传递一个包含 np.log
的 func()
时,即我实际想要适应的函数时,curve_fit
声明 p0
(初始条件)是最优解,并且returns 立即具有无限协方差。
如果我 运行 do_fitting()
使用非对数 func()
:
会发生什么
def func(x, a, b, c):
return a * np.exp(x*b) + c
popt = [ 0.90894173 0.44279212 5.19928151]
pcov = [[ 0.02044817 -0.00471525 -0.02601574]
[-0.00471525 0.00109879 0.00592502]
[-0.02601574 0.00592502 0.0339901 ]]
这是我 运行 do_fitting()
和对数 func()
:
时发生的情况
def func(x, a, b, c):
return a * np.log(x*b) + c
popt = [ 2. 0.5 1. ]
pcov = inf
你会注意到 popt
的对数解等于我在上面 do_fitting()
中为 p0
给出的 curve_fit
的值。这是真的,并且 pcov
是无限的,对于我尝试过的每个 p0
值。
我做错了什么?
我能够使用以下代码(几乎没有修改您的原始代码)很好地拟合对数函数:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def func(x, a, b, c):
return a * np.log(x+b) + c
def do_fitting():
x = np.linspace(0, 4, 100)
y = func(x, 1.1, .4, 5)
y2 = y + 0.2 * np.random.normal(size=len(x))
popt, pcov = curve_fit(func, x, y2, p0=np.array([2, 0.5, 1]))
plt.figure()
plt.plot(x, y, 'bo', label="Clean Data")
plt.plot(x, y2, 'ko', label="Fuzzed Data")
plt.plot(x, func(x, *popt), 'r-', label="Fitted Curve")
plt.legend()
plt.show()
do_fitting()
(不幸的是,我无法 post 最终拟合的图片,但它与干净的数据非常吻合)。
您的问题可能不是对数本身,而是 curve_fit 您尝试拟合的特定函数存在一些困难。您能否编辑您的问题以提供您要拟合的精确对数函数的示例?
编辑:您提供的函数没有为 x=0 明确定义,并在执行时产生 RuntimeWarning。 curve_fit 不擅长处理 NaN,在这种情况下将无法适应该功能。如果将 x 更改为
x = np.linspace(1, 4, 100)
curve_fit 执行得很好。
问题很简单 - 因为 x
数组中的第一个值是 0,所以你取 0 的对数,等于 -inf
:
x = np.linspace(0, 4, 100)
p0 = np.array([2, 0.5, 1])
print(func(x, *p0).min())
# -inf
我正在尝试使用 scipy.optimize.curve_fit
优化对数据集的对数拟合。在实际数据集上尝试之前,我在虚拟数据集上编写代码 运行。
def do_fitting():
x = np.linspace(0, 4, 100)
y = func(x, 1.1, .4, 5)
y2 = y + 0.2 * np.random.normal(size=len(x))
popt, pcov = curve_fit(func, x, y2, p0=np.array([2, 0.5, 1]))
plt.figure()
plt.plot(x, y, 'bo', label="Clean Data")
plt.plot(x, y2, 'ko', label="Fuzzed Data")
plt.plot(x, func(x, *popt), 'r-', label="Fitted Curve")
plt.legend()
plt.show()
当然,do_fitting()
依赖于 func()
,它传递给 curve_fit
。这就是问题所在。当我传递一个包含 np.log
的 func()
时,即我实际想要适应的函数时,curve_fit
声明 p0
(初始条件)是最优解,并且returns 立即具有无限协方差。
如果我 运行 do_fitting()
使用非对数 func()
:
def func(x, a, b, c):
return a * np.exp(x*b) + c
popt = [ 0.90894173 0.44279212 5.19928151]
pcov = [[ 0.02044817 -0.00471525 -0.02601574]
[-0.00471525 0.00109879 0.00592502]
[-0.02601574 0.00592502 0.0339901 ]]
这是我 运行 do_fitting()
和对数 func()
:
def func(x, a, b, c):
return a * np.log(x*b) + c
popt = [ 2. 0.5 1. ]
pcov = inf
你会注意到 popt
的对数解等于我在上面 do_fitting()
中为 p0
给出的 curve_fit
的值。这是真的,并且 pcov
是无限的,对于我尝试过的每个 p0
值。
我做错了什么?
我能够使用以下代码(几乎没有修改您的原始代码)很好地拟合对数函数:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def func(x, a, b, c):
return a * np.log(x+b) + c
def do_fitting():
x = np.linspace(0, 4, 100)
y = func(x, 1.1, .4, 5)
y2 = y + 0.2 * np.random.normal(size=len(x))
popt, pcov = curve_fit(func, x, y2, p0=np.array([2, 0.5, 1]))
plt.figure()
plt.plot(x, y, 'bo', label="Clean Data")
plt.plot(x, y2, 'ko', label="Fuzzed Data")
plt.plot(x, func(x, *popt), 'r-', label="Fitted Curve")
plt.legend()
plt.show()
do_fitting()
(不幸的是,我无法 post 最终拟合的图片,但它与干净的数据非常吻合)。
您的问题可能不是对数本身,而是 curve_fit 您尝试拟合的特定函数存在一些困难。您能否编辑您的问题以提供您要拟合的精确对数函数的示例?
编辑:您提供的函数没有为 x=0 明确定义,并在执行时产生 RuntimeWarning。 curve_fit 不擅长处理 NaN,在这种情况下将无法适应该功能。如果将 x 更改为
x = np.linspace(1, 4, 100)
curve_fit 执行得很好。
问题很简单 - 因为 x
数组中的第一个值是 0,所以你取 0 的对数,等于 -inf
:
x = np.linspace(0, 4, 100)
p0 = np.array([2, 0.5, 1])
print(func(x, *p0).min())
# -inf