快速,准确的中文文本摘要实现方法

以前发布过一个Yaha库 ,里面有三种不同的摘要实现方法。它们都是基于关键字提取的,缺点很明显(测试地址):

  1. 基于关键字的摘要不够准确,会提供到不少关键字份量很大同时很垃圾的句子

  2. 基于cluster簇的办法,代码相对复杂,同时运行很慢

所以在实际项目中,我尝试过不少改进,但最好我发现了更好的摘要实现办法:

基于textrank,它的思路是:

计算整个文章的各个句子之间的相似度

通过句子之间的相似性,建立一张句子之间的权重图,然后使用类似google的pagerank技术来获取权重最大的前面几个句子

上面具体算法自己参考网络文章,下面贴出具体的实现代码,非常简洁,配合numpy, scipy的矩阵运算库实现起来效率非常高:

# -*- coding: UTF-8 -*-
import cProfile as profile
import pstats
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import TfidfVectorizer
import networkx as nx

def textrank(content):
    sents = list(cut_sentence(content))
    vect = TfidfVectorizer(min_df=1,tokenizer=Tokenize)
    tfidf = vect.fit_transform(sents)
    tfidf_graph = tfidf*tfidf.T
    nx_graph = nx.from_scipy_sparse_matrix(tfidf_graph)
    scores = nx.pagerank(nx_graph)
    res = sorted(((scores[i],i) for i,s in enumerate(sents)), reverse=True)
    summary = [sents[i] for _,i in sorted(res[:3])]
    print 'text_rank', u'。 '.join(summary).replace('\r','').replace('\n','')+u'。'
    

'''
prof = profile.Profile()
prof.run('test4()')
stats = pstats.Stats(prof)
stats.strip_dirs().print_stats()
'''

可以看到,只需要通过9行代码便可以实现,关键的相似度计算直接使用scipy来优化。当然其中还调用了networkx库的pagerank函数,通过它可以得到textrank的权重最高的三个句子。

cut_sentence与Tokenize就只是中文分句与中文切词。可以从jieba或yaha库,或jieba的c++实现的Python封装版cppjiebapy(好绕口)

优点非常明显:

  1. 全程矩阵运算,速度快

  2. 通过句子之间的相似度,而不是单纯计算某些句子含有的关键字数量,考虑到了整个句子的信息

  3. 基于pagerank的算法,考虑到了句子的全文信息

继续优化:(考虑到整个语料的idf信息)

代码当中的fit_transform只是计算当前文章的idf,这样得到的结果只体现了当前文章的词的idf,难免不够准确。若要得到更准确的信息可以先输入给vect个很大的语料vect.fit(big_corpus),然后再对当前的content计算tfidf:vect.transform(sents)。同时vect训练了一个大的语料库之后可以保存到本地,在需要的时候再进行加载。


过程当中有疑问可加我开源项目交流QQ群:27498_3126 欢迎对数据处理有兴趣的同学多多交流。



你可能感兴趣的:(自动摘要)