转载请注明出处:http://blog.csdn.net/rubinorth/article/details/52231620

本文介绍HITS算法的相关内容。

  • 算法来源
  • 算法原理
  • 算法证明
  • 算法实现
    • 1 基于迭代法的简单实现
    • 2 MapReduce实现
  • HITS算法的缺点
  • 写在最后
  • 参考资料

1. 算法来源

1999年,Jon Kleinberg 提出了HITS算法。作为几乎是与PageRank同一时期被提出的算法,HITS同样以更精确的搜索为目的,并到今天仍然是一个优秀的算法。

HITS算法的全称是Hyperlink-Induced Topic Search。在HITS算法中,每个页面被赋予两个属性:hub属性和authority属性。同时,网页被分为两种:hub页面和authority页面。hub,中心的意思,所以hub页面指那些包含了很多指向authority页面的链接的网页,比如国内的一些门户网站;authority页面则指那些包含有实质性内容的网页。HITS算法的目的是:当用户查询时,返回给用户高质量的authority页面。


2. 算法原理

很多算法都是建立在一些假设之上的,HITS算法也不例外。HITS算法基于下面两个假设1:

  • 一个高质量的authority页面会被很多高质量的hub页面所指向。
  • 一个高质量的hub页面会指向很多高质量的authority页面。

什么叫“高质量”,这由每个页面的hub值和authority值确定。其确定方法为:

  • 页面hub值等于所有它指向的页面的authority值之和。
  • 页面authority值等于所有指向它的页面的hub值之和。

为了让大家快速理解HITS算法,先举一个简单的例子2。

图中共有3个网页,它们构成了一个有向图。我们设每个网页的初始hub值和authority值都为1。记 h(p) h(p)为页面 p p的hub值,a(p)a(p)为页面 p p的authority值。则有h(1)=h(2)=h(3)=1h(1)=h(2)=h(3)=1, a(1)=a(2)=a(3)=1 a(1)=a(2)=a(3)=1。

HITS算法的计算过程也是一个迭代的过程。在第一次迭代中,有:

a(1)=0,a(2)=0,a(3)=h(1)+h(2)=2(没有页面指向网页1和网页2)h(1)=a(3)=2,h(2)=a(3)=2,h(3)=0(网页3没有指向任何页面)

a(1) = 0, a(2) = 0, a(3) = h(1) + h(2) = 2 (没有页面指向网页1和网页2)\\ h(1) = a(3) = 2, h(2) = a(3) = 2, h(3) = 0 (网页3没有指向任何页面)

这里就已经可以看出网页3是一个相对好的authority页面,而网页1和网页2是相对好的hub页面。其实到这里迭代也可以结束了,因为再迭代下去无非是 a(3) a(3), h(1) h(1)与 h(2) h(2)的值不断增大,而哪个是hub页面,哪个是authority页面并不会改变。

上面的简单例子只是为了帮助理解,省略掉了很多步骤和细节。下面将详细地介绍HITS算法3:。

与PageRank算法不同,HITS算法是在用户搜索后运行的,所以HITS算法的处理对象集合肯定得小很多。

首先,我们需要确定这个集合。整个互联网中的网页之间的关系可以抽象为一个有向图 G=(V,E) G = (V,E),当有一个搜索请求产生时(不妨设关键字为 σ \sigma),我们可以取所有包含关键字 σ \sigma的网页组成的集合 Qσ Q_\sigma为初始集合,并在这个集合上运行我们的HITS算法。然而,这个集合却有着明显的缺陷:这个集合可能非常之大,大到包含了数百万个网页,而这显然不是理想的集合大小。于是,我们进而想找到一个更小的集合 Sσ S_\sigma,满足以下条件:

  1. Sσ S_\sigma确实足够小。
  2. Sσ S_\sigma包含很多与查询相关的页面。
  3. Sσ S_\sigma包含很多高质量的authority页面。

如何找到这个 Sσ S_\sigma集合?我们假设用户输入关键字搜索,搜索引擎使用一个基于文本的引擎进行搜索。然后我们取排名(按照相关度排名)最靠前的t(t一般取200左右)个网页作为初始集合,记为根集合 Rσ R_\sigma。这个集合满足我们上面提到的前两个条件,但是还远远不能满足第三个条件。

