PageRank演算法原理及實現

2022-02-19 07:29:18 字數 3392 閱讀 5826

pagerank演算法原理介紹

pagerank演算法是google的網頁排序演算法,在《the top ten algorithms in data mining》一書中第6章有介紹。大致原理是使用者搜尋出的多個網頁需要按照一定的重要程度(即後面講的權重)排序,每個網頁的權重由所有鏈結到它的其他網頁的權重的加權和,加權係數為每個網頁鏈出的網頁數的倒數,也就是說每個網頁的權重會平均分配到其鏈向的所有網頁。

例如a鏈結到b和c,b鏈結到c,c鏈結到a,p(x)表示x的權重,如下圖所示

則每個節點的權重關係為:

p(a) = p(c)

p(b) = p(a)/2

p(c) = p(a)/2 + p(b)

一般地,可以寫成個線性方程組形式:

p = ap

如此通過迭代即可求出最終各個網頁的權重值。

但是,當存在某些特殊情況時,如某個網頁的鏈入或鏈出數為0,則迭代不會收斂。因此在上述演算法中增加了個阻尼係數d,d表示使用者會繼續點選下一網頁的概率,同時使用者在1-d的概率下會隨機訪問到任意網頁,那麼上面的公式會修正為:

p = (1-d)/n * ones(n,1) + d*ap

其中n為所有網頁數,ones(n,1)表示n行1列的全1矩陣。通過上述公式可以迭代計算出最終各網頁權重。

詳細介紹可以參考wiki百科。

演算法實現

首先宣告這個cpagerank類:

1 typedef unsigned char

byte;

2class

cpagerank

3;

下面就是具體各個函式的實現了。

首先建構函式主要是初始化一些迭代相關變數,分配空間等,這裡把生成節點指向圖的工作也放在這裡,支援直接隨機生成和讀取二進位制檔案兩種方式。

1 cpagerank::cpagerank(int nwebnum, bool

bloadfromfile)

2

析構函式自然就是釋放記憶體了:

1 cpagerank::~cpagerank()

2

下面就是隨機生成或讀取檔案產生節點指向關係,如果隨機生成的話,會自動儲存當前生成的圖,便於遇到問題時可復現除錯:

1

void cpagerank::initgraph(bool

bloadfromfile)213

}1415//

建立隨機的節點指向圖

16int

i, j;

17srand((unsigned)time(null));

18for(i = 0; i < m_nnum; i++)

1925

//自己不指向自己

26 m_pu8relation[i * m_nnum + i] = 0;27

}2829 pf = fopen("

map.dat

", "wb"

);30

if(pf)

31

35 }

既然已經產生了各個節點的關係了,那pagerank的核心思想就是根據關係,生成出上面的轉移矩陣p:

1

void

cpagerank::generatep()217

}1819//

生成轉移矩陣,每個節點的權重平均流出

20 pu8relation =m_pu8relation;

21 pf32p =m_pf32p;

22for(i = 0; i < m_nnum; i++)

2330

else

3134 pu8relation++;

35 pf32p++;36}

37}3839

//考慮阻尼係數,修正轉移矩陣

40 pf32p =m_pf32p;

41for(i = 0; i < m_nnum; i++)

4248

}49 }

接下來就需要求解出各個節點的權重,process函式裡先呼叫generatep生成出p矩陣,然後採用迭代法求解,當時為了測試收斂速度,直接返回了迭代次數:

1

intcpagerank::process()214

15//

生成p矩陣

16generatep();

1718

//迭代

19for(t = 0; t < m_nmaxitertime; t++)

2031

32float f32err = fabs(pf32new[i] -pf32org[i]);

33if(f32err >f32maxerr)

3437}38

39//

迭代誤差足夠小,停止

40if(f32maxerr

4144

45//

交換2次迭代結果

46float *pf32temp =pf32org;

47 pf32org =pf32new;

48 pf32new =pf32temp;49}

5051

//迭代結果存在pf32new中

52 m_pf32outweight =pf32new;

53return

t;54 }

最後的結果已經存在了m_pf32outweight中了,下面函式直接傳出結果:

1

float *cpagerank::getweight()

2

這樣,整個演算法就算完成了,考慮到篇幅,貼上來的**把opencv顯示相關的**去掉了,完整**見

下面是結果圖,即便節點數較多時,演算法收斂也比較快。

分析總結

對於上面這個公式,看到網上有人假定p的總能量是1,則可以改寫為p=bp的形式來進行迭代,這種方法也實現了一下,問題仍然是當存在網頁鏈入或者鏈出數為0時,每次迭代後不能保證能量守恆,那麼下一次就會導致p=bp這個公式不成立,從而出現迭代不收斂;一種有效的做法是每次迭代後就將p進行能量規一化,這樣是可以保證結果的收斂性的。但是這種做法與原始演算法的結果會有一點細微的出入。因此建議按照原始的公式進行迭代求解。

PageRank演算法原理剖析及Spark實現

pagerank對網頁排名的演算法,曾是google發家致富的法寶。pagerank演算法計算每乙個網頁的pagerank值,然後根據這個值的大小對網頁的重要性進行排序 首先,將web做如下抽象 1 將每個網頁抽象成乙個節點 2 如果乙個頁面a有鏈結直接鏈向b,則存在一條有向邊從a到b 多個相同鏈結...

PageRank演算法實現

在網際網路上,如果乙個網頁被很多其他網頁所鏈結,說明它受到普遍的承認和信賴,那麼它的排名就高。這就是pagerank的核心思想。引用來自 數學之美 的簡單例子 網頁y的排名應該來自於所有指向這個網頁的其他網頁的權重之和,在上圖中y的網頁排名就是0.001 0.01 0.02 0.05 0.081。如...

PageRank演算法的python實現

演算法原理不在贅述,請參考 將 儲存為.py格式,預設使用的資料是 檔案所在目錄下data目錄下的 pgr data.txt 檔案分別作為源資料輸入。以上引數可以在源 中修改,也可以使用命令列引數傳入,參考以下啟動方式 python pagerank.py pgr data.txt 命令中後引數為輸...