zoukankan      html  css  js  c++  java
  • 关键词提取算法TextRank

    很久以前,我用过TFIDF做过行业关键词提取。TFIDF仅仅从词的统计信息出发,而没有充分考虑词之间的语义信息。现在本文将介绍一种考虑了相邻词的语义关系、基于图排序的关键词提取算法TextRank。

    1. 介绍

    TextRank由Mihalcea与Tarau于EMNLP'04 [1]提出来,其思想非常简单:通过词之间的相邻关系构建网络,然后用PageRank迭代计算每个节点的rank值,排序rank值即可得到关键词。PageRank本来是用来解决网页排名的问题,网页之间的链接关系即为图的边,迭代计算公式如下:

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

    其中,(PR(V_i))表示结点(V_i)的rank值,(In(V_i))表示结点(V_i)的前驱结点集合,(Out(V_j))表示结点(V_j)的后继结点集合,(d)为damping factor用于做平滑。

    网页之间的链接关系可以用图表示,那么怎么把一个句子(可以看作词的序列)构建成图呢?TextRank将某一个词与其前面的N个词、以及后面的N个词均具有图相邻关系(类似于N-gram语法模型)。具体实现:设置一个长度为N的滑动窗口,所有在这个窗口之内的词都视作词结点的相邻结点;则TextRank构建的词图为无向图。下图给出了由一个文档构建的词图(去掉了停用词并按词性做了筛选):

    考虑到不同词对可能有不同的共现(co-occurrence),TextRank将共现作为无向图边的权值。那么,TextRank的迭代计算公式如下:

    [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做对比;准确率计算公式如下:

    [Precision = frac{1}{N} sum_{i=0}^{N-1} frac{left|P_i cap T_i ight|}{left|P_i ight|} ]

    其中,(N)为文档数量,(P_i)为文档(i)所提取出的关键词,(T_i)为文档的标注关键词。召回率与F1的计算公式如下:

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

    [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.

  • 相关阅读:
    内存管理 Autorelease、retain、copy、assign的set方法和含义?
    解决 项目cocoapods diff: /../Podfile.lock: No such file or directory
    iOS按钮点击的频率 防止按钮连续点击时重复执行按钮的点击方法
    iOS 网络篇--PDF网络文件下载和打开
    使用runtime获取属性
    取到 tableview 自定义section header 上的button
    JavaScript第一天 改变DIV的样式
    iOS 因为reason: 'Pushing the same view controller instance more than once is not supported而奔溃(下)
    iOS 因为reason: 'Pushing the same view controller instance more than once is not supported而奔溃(上)
    iOS缓存功能
  • 原文地址:https://www.cnblogs.com/en-heng/p/6626210.html
Copyright © 2011-2022 走看看