于是,我们需要扩展 Rσ R_\sigma。一般认为,一个与关键字相关的高质量的网页即使不在 Rσ R_\sigma中,那也很可能在 Rσ R_\sigma中有某些网页指向它。基于此,我们扩展 Rσ R_\sigma的过程如下(摘自Jon Kleinberg 的论文):

Subgraph( σ \sigma, ψ \psi, t, d)
   σ \sigma: a query string.
   ψ \psi: a text-based search engine.
  t, d: natural numbers.

  Let Rσ R_\sigma denote the top t results of ψ \psi on σ \sigma.
  Set Sσ S_\sigma := Rσ R_\sigma

  For each page p ∈ \in Rσ R_\sigma
    Let Γ+(p) \Gamma^+(p) denote the set of all pages p points to.
    Let Γ−(p) \Gamma^-(p) denote the set of all pages pointing to p.
    Add all pages in Γ+(p) \Gamma^+(p) to Sσ S_\sigma.
    If |Γ−(p)|≤d |\Gamma^-(p)| \leq d, then
      Add all pages in Γ−(p) \Gamma^-(p) to Sσ S_\sigma.
    Else
      Add an arbitrary set of d pages from Γ−(p) \Gamma^-(p) to Sσ S_\sigma.
  End
  Return Sσ S_\sigma

一开始我们令 Sσ S_\sigma = Rσ R_\sigma。然后通过上面的方法,我们将所有被 Rσ R_\sigma中网页所指向的网页加入到 Sσ S_\sigma中,再把一定数量的指向 Rσ R_\sigma集合中网页的那些网页(每个 Rσ R_\sigma中网页最多能添加d个指向它的网页)加入到 Sσ S_\sigma中。为了保证 Sσ S_\sigma集合的合适的大小,d不能太大,一般设置为50左右。通常情况下,扩展之后集合的大小为1000~5000个网页,满足上面的三个条件。

在计算hub值和authority值之前,我们还需要对 Sσ S_\sigma进行一下处理。我们把同一个“域名”(域名指一个网站)下的网页之间的链接全部删除,因为通常这些链接只是为了让人能在这个网站下的不同网页之间进行切换,例如网站内的导航链接。在HITS算法中,这些链接与不同网站之间的链接相比,肯定是后者更能体现hub值和authority值的传递关系。所以我们在 Sσ S_\sigma集合中删除这些链接,形成新集合 Gσ G_\sigma。

现在,就可以开始计算hub值和authority值了4。我们用 h(p) h(p)表示页面 p p的hub值,a(p)a(p)表示页面 p p的authority值。首先令每个页面的初始hub值h(p)h(p)为1,初始authority值 a(p) a(p)也为1。然后就开始迭代计算的过程(n为 Gσ G_\sigma中总的网页数):

∀p,a(p)=∑i=1nh(i),∀p,h(p)=∑i=1na(i)

\forall p, a(p) = \sum_{i = 1}^n h(i), \\ \forall p, h(p) = \sum_{i = 1}^n a(i)

每一轮迭代结束,都需要进行标准化,使 ∑ni=1h(i)2=∑ni=1a(i)2=1 \sum_{i = 1}^n h(i)^2 = \sum_{i = 1}^n a(i)^2 = 1。标准化的必要性将在算法证明部分解释。

什么时候迭代结束呢?我们可以设置一个迭代次数上限k来控制,或者设定一个阈值,当变化小于阈值的时候迭代结束。然后只要返回给用户authority值靠前的十几个网页就行了。

好了,HITS算法的原理其实就这么点,十分通俗易懂。


3. 算法证明

上面说到如何控制迭代的终止,而这又有个前提条件,那就是经过不断的迭代,每个网页的hub值和authority值最终会收敛。下面我们就来证明HITS算法的收敛性。

为了证明的方便,我们用矩阵的方式来表示HITS算法。

对于初始集合 Gσ G_\sigma,用一个矩阵 M M表示GσG_\sigma中网页之间的关系: mij=1 m_{ij} = 1表示网页 i i指向网页jj,否则为0。用向量 H H表示所有页面的hub值,其中第i个分量表示网页i的hub值;用向量AA表示所有页面的authority值,其中第i个分量表示网页i的authority值。所有页面的hub值和authority值初始都为1。例如上面算法原理的例子中的图就可以表示为:

M=⎛⎝⎜000000110⎞⎠⎟

M = \left(\begin{array}{ccc}0 & 0 & 1 \\ 0 & 0 & 1 \\ 0 & 0 & 0 \\ \end{array}\right)

