我想以一种在内存使用和计算时间方面有效的方式计算矩阵乘积的某些特定值 . 问题是中间矩阵具有两个非常大的尺寸并且可能不可存储 .
带示例值的尺寸:
N = 7 # very large
K = 3
M = 10 # very large
L = 8 # very very large
'a'是一个形状矩阵(N,K)
'b'是形状矩阵(K,N)
a = np.arange(N*K).reshape(N,K)
b = np.arange(K*M).reshape(K,M)
rows是一个索引数组,其值在范围(N)和长度L之内
cols是一系列索引,其值在范围(M)和长度L之内
rows = [0,0,1,2,3,3,4,6]
cols = [0,9,5,8,2,8,3,6]
我需要以下内容,但由于其大小,无法计算形状(MxN)作为中间结果的矩阵 (a @ b)
:
values = (a @ b)[rows, cols]
另一种实现可能涉及切片[rows]和b [:,cols],创建具有形状(L,K)和(K,L)的矩阵,但这些矩阵也太大了 . Numpy在进行花式切片时复制值
values = np.einsum("ij,ji->i", a[rows], b[:,cols])
提前致谢
2 回答
一种可能性是直接计算结果 . 也许还有一些其他技巧可以使用BLAS例程而没有庞大的临时数组,但这也有效 .
Example
计算步骤,包括预制(b矩阵的排序,转置)应在不到60秒的时间内运行 .
一种可能性就是简单地对你的方法进行分块 . 将
rows
和cols
分成大小为20的位可以解决笔记本电脑上约2分钟内的大(10 ^ 7)问题 . 人们可以通过调整块大小来改善这一点 .但是我们可以做得更好:我们可以按行或列分组(我选择了cols),然后将各个cols与所有成对的行相乘 . 我们可以使用稀疏csc / csr矩阵为我们进行所有排序/重排/重建索引 . 对同一数据的这种方法在~30秒内完成 .
样品运行: