科学界有句名言:到最后,一切都归结为矩阵乘法。无论你是在物理学或工程学中求解偏微分方程,还是在使用经典模型或深度神经网络进行机器学习,最终在数值上,都是在某种顺序中重复地进行矩阵和向量的乘法。这些矩阵通常可能非常大,比如1000,000 x 1000, 000。在这种情况下,如果矩阵没有特定的结构,那么就真的需要在内存中存储大量的数据值,并且算术计算也非常耗时。这被称为密集矩阵(dense matrix)。
然而,在许多科学应用中,所涉及的矩阵确实具有某种结构。通常情况下,矩阵的大部分值都是零。如果是这种情况,这就是稀疏矩阵(Sparse matrices)。对于稀疏矩阵,所需的内存会大幅减少。例如,如果1000,000 x 1000,000矩阵是对角矩阵,你只需存储10^6个值,而不是10^12个值。而且如果你将其与一个10^6维度的向量相乘,只需进行10^6次乘法,而不是10^12次乘法和加法。你看,区别是巨大的!即使矩阵不是对角矩阵,只要大部分值为零,内存和速度的优势也是巨大的,因为你只需保存相对较少的非零值,并且与向量的乘法只需考虑那些非零值。
如何使用稀疏矩阵
Python的SciPy包中有一个优秀的子包专门用于稀疏矩阵的实现。根据稀疏矩阵的结构以及你想用稀疏矩阵做什么,包中有不同的表示形式,这些形式针对特定任务进行了优化。但不用担心选择正确的类型!只要你使用任何稀疏矩阵类,通常会获得99%的速度和内存优势。
首先,考虑一个大的密集矩阵。我们用介于-0.5和0.5之间的随机值填充它:
import numpy as npn = 10000
A = np.random.random((n, n)) - 0.5
我只使用了10000行和列,因为我不想等太久。然后让我们使用numpy的matmul函数计算⋅的乘积。
np.matmul(A, A)
在我的电脑上,这耗时7.07秒。你也可以使用numpy的dot函数,但我不确定它是否像matmul一样优化。
现在我们用相同的方法使用一个对角矩阵,并将其存储为普通矩阵:
diag_values = np.random.random(n)A_dense = np.diag(diag_values)AA_dense = np.matmul(A_dense, A_dense)
这在我的电脑上耗时7.00秒,几乎相同的时间,尽管我们知道大部分的乘法必然是零。现在让我们用稀疏矩阵做同样的操作。由于这里的矩阵是对角矩阵,我们可以使用scipy.sparse.diags:
import scipy.sparseA_sparse = scipy.sparse.diags(diag_values)
如果你print A_sparse,它会显示:
<10000x10000 sparse matrix of type '<class 'numpy.float64'>' with 10000 stored elements (1 diagonals) in DIAgonal format>
数学联邦政治世界观提示您:看后求收藏(同人小说网http://tongren.me),接着再看更方便。