然后可以计算:

A=MTH=⎛⎝⎜001001000⎞⎠⎟⎛⎝⎜111⎞⎠⎟=⎛⎝⎜002⎞⎠⎟,H=MA=⎛⎝⎜000000110⎞⎠⎟⎛⎝⎜002⎞⎠⎟=⎛⎝⎜220⎞⎠⎟

A = M^T H = \left(\begin{array}{ccc}0 & 0 & 0 \\ 0 & 0 & 0 \\ 1 & 1 & 0 \\ \end{array}\right)\left(\begin{array}{ccc}1 \\ 1 \\ 1 \\ \end{array}\right)=\left(\begin{array}{ccc}0 \\ 0 \\ 2 \\ \end{array}\right), \\ H = M A = \left(\begin{array}{ccc}0 & 0 & 1 \\ 0 & 0 & 1 \\ 0 & 0 & 0 \\ \end{array}\right)\left(\begin{array}{ccc}0 \\ 0 \\ 2 \\ \end{array}\right)=\left(\begin{array}{ccc}2 \\ 2 \\ 0 \\ \end{array}\right)

一般的,我们有:

Ak=MTHk−1,Hk=MAk(每一轮先计算Ak,然后根据Ak计算Hk)

A_k = M^T H_{k - 1}, \\ H_k = M A_k \\ (每一轮先计算A_k,然后根据A_k计算H_k)

更进一步,有:

Ak=(MTM)k−1MTZ,Hk=(MMT)kZ(其中Z的所有分量都为1)

A_k = (M^T M)^{k - 1} M^T Z, \\ H_k = (M M^T)^k Z \\ (其中Z的所有分量都为1)

在这里我们引用一些线性代数的知识:

定理1
一个矩阵与该矩阵的转置的乘积是对称矩阵。
定理2
实对称矩阵的特征值都是实数,且若矩阵大小为n * n,则其必有n个实特征值(包含重根)。
定理3
含有n个特征值的n阶矩阵,其主对角线元素之和等于其特征值之和。
定义1
对于实数矩阵,绝对值最大的特征值称为主特征值,对应的特征向量称为主特征向量。
定理4
如果一个实对称矩阵是非负矩阵,则其主特征向量也是非负的,并且是非0向量。
定理5
令 W W为一个n*n实对称矩阵,vv是一个n维向量且与 W W的主特征向量ωw\omega_w非正交,则一个n维单位向量将沿着 Wkv W^k v的方向收敛至 ωw \omega_w。

由定理1可知上面的 MTM M^T M和 MMT M M^T都是对称矩阵,且由定理2可知都有n个实特征值。

在 Hk=(MMT)kZ H_k = (M M^T)^k Z中, Z Z与MTMM^T M的主特征向量非正交,所以 H H向量最终将收敛至MTMM^T M的主特征向量。定理5中的单位向量指的就是 H H向量,为了保证其每轮迭代时都是一个单位向量,我们在每次迭代之后都对其进行标准化

在Ak=(MTM)k−1MTZA_k = (M^T M)^{k - 1} M^T Z中, MTZ M^T Z与 MTM M^T M的主特征向量非正交。证明如下(这部分证明在 Jon Kleinberg 的原论文中省略了,自行证明,仅供参考):

假设MTZ与MTM的主特征向量ωw正交,则有:(MTZ)Tωw=0⇒(ZTM)ωw=0⇒ZT(Mωw)=0∵M是非负矩阵,ωw也是非负矩阵∴Mωw是非负矩阵

假设 M^T Z与M^T M的主特征向量\omega_w正交,则有: \\ (M^T Z)^T \omega_w = 0 \\ \Rightarrow (Z^T M) \omega_w = 0 \\ \Rightarrow Z^T (M \omega_w) = 0 \\ \because M是非负矩阵,\omega_w也是非负矩阵 \\ \therefore M \omega_w是非负矩阵

我们只要再证 Mωw M \omega_w不是 0 0矩阵,就可以推翻我们的假设了。因为ZTZ^T的所有分量都为1,所以 ZT Z^T与非负且非0矩阵的内积一定不为0。在进一步证明之前,我们先证 MTM的主特征值λw≠0 M^T M 的主特征值 \lambda_w \neq 0:

