问题
I am trying to fit a kinetic model for population growth and decay of four variables A,B,C,D in a chemical system. I am trying to solve the following set of equations, which I have attached in matrix form:
Matrix form of equations
where t is a time step and k1,k2,k3 are constants in an exponential function. I want to fit curves based on these equations to solve for k1,k2, and k3 given my populations of A,B,C,D.
For this I am using optimize.curve_fit, t is the time step in a (1000,) array, X is a (4,1000) matrix and where u and w are the two matrices:
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')
When I run this piece of code, I get the following output:
ValueError: object too deep for desired array
error: Result from function call is not a proper array of floats.
I have seen in a similar post that the shapes of the arrays in important, but as far as I can tell these are correct.
Could anyone suggest where the problem may be in this code and how I can best go about solving for k1,k2,k3 using the curve fit function?
Thanks
回答1:
As I mentioned in my comment, you don't need to pass X
onto func
. @WarrenWeckesser briefly explains why. So here is how func
should be:
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()
The output at the end is flattened because otherwise it would give an error with curve_fit
. Now we test it:
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)
The optimised values are pretty close to the original ones and the fit seems good
来源:https://stackoverflow.com/questions/51522103/valueerror-object-too-deep-for-desired-array-in-optimize-curve-fit