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 的博客

相關文章
相關標籤/搜索