所以,我有这个代码
from __future__ import division, print_function
import sympy as sp
import numpy as np
from sympy.utilities.lambdify import *
u = np.random.uniform(4, 6, 500)
w, k = sp.symbols('w k')
f = sp.log((k - w) * sp.exp((k - w)**5))
l = sum(f.subs(dict(k=k)) for k in u)
现在我想将l
用作w
的函数。所以我知道一些选择
z_lambdify = lambdify(w, l)
z_subs = lambda x: l.subs(w, x)
第一个函数给出错误
>>> z_lambdify(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <lambda>
OverflowError: math range error
>>> z_lambdify(4)
40.862695278600114
虽然第二个给出答案
>>> z_subs(1)
11469.9130597554
>>> z_subs(4)
40.8626952786003
我会用它,但它很慢。有什么方法可以解决这个问题(修复lamdify错误或使用l
作为一个不那么慢的函数的方法)?
版本:Python 2.7.6,NumPy 1.8.1,SymPy 0.7.4.1
答案 0 :(得分:1)
问题在于:
z_lambdify = lambdify(w, l)
告诉新函数使用内置的math
函数执行计算,您可以使用cProfile.run('z_lambdify(1)')
检查运行情况;在执行z_subs(1)
调用sympy
函数时。要获得相同的行为,您应该告诉lambdify()
使用相同的模块:
z_lambdify = lambdify(w, l, "sympy")
您应该在其定义中简化您的功能,然后使用NumPy
更有效地执行计算。使用一些简单的代数,您的函数可以以“非溢出”格式重写为:
f = lambda k, w: np.log(k - w) + (k - w)**5
这样可以实现您想要的答案:
f(k=u, w=1).sum()
当您执行f(k=u, w=1)
时,您会得到一个具有相同形状u
的数组,其中每个值表示使用u
的每个值计算的函数的结果。您可以使用此功能同时评估f()
k
和w
的不同值,即将w
作为具有相同形状u
的另一个数组传递使用恒定值。