令mij为矩阵M第i行第j列的元素即M=⎛⎝⎜⎜m11⋮mn1…mij…m1n⋮mnn⎞⎠⎟⎟,MT=⎛⎝⎜⎜m11⋮m1n…mji…mn1⋮mnn⎞⎠⎟⎟则MTM的主对角线元素wii=∑j=1nm2ji∵M不是0矩阵∴wii不全为0∴MTM主对角线元素之和必不为0又∵由定理2和定理3可知对称矩阵的主对角线元素之和为特征值之和∴MTM的特征值之和必不为0∴MTM的主特征值λw≠0

令m_{ij}为矩阵M第i行第j列的元素 \\ 即M = \left(\begin{array}{ccc}m_{11} & \dots & m_{1n} \\ \vdots & m_{ij} & \vdots \\ m_{n1} & \dots & m_{nn} \\ \end{array}\right), M^T = \left(\begin{array}{ccc}m_{11} & \dots & m_{n1} \\ \vdots & m_{ji} & \vdots \\ m_{1n} & \dots & m_{nn} \\ \end{array}\right) \\ 则M^T M 的主对角线元素w_{ii} = \sum_{j = 1}^n m_{ji}^2 \\ \because M不是0矩阵 \\ \therefore w_{ii}不全为0 \\ \therefore M^T M 主对角线元素之和必不为0 \\ 又 \because 由定理2和定理3可知对称矩阵的主对角线元素之和为特征值之和 \\ \therefore M^T M 的特征值之和必不为0 \\ \therefore M^T M 的主特征值 \lambda_w \neq 0

下面证明 Mωw M \omega_w不是 0 0矩阵:

∵ωw是MTM的主特征向量∴有MTMωw=λwωw,其中λw为主特征值假设Mωw是0矩阵,则:MTMωw=0⇒λwωw=0但这显然不成立∵λw≠0且ωw是非负矩阵∴λwωw≠0∴假设不成立∴Mωw不是0矩阵

\because \omega_w是M^T M的主特征向量 \\ \therefore 有 M^T M \omega_w = \lambda_w \omega_w,其中 \lambda_w 为主特征值 \\ 假设M \omega_w 是0矩阵,则: \\ M^T M \omega_w = 0 \Rightarrow \lambda_w \omega_w = 0 \\ 但这显然不成立 \\ \because \lambda_w \neq 0 且 \omega_w是非负矩阵 \\ \therefore \lambda_w \omega_w \neq 0 \\ \therefore 假设不成立 \\ \therefore M \omega_w 不是0矩阵

再结合上面的结论: Mωw是非负矩阵 M \omega_w是非负矩阵,即可得出: Mωw M \omega_w是非负矩阵且不是 0 0矩阵。

所以上面的假设:假设MTZ与MTM的主特征向量ωw正交假设 M^T Z与M^T M的主特征向量\omega_w 正交 不成立。所以 MTZ M^T Z与 MTM M^T M的主特征向量非正交。也即 A A向量最终将收敛至MTMM^T M的主特征向量。同样的,为了保证其每轮迭代时都是一个单位向量,我们在每次迭代之后都对其进行标准化

至此,我们便证明了HITS算法的收敛性。


4. 算法实现

下面的代码原理与我的另一篇博客PageRank相似。

4.1 基于迭代法的简单实现

用python实现,需要先安装python-graph-core。

class HITSIterator:__doc__ = '''计算一张图中的hub,authority值'''def __init__(self, dg):self.max_iterations = 100  # 最大迭代次数self.min_delta = 0.0001  # 确定迭代是否结束的参数self.graph = dgself.hub = {}self.authority = {}for node in self.graph.nodes():self.hub[node] = 1self.authority[node] = 1def hits(self):"""计算每个页面的hub,authority值:return:"""if not self.graph:returnflag = Falsefor i in range(self.max_iterations):change = 0.0  # 记录每轮的变化值norm = 0  # 标准化系数tmp = {}# 计算每个页面的authority值tmp = self.authority.copy()for node in self.graph.nodes():self.authority[node] = 0for incident_page in self.graph.incidents(node):  # 遍历所有“入射”的页面self.authority[node] += self.hub[incident_page]norm += pow(self.authority[node], 2)# 标准化norm = sqrt(norm)for node in self.graph.nodes():self.authority[node] /= normchange += abs(tmp[node] - self.authority[node])# 计算每个页面的hub值norm = 0tmp = self.hub.copy()for node in self.graph.nodes():self.hub[node] = 0for neighbor_page in self.graph.neighbors(node):  # 遍历所有“出射”的页面self.hub[node] += self.authority[neighbor_page]norm += pow(self.hub[node], 2)# 标准化norm = sqrt(norm)for node in self.graph.nodes():self.hub[node] /= normchange += abs(tmp[node] - self.hub[node])print("This is NO.%s iteration" % (i + 1))print("authority", self.authority)print("hub", self.hub)if change < self.min_delta:flag = Truebreakif flag:print("finished in %s iterations!" % (i + 1))else:print("finished out of 100 iterations!")print("The best authority page: ", max(self.authority.items(), key=lambda x: x[1]))print("The best hub page: ", max(self.hub.items(), key=lambda x: x[1]))if __name__ == '__main__':dg = digraph()dg.add_nodes(["A", "B", "C", "D", "E"])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"))hits = HITSIterator(dg)hits.hits()

