關鍵詞提取算法TextRank

好久之前,我用過TFIDF作過行業關鍵詞提取。TFIDF僅僅從詞的統計信息出發,而沒有充分考慮詞之間的語義信息。如今本文將介紹一種考慮了相鄰詞的語義關係、基於圖排序的關鍵詞提取算法TextRank。html

1. 介紹

TextRank由Mihalcea與Tarau於EMNLP'04 [1]提出來,其思想很是簡單:經過詞之間的相鄰關係構建網絡,而後用PageRank迭代計算每一個節點的rank值,排序rank值便可獲得關鍵詞。PageRank原本是用來解決網頁排名的問題,網頁之間的連接關係即爲圖的邊,迭代計算公式以下:python

\[ PR(V_i) = (1-d) + d * \sum_{j \in In(V_i)} \frac{1}{|Out(V_j)|}PR(V_j) \]git

其中,\(PR(V_i)\)表示結點\(V_i\)的rank值,\(In(V_i)\)表示結點\(V_i\)的前驅結點集合,\(Out(V_j)\)表示結點\(V_j\)的後繼結點集合,\(d\)爲damping factor用於作平滑。github

網頁之間的連接關係能夠用圖表示,那麼怎麼把一個句子(能夠看做詞的序列)構建成圖呢?TextRank將某一個詞與其前面的N個詞、以及後面的N個詞均具備圖相鄰關係(相似於N-gram語法模型)。具體實現:設置一個長度爲N的滑動窗口,全部在這個窗口以內的詞都視做詞結點的相鄰結點;則TextRank構建的詞圖爲無向圖。下圖給出了由一個文檔構建的詞圖(去掉了停用詞並按詞性作了篩選):算法

考慮到不一樣詞對可能有不一樣的共現(co-occurrence),TextRank將共現做爲無向圖邊的權值。那麼,TextRank的迭代計算公式以下:json

\[ WS(V_i) = (1-d) + d * \sum_{j \in In(V_i)} \frac{w_{ji}}{\sum_{V_k \in Out(V_j)} w_{jk}} WS(V_j) \]網絡

2. 評估

接下來將評估TextRank在關鍵詞提取任務上的準確率、召回率與F1-Measure,並與TFIDF作對比;準確率計算公式以下:app

\[ Precision = \frac{1}{N} \sum_{i=0}^{N-1} \frac{\left|P_i \cap T_i\right|}{\left|P_i\right|} \]測試

其中,\(N\)爲文檔數量,\(P_i\)爲文檔\(i\)所提取出的關鍵詞,\(T_i\)爲文檔的標註關鍵詞。召回率與F1的計算公式以下:lua

\[ Recall = \frac{1}{N} \sum_{i=0}^{N-1} \frac{\left|P_i \cap T_i\right|}{\left|T_i\right|} \]

\[ F1 = \frac{2*Precision*Recall}{Precision + Recall} \]

測試集是由劉知遠老師提供的網易新聞標註數據集,共有13702篇文檔。Jieba完整地實現了關鍵詞提取TFIDF與TextRank算法,基於Jieba-0.39的評估實驗代碼以下:

import jieba.analyse
import json
import codecs


def precision_recall_fscore_support(y_true, y_pred):
    """
    evaluate macro precision, recall and f1-score.
    """
    doc_num = len(y_true)
    p_macro = 0.0
    r_macro = 0.0
    for i in range(doc_num):
        tp = 0
        true_len = len(y_true[i])
        pred_len = len(y_pred[i])
        for w in y_pred[i]:
            if w in y_true[i]:
                tp += 1
        p = 1.0 if pred_len == 0 else tp / pred_len
        r = 1.0 if true_len == 0 else tp / true_len
        p_macro += p
        r_macro += r
    p_macro /= doc_num
    r_macro /= doc_num
    return p_macro, r_macro, 2 * p_macro * r_macro / (p_macro + r_macro)


