HanLP 关键词提取算法分析详解

HanLP 关键词提取算法分析详解程序员

  1. 参考论文:《TextRank: Bringing Order into Texts》
  2. TextRank算法提取关键词的Java实现
  3. TextRank算法自动摘要的Java实现这篇文章中做者大概解释了一下TextRank公式

1. 论文算法

In this paper, we introduce the TextRank graphbased ranking model for graphs extracted from naturalapp

language textside

TextRank是一个非监督学习算法,它将文本中构形成一个图,将文本中感兴趣的东西(好比分词)当成一个个顶点,而后应用TextRank算法来抽取文本中的一些信息。学习

Such keywords may constitute useful entries for building an automatic index for a document collection, can be used to classify a text, or may serve as a concise summary for a given document.ui

提取出来的关键词,可用来做为文本分类,或者归纳文本的中心思想。this

TextRank经过不断地迭代来提取关键词,每一轮迭代,算法给图中的顶点打分。直到知足某个条件(好比说迭代次数克到200次,或者设置的某个参数达到一个阈值)为止。spa

For loosely connected graphs, with the number of edges proportional with the number of vertices,设计

undirected graphs tend to have more gradual convergence curves.3d

对于稀疏图而言,边的数目与顶点的数目成线性关系,对这样的图进行关键词提取,有着更平缓的收敛曲线(或者叫收敛得慢吧)

It may be therefore useful to indicate and incorporate into the model the “strength”

of the connection between two vertices $V_i$ and $V_j$ as a weight $w_{ij}$ added to the corresponding edge that connects the two vertices.

有时,图中顶点之间的关系并不彻底平等,好比某些顶点之间关系密切,这里可用边的权重来衡量顶点之间的相关性重要程度,而这就是带权图模型。

2. 源码实现

2.1 关键词提取流程

给定若干个句子,提取关键词。而TextRank算法是 graphbased ranking model,所以须要构造一个图,要想构造图,就须要肯定图中的顶点如何构造,因而就把句子进行分词,将分得的每一个词做为图中的顶点。

在选取某个词做为图的顶点的时候,能够应用一些过滤规则:好比说,去除掉分词结果中的停用词、根据词性来添加顶点(好比只将名词和动词做为图的顶点)……

The vertices added to the graph can be restricted with syntactic filters, which select only lexical units of a certain part of speech. One can for instance consider only nouns and verbs for addition to the graph, and consequently draw potential edges based only on relations that can be established between nouns and verbs.

在肯定好哪些词做为图的顶点以后,另外一个是肯定词与词之间的关系,也即:图中的哪些顶点有边?好比说设置一个窗口大小,落在这个窗口内的词,都添加一条边。

it is the application that dictates the type of relations that are used to draw connections between any two such vertices,

肯定了边的关系后,接下来是肯定边上权值。这个也是根据实际状况而定。

2.2 根据窗口大小肯定词的邻接点

前面提到,若干句话分词以后,获得的一个个的词,或者叫Term。假设窗口大小为5。解释一下TextRank算法提取关键词的Java实现文章中提到的如何肯定某个Term有哪些邻接Term。

好比说:'程序员' 这个Term,它在多个句子中出现了,所以分词结果'程序员' 出如今四个地方:

索引0处:'程序员'的邻接点有:

英文、programmer、从事、程序

索引9处:'程序员'的邻接点有:

开发、维护、专业、人员、分为、程序、设计、人员

    

索引26处,'程序员'的邻接点有:

中国、软件、从业人员、分为、高级、程序员、系统分析员、项目经理

索引28处,'程序员'的邻接点有:

从业人员、分为、程序员、高级、系统分析员、项目经理、四大

结合这四处窗口中的全部的词,获得'程序员'的邻接点以下:

所以,当窗口大小设置为5时,Term的先后四个Term都将视为它的邻接点,而且当这个Term出现屡次时,则是将它各次出现位置处的先后4个Term合并,最终做为这个Term的邻接点。

从这里可看出:若是某个Term在句子中出现了屡次,意味着该Term会比较重要。由于它的邻接点会比较多,也即有不少其余Term给它投了票。这就有点相似于Term Frequency来衡量Term的重要性。

2.3 得分(score)的更新算法

m.put(key, m.get(key) + d / size * (score.get(element) == null ? 0 : score.get(element)));代码的解读:

m.get(key)若是是第一次进入for (String element : value),则是拿到公式前半部分1-d的结果;若是是已经在for (String element : value)进行了迭代,for循环至关于求和:Σvj∈In(vi)Σvj∈In(vi)

for (String element : value) {

    int size = words.get(element).size();

    m.put(key, m.get(key) + d / size * (score.get(element) == null ? 0 : score.get(element)));

}

以”他说的确实在理“ 举例来讲:,选取窗口大小为5,通过分词并去除停用词后:

构造的无向图以下:(每条边的权值都为1)

以顶点'理'为例,来看一下'理'的得分是如何被更新的。在for (String element : value)一共有两个顶点对 '理'进行投票,首先是 '确实'顶点,与'确实'顶点邻接的顶点有两个,所以:int size = words.get(element).size();中size=2。接下来,来分解一下这行代码:

