加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

NLP11-基于Gensim的文本相似性挖掘[LsiModel]

发布时间:2020-12-14 04:57:44 所属栏目:大数据 来源:网络整理
导读:摘要:通过对数据的抓取,基于jieba分词,去掉停用词,运用Gensim建立词典,生成BOW语料,运行tfidf模型计算词权重,采用LsiModel进行降维,最后运用Gensim提供的MatrixSimilarity类来计算两文档的相似性【基于余弦的距离的计算】。 1. 爬取数据 确定一个内


这里写图片描述



摘要:通过对数据的抓取,基于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,(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,(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,(20792,(21325,(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,5个小锻炼让你越来越年轻[主要抗衰老的养生]
相似文档06(2871,八个简单方法缓解心理压力
相似文档07(3876,有趣的人活得长
相似文档08(8908,三个特征确实和长寿有关
相似文档09(9589,有1种病竟然更长寿
相似文档10(4171,锻炼能治拖延症;帮助人们调节心情,增加完成目标的动力
相似文档11(9164,哪种性格的人更长寿
相似文档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
from kadml.common.common import isXiaoShu

# 分词
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,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://www.voidcn.com/article/p-czwgysxe-bqt.html】

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读