PageRank算法--从原理到实现
本文將介紹PageRank算法的相關(guān)內(nèi)容,具體如下:
1.算法來源
2.算法原理
3.算法證明
4.PR值計(jì)算方法
4.1 冪迭代法
4.2 特征值法
4.3 代數(shù)法
5.算法實(shí)現(xiàn)
5.1 基于迭代法的簡單實(shí)現(xiàn)
5.2 MapReduce實(shí)現(xiàn)
6.PageRank算法的缺點(diǎn)
7.寫在最后
參考資料
1. 算法來源
這個(gè)要從搜索引擎的發(fā)展講起。最早的搜索引擎采用的是 分類目錄[^ref_1] 的方法,即通過人工進(jìn)行網(wǎng)頁分類并整理出高質(zhì)量的網(wǎng)站。那時(shí) Yahoo 和國內(nèi)的 hao123 就是使用的這種方法。
后來網(wǎng)頁越來越多,人工分類已經(jīng)不現(xiàn)實(shí)了。搜索引擎進(jìn)入了 文本檢索 的時(shí)代,即計(jì)算用戶查詢關(guān)鍵詞與網(wǎng)頁內(nèi)容的相關(guān)程度來返回搜索結(jié)果。這種方法突破了數(shù)量的限制,但是搜索結(jié)果不是很好。因?yàn)榭傆心承┚W(wǎng)頁來回地倒騰某些關(guān)鍵詞使自己的搜索排名靠前。
于是我們的主角要登場了。沒錯(cuò),谷歌的兩位創(chuàng)始人,當(dāng)時(shí)還是美國斯坦福大學(xué) (Stanford University) 研究生的佩奇 (Larry Page) 和布林 (Sergey Brin) 開始了對(duì)網(wǎng)頁排序問題的研究。他們的借鑒了學(xué)術(shù)界評(píng)判學(xué)術(shù)論文重要性的通用方法, 那就是看論文的引用次數(shù)。由此想到網(wǎng)頁的重要性也可以根據(jù)這種方法來評(píng)價(jià)。于是PageRank的核心思想就誕生了[^ref_2],非常簡單:
- 如果一個(gè)網(wǎng)頁被很多其他網(wǎng)頁鏈接到的話說明這個(gè)網(wǎng)頁比較重要,也就是PageRank值會(huì)相對(duì)較高
- 如果一個(gè)PageRank值很高的網(wǎng)頁鏈接到一個(gè)其他的網(wǎng)頁,那么被鏈接到的網(wǎng)頁的PageRank值會(huì)相應(yīng)地因此而提高
就如下圖所示(一個(gè)概念圖):
2. 算法原理
PageRank算法[^ref_3]總的來說就是預(yù)先給每個(gè)網(wǎng)頁一個(gè)PR值(下面用PR值指代PageRank值),由于PR值物理意義上為一個(gè)網(wǎng)頁被訪問概率,所以一般是$ \frac{1}{N} $,其中N為網(wǎng)頁總數(shù)。另外,一般情況下,所有網(wǎng)頁的PR值的總和為1。如果不為1的話也不是不行,最后算出來的不同網(wǎng)頁之間PR值的大小關(guān)系仍然是正確的,只是不能直接地反映概率了。
預(yù)先給定PR值后,通過下面的算法不斷迭代,直至達(dá)到平穩(wěn)分布為止。
互聯(lián)網(wǎng)中的眾多網(wǎng)頁可以看作一個(gè)有向圖。下圖是一個(gè)簡單的例子[^ref_4]:
這時(shí)A的PR值就可以表示為:
\[ PR(A) = PR(B) + PR(C) \]
然而圖中除了C之外,B和D都不止有一條出鏈,所以上面的計(jì)算式并不準(zhǔn)確。想象一個(gè)用戶現(xiàn)在在瀏覽B網(wǎng)頁,那么下一步他打開A網(wǎng)頁還是D網(wǎng)頁在統(tǒng)計(jì)上應(yīng)該是相同概率的。所以A的PR值應(yīng)該表述為:
\[ PR(A) = \frac{PR(B)}{2} + \frac{PR(C)}{1} \]
互聯(lián)網(wǎng)中不乏一些沒有出鏈的網(wǎng)頁,如下圖:
圖中的C網(wǎng)頁沒有出鏈,對(duì)其他網(wǎng)頁沒有PR值的貢獻(xiàn),我們不喜歡這種自私的網(wǎng)頁(其實(shí)是為了滿足 Markov 鏈的收斂性),于是設(shè)定其對(duì)所有的網(wǎng)頁(包括它自己)都有出鏈,則此圖中A的PR值可表示為:
\[ PR(A) = \frac{PR(B)}{2} + \frac{PR(C)}{4} \]
然而我們?cè)倏紤]一種情況:互聯(lián)網(wǎng)中一個(gè)網(wǎng)頁只有對(duì)自己的出鏈,或者幾個(gè)網(wǎng)頁的出鏈形成一個(gè)循環(huán)圈。那么在不斷地迭代過程中,這一個(gè)或幾個(gè)網(wǎng)頁的PR值將只增不減,顯然不合理。如下圖中的C網(wǎng)頁就是剛剛說的只有對(duì)自己的出鏈的網(wǎng)頁:
為了解決這個(gè)問題。我們想象一個(gè)隨機(jī)瀏覽網(wǎng)頁的人,當(dāng)他到達(dá)C網(wǎng)頁后,顯然不會(huì)傻傻地一直被C網(wǎng)頁的小把戲困住。我們假定他有一個(gè)確定的概率會(huì)輸入網(wǎng)址直接跳轉(zhuǎn)到一個(gè)隨機(jī)的網(wǎng)頁,并且跳轉(zhuǎn)到每個(gè)網(wǎng)頁的概率是一樣的。于是則此圖中A的PR值可表示為:
\[ PR(A) = \alpha(\frac{PR(B)}{2}) + \frac{(1 - \alpha)}{4}\]
在一般情況下,一個(gè)網(wǎng)頁的PR值計(jì)算如下:
\[ PR(p_{i}) = \alpha \sum_{p_{j} \in M_{p_{i}}} \frac{PR(p_{j})}{L(p_{j})} + \frac{(1 - \alpha)}{N} \]
其中\(M_{p_{i}}\)是所有對(duì)\(p_{i}\)網(wǎng)頁有出鏈的網(wǎng)頁集合,\(L(p_{j})\)是網(wǎng)頁\(p_{j}\)的出鏈數(shù)目,\(N\)是網(wǎng)頁總數(shù),\(\alpha\)一般取0.85。
根據(jù)上面的公式,我們可以計(jì)算每個(gè)網(wǎng)頁的PR值,在不斷迭代趨于平穩(wěn)的時(shí)候,即為最終結(jié)果。具體怎樣算是趨于平穩(wěn),我們?cè)谙旅娴腜R值計(jì)算方法部分再做解釋。
3. 算法證明
- $ \lim_{n \rightarrow \infty}P_{n} $是否存在?
- 如果極限存在,那么它是否與\(P_0\)的選取無關(guān)?
PageRank算法的正確性證明包括上面兩點(diǎn)[^ref_5]。為了方便證明,我們先將PR值的計(jì)算方法轉(zhuǎn)換一下。
仍然拿剛剛的例子來說
我們可以用一個(gè)矩陣來表示這張圖的出鏈入鏈關(guān)系,\(S_{ij} = 0\)表示\(j\)網(wǎng)頁沒有對(duì)\(i\)網(wǎng)頁的出鏈:
\[ S = \left( \begin{array}{cccc} 0 & 1/2 & 0 & 0 \\ 1/3 & 0 & 0 & 1/2 \\ 1/3 & 0 & 1 & 1/2 \\ 1/3 & 1/2 & 0 & 0 \\ \end{array} \right) \]
取\(e\)為所有分量都為 1 的列向量,接著定義矩陣:
\[ A = \alpha S + \frac{(1 - \alpha)}{N}ee^T \]
則PR值的計(jì)算如下,其中\(P_{n}\)為第n次迭代時(shí)各網(wǎng)頁P(yáng)R值組成的列向量:
\[ P_{n+1} = A P_{n} \]
于是計(jì)算PR值的過程就變成了一個(gè) Markov 過程,那么PageRank算法的證明也就轉(zhuǎn)為證明 Markov 過程的收斂性證明:如果這個(gè) Markov 過程收斂,那么$ \lim_{n \rightarrow \infty}P_{n} \(存在,且與\)P_0$的選取無關(guān)。
若一個(gè) Markov 過程收斂,那么它的狀態(tài)轉(zhuǎn)移矩陣\(A\)需要滿足[^ref_6]:
先看第一點(diǎn),隨機(jī)矩陣又叫概率矩陣或 Markov 矩陣,滿足以下條件:
\[ 令a_{ij}為矩陣A中第i行第j列的元素,則 \forall i = 1 \dots n, j = 1 \dots n, a_{ij} \geq 0, 且 \forall i = 1 \dots n, \sum_{j = 1}^n a_{ij} = 1 \]
顯然我們的A矩陣所有元素都大于等于0,并且每一列的元素和都為1。
第二點(diǎn),不可約矩陣:方針A是不可約的當(dāng)且僅當(dāng)與A對(duì)應(yīng)的有向圖是強(qiáng)聯(lián)通的。有向圖\(G = (V,E)\)是強(qiáng)聯(lián)通的當(dāng)且僅當(dāng)對(duì)每一對(duì)節(jié)點(diǎn)對(duì)\(u,v \in V\),存在從\(u\)到\(v\)的路徑。因?yàn)槲覀冊(cè)谥霸O(shè)定用戶在瀏覽頁面的時(shí)候有確定概率通過輸入網(wǎng)址的方式訪問一個(gè)隨機(jī)網(wǎng)頁,所以A矩陣同樣滿足不可約的要求。
第三點(diǎn),要求A是非周期的。所謂周期性,體現(xiàn)在Markov鏈的周期性上。即若A是周期性的,那么這個(gè)Markov鏈的狀態(tài)就是周期性變化的。因?yàn)锳是素矩陣(素矩陣指自身的某個(gè)次冪為正矩陣的矩陣),所以A是非周期的。
至此,我們證明了PageRank算法的正確性。
4. PR值計(jì)算方法
4.1 冪迭代法
首先給每個(gè)頁面賦予隨機(jī)的PR值,然后通過$ P_{n+1} = A P_{n} $不斷地迭代PR值。當(dāng)滿足下面的不等式后迭代結(jié)束,獲得所有頁面的PR值:
\[ |P_{n+1} - P_{n}| < \epsilon \]
4.2 特征值法
當(dāng)上面提到的Markov鏈?zhǔn)諗繒r(shí),必有:
\[ P = A P \Rightarrow P為矩陣A特征值1對(duì)應(yīng)的特征向量 \\ (隨機(jī)矩陣必有特征值1,且其特征向量所有分量全為正或全為負(fù)) \]
4.3 代數(shù)法
相似的,當(dāng)上面提到的Markov鏈?zhǔn)諗繒r(shí),必有:
\[ P = A P \\ \Rightarrow P = \lgroup \alpha S + \frac{(1 - \alpha)}{N}ee^T \rgroup P \\ 又\because e為所有分量都為 1 的列向量,P的所有分量之和為1 \\ \Rightarrow P = \alpha SP + \frac{(1 - \alpha)}{N}e \\ \Rightarrow (ee^T - \alpha S)P = \frac{(1 - \alpha)}{N}e \\ \Rightarrow P = (ee^T - \alpha S)^{-1} \frac{(1 - \alpha)}{N}e \\ \]
5. 算法實(shí)現(xiàn)
5.1 基于迭代法的簡單實(shí)現(xiàn)
用python實(shí)現(xiàn)[^ref_7],需要先安裝python-graph-core。
# -*- coding: utf-8 -*-from pygraph.classes.digraph import digraphclass PRIterator:__doc__ = '''計(jì)算一張圖中的PR值'''def __init__(self, dg):self.damping_factor = 0.85 # 阻尼系數(shù),即αself.max_iterations = 100 # 最大迭代次數(shù)self.min_delta = 0.00001 # 確定迭代是否結(jié)束的參數(shù),即?self.graph = dgdef page_rank(self):# 先將圖中沒有出鏈的節(jié)點(diǎn)改為對(duì)所有節(jié)點(diǎn)都有出鏈for node in self.graph.nodes():if len(self.graph.neighbors(node)) == 0:for node2 in self.graph.nodes():digraph.add_edge(self.graph, (node, node2))nodes = self.graph.nodes()graph_size = len(nodes)if graph_size == 0:return {}page_rank = dict.fromkeys(nodes, 1.0 / graph_size) # 給每個(gè)節(jié)點(diǎn)賦予初始的PR值damping_value = (1.0 - self.damping_factor) / graph_size # 公式中的(1?α)/N部分flag = Falsefor i in range(self.max_iterations):change = 0for node in nodes:rank = 0for incident_page in self.graph.incidents(node): # 遍歷所有“入射”的頁面rank += self.damping_factor * (page_rank[incident_page] / len(self.graph.neighbors(incident_page)))rank += damping_valuechange += abs(page_rank[node] - rank) # 絕對(duì)值page_rank[node] = rankprint("This is NO.%s iteration" % (i + 1))print(page_rank)if change < self.min_delta:flag = Truebreakif flag:print("finished in %s iterations!" % node)else:print("finished out of 100 iterations!")return page_rankif __name__ == '__main__':dg = digraph()dg.add_nodes(["A", "B", "C", "D", "E"])dg.add_edge(("A", "B"))dg.add_edge(("A", "C"))dg.add_edge(("A", "D"))dg.add_edge(("B", "D"))dg.add_edge(("C", "E"))dg.add_edge(("D", "E"))dg.add_edge(("B", "E"))dg.add_edge(("E", "A"))pr = PRIterator(dg)page_ranks = pr.page_rank()print("The final page rank is\n", page_ranks)運(yùn)行結(jié)果:
finished in 36 iterations! The final page rank is {'A': 0.2963453309000821, 'C': 0.11396451042168992, 'B': 0.11396451042168992, 'E': 0.31334518664434013, 'D': 0.16239975107315852}程序中給出的網(wǎng)頁之間的關(guān)系一開始如下:
迭代結(jié)束后如下:
5.2 MapReduce實(shí)現(xiàn)
作為Hadoop(分布式系統(tǒng)平臺(tái))的核心模塊之一,MapReduce是一個(gè)高效的分布式計(jì)算框架。下面首先簡要介紹一下MapReduce原理。
所謂MapReduce,就是兩種操作:Mapping和Reducing[^ref_8]。
- 映射(Mapping):對(duì)集合里的每個(gè)目標(biāo)應(yīng)用同一個(gè)操作。
- 化簡(Reducing ):遍歷Mapping返回的集合中的元素來返回一個(gè)綜合的結(jié)果。
就拿一個(gè)最經(jīng)典的例子來說:現(xiàn)在有3個(gè)文本文件,需要統(tǒng)計(jì)出所有出現(xiàn)過的詞的詞頻。傳統(tǒng)的想法是讓一個(gè)人順序閱讀這3個(gè)文件,每遇到一個(gè)單詞,就看之前有沒有遇到過。遇到過的話詞頻加一:(單詞,N + 1),否則就記錄新詞,詞頻為一:(單詞,1)。
MapReduce方式為:把這3個(gè)文件分給3個(gè)人,每個(gè)人閱讀一份文件。每當(dāng)遇到一個(gè)單詞,就記錄這個(gè)單詞:(單詞,1)(不管之前有沒有遇到過這個(gè)單詞,也就是說可能出現(xiàn)多個(gè)相同單詞的記錄)。之后將再派一個(gè)人把相同單詞的記錄相加,即可得到最終結(jié)果。
詞頻統(tǒng)計(jì)的具體實(shí)現(xiàn)可見點(diǎn)我。
下面是使用MapReduce實(shí)現(xiàn)PageRank的具體代碼[^ref_9]。首先是通用的map與reduce模塊。若是感覺理解有困難,可以先看看詞頻統(tǒng)計(jì)的實(shí)現(xiàn)代碼,其中同樣使用了下面的模塊:
class MapReduce:__doc__ = '''提供map_reduce功能'''@staticmethoddef map_reduce(i, mapper, reducer):"""map_reduce方法:param i: 需要MapReduce的集合:param mapper: 自定義mapper方法:param reducer: 自定義reducer方法:return: 以自定義reducer方法的返回值為元素的一個(gè)列表"""intermediate = [] # 存放所有的(intermediate_key, intermediate_value)for (key, value) in i.items():intermediate.extend(mapper(key, value))# sorted返回一個(gè)排序好的list,因?yàn)閘ist中的元素是一個(gè)個(gè)的tuple,key設(shè)定按照tuple中第幾個(gè)元素排序# groupby把迭代器中相鄰的重復(fù)元素挑出來放在一起,key設(shè)定按照tuple中第幾個(gè)元素為關(guān)鍵字來挑選重復(fù)元素# 下面的循環(huán)中g(shù)roupby返回的key是intermediate_key,而group是個(gè)list,是1個(gè)或多個(gè)# 有著相同intermediate_key的(intermediate_key, intermediate_value)groups = {}for key, group in itertools.groupby(sorted(intermediate, key=lambda im: im[0]), key=lambda x: x[0]):groups[key] = [y for x, y in group]# groups是一個(gè)字典,其key為上面說到的intermediate_key,value為所有對(duì)應(yīng)intermediate_key的intermediate_value# 組成的一個(gè)列表return [reducer(intermediate_key, groups[intermediate_key]) for intermediate_key in groups]接著是計(jì)算PR值的類,其中實(shí)現(xiàn)了用于計(jì)算PR值的mapper和reducer:
class PRMapReduce:__doc__ = '''計(jì)算PR值'''def __init__(self, dg):self.damping_factor = 0.85 # 阻尼系數(shù),即αself.max_iterations = 100 # 最大迭代次數(shù)self.min_delta = 0.00001 # 確定迭代是否結(jié)束的參數(shù),即?self.num_of_pages = len(dg.nodes()) # 總網(wǎng)頁數(shù)# graph表示整個(gè)網(wǎng)絡(luò)圖。是字典類型。# graph[i][0] 存放第i網(wǎng)頁的PR值# graph[i][1] 存放第i網(wǎng)頁的出鏈數(shù)量# graph[i][2] 存放第i網(wǎng)頁的出鏈網(wǎng)頁,是一個(gè)列表self.graph = {}for node in dg.nodes():self.graph[node] = [1.0 / self.num_of_pages, len(dg.neighbors(node)), dg.neighbors(node)]def ip_mapper(self, input_key, input_value):"""看一個(gè)網(wǎng)頁是否有出鏈,返回值中的 1 沒有什么物理含義,只是為了在map_reduce中的groups字典的key只有1,對(duì)應(yīng)的value為所有的懸掛網(wǎng)頁的PR值:param input_key: 網(wǎng)頁名,如 A:param input_value: self.graph[input_key]:return: 如果沒有出鏈,即懸掛網(wǎng)頁,那么就返回[(1,這個(gè)網(wǎng)頁的PR值)];否則就返回[]"""if input_value[1] == 0:return [(1, input_value[0])]else:return []def ip_reducer(self, input_key, input_value_list):"""計(jì)算所有懸掛網(wǎng)頁的PR值之和:param input_key: 根據(jù)ip_mapper的返回值來看,這個(gè)input_key就是:1:param input_value_list: 所有懸掛網(wǎng)頁的PR值:return: 所有懸掛網(wǎng)頁的PR值之和"""return sum(input_value_list)def pr_mapper(self, input_key, input_value):"""mapper方法:param input_key: 網(wǎng)頁名,如 A:param input_value: self.graph[input_key],即這個(gè)網(wǎng)頁的相關(guān)信息:return: [(網(wǎng)頁名, 0.0), (出鏈網(wǎng)頁1, 出鏈網(wǎng)頁1分得的PR值), (出鏈網(wǎng)頁2, 出鏈網(wǎng)頁2分得的PR值)...]"""return [(input_key, 0.0)] + [(out_link, input_value[0] / input_value[1]) for out_link in input_value[2]]def pr_reducer_inter(self, intermediate_key, intermediate_value_list, dp):"""reducer方法:param intermediate_key: 網(wǎng)頁名,如 A:param intermediate_value_list: A所有分得的PR值的列表:[0.0,分得的PR值,分得的PR值...]:param dp: 所有懸掛網(wǎng)頁的PR值之和:return: (網(wǎng)頁名,計(jì)算所得的PR值)"""return (intermediate_key,self.damping_factor * sum(intermediate_value_list) +self.damping_factor * dp / self.num_of_pages +(1.0 - self.damping_factor) / self.num_of_pages)def page_rank(self):"""計(jì)算PR值,每次迭代都需要兩次調(diào)用MapReduce。一次是計(jì)算懸掛網(wǎng)頁P(yáng)R值之和,一次是計(jì)算所有網(wǎng)頁的PR值:return: self.graph,其中的PR值已經(jīng)計(jì)算好"""iteration = 1 # 迭代次數(shù)change = 1 # 記錄每輪迭代后的PR值變化情況,初始值為1保證至少有一次迭代while change > self.min_delta:print("Iteration: " + str(iteration))# 因?yàn)榭赡艽嬖趹覓炀W(wǎng)頁,所以才有下面這個(gè)dangling_list# dangling_list存放的是[所有懸掛網(wǎng)頁的PR值之和]# dp表示所有懸掛網(wǎng)頁的PR值之和dangling_list = MapReduce.map_reduce(self.graph, self.ip_mapper, self.ip_reducer)if dangling_list:dp = dangling_list[0]else:dp = 0# 因?yàn)镸apReduce.map_reduce中要求的reducer只能有兩個(gè)參數(shù),而我們# 需要傳3個(gè)參數(shù)(多了一個(gè)所有懸掛網(wǎng)頁的PR值之和,即dp),所以采用# 下面的lambda表達(dá)式來達(dá)到目的# new_pr為一個(gè)列表,元素為:(網(wǎng)頁名,計(jì)算所得的PR值)new_pr = MapReduce.map_reduce(self.graph, self.pr_mapper, lambda x, y: self.pr_reducer_inter(x, y, dp))# 計(jì)算此輪PR值的變化情況change = sum([abs(new_pr[i][1] - self.graph[new_pr[i][0]][0]) for i in range(self.num_of_pages)])print("Change: " + str(change))# 更新PR值for i in range(self.num_of_pages):self.graph[new_pr[i][0]][0] = new_pr[i][1]iteration += 1return self.graph最后是測試部分,我使用了python的digraph創(chuàng)建了一個(gè)有向圖,并調(diào)用上面的方法來計(jì)算PR值:
if __name__ == '__main__':dg = digraph()dg.add_nodes(["A", "B", "C", "D", "E"])dg.add_edge(("A", "B"))dg.add_edge(("A", "C"))dg.add_edge(("A", "D"))dg.add_edge(("B", "D"))dg.add_edge(("C", "E"))dg.add_edge(("D", "E"))dg.add_edge(("B", "E"))dg.add_edge(("E", "A"))pr = PRMapReduce(dg)page_ranks = pr.page_rank()print("The final page rank is")for key, value in page_ranks.items():print(key + " : ", value[0])附上運(yùn)行結(jié)果:
Iteration: 44 Change: 1.275194338951069e-05 Iteration: 45 Change: 1.0046004543212694e-05 Iteration: 46 Change: 7.15337406470562e-06 The final page rank is E : 0.3133376132128915 C : 0.11396289866948645 B : 0.11396289866948645 A : 0.2963400114149353 D : 0.1623965780332006以上便是PageRank的MapReduce實(shí)現(xiàn)。代碼中的注釋較為詳細(xì),理解應(yīng)該不難。
6. PageRank算法的缺點(diǎn)
這是一個(gè)天才的算法,原理簡單但效果驚人。然而,PageRank算法還是有一些弊端。
第一,沒有區(qū)分站內(nèi)導(dǎo)航鏈接。很多網(wǎng)站的首頁都有很多對(duì)站內(nèi)其他頁面的鏈接,稱為站內(nèi)導(dǎo)航鏈接。這些鏈接與不同網(wǎng)站之間的鏈接相比,肯定是后者更能體現(xiàn)PageRank值的傳遞關(guān)系。
第二,沒有過濾廣告鏈接和功能鏈接(例如常見的“分享到微博”)。這些鏈接通常沒有什么實(shí)際價(jià)值,前者鏈接到廣告頁面,后者常常鏈接到某個(gè)社交網(wǎng)站首頁。
第三,對(duì)新網(wǎng)頁不友好。一個(gè)新網(wǎng)頁的一般入鏈相對(duì)較少,即使它的內(nèi)容的質(zhì)量很高,要成為一個(gè)高PR值的頁面仍需要很長時(shí)間的推廣。
針對(duì)PageRank算法的缺點(diǎn),有人提出了TrustRank算法。其最初來自于2004年斯坦福大學(xué)和雅虎的一項(xiàng)聯(lián)合研究,用來檢測垃圾網(wǎng)站。TrustRank算法的工作原理:先人工去識(shí)別高質(zhì)量的頁面(即“種子”頁面),那么由“種子”頁面指向的頁面也可能是高質(zhì)量頁面,即其TR值也高,與“種子”頁面的鏈接越遠(yuǎn),頁面的TR值越低。“種子”頁面可選出鏈數(shù)較多的網(wǎng)頁,也可選PR值較高的網(wǎng)站。
TrustRank算法給出每個(gè)網(wǎng)頁的TR值。將PR值與TR值結(jié)合起來,可以更準(zhǔn)確地判斷網(wǎng)頁的重要性。
7. 寫在最后
谷歌用PR值來劃分網(wǎng)頁的等級(jí),有0~10級(jí),一般4級(jí)以上的都是比較好的網(wǎng)頁了。谷歌自己PR值為9,百度也是9,博客園的PR值則為6。
如今PR值雖不如以前重要了(沒有區(qū)分頁面內(nèi)的導(dǎo)航鏈接、廣告鏈接和功能鏈接導(dǎo)致PR值本身能夠反映出的網(wǎng)頁價(jià)值不精確,并且對(duì)新網(wǎng)頁不友好),但是流量交易里PR值還是個(gè)很重要的參考因素。
最后,有一個(gè)圖形化網(wǎng)站提供PageRank過程的動(dòng)態(tài)圖:點(diǎn)我。
最近發(fā)現(xiàn)博客園對(duì)于markdown語法的支持不太好。如果文中有公式顯示不完全的話,可以去這里看。
參考資料
1:《這就是搜索引擎:核心技術(shù)詳解》,張俊林
2:當(dāng)年P(guān)ageRank誕生的論文:The PageRank Citation Ranking: Bringing Order to the Web
3:維基百科PageRank
4:PageRank算法簡介及Map-Reduce實(shí)現(xiàn)
5:博客《谷歌背后的數(shù)學(xué)》,盧昌海
6:博客PageRank背后的數(shù)學(xué)
7:深入淺出PageRank算法
8:MapReduce原理與設(shè)計(jì)思想
9:Using MapReduce to compute PageRank
轉(zhuǎn)載于:https://www.cnblogs.com/rubinorth/p/5799848.html
總結(jié)
以上是生活随笔為你收集整理的PageRank算法--从原理到实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用device.js检测设备并实现不同
- 下一篇: 计算字符个数