谷歌PageRank算法

 

1. 從Google網頁排序到PageRank算法

(1)谷歌網頁怎麼排序?html

  • 先對搜索關鍵詞進行分詞,如「技術社區」分詞爲「技術」和「社區」;
  • 根據創建的倒排索引返回同時包含分詞後結果的網頁;
  • 將返回的網頁相關性(相似上篇文章所講的文本類似度)網頁,相關性越高排名越靠前

(2)怎麼處理垃圾網頁?
那麼問題來了,假若有某個垃圾網頁中雖然也包含大量的查詢詞,但卻並不是知足用戶須要的文檔,所以,頁面自己的重要性在網頁排序中也起着很重要的做用。
(3)如何度量網頁自己的重要性?
實際上互聯網上的每一篇HTML文檔除了包含文本、圖片、視頻等信息外,還包含了大量的連接關係,利用這些連接關係,可以發現某些重要的網頁,其中網頁是節點,網頁間的連接關係是邊。node


圖片來自網絡

如上圖,某網頁1鏈向網頁2,則能夠認爲網頁1以爲網頁2有連接價值,是比較重要的網頁。某網頁被指向的次數越多,則它的重要性越高;越是重要的網頁,所連接的網頁的重要性也越高。
經過下圖咱們能夠更形象地看出鏈向網頁E的連接遠遠大於鏈向網頁C的連接,可是網頁C的重要性卻大於網頁E。這是由於網頁C被網頁B所連接,而網頁B有很高的重要性。python


圖片來自網絡


(4)PageRank核心思想
PageRank對網頁的排序能夠獨立於用戶搜索進行。若是一個網頁被不少其它網頁所連接,說明它受到廣泛的認可和信賴,那麼它的排名就高。這就是 Page Rank 的核心思想。固然 Google 的 Page Rank 算法實際上要複雜得多。好比說,對來自不一樣網頁的連接對待不一樣,自己網頁排名高的連接更可靠,因而給這些連接予較大的權重。
通俗理解,咱們能夠將互聯網中的網頁理解成咱們現實中的每一個人,人與人之間的聯繫就相似於網頁與網頁之間聯繫,通常人的社交影響力是跟其人脈的廣度與人脈的質量有關,網頁也同理,其重要性也跟網頁的被鏈的數量與質量有關。
具體參考:PageRank算法講解PageRank算法--從原理到實現算法

2 PageRank的python實現

2.1 需求

利用PageRank隨機瀏覽模型求以下圖個網頁的PageRank值。spring


網頁關係

即網頁之間的關係以下表格:微信

連接源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)可視化結果app


網頁關係可視化結果


其中圓圈編號表示網頁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)結果分析.net

  • 被連接個數越多其PageRank值越大,當被連接個數相同則發出連接個數越多其PageRank值越大;
  • ID=1的頁面的PageRank值是0.28026,佔據全體接近三分之一,成爲了第1位。從可視化圖與結果彙總表格能夠看出,由於ID=1頁面是鏈出連接和鏈入連接最多的頁面,也能夠理解它是最受歡迎的頁面。
    同時須要注意的是在PageRank值排在第3位的ID=2頁面,被3個連接所連接,而只有面向ID=1頁面發出一個連接,所以(面向ID=1頁面的)連接就獲得ID=2的全部的PageRank值。

 

附另外一個簡單的PageRank程序:

from numpy import *  
  
a = array([[0,1,1,0],  
           [1,0,0,1],  
           [1,0,0,1],  
           [1,1,0,0]],dtype = float)  #dtype指定爲float  
  
def graphMove(a):   #構造轉移矩陣
    c = zeros((a.shape),dtype = float)  
    for i in range(a.shape[0]):  
        for j in range(a.shape[1]):  
            c[i][j] = a[i][j] / (a[:, j].sum())  #完成初始化分配  
    return c  
  
def pageRank(p,m,v):  #計算pageRank值
    #判斷pr矩陣是否收斂,(v == p*dot(m,v) + (1-p)*v).all()判斷先後的pr矩陣是否相等,若相等則中止循環  
    while((v == p*dot(m,v) + (1-p)*v).all()==False):  
        v = p*dot(m,v) + (1-p)*v  
    return v  
  
if __name__=="__main__":  
    M = graphMove(a)
    pr = array([float(1)/M.shape[0] for _ in range(M.shape[0])]) #pr值的初始化  
    p = 0.8           #引入瀏覽當前網頁的機率爲p,假設p=0.8  
    print pageRank(p,M,pr)  # 計算pr值

  

 

3 應用場景

在數據分析咱們常常須要從用戶的角度思考問題,如用戶購買路徑,用戶之因此沒產生購買,那麼究竟是在哪一個環節出現了問題?基於用戶還有許許多多的分析問題,如流失用戶分析、流失用戶預警、用戶信用度分析等。
從基於用戶的分析咱們能夠延伸到用戶與信息、用戶與商品、用戶與用戶之間的分析,固然這三點對號入座的便分別是BAT的基因所在,其中人與人之間的分析便是社交關係分析,這也是PageRank適合的領域之一。在不一樣行業的應用場景不用,如如下應用場景:

  • 微信、微博等應用的社交網絡分析,能夠實現基於用戶的類似度的內容推薦、能夠挖掘用戶的價值、用戶的社交影響力等;電商如京東等可利用用戶關係,在必定程度上協助風險控制(抓刷單等)。
  • 在電信行業中利用交往圈數據能夠獲得用戶的社交影響力,從而在必定程度上能夠協助垃圾短信等的治理;
  • 文獻重要性研究(引用與被引用)
  • ......

後記

數據分析與挖掘不少都是從人出發,逐漸延伸到人與人,甚至是人、人與人在時間與空間上的表現,其中人與人之間的關係能夠說是很重要的一環,因此我的以爲PageRank仍是有挺大的應用性,在工做中也是深有體會。固然文中只是舉了簡單的例子並實現,代碼可優化的地方應該很多,望各路小夥伴一塊兒交流一塊兒進步。



做者:whenif 連接:http://www.jianshu.com/p/5657910d7df6
相關文章
相關標籤/搜索