算法学习(2)--- 谷歌PageRank算法

图片来自网络

1. 从Google网页排序到PageRank算法

(1)谷歌网页怎么排序?

  • 先对搜索关键词进行分词,如“技术社区”分词为“技术”和“社区”;
  • 根据建立的倒排索引返回同时包含分词后结果的网页;
  • 将返回的网页相关性(类似上篇文章所讲的文本相似度)网页,相关性越高排名越靠前

(2)怎么处理垃圾网页?
那么问题来了,假如有某个垃圾网页中虽然也包含大量的查询词,但却并非满足用户需要的文档,因此,页面本身的重要性在网页排序中也起着很重要的作用。
(3)如何度量网页本身的重要性?
实际上互联网上的每一篇HTML文档除了包含文本、图片、视频等信息外,还包含了大量的链接关系,利用这些链接关系,能够发现某些重要的网页,其中网页是节点,网页间的链接关系是边。

图片来自网络

如上图,某网页1链向网页2,则可以认为网页1觉得网页2有链接价值,是比较重要的网页。某网页被指向的次数越多,则它的重要性越高;越是重要的网页,所链接的网页的重要性也越高。
通过下图我们可以更形象地看出链向网页E的链接远远大于链向网页C的链接,但是网页C的重要性却大于网页E。这是因为网页C被网页B所链接,而网页B有很高的重要性。

图片来自网络

(4)PageRank核心思想
PageRank对网页的排序可以独立于用户搜索进行。如果一个网页被很多其它网页所链接,说明它受到普遍的承认和信赖,那么它的排名就高。这就是 Page Rank 的核心思想。当然 Google 的 Page Rank 算法实际上要复杂得多。比如说,对来自不同网页的链接对待不同,本身网页排名高的链接更可靠,于是给这些链接予较大的权重。
通俗理解,我们可以将互联网中的网页理解成我们现实中的每个人,人与人之间的联系就类似于网页与网页之间联系,一般人的社交影响力是跟其人脉的广度与人脉的质量有关,网页也同理,其重要性也跟网页的被链的数量与质量有关。
具体参考:PageRank算法讲解

2 PageRank的python实现

2.1 需求

利用PageRank随机浏览模型求如下图个网页的PageRank值。


网页关系

即网页之间的关系如下表格:

链接源ID 链接目标 ID
1 2,3,4,5, 7
2 1
3 1,2
4 2,3,5
5 1,3,4,6
6 1,5
7 5

2.2 Python实现

"""
Created on Sun Jan  8 23:41:29 2017

@author: whenif
"""
 
import numpy as np 
import networkx as nx
import matplotlib.pyplot as plt

def getGm(A):
    '''
    功能:求状态转移概率矩阵Gm
    @A:网页链接图的邻接矩阵
    '''
    Gm = []   
    for i in range(len(A)):
        cnt = 0
        for j in range(len(A[i])):
         if A[i][j] != 0:
             cnt += 1
        tran_prob = 1/cnt#转移概率
        Gm_tmp = []
        for j in range(len(A[i])):
         Gm_tmp.append(tran_prob*A[i][j])
        Gm.append(Gm_tmp)
    Gm = np.transpose(Gm) 
    return Gm

def getBaseLev(N):
    '''
    功能:计算网页所获得的基本级别(1-P)*e/n 
    @N:网页总个数
    '''
    P = 0.85
    e = np.ones(N)
    R = [ [(1-P)*i*1/N] for i in e ]  
    return R

    
def getPR(P,Gm,R,PR):
    '''
    功能:获取PR值
    @P:加权系数,通常取 0.85 左右,按照超链接进行浏览的概率
    @Gm:状态转移概率矩阵
    @R:网页所获得的基本级别
    @PR:每个网页节点的PageRank值
    '''
    #状态转移概率矩阵Gm与PR值相乘矩阵相乘
    Gm_PR = np.dot(Gm,PR) 
    #矩阵乘以常数P
    P_Gm_PR = P*Gm_PR
    #矩阵相加
    new_PR = P_Gm_PR+R #PR=P*Gm'PR+(1-d)*e/n PageRank算法的核心  
    return new_PR