file_path = 'data/163_chinese_news_dataset_2011.dat'
with codecs.open(file_path, 'r', 'utf-8') as fr:
    y_true = []
    y_pred = []
    for line in fr.readlines():
        d = json.loads(line)
        content = d['content']
        true_key_words = [w for w in set(d['tags'])]
        y_true.append(true_key_words)
        # for w in true_key_words:
        #     jieba.add_word(w)
        key_word_pos = ['x', 'ns', 'n', 'vn', 'v', 'l', 'j', 'nr', 'nrt', 'nt', 'nz', 'nrfg', 'm', 'i', 'an', 'f', 't',
                        'b', 'a', 'd', 'q', 's', 'z']
        extract_key_words = jieba.analyse.extract_tags(content, topK=2, allowPOS=key_word_pos)
        # trank = jieba.analyse.TextRank()
        # trank.span = 5
        # extract_key_words = trank.textrank(content, topK=2, allowPOS=key_word_pos)
        y_pred.append(extract_key_words)
    prf = precision_recall_fscore_support(y_true, y_pred)
    print('precision: {}'.format(prf[0]))
    print('recall: {}'.format(prf[1]))
    print('F1: {}'.format(prf[2]))

其中,每一個文檔提取的關鍵詞數爲2,並按詞性作過濾;span表示TextRank算法中的滑動窗口的大小。評估結果以下:

方法 Precision Recall F1-Measure
TFIDF 0.2697 0.2256 0.2457
TextRank span=5 0.2608 0.2150 0.2357
TextRank span=7 0.2614 0.2155 0.2363

若是將標註關鍵詞添加到自定義詞典,則評估結果以下:

方法 Precision Recall F1-Measure
TFIDF 0.3145 0.2713 0.2913
TextRank span=5 0.2887 0.2442 0.2646
TextRank span=7 0.2903 0.2455 0.2660

直觀感覺下關鍵詞提取結果(添加了自定義詞典):

// TFIDF, TextRank, labelled
['文強', '陳洪剛'] ['文強', '陳洪剛'] {'文強', '重慶'}
['內賈德', '伊朗'] ['伊朗', '內賈德'] {'制裁', '世博', '伊朗'}
['調控', '王珏林'] ['調控', '樓市'] {'樓市', '調控'}
['羅平縣', '男子'] ['男子', '羅平縣'] {'被砍', '副局長', '情感糾葛'}
['佟某', '黃玉'] ['佟某', '黃現忠'] {'盲井', '僞造礦難'}
['女生', '聚衆淫亂'] ['女生', '聚衆淫亂'] {'聚衆淫亂', '東莞', '不雅視頻'}
['馬英九', '和平協議'] ['馬英九', '推動'] {'國臺辦', '馬英九', '和平協議'}
['東帝汶', '巡邏艇'] ['東帝汶', '中國'] {'東帝汶', '軍艦', '澳大利亞'}
['墨西哥', '警方'] ['墨西哥', '襲擊'] {'槍手', '墨西哥', '打死'}

從上述兩組實驗結果,能夠發現:

  • TextRank與TFIDF均嚴重依賴於分詞結果——若是某詞在分詞時被切分紅了兩個詞,那麼在作關鍵詞提取時沒法將兩個詞黏合在一塊兒(TextRank有部分黏合效果,但須要這兩個詞均爲關鍵詞)。所以是否添加標註關鍵詞進自定義詞典,將會形成準確率、召回率截然不同。
  • TextRank的效果並不優於TFIDF。
  • TextRank雖然考慮到了詞之間的關係,可是仍然傾向於將頻繁詞做爲關鍵詞。

此外,因爲TextRank涉及到構建詞圖及迭代計算,因此提取速度較慢。

3. 參考資料

[1] Rada, Mihalcea, and Paul Tarau. "TextRank: Bringing Order into Texts." empirical methods in natural language processing (2004): 404-411.

相關文章
相關標籤/搜索