可以说M是一个非常大的2D numpy.array,它的元素只能是5个不同的整数(-4,-2、0、2、4)。我想计算np.exp(M)。是否比使用上面的函数利用矩阵仅包含很少数量的不同元素的事实来实现这一目的的方法更快?
答案 0 :(得分:4)
在@alkasm提到的答案的基础上,您可以使用查找表(LUT),只要您可以将输入矩阵转换为非负整数矩阵,因为它们被用作索引的整数。 LUT。就您而言:
import numpy as np
M = np.array([[-4, -2, 0],
[-2, 0, 2],
[ 0, 2, 4]])
lut = np.exp(np.arange(-4, 4+1))
E = lut[M + 4]
print(f"M:\n{M}\nlut:\n{lut}\nE:\n{E}")
# M:
# [[-4 -2 0]
# [-2 0 2]
# [ 0 2 4]]
# lut:
# [1.83156389e-02 4.97870684e-02 1.35335283e-01 3.67879441e-01
# 1.00000000e+00 2.71828183e+00 7.38905610e+00 2.00855369e+01
# 5.45981500e+01]
# E:
# [[1.83156389e-02 1.35335283e-01 1.00000000e+00]
# [1.35335283e-01 1.00000000e+00 7.38905610e+00]
# [1.00000000e+00 7.38905610e+00 5.45981500e+01]]
您还可以像这样使用较小的LUT:
lut = np.exp(np.arange(-4, 4+1, 2))
E = lut[M // 2 + 2]
但是在我的示例中,这用4个指数乘以9个整数除法,如果M是n×m矩阵,则要用4个指数乘以n×m个整数除法。如果矩阵大于3×3,则最好使用未使用索引的“长” LUT。
在不同于该索引的情况下,使用“长” LUT来分开索引,但仅计算使用的索引可能是最佳解决方案。上面的示例变为:
import numpy as np
import math
M = np.array([[-4, -2, 0],
[-2, 0, 2],
[ 0, 2, 4]])
values = range(-4, 4+1, 2) # or whatever integers can appear in your matrix
offset = -min(values)
span = max(values) + 1 + offset
lut = np.zeros(span) # or, even faster, np.empty(span)
for x in values:
lut[x + offset] = math.exp(x) # or whatever your mapping is
E = lut[M + offset]
print(f"M:\n{M}\nlut:\n{lut}\nE:\n{E}")
# M:
# [[-4 -2 0]
# [-2 0 2]
# [ 0 2 4]]
# lut:
# [1.83156389e-02 0.00000000e+00 1.35335283e-01 0.00000000e+00
# 1.00000000e+00 0.00000000e+00 7.38905610e+00 0.00000000e+00
# 5.45981500e+01]
# E:
# [[1.83156389e-02 1.35335283e-01 1.00000000e+00]
# [1.35335283e-01 1.00000000e+00 7.38905610e+00]
# [1.00000000e+00 7.38905610e+00 5.45981500e+01]]
顺便说一句,我也使用np.take(lut, M)
而不是lut[M]
进行计时,发现没有区别。这里没有理由使用np.take()
。