Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 加快Sympy符号表达式的求值_Python_Performance_Numpy_Matrix_Sympy - Fatal编程技术网

Python 加快Sympy符号表达式的求值

Python 加快Sympy符号表达式的求值,python,performance,numpy,matrix,sympy,Python,Performance,Numpy,Matrix,Sympy,我目前正在开发的一个Python程序(Gaussian进程分类)在计算Sympy符号矩阵方面遇到了瓶颈,我不知道我能做些什么来加速它。我已经确保程序的其他部分是正确键入的(就numpy数组而言),因此它们之间的计算是正确矢量化的,等等 我特别研究了Sympy的codegen函数(autowrap,binary_函数),但由于我的ImmutableMatrix对象本身是符号矩阵元素的偏导数,因此有一长串“不可损坏”的东西阻止我使用codegen功能 我研究的另一种可能性是使用Theano——但在一

我目前正在开发的一个Python程序(Gaussian进程分类)在计算Sympy符号矩阵方面遇到了瓶颈,我不知道我能做些什么来加速它。我已经确保程序的其他部分是正确键入的(就numpy数组而言),因此它们之间的计算是正确矢量化的,等等

我特别研究了Sympy的codegen函数(autowrap,binary_函数),但由于我的ImmutableMatrix对象本身是符号矩阵元素的偏导数,因此有一长串“不可损坏”的东西阻止我使用codegen功能

我研究的另一种可能性是使用Theano——但在一些初始基准测试之后,我发现虽然它构建初始偏导数符号矩阵的速度要快得多,但在评估时似乎慢了几个数量级,这与我所寻求的正好相反

下面是我目前正在处理的代码的一个工作、提取片段

import theano
import sympy
from sympy.utilities.autowrap import autowrap
from sympy.utilities.autowrap import binary_function
import numpy as np
import math
from datetime import datetime

# 'Vectorized' cdist that can handle symbols/arbitrary types - preliminary benchmarking put it at ~15 times faster than python list comprehension, but still notably slower (forgot at the moment) than cdist, of course
def sqeucl_dist(x, xs):
    m = np.sum(np.power(
        np.repeat(x[:,None,:], len(xs), axis=1) -
        np.resize(xs, (len(x), xs.shape[0], xs.shape[1])),
        2), axis=2)
    return m


def build_symbolic_derivatives(X):
    # Pre-calculate derivatives of inverted matrix to substitute values in the Squared Exponential NLL gradient
    f_err_sym, n_err_sym = sympy.symbols("f_err, n_err")

    # (1,n) shape 'matrix' (vector) of length scales for each dimension
    l_scale_sym = sympy.MatrixSymbol('l', 1, X.shape[1])

    # K matrix
    print("Building sympy matrix...")
    eucl_dist_m = sqeucl_dist(X/l_scale_sym, X/l_scale_sym)
    m = sympy.Matrix(f_err_sym**2 * math.e**(-0.5 * eucl_dist_m) 
                     + n_err_sym**2 * np.identity(len(X)))


    # Element-wise derivative of K matrix over each of the hyperparameters
    print("Getting partial derivatives over all hyperparameters...")
    pd_t1 = datetime.now()
    dK_df   = m.diff(f_err_sym)
    dK_dls  = [m.diff(l_scale_sym) for l_scale_sym in l_scale_sym]
    dK_dn   = m.diff(n_err_sym)
    print("Took: {}".format(datetime.now() - pd_t1))

    # Lambdify each of the dK/dts to speed up substitutions per optimization iteration
    print("Lambdifying ")
    l_t1 = datetime.now()
    dK_dthetas = [dK_df] + dK_dls + [dK_dn]
    dK_dthetas = sympy.lambdify((f_err_sym, l_scale_sym, n_err_sym), dK_dthetas, 'numpy')
    print("Took: {}".format(datetime.now() - l_t1))
    return dK_dthetas


# Evaluates each dK_dtheta pre-calculated symbolic lambda with current iteration's hyperparameters
def eval_dK_dthetas(dK_dthetas_raw, f_err, l_scales, n_err):
    l_scales = sympy.Matrix(l_scales.reshape(1, len(l_scales)))
    return np.array(dK_dthetas_raw(f_err, l_scales, n_err), dtype=np.float64)


dimensions = 3 
X = np.random.rand(50, dimensions)
dK_dthetas_raw = build_symbolic_derivatives(X)

f_err = np.random.rand()
l_scales = np.random.rand(3)
n_err = np.random.rand()

t1 = datetime.now()
dK_dthetas = eval_dK_dthetas(dK_dthetas_raw, f_err, l_scales, n_err) # ~99.7%
print(datetime.now() - t1) 
在此示例中,计算了5个50x50符号矩阵,即仅12500个元素,耗时7秒。我花了相当长的时间寻找资源来加速这样的操作,并试图将其翻译成Theano(至少直到我发现它的评估在我的案例中变慢为止),但也没有运气


非常感谢您的帮助

您是否研究过使用SymEngine来加速Symphy操作?编辑:可以使用
conda安装-c conda forge python SymEngine安装它
感谢@BjoernDahlgren提供的提示-我将对此进行研究。目前仍在使用它,但使用autowrap将速度提高了约40倍,但autowrap过程反而占用了大量时间(但与不使用autowrap相比仍有很大改进)。代码出现问题的部分原因是生成的函数在Symphy矩阵上运行(使用
sympy.Matrix
创建)而不是numpy矩阵。如果将
sympy.Matrix
替换为
np.Matrix
,是否有帮助?