起初,由于工作需要,需要对大量技术文章进行分类并用一两句话描述关键内容,做成类似简报之类的报告给领导看,但是材料又多又长,不可能一篇篇去读,怎么办呢?
最先想到的办法,就是抽取关键词,简单易行,就是后期需要自己梳理成句,当然还是需要浏览一遍文章,不过至少有的放矢了
1、第一版:获取TFIDF最高的n个词汇,作为关键词提取;
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
countVectorizer =CountVectorizer(stop_words=None,token_pattern=r'(?u)\b\w\w+\b',max_df=1.0,min_df=1)
text_seq_count = countVectorizer.fit_transform(text_seq)
tfidftransformer = TfidfTransformer()
text_seq_tfidf = tfidftransformer.fit_transform(text_seq_count)
Tfidf公式=该词在某文档中出现的频率(即次数除以总词数)**log[1/(含有该词的文档在所有文件中出现的频率(即(含词文档数+1)除以总文档数))]
注:
1)除以总词数是为了排除文档长度对一个词出现次数的影响
2)+1是为了防止产生为0的除数;
3)取log是因为从信息论的角度分析:一个词对某个文档的贡献度,不仅与该词在该文档中出现的次数(词袋模型)有关,同时与该词所含有的信息量有关,而根据信息论,某事件信息量可以近似为其概率的负对数,那么一个词本身含有的信息量可以近似为该词的出现概率取负对数,即-log(含有这个词的文档数目与总文档数目的比值);因而,一个词在某文档中次数越多,信息量越大,那么贡献度就越大,即(word_count/text_word_num)-log(word_text_num/text_num)
4) 为什么一个词出现概率不用所有文件中该词出现次数/总文件词数呢?我想原因同样与1)类似,为了排除不同长度的文档对一个词出现次数的影响,因为首先文档的重要性并不能由其长度确定,而如果简单通过词数相加的总文件次数做分母,无形中长度长的文档所占比重更大,其次一个词在某个文档中的出现次数已经由TF表达了,如果次数再用该词在总文件中出现的次数进行计算,那么就部分与之重复,相当于扩大了这部分的作用,所以只需要用文档的频率进行信息量的计算。
2、后来工作增多,实在没有时间篇篇浏览,但是又不能随意就用几个关键词直接造句,怎么办呢?
第二版:获取这些词汇出现的句子进行整合作为摘要雏形
,句子筛选的原则就是:一句话里关键词出现的越多,这句话就越关键;一句话里关键词tfidf值之和越大,这句话就越关键。用这两个原则分别筛选前N条句子,然后根据这些句子进行摘要编写
3、之后接触到nlp,学习了文本摘要相关的算法,目前已经尝试过的有:1)textrank算法进行摘要抽取;2)用神经网络LSTM构建encoder-decoder的seq2seq+attention模型
1)第三版:textrank,摘要抽取
这个抽取效果不错,但作为简报给领导看还是不行
总体思想:采用词向量计算句子向量,进而计算句子相似度,采用pagerank算法获取与其他句子连接度最大,相似度最大的句子作为摘要;
词向量:
from gensim.models import word2vec
all_text = list(washed_text)
word_dim = 300 # Word vector dimensionality
min_word_count = 0 # Minimum word count
num_workers = 16 # Number of threads to run in parallel
context =2 # Context window size
downsampling = 1e-3 # Downsample setting for frequent words
model_sg_hs = word2vec.Word2Vec(all_text,size=word_dim,window=context,min_count=min_word_count,workers=num_workers,sg= 1,hs=1,sample= downsampling)
#Sg=1-----skip-gram(w--context); 0-----cbow (context--w)
#Hs=1-----层级softmax(构建霍夫曼树);0------Negative Sampling
计算句子向量:
sentences_vectors = [sum(np.array(word2vec_model[word],dtype='float32').reshape(100,-1) for word