程序中给出的网页之间的关系如下:

运行结果如下:

This is NO.9 iteration
authority {'E': 0.7886751345855355, 'C': 0.2113248654398108, 'B': 0.0, 'A': 7.119870133749228e-06, 'D': 0.5773502691457247}
hub {'E': 3.6855159786102477e-06, 'C': 0.40824829046663563, 'B': 0.7071067811721405, 'A': 0.40824829046663563, 'D': 0.40824829046663563}
finished in 9 iterations!
The best authority page:  ('E', 0.7886751345855355)
The best hub page:  ('B', 0.7071067811721405)

4.2 MapReduce实现

MapReduce是一个高效的分布式计算框架,在这里就不多做介绍了(若还不怎么了解MapReduce可以参考我另一篇博客PageRank,里面有简单的原理介绍和代码展示)。

下面是实现HITS算法的类,其中注释较为详细,就不多做解释了:

class HITSMapReduce:__doc__ = '''计算一张图中的hub,authority值'''def __init__(self, dg):self.max_iterations = 100  # 最大迭代次数self.min_delta = 0.0001  # 确定迭代是否结束的参数# graph表示整个网络图。是字典类型。# graph[i][authority][0] 存放第i网页的authority值# graph[i][authority][1] 存放第i网页的入链网页,是一个列表# graph[i][hub][0] 存放第i网页的hub值# graph[i][hub][1] 存放第i网页的出链网页,是一个列表self.graph = {}for node in dg.nodes():self.graph[node] = {"authority": [1, dg.incidents(node)], "hub": [1, dg.neighbors(node)]}@staticmethoddef normalize(ah_list):"""标准化:param ah_list: 一个列表,其元素为(网页名,数值):return: 返回一个标准化的列表,其元素为(网页名,标准化的数值)"""norm = 0for ah in ah_list:norm += pow(ah[1], 2)norm = sqrt(norm)return [(ah[0], ah[1] / norm) for ah in ah_list]def hits_authority_mapper(self, input_key, input_value):"""用于计算每个页面能获得的hub值,这个hub值将传递给页面的authority值:param input_key: 网页名,如 A:param input_value: self.graph[input_key],即这个网页的相关信息,包含两个字典,{a...}和{h...}:return: [(网页名, 0.0), (出链网页1, A的hub值), (出链网页2, A的hub值)...]"""return [(input_key, 0.0)] + \[(out_link, input_value["hub"][0]) for out_link in input_value["hub"][1]]def hits_hub_mapper(self, input_key, input_value):"""用于计算每个页面能获得的authority值,这个authority值将传递给页面的hub值:param input_key: 网页名,如 A:param input_value: self.graph[input_key],即这个网页的相关信息,包含两个字典,{a...}和{h...}:return: [(网页名, 0.0), (入链网页1, A的authority值), (入链网页2, A的authority值)...]"""return [(input_key, 0.0)] + \[(in_link, input_value["authority"][0]) for in_link in input_value["authority"][1]]def hits_reducer(self, intermediate_key, intermediate_value_list):"""统计每个网页获得的authority或hub值:param intermediate_key: 网页名,如 A:param intermediate_value_list: A所有获得的authority值或hub值的列表:[0.0,获得的值,获得的值...]:return: (网页名,计算所得的authority值或hub值)"""return intermediate_key, sum(intermediate_value_list)def hits(self):"""计算authority值与hub值,各需要调用一次mapreduce模块:return: self.graph,其中的 authority值与hub值 已经计算好"""iteration = 1  # 迭代次数change = 1  # 记录每轮迭代后的PR值变化情况,初始值为1保证至少有一次迭代while change > self.min_delta:print("Iteration: " + str(iteration))# 计算每个页面的authority值并标准化# new_authority为一个列表,元素为:(网页名,此轮迭代所得的authority值)new_authority = HITSMapReduce.normalize(MapReduce.map_reduce(self.graph, self.hits_authority_mapper, self.hits_reducer))# 计算每个页面的hub值并标准化# new_hub为一个列表,元素为:(网页名,此轮迭代所得的hub值)new_hub = HITSMapReduce.normalize(MapReduce.map_reduce(self.graph, self.hits_hub_mapper, self.hits_reducer))# 计算此轮 authority值+hub值 的变化情况change = sum([abs(new_authority[i][1] - self.graph[new_authority[i][0]]["authority"][0]) for i in range(len(self.graph))])change += sum([abs(new_hub[i][1] - self.graph[new_hub[i][0]]["hub"][0]) for i in range(len(self.graph))])print("Change: " + str(change))# 更新authority值与hub值for i in range(len(self.graph)):self.graph[new_authority[i][0]]["authority"][0] = new_authority[i][1]self.graph[new_hub[i][0]]["hub"][0] = new_hub[i][1]iteration += 1return self.graph

