浅谈HITS算法

HITS算法

参考文献:HITS算法–从原理到实现、链接分析算法之 HITS算法、链接挖掘算法之PageRank算法和HITS算法、什么是HITS算法|集智百科。

还是建议阅读一下最初始的论文:Authoritative sources in a hyperlinked environment。

1、关于HITS

HITS全称为Hyperlink-Induced Topic Search。

在HITS算法中,每个页面被赋予两个属性:Hub属性和Authority属性。具有上述两种属性的网页分为两种:Hub页面和Authority页面。

Hub(枢纽)页面:类似于一个分类器,其为包含了很多指向高质量Authority页面链接的网页。例如,hao123首页汇集了全网优质网址,故可以认为其是一个典型的高质量Hub网页;

Authority(权威)页面:类似于一个聚类器,其为与某个领域或者某个话题相关的高质量网页。例如,京东首页、淘宝首页等,都是与网络购物领域相关的高质量网页。

HITS算法的目的即是通过一定的技术手段,在海量网页中找到与用户查询主题相关的高质量Authority页面和Hub页面,尤其是Authority页面,因为这些页面代表了能够满足用户查询的高质量内容,搜索引擎以此作为搜索结果返回给用户。

2、算法中心思想

HITS算法基于两个重要的假设:

(1)一个高质量的Authority页面会被很多高质量的Hub页面所指向;

(2)一个高质量的Hub页面会指向很多高质量的Authority页面。

其中,页面的质量由自身的Hub值或Authority值决定,如下图,即:

(1)页面Hub值等于所有它指向的页面的Authority值之和:H(1)=A(5)+A(6)+A(7);

(2)页面Authority值等于所有指向它的页面的Hub值之和:A(1)=H(2)+H(3)+H(4)。

由此可见,Hub页面和Authority页面相互迭代增强,每轮迭代计算更新每个页面的两个权值,直到权值稳定不再发生明显的变化为止。

浅谈HITS算法_第1张图片

其实,根据HITS算法的思想,不难看出,HITS算法中隐藏了一个二分图,即Hub页面和Authority页面被分成两类不同的节点。

浅谈HITS算法_第2张图片

假设左侧为Authority节点集,右边为Hub节点集。如果所有网页中构成的网络图中 i i i页面有指向 j j j页面的链接,则 e [ i ] [ j ] = 1 e[i][j]=1 e[i][j]=1,否则 e [ i ] [ j ] = 0 e[i][j]=0 e[i][j]=0。对于网络图中的每个页面节点 i i i,都存在两个权值hub[i]、auth[i],且初始值均为1。HITS算法的工作就是调整这两个权值的大小,使之满足:
a u t h [ i ]   = ∑ j = 1 n   h u b [ j ] ⋅ e [ j ] [ i ] , h u b [ i ]   = ∑ j = 1 n   a u t h [ j ] ⋅ e [ i ] [ j ] . {\rm auth}[i]\ =\sum^n_{j=1}\ {\rm hub} [j] \cdot {\rm e}[j][i], \\{\rm hub}[i]\ =\sum^n_{j=1}\ {\rm auth} [j] \cdot {\rm e}[i][j]. auth[i] =j=1n hub[j]e[j][i],hub[i] =j=1n auth[j]e[i][j].

3、算法和公式

HITS 算法步骤

(1) 接受一个用户查询的请求。HITS 算法与用户输入的查询请求密切相关,其是在用户执行查询操作后运行的,所以HITS算法的处理对象集合较PAgeRank算法小。它的查询结果是动态生成的,而 PageRank 算法则与用户的查询无关。

(2) 将查询提交给某个现有的搜索引擎(或者是自己构造的检索系统),并在返回的搜索结果中,提取排名在前n(n一般取200左右)的网页,得到一组与用户查询高度相关的初始网页集合,这个集合被称作为 root set(即根集),满足:

​ 1)根集中的网页数量较少;

​ 2)根集中的网页是与查询内容有关的网页;

但显然只满足上述两个条件的集合远远不够,所以要求在根集的基础可以上包含更多多的Authority网页。

(3) 在根集的基础上,将与根集内网页有直接链接指向关系的网页(每个网页取d个,d一般取50左右)扩充进来形成base set(即扩展集)。将扩展集中同一域名下的网页之间的链接删除,如网站导航链接等,因为这些链接只能使人在同一网站内的页面中跳转。显然比起这些同一网站内的链接,不同网站之间的链接更加能够体现Hub值和Authority值的传递。删除同一网站内的链接后,扩展集中的所有元素构成最终集。如下图,HITS算法就是在这个最终集合内寻找高质量的Hub页面与高质量的Authority页面。

浅谈HITS算法_第3张图片

(4) 计算最终集中所有页面的Hub值和Authority值:

​ 1)hub[i]、auth[i]分别表示网页节点i的Hub值和Authority值;

