简述

PageRank有点被神化了,其实公式很简单。


文章目录

  • 简述
  • 算法
  • 模型定义
  • Flow版本
  • Google Formula
  • 实现


算法

主要是分为两种:

  • The ‘Flow’ formula
  • The Google formula

模型定义

很多个网页,直接存在链路关系,设为G,N*N的矩阵

这里先只考虑有向无权无环图,即边有方向,且权重都一样,且没有自己到自己的边(环)。

  • N为节点数或者是网页数
  • G[i][j] = 1表示,i->j有条边

Flow版本

python如何使用PAGE_PageRank

一个很好是数学写法就是:

python如何使用PAGE_python如何使用PAGE_02

  • 如果有i->j, M[j][i] = 1/dj,否者为0

算法流程:

  • 也就是,随机初始化每个点的分数
  • 然后,迭代:
  • 每个点的分数,由所有 指向他的节点的分数 除以 这个节点的出度数 求和所替代
  • Flow版本会出现两个重要的问题;
  • Dead End:例如只有两个点,然后边为A->B,B就是一个Dead END。即到这时候的分数就出不去了。
  • Spider Traps:循环指向,例如A->B->A。那么这个分数就会这之间打转

Google Formula

刚刚说的两个问题在Google Formula上得到很好的改进:

  • 提出了一个叫做Teleport的概念,也称之为意念转移。

很简单,就是说,每个节点有一定的概率发生随机跳转到任意一个点的情况。再结合MapReduce的概念,Google就这样发家了emmmm

python如何使用PAGE_GoogleFormula_03

直接的数学表达:

python如何使用PAGE_数据挖掘_04

Google简化后的数学表达:

python如何使用PAGE_python如何使用PAGE_05

  • 如果有i->j, M[j][i] = 1/dj,否者为0

存在的问题:

  • 虽然直接的数学表达会更简洁,但是多出来的A一定会是稠密矩阵使得空间消耗为O(N^2)了,这样的在网站达到数亿的情况下,这个东西就不太现实了。
  • 而Google简化的版本中就只需要记录同样稀疏的M即可,1/N是一个数,只需要让r这个向量的每个元素都加上即可(简单的数学变形,在工业上的产生的价值就很大的不一样了。真的佩服研究数学的哥们)

实现

实现同样做两个不同的版本的:

但有些共同的模型:

导入包:

import numpy as np
import random

创造数据:

def create_data(N, alpha=0.5): # random > alpha, then here is a edge.
    G = np.zeros((N, N))
    for i in range(N):
        for j in range(N):
            if i == j:
                continue
            if random.random() < alpha:
                G[i][j] = 1
    return G
G = create_data(10)

GtoM:

def GtoM(G, N):
    M = np.zeros((N, N))
    for i in range(N):
        D_i = sum(G[i])
        if D_i == 0:
            continue
        for j in range(N):
            M[j][i] = G[i][j] / D_i # watch out! M_j_i instead of M_i_j
    return M
M = GtoM(G, 10)
  • Flow版本的PageRank
def PageRank(M, N, T=300, eps=1e-6):
    R = np.ones(N) / N
    for time in range(T):
        R_new = np.dot(M, R)
        if np.linalg.norm(R_new - R) < eps:
            break
        R = R_new.copy()
    return R_new

测试下:

values = PageRank(M, 10, T=2000)
values

输出:

array([0.09972576, 0.09193927, 0.07843151, 0.09125886, 0.08925602,
       0.10407245, 0.09623654, 0.13851257, 0.13086464, 0.07970237])
  • Google Formula
def PageRank(M, N, T=300, eps=1e-6, beta=0.8):
    R = np.ones(N) / N
    teleport = np.ones(N) / N
    for time in range(T):
        R_new = beta * np.dot(M, R) + (1-beta)*teleport
        if np.linalg.norm(R_new - R) < eps:
            break
        R = R_new.copy()
    return R_new

同样的数据测试下:

测试下:

values = PageRank(M, 10, T=2000)
values

输出:

array([0.09815807, 0.09250429, 0.08376235, 0.09300133, 0.09324628,
       0.10108776, 0.09855127, 0.13019363, 0.12458992, 0.0849051 ])