TextRank算法提取關鍵詞的Java實現

談起自動摘要算法,常見的而且最易實現的當屬TF-IDF,可是感受TF-IDF效果通常,不如TextRank好。html

TextRank是在 Google的PageRank算法啓發下,針對文本里的句子設計的權重算法,目標是自動摘要。它利用投票的原理,讓每個單詞給它的鄰居(術語稱窗口) 投同意票,票的權重取決於本身的票數。這是一個「先有雞仍是先有蛋」的悖論,PageRank採用矩陣迭代收斂的方式解決了這個悖論。TextRank也 不例外:html5

PageRank的計算公式:

 

正規的TextRank公式

正規的TextRank公式在PageRank的公式的基礎上,引入了邊的權值的概念,表明兩個句子的類似度。java

 

可是很明顯我只想計算關鍵字,若是把一個單詞視爲一個句子的話,那麼全部句子(單詞)構成的邊的權重都是0(沒有交集,沒有類似性),因此分子分母的權值w約掉了,算法退化爲PageRank。因此說,這裏稱關鍵字提取算法爲PageRank也不爲過。程序員

另外,若是你想提取關鍵句(自動摘要)的話,請參考姊妹篇《TextRank算法自動摘要的Java實現》。算法

TextRank的Java實現

先看看測試數據:spring

程序員(英文Programmer)是從事程序開發、維護的專業人員。通常將程序員分爲程序設計人員和程序編碼人員,但二者的界限並不很是清楚,特別是在中國。軟件從業人員分爲初級程序員、高級程序員、系統分析員和項目經理四大類。mybatis

我取出了百度百科關於「程序員」的定義做爲測試用例,很明顯,這段定義的關鍵字應當是「程序員」而且「程序員」的得分應當最高。併發

首先對這句話分詞,這裏能夠藉助各類分詞項目,好比Ansj分詞,得出分詞結果:mvc

[程序員/n, (, 英文/nz, programmer/en, ), 是/v, 從事/v, 程序/n, 開發/v, 、/w, 維護/v, 的/uj, 專業/n, 人員/n, 。/w, 通常/a, 將/d, 程序員/n, 分爲/v, 程序/n, 設計/vn, 人員/n, 和/c, 程序/n, 編碼/n, 人員/n, ,/w, 但/c, 二者/r, 的/uj, 界限/n, 並/c, 不/d, 很是/d, 清楚/a, ,/w, 特別/d, 是/v, 在/p, 中國/ns, 。/w, 軟件/n, 從業/b, 人員/n, 分爲/v, 初級/b, 程序員/n, 、/w, 高級/a, 程序員/n, 、/w, 系統/n, 分析員/n, 和/c, 項目/n, 經理/n, 四/m, 大/a, 類/q, 。/w]框架

而後去掉裏面的停用詞,這裏我去掉了標點符號、經常使用詞、以及「名詞、動詞、形容詞、副詞以外的詞」。得出實際有用的詞語:

[程序員, 英文, 程序, 開發, 維護, 專業, 人員, 程序員, 分爲, 程序, 設計, 人員, 程序, 編碼, 人員, 界限, 特別, 中國, 軟件, 人員, 分爲, 程序員, 高級, 程序員, 系統, 分析員, 項目, 經理]

獲取下載地址   java大數據 高併發 系統框架 springmvc mybatis Bootstrap html5 shiro maven SSM

以後創建兩個大小爲5的窗口,每一個單詞將票投給它身前身後距離5之內的單詞:

{開發=[專業, 程序員, 維護, 英文, 程序, 人員],

 軟件=[程序員, 分爲, 界限, 高級, 中國, 特別, 人員],

 程序員=[開發, 軟件, 分析員, 維護, 系統, 項目, 經理, 分爲, 英文, 程序, 專業, 設計, 高級, 人員, 中國],

 分析員=[程序員, 系統, 項目, 經理, 高級],

 維護=[專業, 開發, 程序員, 分爲, 英文, 程序, 人員],

 系統=[程序員, 分析員, 項目, 經理, 分爲, 高級],

 項目=[程序員, 分析員, 系統, 經理, 高級],

 經理=[程序員, 分析員, 系統, 項目],

 分爲=[專業, 軟件, 設計, 程序員, 維護, 系統, 高級, 程序, 中國, 特別, 人員],

 英文=[專業, 開發, 程序員, 維護, 程序],

 程序=[專業, 開發, 設計, 程序員, 編碼, 維護, 界限, 分爲, 英文, 特別, 人員],

 特別=[軟件, 編碼, 分爲, 界限, 程序, 中國, 人員],

 專業=[開發, 程序員, 維護, 分爲, 英文, 程序, 人員],

 設計=[程序員, 編碼, 分爲, 程序, 人員],

 編碼=[設計, 界限, 程序, 中國, 特別, 人員],

 界限=[軟件, 編碼, 程序, 中國, 特別, 人員],

 高級=[程序員, 軟件, 分析員, 系統, 項目, 分爲, 人員],

 中國=[程序員, 軟件, 編碼, 分爲, 界限, 特別, 人員],

 人員=[開發, 程序員, 軟件, 維護, 分爲, 程序, 特別, 專業, 設計, 編碼, 界限, 高級, 中國]}

而後開始迭代投票:

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

        {

            Map<String, Float> m = new HashMap<String, Float>();

            float max_diff = 0;

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

            {

                String key = entry.getKey();

                Set<String> value = entry.getValue();

                m.put(key, 1 - d);

                for (String other : value)

                {

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

                    if (key.equals(other) || size == 0) continue;

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

                }

                max_diff = Math.max(max_diff, Math.abs(m.get(key) - (score.get(key) == null ? 0 : score.get(key))));

            }

            score = m;

            if (max_diff <= min_diff) break;

        }


 

 

[程序員=1.9249977,排序後的投票結果:

人員=1.6290349,

分爲=1.4027836,

程序=1.4025855,

高級=0.9747374,

軟件=0.93525416,

中國=0.93414587,

特別=0.93352026,

維護=0.9321688,

專業=0.9321688,

系統=0.885048,

編碼=0.82671607,

界限=0.82206935,

開發=0.82074183,

分析員=0.77101076,

項目=0.77101076,

英文=0.7098714,

設計=0.6992446,

經理=0.64640945]

相關文章
相關標籤/搜索