下面是一个测试用例:

if __name__ == '__main__':dg = digraph()dg.add_nodes(["A", "B", "C", "D", "E"])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"))h = HITSMapReduce(dg)hits_result = h.hits()print("The final iteration result is")for key, value in hits_result.items():print(key + " authority: ", value["authority"][0], " hub: ", value["hub"][0])max_authority_page = max(hits_result.items(), key=lambda x: x[1]["authority"][0])max_hub_page = max(hits_result.items(), key=lambda x: x[1]["hub"][0])print("The best authority page: ", (max_authority_page[0], max_authority_page[1]["authority"][0]))print("The best hub page: ", (max_hub_page[0], max_hub_page[1]["hub"][0]))

运行结果为:

The final iteration result is
E authority:  0.7886751345948128  hub:  8.64738646858812e-10
A authority:  7.060561487452559e-10  hub:  0.408267180858587
C authority:  0.2113248654051872  hub:  0.40823884510260666
B authority:  0.0  hub:  0.7071067809972986
D authority:  0.5773502691896258  hub:  0.40823884510260666
The best authority page:  ('E', 0.7886751345948128)
The best hub page:  ('B', 0.7071067809972986)

以上便是HITS算法的MapReduce实现。


5. HITS算法的缺点

  • 计算效率低

这里说的“效率低”是针对其实时计算的特点而提出的。HITS算法是在用户提出搜索请求之后才开始运行的,然而计算出结果又需要多次迭代计算,所以就这点上来说HITS算法效率仍然较低。

  • 主题漂移

在算法原理部分我们介绍了HITS算法是如何生成初始集合 Gσ G_\sigma。从根集合 Rσ R_\sigma我们通过链接添加网页的方法进行扩展,但这也很可能添加进与搜索主题无关的网页。若是这部分网页中又恰恰有着一些高质量的authority页面,则很有可能返回给用户,降低用户的搜索体验。

  • 作弊网页

试想我们弄一个页面指向很多高质量的authority页面,那么这个页面就成为了一个高质量的hub页面。然后再弄个链接指向自己的搓网页,按照HITS算法,将大大提升自己的搓网页的authority值。

  • 稳定性差

对于一个网页集合,若是删除其中的某条链接,就有可能造成一些网页的hub值和authority值发生巨大变化。


6. 写在最后

以后想到什么再写上来吧。


参考资料


  1. 《这就是搜索引擎:核心技术详解》,张俊林 ↩
  2. The Mathematics of Web Search,这个网站上有HITS和PageRank的一些数学知识。 ↩
  3. 原论文:Authoritative Sources in a Hyperlinked Environment ↩
  4. “标准参考文献”:维基百科 ↩

