NLP11-基于Gensim的文本相似性挖掘[LsiModel]
2017-11-11 20:02
363 查看
摘要:通过对数据的抓取,基于jieba分词,去掉停用词,运用Gensim建立词典,生成BOW语料,运行tfidf模型计算词权重,采用LsiModel进行降维,最后运用Gensim提供的MatrixSimilarity类来计算两文档的相似性【基于余弦的距离的计算】。
1. 爬取数据
确定一个内容主题为健康信息类, python的requests包可以对所给的信息URL进行请求并抓取,可采用beautifulsoup来解释,共21754篇;保存成一行一个文档, 用分号把题目与内容分开;如下:2. 分词与去掉停用词处理
对文本进行分词,并对停用词作相关处理,分词后的结果:注:停用词下载:http://download.csdn.net/download/ld326/10112475
3. 建立语料词典
运行gensim的建立词典类,共建立差不多20W左右的词汇列表,2W多文档数,518W多词。=================dictinary info=============
词数: 199252
处理的文档数(num_docs): 21754
没有去重词条总数(num_pos): 5188031
================= dictinary =============
4. 生成语料词袋表示
把所有文档转换成BOW形式,也即是文本转成了向量的初步;数组(词id,词频),每行对应一个文档,对于整个语料来看其实这是一个大的稀疏矩阵。M*N,M表示文档数,N表示词数;5. 计算tfidf向量
主要是把重点信息的权重增加,是属于特征选择的范畴;词频大的表示这个词对于这篇文章的重要性不一定大,如果这个词对于每篇文档都多,这个词在某篇文档就可以显得不太重要了,对全部文档进行一个综合计算,这样,就应用到了tfidf模型。6. LSA模型
面对着高维度,有199252维,建立LSA模型,把整个大的矩阵映射到100~300之间的维度,这个有相关学术研究的结果的。这里选择150维,如把所有语料都降维到150维,把稀疏的高级矩阵变成一个计算起来会比较轻松的小矩阵,也把一些没有用的燥音给过滤掉了,这个模型可以被后来的语料查询与分类所调用。7. 文本相似应用
文本相似可以应用到文本检索,推荐系统等场景,计算相似性的算法比较多,一般三个思想,思想一,直接对文本进行比较,例如,判断是否相等,判断文档最小修改次数转换等等;思想二,把文本转接成局部敏感的hash编码,通过计算编码的差异来判断文本的相似性,例如simhash; 思想三,采用文本的主题模型来分析,主题相同或相似的词、文档也是很相似的;对于计算的方法方面,各种vec距离等等都可以用;gensim求相似的用了余弦来求解的,实现方法是先把两向量换算成单位向量,然后作点乘。任选取第39条文档作为测试:文本内容url:http://news.familydoctor.com.cn/a/201708/2238329.html
页面显示内容为,主要是讲述了长寿,笑,心情相关等内容.
Gensim对原语料中每行作点乘,这里只把结果大于0.6拿出来,如下显示<文档id,相似关系值>,注意,这个文档标号为从0开始的。
(38, 1.0), (8247, 0.82197654), (9157, 0.79860479), (6145, 0.76660019), (21559, 0.74808526), (21028, 0.71339124), (8473, 0.70313895), (2871, 0.69301218), (3876, 0.68953127), (8908, 0.68686718), (9589, 0.67818797), (4171, 0.67647427), (9164, 0.67124206), (21179, 0.66530234), (9967, 0.66434395), (9160, 0.66402805), (9171, 0.66402805), (6905, 0.66163081), (21023, 0.65950018), (3872, 0.65947652), (4163, 0.65850592), (3718, 0.65803713), (4957, 0.65741718), (9057, 0.65515375), (15104, 0.65506059), (9196, 0.64842445), (638, 0.64582705), (2042, 0.64499903), (16153, 0.644602), (6889, 0.64316607), (9607, 0.64258647), (9804, 0.64086813), (9989, 0.64086813), (20105, 0.63806242), (1171, 0.63073081), (4071, 0.62697035), (11939, 0.62295383), (368, 0.62168962), (9453, 0.61991268), (4066, 0.61936527), (21723, 0.61891901), (14141, 0.61883008), (4150, 0.6184234), (11813, 0.61639971), (9174, 0.61517316), (362, 0.61501044), (9190, 0.61155277), (4997, 0.61000597), (19149, 0.60973948), (19058, 0.6090942), (19944, 0.6090942), (20792, 0.6090942), (21325, 0.6090942), (370, 0.60723531), (9613, 0.60543227), (19320, 0.60264295), (7638, 0.60229903), (8010, 0.60081267)
讲述笑与长寿的关系,解释为什么可以长寿.笑可以帮助减轻压力,促进血液循环,促进疾病康复等,推荐的相关文档基本也是跟这个主题相关。
8. 结果分析
相似文档01:(8247, 0.82197654)、(6145, 0.76660019),这两篇是同一篇文章:相似文档02(9157, 0.79860479):笑起来时,大脑发生了什么变化
相似文档03(21559, 0.74808526):冥想15分钟 身体能发生12个变化
相似文档04(21028, 0.71339124):医学家解释人体六个怪现象 [可能这里面涉及到笑]
相似文档05(8473, 0.70313895), 5个小锻炼让你越来越年轻[主要抗衰老的养生]
相似文档06(2871, 0.69301218), 八个简单方法缓解心理压力
相似文档07(3876, 0.68953127),有趣的人活得长
相似文档08(8908, 0.68686718),三个特征确实和长寿有关
相似文档09(9589, 0.67818797), 有1种病竟然更长寿
相似文档10(4171, 0.67647427), 锻炼能治拖延症;帮助人们调节心情,增加完成目标的动力
相似文档11(9164, 0.67124206), 哪种性格的人更长寿
相似文档12(21179, 0.66530234):爱做六件事的人不会长寿
9. 代码
实现的代码:# -*- coding:utf-8 -*- import string import jieba import jieba.analyse from bs4 import BeautifulSoup from gensim import corpora, models, similarities # 判断是否是数字 def isXiaoShu(word): rs = False a = re.search(r'^\d*\.?\d*$', word) if a: if a.group(0) == '': pass else: rs = True else: pass return rs # 分词 def cutPhase(inFile, outFile): # 如果没有自己定义的词典,这行不要 jieba.load_userdict("dict_all.txt") # 加载停用词 stoplist = {}.fromkeys([line.strip() for line in open('stopwords.txt', 'r', encoding='utf-8')]) f1 = open(inFile, 'r', encoding='utf-8') f2 = open(outFile, 'a', encoding='utf-8') line = f1.readline() count = 0 while line: b = BeautifulSoup(line, "lxml") line = b.text # line.replace('\u3000', '').replace('\t', '').replace(' ', '') # 分词 segs = jieba.cut(line, cut_all=False) # 过滤停用词 segs = [word for word in list(segs) if word.lstrip() is not None and word.lstrip() not in stoplist and word.lstrip() not in string.punctuation and not isXiaoShu(word.lstrip()) ] # 每个词用空格隔开 f2.write(" ".join(segs)) f2.write('\n') line = f1.readline() count += 1 if count % 100 == 0: print(count) f1.close() f2.close() class MyNews(object): def __init__(self, dict, in_file): self.dict = dict self.in_file = in_file def __iter__(self): for line in open(self.in_file, encoding='utf-8'): yield self.dict.doc2bow(line.split()) if __name__ == '__main__': is_train = True # 进行训练计算模型 if is_train: # 分词 cutPhase(inFile=u'a\资讯文章数据.txt', outFile=u"a\资讯文章数据.cut") # 建立词典 dict = corpora.Dictionary(line.lower().split() for line in open(u'a\资讯文章数据_cut.txt', encoding='utf-8')) dict.save('a\资讯文章数据.dic') # 加载词典:建立词袋语料 # if is_load: # dict = corpora.Dictionary.load(u'a/资讯文章数据.dic') print('=================dictinary info=============') print('词数:', len(dict.keys())) print('处理的文档数(num_docs):', dict.num_docs) print('没有去重词条总数(num_pos):', dict.num_pos) print('=================dictinary=============') bows = MyNews(dict, in_file=u'a/资讯文章数据.cut') # 保存词代信息 corpora.MmCorpus.serialize('a/资讯文章数据.mm', bows) # 计算iftdf tfidf = models.TfidfModel(dictionary=dict) corpus_tfidf = tfidf[bows] tfidf.save(u'a/资讯文章数据.tfidf') # 计算lsi模型并保存 lsi = models.LsiModel(corpus_tfidf, id2word=dict, num_topics=150) lsi.save(u'a/资讯文章数据.lsi') # 计算所有语料 corpus_lsi = lsi[corpus_tfidf] # 生成相似矩阵 print('加载bows') bows = corpora.MmCorpus(u'a/资讯文章数据.mm') print('加载tfidf模型') tfidf = models.TfidfModel.load(u'a/资讯文章数据.tfidf') print('加载LSI模型') lsi = models.LsiModel.load(u'a/资讯文章数据.lsi') print('保存相似矩阵') mSimilar = similarities.MatrixSimilarity(lsi[tfidf[bows]]) mSimilar.save(u'a/资讯文章数据.mSimilar') # 应用模型,相关的查询 else: print('加载词典') dict = corpora.Dictionary.load(u'a/资讯文章数据.dic') print('加载tfidf模型') tfidf = models.TfidfModel.load(u'a/资讯文章数据.tfidf') print('加载LSI模型') lsi = models.LsiModel.load(u'a/资讯文章数据.lsi') mSimilar = similarities.MatrixSimilarity.load(u'a/资讯文章数据.mSimilar') # 任先一句分好词的文档 doc = """ 长寿 秘方 疫力 ... 补品 笑一笑 增 寿命 心情 """ # 把测试语料转成词袋向量 vec_bow = dict.doc2bow(doc.split()) # 求tfidf值 vec_tfidf = tfidf[vec_bow] # 转成lsi向量 vec_lsi = lsi[vec_tfidf] # 求解相似性文档 sims = mSimilar[vec_lsi] print('排序后的结果:') sims = sorted(enumerate(sims), key=lambda item: -item[1]) print(sims)
这是一个文本相似性挖掘粗略过程,请大家多多指教。
【作者:happyprince, http://blog.csdn.net/ld326/article/details/78508162】
相关文章推荐
- 互联网时代的社会语言学:基于SNS的文本数据挖掘
- 深度学习:基于 Gensim 的 Yelp 评论文本分类实例
- python+gensim︱jieba分词、词袋doc2bow、TFIDF文本挖掘
- R语言文本挖掘1——词云制作,基于Rwordseg包
- 文本相似度——基于TF-IDF与余弦相似性
- 互联网时代的社会语言学:基于SNS的文本数据挖掘
- 互联网时代的社会语言学:基于SNS的文本数据挖掘(转载)
- 互联网时代的社会语言学:基于SNS的文本数据挖掘
- [转]基于SNS的文本数据挖掘
- 文本挖掘——基于TF-IDF的KNN分类算法实现
- 基于SNS的文本数据挖掘
- 数据挖掘——基于R文本情感分析(1)
- 互联网时代的社会语言学:基于SNS的文本数据挖掘
- 转:Python 文本挖掘:使用gensim进行文本相似度计算
- 互联网时代的社会语言学:基于SNS的文本数据挖掘
- 互联网时代的社会语言学:基于SNS的文本数据挖掘
- 互联网时代的社会语言学:基于SNS的文本数据挖掘
- Tmsvm_基于SVM的文本挖掘系统
- 基于SNS的文本数据挖掘--非监督分词
- 互联网时代的社会语言学:基于SNS的文本数据挖掘