我希望在Python中对三个(或四个)大型2D数组进行逐元素外积运算(值为float32,舍入到2位小数)。它们都有相同的行数“n”,但不同的列数“i”、“j”、“k”。
结果数组应该具有形状(n,i*j*k)。然后,我想对结果的每一列求和,以得到形状为(i*j*k)的1D数组。
np.shape(a) = (75466, 10)
np.shape(b) = (75466, 28)
np.shape(c) = (75466, 66)
np.shape(intermediate_result) = (75466, 18480)
np.shape(result) = (18480)
感谢ruankesi和divakar,我得到了一段可行的代码:关于numpy元素级外积。
# Multiply first two matrices
first_multi = a[...,None] * b[:,None]
# could use np.einsum('ij,ik->ijk',a,b), which is slightly faster
ab_fills = first_multi.reshape(a.shape[0], a.shape[1]*b.shape[1])
# Multiply the result with the third matrix
second_multi = ab_fills[..., None] * c[:,None]
abc_fills = second_multi.reshape(ab_fills.shape[0], ab_fills.shape[1] * c.shape[1])
# Get the result: sum columns and get a 1D array of length 10*28*66 = 18 480
result = np.sum(abc_fills, axis = 0)
问题1: 性能
每次操作大约需要3秒,但我必须重复多次这个操作,而有些矩阵甚至更大(行数)。虽然可以接受,但让它变快会更好。
问题2: 我的矩阵是稀疏的
确实,例如,“a”包含70%的0。我尝试使用scipy csc_matrix,但确实无法得到一个可用的版本。(为了在此处获取逐元素外积,我通过转换为3D矩阵进行,但scipy sparse_matrix不支持)
问题3: 内存使用
如果我尝试处理第4个矩阵,我会遇到内存问题。
我想象中将这段代码转换为sparse_matrix会节省很多内存,并通过忽略众多0值使计算更快。
这是真的吗?如果是,有人能帮帮我吗?
当然,如果你有更好的实现建议,我也非常感兴趣。我不需要任何中间结果,只需要最终的1D结果。
我被卡在这段代码上已经几周了,我要疯了!
谢谢!
Divakar答案后的编辑
方法#1:
非常好的一行代码但比原始方法慢得出乎意料(?)。
在我的测试数据集上,方法#1每次循环需要4.98秒±3.06毫秒(使用optimize = True没有加速)
原始分解方法需要3.01秒±16.5毫秒每次循环
方法#2:
绝对棒,谢谢!真是一个令人印象深刻的加速!
每次循环需要62.6毫秒±233微秒
关于numexpr,我尽可能避免对外部模块的要求,并且不打算使用多核/线程。这是一个“令人尴尬”的可并行任务,有成千上万的对象需要分析,在生产过程中我将把列表分散到可用的CPU上。我会尝试使用它来进行内存优化。
作为使用限制为1个线程,执行1个乘法的numexpr的简短尝试中,我在没有numexpr的情况下获得了40ms的运行时间,而使用numexpr则为52ms。
再次感谢!!