Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的页面排名_Python_Algorithm_Pagerank - Fatal编程技术网

Python中的页面排名

Python中的页面排名,python,algorithm,pagerank,Python,Algorithm,Pagerank,我是Python新手,我尝试根据Python中的以下等式计算页面排名向量: 其中,Pi(k)是第k次迭代后的页面排名向量,G是谷歌矩阵,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

我是Python新手,我尝试根据Python中的以下等式计算页面排名向量:

其中,Pi(k)是第k次迭代后的页面排名向量,G是谷歌矩阵,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是所需的迭代次数

字典链接包含所有URL

代码执行后,矩阵πk应具有所有π向量

我计算了所有需要的变量。我使用H矩阵得到的运行时间几乎等于使用G矩阵得到的运行时间,尽管理论上应该有所不同

为什么??我应该改变什么来减少运行时间


谢谢。

根据你的公式,矩阵H的计算看起来并不比矩阵G快

说明:

你可能想看一看

公式中最右边的部分(在
+
之后)只包含一个没有循环的简单计算,它的大O表示法就是
O(1)
。这意味着,它不取决于您考虑的URL数量

而H和G的计算似乎至少是
O(n^2)
n
是URL的数量)

编辑:

在代码的深层嵌套部分,有两条指令,其中一条指令取决于
matrix_H[k][j]
是否为0。尽管如此,如果它是0(如果H是稀疏矩阵,则大多数情况下都是这样),则将执行第二条指令。另外,你还是进入了循环


这仍然会使您的复杂性达到O(n^2),因此解析H并不比解析G快(很多)。

问题在于,您使用相同的旧密集矩阵向量乘法算法将稀疏矩阵乘以密集向量。这样你就看不到任何加速了

假设有一个
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进行矩阵乘法,这(由于类型检查、非连续数据结构等)速度很慢。解决方案是使用,它提供了快速算法和数据结构。然后您可以使用,因为它们为您实现了快速稀疏矩阵向量乘法

实验 我们可以通过一个快速的实验来展示这一切。首先,我们将生成一个
10000 x 10000
密集矩阵
a

>>> import numpy as np
>>> n = 10000
>>> A = np.random.sample((n,n))
然后我们将通过阈值化
a
来生成稀疏矩阵
B
B
A
的大小相同,但只有10%的条目为非零:

>>> B = np.where(A < .1, A, 0).astype(float)
计算
Ax
所需的时间与计算
Bx
所需的时间相同,即使
B
是“稀疏的”。当然,它不是真正稀疏的:它存储为一个密集的矩阵,有很多零条目。让我们将其稀疏化:

>>> 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
存储为稀疏矩阵将在乘法过程中产生一些开销。

根据我所读的内容,在稀疏矩阵上进行向量乘法所需的时间比在密集矩阵上进行乘法所需的时间要少得多。G是稠密矩阵,而H是稀疏矩阵。这应该会影响运行时间。@RomanYanovitski刚刚编辑了我的答案,以考虑您的评论,这正是我要问的:)。显然,我的代码效率不高,而且花费的时间比它应该花费的时间多得多。我不知道如何改进它,以减少它的运行时间。@RomanYanovitski好的,我是在回答你问题的“为什么”部分。现在关于“如何”,这是另一个故事:)让我看看我是否能得到一些有价值的东西。好吧,但问题是,即使我知道哪些条目是零,我也应该进行计算的第二部分,这会影响每次迭代。第二部分是指Pi向量与向量a的乘积,并将结果加到Pi向量上。因此,我不能跳过迭代,即使在使用zero@RomanYanovitski这很好,因为您不需要同时计算
pi*H
pi*a
。无论如何,你真的应该使用
numpy
>>> sparse_A = scipy.sparse.csr_matrix(A)
>>> %timeit sparse_A.dot(x)
10 loops, best of 3: 112 ms per loop