问题描述
我正在将代码从 Python 2.7 转换为 Python 3.8。
在 Python 2.7 版本中,我不得不使用 scipy 和 numpy 的降级版本以避免 TypeError(见下文)。使用 Python 3.8,这些降级版本的 scipy 和 numpy 不再可用,我收到此错误,无法修复。
1.设置
上一个:MacOS Catalina 10.15.7、Python 2.7.16、numpy 1.9.0、scipy 1.0.1
新:MacOS Catalina 10.15.7、Python 3.8.6、numpy 1.20.3、scipy 1.4.0
2.代码
调用 scipy.integrate.odeint
时发生:
y_trajectory = scipy.integrate.odeint(growth_a_derivs,y_start,t_array,atol=eps,args=myargs)
使用 growth_a_derivs
函数,y_start,t_array
numpy 数组,dtype float64
,eps
浮点数和 myargs
包含字典的长度为 1 的元组。
3.错误
弹出以下回溯:
Traceback (most recent call last):
<long blah blah blah>
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyxcosmo/icosmo_cosmo.py",line 149,in growth_a
result=growth_a_ode(cosmo,a,unnorm=unnorm)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyxcosmo/icosmo_cosmo.py",line 671,in growth_a_ode
y_trajectory = scipy.integrate.odeint(growth_a_derivs,args=myargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/scipy/integrate/odepack.py",line 242,in odeint
output = _odepack.odeint(func,y0,t,args,Dfun,col_deriv,ml,mu,TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'
所以最后一行是在 scipy 的集成 pckg 中,对 odeint 的完整调用是:
output = _odepack.odeint(func,full_output,rtol,atol,tcrit,h0,hmax,hmin,ixpr,mxstep,mxhnil,mxordn,mxords,int(bool(tfirst)))
在这里面,错误在一个编译的 scipy .so
文件中,因此我无法进一步分析这个错误。我只知道对growth_a_derivs 的调用没有问题(它的print() 调用所有工作)。但我不知道这是一个 numpy 还是 scipy 问题,以及如何克服它。
4.分辨率!
多亏了下面的@RFoxtea 回答,我才能够理解这个问题。
我相信这个问题是由 numpy 版本的变化引起的。
growth_a_derivs
的输出是:
np.array([f1,f2])
与:
type(f1) = numpy.float64
type(f2) = numpy.ndarray
f2.shape = (1,)
使用 numpy 1.9,这给出:
np.array([f1,f2]) = [1.234,np.array([1.234])]
np.array([f1,f2]).dtype = numpy.float64
使用 numpy 1.20,这给出:
np.array([f1,f2]).dtype = numpy.object
这不被scipy.integrate.odeint
接受。
但是,请注意 scipy.integrate.solve_ivp
可以。
感谢您的帮助!
解决方法
在运行 scipy.integrate.odeint
的某个时刻,Numpy 被告知将 Python 对象数组转换为浮点数数组,它回答您说它不能这样做。您的描述表明问题必须与 y_start
、t_start
或(也许,我不确定)growth_a_derivs
的返回值有关。请确保这些都具有可以转换为浮点数的适当 dtype
。可能很容易修复。
感谢@RFoxtea 提供了正确的解决方案。
然而,还有一个有趣的选择。您可以使用 scipy.integrate.solve_ivp 而不是 scipy.integrate.odeint
。
Solve_ivp 可以处理带有 dtype fun
的 object
输出。