我是Python新手,我正在尝试根据Python中的这个等式计算网页排名向量:
其中 Pi(k)是k-Th迭代后的Page-rank向量, G 是Google矩阵, H 是超链接矩阵, a 是悬空节点矢量, alpha = 0.85而 e 是1的矢量。
使用 G 进行计算需要花费大量时间,而使用超链接矩阵 H (稀疏矩阵)应该会花费更少的时间。
这是我的代码:
for i in range(1, k_steps+1):
for j in range(0, len(dictionary_urls)):
for k in range(0, len(dictionary_urls)):
if matrix_H[k][j] != 0:
matrix_pi_k[i][j] += matrix_pi_k[i-1][k] * float(matrix_H[k][j])
alpha_pi_k_a += matrix_pi_k[i-1][k]*float(vector_a[k])
alpha_pi_k_a = alpha_pi_k_a * float(alpha)
alpha_pi_k_a = alpha_pi_k_a + float((1- alpha))
alpha_pi_k_a = alpha_pi_k_a / float(len(dictionary_urls))
matrix_pi_k[i][j] = matrix_pi_k[i][j] * float(alpha)
matrix_pi_k[i][j] = matrix_pi_k[i][j] + float(alpha_pi_k_a)
alpha_pi_k_a = 0
k_steps是所需的迭代次数。
dictionary_links包含所有网址。
执行代码后,matrix_pi_k应该包含所有Pi向量
我计算了所需的所有变量。我使用 H 矩阵运行时间几乎等于使用 G 矩阵的运行时间,但理论上它应该是不同的。
为什么呢?我应该改变什么来减少运行时间?
谢谢。
答案 0 :(得分:5)
问题在于,您使用相同的密集矩阵向量乘法算法将稀疏矩阵乘以密集向量。你不会以这种方式看到任何加速。
假设您有nxn
矩阵A
(密集或稀疏)和n
- 向量x
。要计算y = Ax
,我们可以写:
y = [0]*n
for i in range(n):
for j in range(n):
y[i] += A[i,j]*x[j]
无论矩阵A
是密集的还是稀疏的,这都有效。但是假设A
稀疏。我们仍然遍历 A
的所有列以计算y
的单个条目,即使大多数条目都为零。因此外部循环经历n
次迭代,内部循环也经历n
次迭代。
如果我们知道 A
的哪些条目非零,我们可以做得更好。假设我们有一个行i
的所有非零条目的列表,称之为nonzero[i]
。然后我们可以用这个列表上的迭代替换内部循环:
y = [0]*n
for i in range(n):
for j in nonzero[i]:
y[i] += A[i,j]*x[j]
因此,虽然我们的外循环执行n
迭代,但内循环只执行与非零条目一样多的迭代。
这是加速带稀疏矩阵向量乘法的地方。
numpy
!但是你有另一个问题:你正在尝试用纯Python进行矩阵乘法,这(由于类型检查,非连续数据结构等)是慢。解决方案是使用numpy
,它提供快速算法和数据结构。然后你可以使用scipy
's sparse matrices,因为它们会为你实现快速稀疏矩阵向量乘法。
我们可以通过快速实验展示所有这些。首先,我们将生成10,000 x 10,000
密集矩阵A
:
>>> import numpy as np
>>> n = 10000
>>> A = np.random.sample((n,n))
然后我们通过阈值B
制作稀疏矩阵A
。 B
与A
的大小相同,但只有10%的条目非零:
>>> B = np.where(A < .1, A, 0).astype(float)
现在我们制作一个密集的向量,将A
和B
乘以:
>>> x = np.random.sample(n)
>>> %timeit A.dot(x)
10 loops, best of 3: 46.7 ms per loop
>>> %timeit B.dot(x)
10 loops, best of 3: 43.7 ms per loop
计算Ax
与计算Bx
所花费的时间相同,即使B
是&#34;稀疏&#34;。当然,它并非真正稀疏:它被存储为具有大量零条目的密集矩阵。让我们稀疏:
>>> sparse_B = scipy.sparse.csr_matrix(B)
>>> 100 loops, best of 3: 12 ms per loop
我们的加速!现在,只是为了好玩,如果我们将A
存储为稀疏矩阵,即使它真的很密集呢?
>>> sparse_A = scipy.sparse.csr_matrix(A)
>>> %timeit sparse_A.dot(x)
10 loops, best of 3: 112 ms per loop
哎哟!但这是可以预料的,因为将A
存储为稀疏矩阵会在乘法过程中产生一些开销。
答案 1 :(得分:0)
根据您的公式,矩阵H的计算看起来不比矩阵G快。
<强>解释强>
您可能需要查看introduction to Big O notation。
公式中最右边的部分(在+
之后)只包含一个没有循环的简单计算,其Big O表示法只是O(1)
。这意味着,它不依赖于您考虑的网址数量。
而H和G的计算似乎至少为O(n^2)
(n
是网址数。)
修改强>
在代码的深层嵌套部分中,您有两条指令,其中一条指令取决于matrix_H[k][j]
是否为0。但是,如果它是0,如果H是稀疏矩阵,则大多数情况下将是这种情况,但是将执行第二条指令。另外,无论如何都要进入循环。
这仍然给你一个O(n^2)
的复杂性,因此解析H并不比解析G快得多。