HITS算法--从原理到实现相关推荐

  1. 链接挖掘算法之PageRank算法和HITS算法

    参考资料:http://blog.csdn.net/hguisu/article/details/7996185 更多数据挖掘算法:https://github.com/linyiqun/DataMi ...

  2. deeplearning算法优化原理

    deeplearning算法优化原理 目录 • 量化原理介绍 • 剪裁原理介绍 • 蒸馏原理介绍 • 轻量级模型结构搜索原理介绍 Quantization Aware Training量化介绍 1.1 ...

  3. 【机器学习入门】(1) K近邻算法:原理、实例应用(红酒分类预测)附python完整代码及数据集

    各位同学好,今天我向大家介绍一下python机器学习中的K近邻算法.内容有:K近邻算法的原理解析:实战案例--红酒分类预测.红酒数据集.完整代码在文章最下面. 案例简介:有178个红酒样本,每一款红酒 ...

  4. 前景背景分割——ostu算法的原理及实现 OpenCV (八)

    OpenCV [八]--前景背景分割--ostu算法的原理及实现 实验结果 代码实现 实现原理 参考资料 实验结果 代码实现 #include<opencv2/opencv.hpp> #i ...

  5. 视觉SLAM开源算法ORB-SLAM3 原理与代码解析

    来源:深蓝学院,文稿整理者:何常鑫,审核&修改:刘国庆 本文总结于上交感知与导航研究所科研助理--刘国庆关于[视觉SLAM开源算法ORB-SLAM3 原理与代码解析]的公开课. ORB-SLA ...

  6. 神经网络感知器算法调整原理是什么

    算法调整原理 如果点分类正确,则什么也不做. 如果点分类为正,但是标签为负,则分别减去 αp,αq, 和 α 至 w_1, w_2,w1​,w2​, 和 bb 如果点分类为负,但是标签为正,则分别将α ...

  7. Adaboost 算法的原理与推导

    Adaboost 算法的原理与推导 0 引言 一直想写Adaboost来着,但迟迟未能动笔.其算法思想虽然简单:听取多人意见,最后综合决策,但一般书上对其算法的流程描述实在是过于晦涩.昨日11月1日下 ...

  8. layer output 激活函数_一文彻底搞懂BP算法:原理推导+数据演示+项目实战(下篇)...

    在"一文彻底搞懂BP算法:原理推导+数据演示+项目实战(上篇)"中我们详细介绍了BP算法的原理和推导过程,并且用实际的数据进行了计算演练.在下篇中,我们将自己实现BP算法(不使用第 ...

  9. TCP协议、算法和原理

    TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面.所以学习TCP本身是个比较痛苦的过程,但对于学习的过程却能让人有很多收获. 关于TCP这个协议的细节,我还是推荐你 ...

最新文章

  1. 千呼万唤,ACS始出来
  2. 皮一皮:你的工资去哪了?实锤了!
  3. html中h3的样式,比较好看的css自定义样式(标题 h1 h2 h3)
  4. ASP.NET下QueryString不同字符编码间强制转换的解决方案
  5. qt 子窗口与父窗口数据通信_Qt实例--主窗口和子窗口互发信号
  6. 常用的redis命令
  7. MTK 驱动开发(5)---bootloader
  8. 【Flink】Flink Flink 1.14 新特性预览
  9. svn 命令行_小型工作室搭建SVN经验
  10. 算法竞赛入门 第2版 习题3-3 UVa1225
  11. (附源码)springboot电子阅览室app 毕业设计 016514
  12. QTP(Quick Test Professional)安装详细教程
  13. LVS+Keepalived+Nginx+Tomcat高可用负载均衡集群配置
  14. 广州“开四停四”交通限行,技术上是如何实现的?
  15. 微软服务器系统版本有几个,windows系统有几个版本
  16. 【canvas 太阳系的动画】
  17. PLC闪烁电路的实现
  18. pfamscan 的使用_科学网—[转载]InterProScan的使用教程 - 黄顺谋的博文
  19. 图书管理系统(数据库版)
  20. 监听Home键和锁屏键

热门文章

  1. Oracle导出报错: unknown command beginning “exp SCOTT/...“ - rest of line ignored.
  2. day007-列表和字典
  3. matlab 纯迟延_DMC算法MATLAB编程及仿真
  4. java实验报告:实验一 基于控制台的购书系统
  5. 【zotero】从知网万方维普WOS等数据库上导出格式引文-引文格式到zotero中
  6. 机器学习-数据科学库:matplotlib绘图
  7. OpenGL 实现 RGBA 转 I420
  8. 高通MDM平台-LK
  9. 我有一个自己的数字图书馆
  10. FrontEnd笔记 -- JavaScript