def res_vis(A,PR):
    '''
    将计算出来的值进行可视化展示
    @A:网页链接图的邻接矩阵
    @PR:每个网页节点最终的PageRank值
    '''
    #G=nx.Graph()构造的是无向图, G=nx.DiGraph()构造的是有向图
    #初始化有向图,节点数为7,edge(边)被创造的随机概率
    all_edges = []
    for i in range(7):
        for j in range(len(A)):
            if A[i][j]==1:
                all_edges.append([i+1,j+1])         
    #(1)初始化有向图
    G = nx.DiGraph() 
    #(2)添加节点
    G.add_nodes_from(range(1,len(A)))
    #(3)添加有向边
    G.add_edges_from(all_edges)
    #(4)添加PR值
    pr = {}
    for i in range(len(PR)):
        pr[i+1] = PR[i][0]
    # (5)画图
    layout = nx.spring_layout(G)
    plt.figure(1)
    nx.draw(G, pos=layout, node_size=[x * 6000 for x in pr.values()],
                                  node_color='m',with_labels=True)
    plt.show() 
    
def main():
    #初始化参数
    N = 7 #网页个数
    P = 0.85 #一个加权系数,通常取 0.85 左右,按照超链接进行浏览的概率
    #网页链接图的邻接矩阵,每一列表示一个网页的出度
    A =  np.array([[0,1,1,0,1,1,0],
                   [1,0,1,1,0,0,0],
                   [1,0,0,1,1,0,0],
                   [1,0,0,0,1,0,0],
                   [1,0,0,1,0,1,1],
                   [0,0,0,0,1,0,0],
                   [1,0,0,0,0,0,0]])
    A = np.transpose(A) #转置    
    #初始化PR值为0 
    new_PR = []  
    for i in range(N):  
        new_PR.append([0])       
    count = 0#迭代计数器
    while True:  
        PR = new_PR  
        R = getBaseLev(N)
        Gm = getGm(A)
        new_PR = getPR(P,Gm,R,PR)
        count = count +1
        print("第 %s 轮迭代" % count)
        print(str(round(new_PR[0][0],5)) 
                +"\t" + str(round(new_PR[1][0],5)) 
                + "\t" + str(round(new_PR[2][0],5)) 
                + "\t" + str(round(new_PR[3][0],5))
                + "\t" + str(round(new_PR[4][0],5))
                + "\t" + str(round(new_PR[5][0],5))
                + "\t" + str(round(new_PR[6][0],5)))
        #设置迭代条件
        if (    round(PR[0][0],5)==round(new_PR[0][0],5) 
            and round(PR[1][0],5)==round(new_PR[1][0],5) 
            and round(PR[2][0],5)==round(new_PR[2][0],5) 
            and round(PR[3][0],5)==round(new_PR[3][0],5)
            and round(PR[4][0],5)==round(new_PR[4][0],5)
            and round(PR[5][0],5)==round(new_PR[5][0],5)
            and round(PR[6][0],5)==round(new_PR[6][0],5)):   
            break
    print("-------------------")
    print("PageRank值已计算完成")
    res_vis(A,new_PR)

if __name__ == '__main__':  
    main()  

2.3 结果与分析

(1)迭代结果

第 1 轮迭代
0.02143 0.02143 0.02143 0.02143 0.02143 0.02143 0.02143
第 2 轮迭代
0.06241 0.04025 0.0357  0.02963 0.05846 0.02598 0.02507
......
第 57 轮迭代
0.28026 0.15875 0.13887 0.10821 0.18418 0.06057 0.06907
第 58 轮迭代
0.28026 0.15875 0.13887 0.10821 0.18418 0.06057 0.06907
-------------------
PageRank值已计算完成

