gpt4 book ai didi

python - 在 Python 中加速矩阵 vector 乘法和求幂,可能通过调用 C/C++

转载 作者:太空狗 更新时间:2023-10-30 00:16:45 26 4
gpt4 key购买 nike

我目前正在从事一个机器学习项目,其中 - 给定一个数据矩阵 Z和一个 vector rho - 我必须计算 logistic loss function 的值和斜率在 rho .计算涉及基本的矩阵 vector 乘法和 log/exp 运算,以及避免数值溢出的技巧(在 previous post 中描述)。

我目前正在使用 NumPy 在 Python 中执行此操作,如下所示(作为引用,此代码在 0.2 秒内运行)。虽然这很好用,但我想加快它的速度,因为我在我的代码中多次调用该函数(它代表了我项目中超过 90% 的计算)。

我正在寻找无需并行化(即只有 1 个 CPU)的任何方法来改进此代码的运行时间。我很高兴在 Python 中使用任何公开可用的包,或调用 C 或 C++(因为我听说这可以将运行时间提高一个数量级)。预处理数据矩阵 Z也可以。一些可以用于更好计算的东西是 vector rho通常是稀疏的(大约 50% 的条目 = 0)并且通常 行比列多(在大多数情况下 n_cols <= 100 )


import time
import numpy as np

np.__config__.show() #make sure BLAS/LAPACK is being used
np.random.seed(seed = 0)

#initialize data matrix X and label vector Y
n_rows, n_cols = 1e6, 100
X = np.random.random(size=(n_rows, n_cols))
Y = np.random.randint(low=0, high=2, size=(n_rows, 1))
Y[Y==0] = -1
Z = X*Y # all operations are carried out on Z

def compute_logistic_loss_value_and_slope(rho, Z):
#compute the value and slope of the logistic loss function in a way that is numerically stable
#loss_value: (1 x 1) scalar = 1/n_rows * sum(log( 1 .+ exp(-Z*rho))
#loss_slope: (n_cols x 1) vector = 1/n_rows * sum(-Z*rho ./ (1+exp(-Z*rho))
#see also: https://stackoverflow.com/questions/20085768/

scores = Z.dot(rho)
pos_idx = scores > 0
exp_scores_pos = np.exp(-scores[pos_idx])
exp_scores_neg = np.exp(scores[~pos_idx])

#compute loss value
loss_value = np.empty_like(scores)
loss_value[pos_idx] = np.log(1.0 + exp_scores_pos)
loss_value[~pos_idx] = -scores[~pos_idx] + np.log(1.0 + exp_scores_neg)
loss_value = loss_value.mean()

#compute loss slope
phi_slope = np.empty_like(scores)
phi_slope[pos_idx] = 1.0 / (1.0 + exp_scores_pos)
phi_slope[~pos_idx] = exp_scores_neg / (1.0 + exp_scores_neg)
loss_slope = Z.T.dot(phi_slope - 1.0) / Z.shape[0]

return loss_value, loss_slope


#initialize a vector of integers where more than half of the entries = 0
rho_test = np.random.randint(low=-10, high=10, size=(n_cols, 1))
set_to_zero = np.random.choice(range(0,n_cols), size =(np.floor(n_cols/2), 1), replace=False)
rho_test[set_to_zero] = 0.0

start_time = time.time()
loss_value, loss_slope = compute_logistic_loss_value_and_slope(rho_test, Z)
print "total runtime = %1.5f seconds" % (time.time() - start_time)

最佳答案

BLAS 系列的库已经针对最佳性能进行了高度调整。因此,链接到某些 C/C++ 代码的任何努力都不可能给您带来任何好处。但是,您可以尝试各种 BLAS 实现,因为它们有很多,包括一些专门针对某些 CPU 进行调整的。

我想到的另一件事是使用像 theano 这样的库(或谷歌的 tensorflow )能够表示整个计算图(上面函数中的所有操作)并对其应用全局优化。然后它可以通过 C++ 从该图形生成 CPU 代码(并通过翻转一个简单的开关也生成 GPU 代码)。它还可以自动为您计算符号导数。我已经将 theano 用于机器学习问题,它是一个非常好的库,尽管它不是最容易学习的库。

(我将其作为答案发布,因为评论太长了)

编辑:

我实际上在 theano 中尝试过这个,但结果实际上在 CPU 上慢了大约 2 倍,请参见下面的原因。无论如何我都会把它贴在这里,也许它是其他人做更好的事情的起点:(这只是部分代码,完整的代码来自原始帖子)

import theano

def make_graph(rho, Z):
scores = theano.tensor.dot(Z, rho)

# this is very inefficient... it calculates everything twice and
# then picks one of them depending on scores being positive or not.
# not sure how to express this in theano in a more efficient way
pos = theano.tensor.log(1 + theano.tensor.exp(-scores))
neg = theano.tensor.log(scores + theano.tensor.exp(scores))
loss_value = theano.tensor.switch(scores > 0, pos, neg)
loss_value = loss_value.mean()

# however computing the derivative is a real joy now:
loss_slope = theano.tensor.grad(loss_value, rho)

return loss_value, loss_slope

sym_rho = theano.tensor.col('rho')
sym_Z = theano.tensor.matrix('Z')
sym_loss_value, sym_loss_slope = make_graph(sym_rho, sym_Z)

compute_logistic_loss_value_and_slope = theano.function(
inputs=[sym_rho, sym_Z],
outputs=[sym_loss_value, sym_loss_slope]
)

# use function compute_logistic_loss_value_and_slope() as in original code

关于python - 在 Python 中加速矩阵 vector 乘法和求幂,可能通过调用 C/C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35158799/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com