m.put(key, m.get(key) + d / size * (score.get(element) == null ? 0 : score.get(element)))

m.get(key)为1-d,由于在外层for循环中,m.put(key, 1 - d)已经公式的前半分部(1-d)存储了。

score.get(element) == null ? 0 : score.get(element)这个是获取上一轮迭代的结果。对于初始第一轮迭代而言,score.get(element)为0.8807971,这个值是每一个顶点的得分初始值:

          //依据TF来设置初值,  words 表明的是 一张 无向图

          for (Map.Entry<String, Set<String>> entry : words.entrySet()) {

              score.put(entry.getKey(), sigMoid(entry.getValue().size()));//无向图的每一个顶点 得分值 初始化

          }

score.get(element)至关于公式中的WS(Vj)WS(Vj)

最后来分析一个 size,size是由代码int size = words.get(element).size()得到的,因为每条边权值为1,size其实至关于:ΣVk∈Out(Vj)wjkΣVk∈Out(Vj)wjk。

In('理')={'确实','说'}

当VjVj为'确实'时,Out(Vj)Out(Vj)为{'说','理'},所以:ΣVk∈Out(Vj)wjk=2ΣVk∈Out(Vj)wjk=2。因而,更新顶点'理'的得分:1−d+d∗(1/2)∗0.8807971=0.52433871−d+d∗(1/2)∗0.8807971=0.5243387。而后再经过m.put将临时结果保存起来。

接下来,for (String element : value)继续,此时:VjVj为顶点'说',因为顶点'说'也有两条邻接边,所以有:ΣVk∈Out(Vj)wjk=2ΣVk∈Out(Vj)wjk=2。因而更新顶点'理'的得分:0.5243387+d∗(1/2)∗0.8807971=0.898677470.5243387+d∗(1/2)∗0.8807971=0.89867747。而这就是第一轮迭代时,顶点'理'的得分。

根据上面的一、2中的步骤,for (String element : value)就至关于:ΣVj∈In(Vi)ΣVj∈In(Vi),由于每次都把计算好的结果再put回HashMap m中。

所以,在第一轮迭代中,顶点'理'的得分就是:0.89867747

相似于,通过:max_iter次迭代,或者达到阈值:

              if (max_diff <= min_diff)

                  break;

时,就再也不迭代了。

下面再来对代码做个整体说明:

这里是构造无向图的过程

        for (String w : wordList) {

            if (!words.containsKey(w)) {

                //排除了 wordList 中的重复term, 对每一个已去重的term, 用 TreeSet<String> 保存该term的邻接顶点

                words.put(w, new TreeSet<String>());

            }

            // 复杂度O(n-1)

            if (que.size() >= 5) {

                //窗口的大小为5,是写死的. 对于一个term_A而言, 它的前4个term、后4个term 都属于term_A的邻接点

                que.poll();

            }

            for (String qWord : que) {

                if (w.equals(qWord)) {

                    continue;

                }

                //既然是邻居,那么关系是相互的,遍历一遍便可

                words.get(w).add(qWord);

                words.get(qWord).add(w);

            }

            que.offer(w);

        }

这里是对图中每一个顶点赋值一个初始score过程:

        Map<String, Float> score = new HashMap<String, Float>();//保存最终每一个关键词的得分

        //依据TF来设置初值,  words 表明的是 一张 无向图

        for (Map.Entry<String, Set<String>> entry : words.entrySet()) {

            score.put(entry.getKey(), sigMoid(entry.getValue().size()));//无向图的每一个顶点 得分值 初始化

        }

接下来,三个for循环:第一个for循环表明迭代次数;第二个for循环表明:对无向图中每个顶点计算得分;第三个for循环表明:对某个具体的顶点而言,计算它的每一个邻接点给它的投票权重。

for (int i = 0; i < max_iter; ++i) {

    //....

    for (Map.Entry<String, Set<String>> entry : words.entrySet()) {

        //...

        for (String element : value) {

这样,就实现了论文中公式:

WS(vi)=(1−d)+d∗ΣVj∈In(Vi)wjiΣVk∈Out(Vj)wjk∗WS(Vj)

WS(vi)=(1−d)+d∗ΣVj∈In(Vi)wjiΣVk∈Out(Vj)wjk∗WS(Vj)

而最终提取出来的关键词是:

[理, 确实, 说]

上面只是用 ”他说的确实在理“ 这句话 演示了TextRank算法的具体细节,在实际应用中可能不合理。由于会存在:

现有统计信息不足以让TextRank支持 某个词 的重要性,算法有局限性。

可见:TextRank提取关键词是受到分词结果的影响的;其次,也受窗口大小的影响。虽说代码是大体看懂了,可是仍是有一些疑问的:好比,为何用上面那个公式计算,得分高的词语就是关键词了?根据TextRank求关键词与Term Frequency求关键词有什么优点?选取文本中的哪些词创建模型做为图的顶点?基于文本之间的什么样的关系做为图的边?

文章转载自hapjin 的博客

相关文章
相关标签/搜索