(2)可视化结果

网页关系可视化结果

其中圆圈编号表示网页ID,圆圈大小表示PR值大小,连线表示网页之间的关系,有带黑色箭头表示出度方向。
(3)结果汇总

名次 PageRank值 网页ID 发出链接ID 被链接ID
1 0.28026 1 2,3,4,5,7 2,3,5,6
2 0.18418 5 1,3,4,6 1,4,6,7
3 0.15875 2 1 1,3,4
4 0.13887 3 1,2 1,4,5
5 0.10821 4 2,3,5 1,5
6 0.06907 7 5 1
7 0.06057 6 1,5 5

(4)结果分析

  • 被链接个数越多其PageRank值越大,当被链接个数相同则发出链接个数越多其PageRank值越大;
  • ID=1的页面的PageRank值是0.28026,占据全体接近三分之一,成为了第1位。从可视化图与结果汇总表格可以看出,因为ID=1页面是链出链接和链入链接最多的页面,也可以理解它是最受欢迎的页面。
    同时需要注意的是在PageRank值排在第3位的ID=2页面,被3个链接所链接,而只有面向ID=1页面发出一个链接,因此(面向ID=1页面的)链接就得到ID=2的所有的PageRank值。

3 应用场景

在数据分析我们经常需要从用户的角度思考问题,如用户购买路径,用户之所以没产生购买,那么到底是在哪个环节出现了问题?基于用户还有许许多多的分析问题,如流失用户分析、流失用户预警、用户信用度分析等。
从基于用户的分析我们可以延伸到用户与信息、用户与商品、用户与用户之间的分析,当然这三点对号入座的便分别是BAT的基因所在,其中人与人之间的分析即是社交关系分析,这也是PageRank适合的领域之一。在不同行业的应用场景不用,如以下应用场景:

  • 微信、微博等应用的社交网络分析,可以实现基于用户的相似度的内容推荐、可以挖掘用户的价值、用户的社交影响力等;电商如京东等可利用用户关系,在一定程度上协助风险控制(抓刷单等)。
  • 在电信行业中利用交往圈数据可以得到用户的社交影响力,从而在一定程度上可以协助垃圾短信等的治理;
  • 文献重要性研究(引用与被引用)
  • ......

后记

数据分析与挖掘很多都是从人出发,逐渐延伸到人与人,甚至是人、人与人在时间与空间上的表现,其中人与人之间的关系可以说是很重要的一环,所以个人觉得PageRank还是有挺大的应用性,在工作中也是深有体会。当然文中只是举了简单的例子并实现,代码可优化的地方应该不少,望各路小伙伴一起交流一起进步。


参考:
[1] PageRank算法讲解

本文所有代码只用于技术交流,拒绝任何商用活动
个人Github
后续的学习细节将会记录在个人博客DebugNLP中,欢迎各路同学互相交流

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 链接分析 我们在最开始说过,搜索引擎在查找能够满足用户需求的网页时,主要会考虑两方面的因素,一方面是用户发出的查询...
    我偏笑_NSNirvana阅读 3,153评论 1 12
  • 这个系列的第六个主题,主要谈一些搜索引擎相关的常见技术。 1995年是搜索引擎商业公司发展的重要起点,《浅谈推荐系...
    我偏笑_NSNirvana阅读 6,596评论 3 24
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,409评论 25 707
  • 佩奇排名(PageRank),又称网页排名、谷歌左侧排名,是一种由搜索引擎根据网页之间相互的超链接计算的技术,而作...
    Nicky_Ye阅读 20,865评论 1 12
  • 当黑暗占据阳光的余晖 星空闪闪 眨眼的星星看着黑暗的心情 默默地不说话 如果阳光是开心的向往 黑暗是静思的沉默 他...
    杨又芷阅读 141评论 0 3