【发布时间】:2013-12-26 00:14:50
【问题描述】:
我有两个要相乘的 NxN 矩阵:A 和 B。在 NumPy 中,我使用了:
import numpy as np
C = np.dot(A, B)
但是,我碰巧知道,对于矩阵 B,只有第 n 行和第 n 列不为零(这直接来自生成矩阵的分析公式,毫无疑问总是如此)。
希望利用这一事实并减少产生 C 所需的乘法次数,我将上面的内容替换为:
import numpy as np
for row in range(0, N):
for col in range(0, N):
if col != n:
C[row, col] = A[row, n]*B[n, col] #Just one scalar multiplication
else:
C[row, col] = np.dot(A[row], B[:, n])
从分析上讲,这应该会降低总复杂度如下:在一般情况下(不使用任何花哨的技巧,只是基本的矩阵乘法)C = AB,其中 A 和 B 都是 NxN,应该是 O(N^3) .即所有N行必须乘以所有N列,而这些点积中的每一个都包含N次乘法 => O(NNN) = O(N^3).#
像我上面所做的那样利用 B 的结构,但是应该按照 O(N^2 + N^2) = O(2N^2) = O(N^2)。也就是说,所有 N 行必须与所有 N 列相乘,然而,对于所有这些(除了涉及 'B[:, n]' 的那些),只需要一次标量乘法:只有 'B[:, m]' 的一个元素对于 m != n 是非零的。当 n == m 时,将发生 N 次(A 的每一行必须与 B 的 n 列相乘),必须发生 N 次标量乘法。#
但是,第一个代码块(使用 np.dot(A, B))要快得多。我知道(通过诸如Why is matrix multiplication faster with numpy than with ctypes in Python? 之类的信息)np.dot 的低级实现细节可能会为此负责。所以我的问题是:如何利用矩阵 B 的结构来提高乘法效率而不牺牲 NumPy 的实现效率,在 c 中构建自己的低级矩阵乘法?
这种方法是对许多变量进行数值优化的一部分,因此,O(N^3) 是难以处理的,而 O(N^2) 可能会完成这项工作。
感谢您的帮助。另外,我是新手,所以请原谅任何新手错误。
【问题讨论】:
-
您是否考虑过
cython或其他将乘法函数直接编译成机器代码的方法?在过去的好日子里,我可能会为此使用f2py,但我知道不是每个人都想用 fortran 编写代码 ;-) -
我也不完全确定这一点,但 scipy 可能已经使用稀疏矩阵解决了一些类似的问题。任何 scipy 大师都知道吗?
-
看看
scipy.sparse,你可以把B做成一个稀疏矩阵B = scipy.sparse.csr_matrix(B),然后只做A * B,如果你把dense乘以sparse,结果就是dense。我的直觉是,由于我没有测试过,所以效率更高。 -
感谢大家的快速回复! Akavall,我将查找'scipy.sparse' 首先我必须确认 A*B 其中 B 的类型为 scipy.sparse.csr_matrix 给出与 np.dot(A, B) 相同的结果,如果它更快,那么伟大的!如果平等或效率不成功,我仍然对其他方法持开放态度。
标签: python performance numpy matrix matrix-multiplication