​ 2)对于最终集来说,我们并不知道哪些页面是高质量的Hub页面或者高质量的Authority页面,每个网页都有潜在的可能,所以对于每个页面都设立上述两个值,分别来记载这个页面是高质量的Hub页面或者Authority页面的可能性。在初始情况下,在没有更多可利用信息前,每个页面的这两个权值都是相同的,都设置为1。

​ 3)每次迭代计算Hub值和Authority权值:

​ ①某网页的Authority值 = 所有指向它的网页的Hub值之和:

a u t h [ i ]   = ∑ j = 1 n   h u b [ j ] ⋅ e [ j ] [ i ] {\rm auth}[i]\ =\sum^n_{j=1}\ {\rm hub} [j] \cdot {\rm e}[j][i] auth[i] =j=1n hub[j]e[j][i]

​ ②某网页的Hub值 = 所有它指向网页的Authority值之和:

h u b [ i ]   = ∑ j = 1 n   a u t h [ j ] ⋅ e [ i ] [ j ] {\rm hub}[i]\ =\sum^n_{j=1}\ {\rm auth} [j] \cdot {\rm e}[i][j] hub[i] =j=1n auth[j]e[i][j].

​ 假设矩阵M为最终集中网页及链接对应的矩阵,A为由各网页Authority值构成的一维列向量,H为由各网页 Hub值构成的一维列向量,则在每次迭代过程中,实质上都会先计算Authority值再计算Hub值:
A k = M T H k − 1 H k = M A k A_k=M^TH_{k-1}\\H_k=MA_k Ak=MTHk1Hk=MAk
​ 4)对Hub[i]和Auth[i]进行归一化处理:

​ 将Auth向量和hub向量的长度置为1,使其在每次迭代时都是一个单位向量。

h u b [ i ]   = ∑ j = 1 n   h u b 2 [ i ] [ j ] ; A u t h [ i ]   = ∑ j = 1 n   A u t h 2 [ i ] [ j ] {\rm hub}[i]\ =\sqrt{\sum^n_{j=1}\ {\rm hub}^2 [i][j]};{\rm Auth}[i]\ =\sqrt{\sum^n_{j=1}\ {\rm Auth}^2 [i][j]} hub[i] =j=1n hub2[i][j] Auth[i] =j=1n Auth2[i][j]

​ 归一化是为了消除不同维度数据之间的差异,还可以加快训练算法的收敛速度。

​ 5)重复权值计算和归一化,衡量上一轮迭代计算中的权值和本轮迭代之后权值的差异,如果发现总体来说权值没有明显变化,说明系统已进入稳定状态,则可以结束计算,即此时权值收敛 。

浅谈HITS算法_第4张图片

(5) 输出算法结果。依据Authority值对页面进行排序,取值较高的前若干位返回作为用户查询结果的响应。

4、HITS缺陷

(1)计算效率较低

​ 因为HITS算法是与查询相关的算法,所以必须在接收到用户查询后实时进行计算,这使其更适合部署在客户端,而HITS算法本身需要进行很多轮迭代计算才能获得最终结果,这导致其计算效率较低,这是实际应用时必须慎重考虑的问题。

(2)主题漂移问题

​ 如果在扩展网页集合里包含部分与查询主题无关的页面,而且这些页面之间有较多的相互链接指向,那么使用HITS算法很可能会给予这些无关网页很高的排名,导致搜索结果发生主题漂移,这种现象被称为“紧密链接社区现象”(Tightly-Knit CommunityEffect)。

(3)易被作弊者操纵结果

​ HITS从机制上很容易被作弊者操纵,比如作弊者可以建立一个网页,页面内容增加很多指向高质量网页或者著名网站的网址,这就是一个很好的Hub页面,之后作弊者再将这个网页链接指向作弊网页,于是可以提升作弊网页的Authority值。

(4)结构不稳定

​ 所谓结构不稳定,就是说在原有的“扩充网页集合”内,如果添加删除个别网页或者改变少数链接关系,则HITS算法的排名结果就会有非常大的改变。

5、附录

代码摘抄自HITS算法–从原理到实现

class HITSIterator:
    __doc__ = '''计算一张图中的hub,authority值'''

    def __init__(self, dg):
        self.max_iterations = 100  # 最大迭代次数
        self.min_delta = 0.0001  # 确定迭代是否结束的参数
        self.graph = dg

        self.hub = {}
        self.authority = {}
        for node in self.graph.nodes():
            self.hub[node] = 1
            self.authority[node] = 1

    def hits(self):
        """
        计算每个页面的hub,authority值
        :return:
        """
        if not self.graph:
            return

        flag = False
        for 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] = 0
                for 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] /= norm
                change += abs(tmp[node] - self.authority[node])

            # 计算每个页面的hub值
            norm = 0
            tmp = self.hub.copy()
            for node in self.graph.nodes():
                self.hub[node] = 0
                for 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] /= norm
                change += 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 = True
                break
        if 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()

你可能感兴趣的:(机器学习,算法)