我正在尝试使用scipy.integrate.odeint
模块解决相对较大的 ODE 系统。我已经实现了代码,我可以正确解方程。但是这个过程非常缓慢。我分析了代码,我意识到几乎大部分计算时间都花在计算或生成 ODE 系统本身上,sigmoid 函数也很昂贵,但我想我必须接受它。这是我正在使用的一段代码:
def __sigmoid(self, u):
# return .5 * ( u / np.sqrt(u**2 + 1) + 1)
return 0.5 + np.arctan(u) / np.pi
def __connectionistModel(self, g, t):
"""
Returning the ODE system
"""
g_ia_s = np.zeros(self.nGenes * self.nCells)
for i in xrange(0, self.nCells):
for a in xrange(0, self.nGenes):
g_ia = self.Params["R"][a] *\
self.__sigmoid( sum([ self.Params["W"][b + a*self.nGenes]*g[self.nGenes*i + b] for b in xrange(0, self.nGenes) ]) +\
self.Params["Wm"][a]*self.mData[i] +\
self.Params["h"][a] ) -\
self.Params["l"][a] * g[self.nGenes*i + a]
# Uncomment this part for including the diffusion
if i == 0:
g_ia += self.Params["D"][a] * ( - 2*g[self.nGenes*i + a] + g[self.nGenes*(i+1) + a] )
elif i == self.nCells-1:
g_ia += self.Params["D"][a] * ( g[self.nGenes*(i-1) + a] - 2*g[self.nGenes*i + a] )
else:
g_ia += self.Params["D"][a] * ( g[self.nGenes*(i-1) + a] - 2*g[self.nGenes*i + a] + g[self.nGenes*(i+1) + a] )
g_ia_s[self.nGenes*i + a] = g_ia
return g_ia_s
def solve(self, inp):
g0 = np.zeros(self.nGenes * self.nCells)
t = np.arange(self.t0, self.t1, self.dt)
self.integratedExpression = odeint(self.__connectionistModel, g0, t, full_output=0)
return self.integratedExpression
正如您在每次迭代中看到的那样,我应该生成 nCells*nGenes (100*3=300) 方程并将其传递给odeint
. 虽然我不确定,但我想生成方程与求解它们相比非常昂贵。在我的实验中,解决整个系统需要 7 秒,其中包括 1 秒odeint
和 6秒__ConnectionistModel
。
我想知道是否有办法可以改善这一点?我尝试使用 SymPy 定义一个符号 ODE 系统并将符号方程传递给 ,odeint
但它不能正常工作,因为你不能真正定义一个符号数组,以后你可以像数组一样访问它。
在最坏的情况下,我必须处理它或使用 Cython 来加快求解过程,但我想确保我做对了,没有办法改进它。
提前感谢您的帮助。
[更新]:分析结果,
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 7.915 7.915 grnTest.py:1(<module>)
1 0.000 0.000 7.554 7.554 grn.py:83(solve)
1 0.000 0.000 7.554 7.554 odepack.py:18(odeint)
1 0.027 0.027 7.554 7.554 {scipy.integrate._odepack.odeint}
1597 5.506 0.003 7.527 0.005 grn.py:55(__connectionistModel)
479100 1.434 0.000 1.434 0.000 grn.py:48(__sigmoid)
479102 0.585 0.000 0.585 0.000 {sum}
1 0.001 0.001 0.358 0.358 grn.py:4(<module>)
2 0.001 0.001 0.207 0.104 __init__.py:10(<module>)
27 0.014 0.001 0.185 0.007 __init__.py:1(<module>)
7 0.006 0.001 0.106 0.015 __init__.py:2(<module>)
[更新 2]:我公开了代码:pyStGRN