ValueError: object too deep for desired array in optimize.curve_fit
ValueError: object too deep for desired array in optimize.curve_fit
我正在尝试为化学系统中四个变量 A、B、C、D 的人口增长和衰减拟合动力学模型。我正在尝试求解以下我以矩阵形式附上的方程组:
Matrix form of equations
其中 t 是时间步长,k1、k2、k3 是指数函数中的常数。我想根据这些方程来拟合曲线,以根据我的 A、B、C、D 人口来求解 k1、k2 和 k3。
为此,我使用 optimize.curve_fit,t 是 (1000,) 数组中的时间步长,X 是 (4,1000) 矩阵,其中 u 和 w 是两个矩阵:
from scipy import optimize
def func(t,X,k1,k2,k3):
u = np.array([[1,0,0],
[-k1/(k1+k2-k3),k1/(k1+k2-k3),0],
[(k1*k3)/((k1+k2-k3)*(k1+k2)),-k1/(k1+k2k3),k1/(k1+k2)],
[-k2/(k1+k2),0,k2/(k2+k1)]],dtype=float)
w = np.array([[np.exp(-t*(k1+k2))],
[np.exp(-t*k3)],
[1]])
return X*np.dot(u,w)
X = np.array([A,B,C,D]) # A,B,C,D are (1000,) arrays
# X.shape = (4, 1000)
# t.shape = (1000,)
optimize.curve_fit(func,t,X,method='lm')
当我运行这段代码时,我得到以下输出:
ValueError: object too deep for desired array
error: Result from function call is not a proper array of floats.
我在 similar post 中看到数组的形状很重要,但据我所知这些是正确的。
任何人都可以建议此代码中的问题所在以及我如何使用曲线拟合函数最好地解决 k1、k2、k3 问题吗?
谢谢
正如我在评论中提到的,您不需要将 X
传递给 func
。 @WarrenWeckesser 简要解释了原因。 func
应该是这样的:
def func(t,k1,k2,k3):
u = np.array([[1,0,0],
[-k1/(k1+k2-k3),k1/(k1+k2-k3),0],
[(k1*k3)/((k1+k2-k3)*(k1+k2)),-k1/(k1+k2*k3),k1/(k1+k2)],
[-k2/(k1+k2),0,k2/(k2+k1)]],dtype=float)
w = np.array([np.exp(-t*(k1+k2)),
np.exp(-t*k3),
np.ones_like(t)]) # must match shapes with above
return np.dot(u,w).flatten()
最后的输出是扁平化的,否则会给出 curve_fit
的错误。现在我们测试一下:
from scipy.optimize import curve_fit
t = np.arange(1000)*0.01
data = func(t, *[0.5, 2, 1])
data +=np.random.normal(size=data.shape)*0.01 # add some noise
po, pcov = curve_fit(func,t, data.flatten(), method='lm') #data must also be flattened
print(po)
#[ 0.50036411 2.00393807 0.99694513]
plt.plot(t, data.reshape(4,-1).T, t, func(t, *po).reshape(4,-1).T)
优化后的值与原始值非常接近并且拟合得很好
我正在尝试为化学系统中四个变量 A、B、C、D 的人口增长和衰减拟合动力学模型。我正在尝试求解以下我以矩阵形式附上的方程组:
Matrix form of equations
其中 t 是时间步长,k1、k2、k3 是指数函数中的常数。我想根据这些方程来拟合曲线,以根据我的 A、B、C、D 人口来求解 k1、k2 和 k3。
为此,我使用 optimize.curve_fit,t 是 (1000,) 数组中的时间步长,X 是 (4,1000) 矩阵,其中 u 和 w 是两个矩阵:
from scipy import optimize
def func(t,X,k1,k2,k3):
u = np.array([[1,0,0],
[-k1/(k1+k2-k3),k1/(k1+k2-k3),0],
[(k1*k3)/((k1+k2-k3)*(k1+k2)),-k1/(k1+k2k3),k1/(k1+k2)],
[-k2/(k1+k2),0,k2/(k2+k1)]],dtype=float)
w = np.array([[np.exp(-t*(k1+k2))],
[np.exp(-t*k3)],
[1]])
return X*np.dot(u,w)
X = np.array([A,B,C,D]) # A,B,C,D are (1000,) arrays
# X.shape = (4, 1000)
# t.shape = (1000,)
optimize.curve_fit(func,t,X,method='lm')
当我运行这段代码时,我得到以下输出:
ValueError: object too deep for desired array
error: Result from function call is not a proper array of floats.
我在 similar post 中看到数组的形状很重要,但据我所知这些是正确的。
任何人都可以建议此代码中的问题所在以及我如何使用曲线拟合函数最好地解决 k1、k2、k3 问题吗?
谢谢
正如我在评论中提到的,您不需要将 X
传递给 func
。 @WarrenWeckesser 简要解释了原因。 func
应该是这样的:
def func(t,k1,k2,k3):
u = np.array([[1,0,0],
[-k1/(k1+k2-k3),k1/(k1+k2-k3),0],
[(k1*k3)/((k1+k2-k3)*(k1+k2)),-k1/(k1+k2*k3),k1/(k1+k2)],
[-k2/(k1+k2),0,k2/(k2+k1)]],dtype=float)
w = np.array([np.exp(-t*(k1+k2)),
np.exp(-t*k3),
np.ones_like(t)]) # must match shapes with above
return np.dot(u,w).flatten()
最后的输出是扁平化的,否则会给出 curve_fit
的错误。现在我们测试一下:
from scipy.optimize import curve_fit
t = np.arange(1000)*0.01
data = func(t, *[0.5, 2, 1])
data +=np.random.normal(size=data.shape)*0.01 # add some noise
po, pcov = curve_fit(func,t, data.flatten(), method='lm') #data must also be flattened
print(po)
#[ 0.50036411 2.00393807 0.99694513]
plt.plot(t, data.reshape(4,-1).T, t, func(t, *po).reshape(4,-1).T)
优化后的值与原始值非常接近并且拟合得很好