精华内容
下载资源
问答
  • 文本主题提取

    千次阅读 2018-01-13 15:33:46
    主题关键词:能够体现文本内容主题的关键词 一、TF-IDF模型 词频(TF)= 某个词在文本中出现的次数/该文本中总词数 或者一种变种的计算方法 词频(TF)= 某个词在文本中出现的次数/该文本中出现次数最多的词其...

    主题关键词:能够体现文本内容主题的关键词
    一、TF-IDF模型
    这里写图片描述
    词频(TF)= 某个词在文本中出现的次数/该文本中总词数
    或者一种变种的计算方法
    词频(TF)= 某个词在文本中出现的次数/该文本中出现次数最多的词其出现的次数
    逆向文档频(IDF)= log(语料库中所有文档总数/(包含某词的文档数+1))
    注意
    - 为了避免分母为0,所以在分母上加1
    - 所指的词个数,一定时刨除了停用词的计算,甚至时专门的词表
    - 这里的log,可以取log10、log2甚至时log e,根据实际效果调整
    应用场景
    - 计算出文章中每个词的TF-IDF值之后,进行排序,选取其中值最高的几个作为关键字。
    - 计算出每篇文章的关键词,从中各选取相同个数的关键词,合并成一个集合,计算每篇文章对于这个集合中的词的词频,生成两篇文章各自的词频向量,进而通过欧氏距离或余弦距离求出两个向量的余弦相似度,值越大就表示越相似。
    二、TextRank算法
    TextRank算法:一种非监督式的主题抽取算法,不依赖于其他语料,直接从文本中抽取主题词。
    PageRank算法:网页排名算法,核心思想就是一个网页的重要程度取决于它的网页数量以及这些网页的重要程度,即每一个网页的重要程度都是通过其他网页来实现的,而它的重要程度又反过来影响它外链中的网页重要程度。
    - 如果一个网页被很多其他网页链接到的话说明这个网页比较重要,也就是PageRank值会相对较高。
    - 如果一个PageRank值很高的网页链接到一个其他的网页,那么被链接到的网页的PageRank值会相应地因此而提高。
    基于TextRank的关键词提取
    关键词抽取的任务就是从一段给定的文本中自动抽取出若干有意义的词语或词组,TextRank算法是利用局部词汇之间的关系(共现窗口)对后续关键词进行排序,直接从文本本身抽取。其主要步骤如下:
    1. 把给定的文本T按照完整句子进行分割,即T=[s1,s2,...,sn]
    2. 对于每个句子Si,进行分词和词性标注处理,并过滤掉停用词,只保留指定词性的单词,如名词、动词、形容词,即Si=[ti,1,ti,2,...,ti,n],其中ti,j是保留后的候选关键词。
    3. 构建候选关键词图G=(V,E),其中V为节点集,由(2)生成的候选关键词组成,然后采用共现关系(co-occurrence)构造任两点之间的边,两个节点之间存在边仅当它们对应的词汇在长度为K的窗口中共现,K表示窗口大小,即最多共现K个单词。
    4. 根据PageRank的计算公式,迭代传播各节点的权重,直至收敛。
    5. 对节点权重进行倒序排序,从而得到最重要的T个单词,作为候选关键词。
    6. 由(5)得到最重要的T个单词,在原始文本中进行标记,若形成相邻词组,则组合成多词关键词。例如,文本中有句子“Matlab code for plotting ambiguity function”,如果“Matlab”和“code”均属于候选关键词,则组合成“Matlab code”加入关键词序列。
    三、LDA主题模型
    核心思想:认为每一篇文档Doc都是由多个主题Topic组成,而每一个主题Topic由多个词Word组成。
    通过对语料库D中所有文档进行分词或者抽词处理之后,通过模型训练,得到两个概率矩阵:一是每一个Doc对应K个Topic的概率;二是每一个Topic对应N个词组成的词表的概率。

    展开全文
  • python 基于LDA长文本主题提取并预测分类 Lda算法原理,知乎上有很完善的算法介绍,这里就不多废话了。 数据准备 这一阶段主要是对你的问题本进行处理,清洗你的数据。中文文本预处理,主要包括去空格、去表单符号、...

    python 基于LDA长文本主题提取并预测分类

    导读

    Lda算法原理,知乎上有很完善的算法介绍,这里就不多废话了。

    本文主要是用来做文本主题提取,再根据这些主题对现有的文本进行分类。因为数据问题,效果一般,算法设计思路,仅供参考。

    本文代码以及测试数据已上传github:仓库地址

    数据准备

    这一阶段主要是对你的问题本进行处理,清洗你的数据。中文文本预处理,主要包括去空格、去表单符号、去停用词、分词等。根据个人需求进行文本预处理。讲数据处理成下面数据格式即list套list的数据格式。

    最初数据如下所示,一条一条文本,换行符分割。

    在漆黑的夜空里看满天璀璨的星星,非常非常的密集,同时月亮也异常明亮。最主要的是在满天繁星中,靠近月亮的3颗星星排列成“勾”的样子,他们特别的明亮。
    
    ......................................................(省略好多数据)
    
    沟里漂着很多死尸大人小孩都有,我顺着消流的方向走,看到臭水带着死尸流进了苹果园,我很怕!
    

    经过初步处理后,也就是通过下文里面的deal_words()方法得到下面

     [['满天璀璨', '星星', '月亮', '明亮', '靠近', '排列'],........., ['沟里', '漂着', '死尸','大人小孩']]
    

    具体数据处理可以参照:数据预处理

    LDA模型实现

    思路:

    1. 将训练数据和预测数据混合并提取词典库
    2. 利用词典库将训练数据转换成one-hot编码
    3. 利用gensim提供的API做模型提取主题
    4. 将混入的预测数据转换成one-hot编码
    5. 预测分类主题

    这里模型采用gensim提供的API进行实现,代码如下:

    def lad_model(train_data):
        # 读取预测分类数据
        test_data = deal_words(read_text_file('./data/set/test_text.txt'))
        # 拼接提取词典库
        contents = train_data + test_data
        # 根据文本获取词典
        dictionary = corpora.Dictionary(contents)
        # 词典创建语料库
        corpus = [dictionary.doc2bow(doc) for doc in train_data]
    	#调用LDA模型,请求潜在主题数30;训练语料库2次
        lda = gensim.models.ldamodel.LdaModel(corpus, num_topics=30, id2word=dictionary,
                                              passes=2)
        #导出模型分类数量
        data = lda.print_topics(num_topics=3, num_words=5)
        # 打印主题,10个主题,20个单词
        for item in data:
            print(item) 
            print("--------------------split line---------------------")
        # 测试数据转换
        test_vec = [dictionary.doc2bow(doc) for doc in test_data]
    	#预测并打印结果
        for i, item in enumerate(test_vec):
            topic = lda.get_document_topics(item)
            keys = target.keys()
            print('第',i+1,'条记录分类结果:',topic)
    

    全部代码以及效果

    lad模型代码以及处理数据代码。这里处理数据的核心代码text_deal.py,写在了同级目录(lda_demo)下面。

    from lda_demo import text_deal as td
    from gensim import corpora, models
    import gensim
    
    """
    读取text文件
    intput:url
    output:list结构的文本数据
    """
    
    
    def read_text_file(url):
        dream_text = open(url, 'r+', encoding='utf-8')
        return dream_text.read().split("\n\n")
    
    
    """
    停用词/分词
    """
    
    
    def deal_words(contents):
        # 去除空格
        contents = td.remove_blank_space(contents)
        # 获取分词结果
        contents = td.cut_words(contents)
        # 去除停用词
        contents = td.drop_stopwords(contents)
        return contents
    
    def lad_model(train_data):
        # 读取预测分类数据
        test_data = deal_words(read_text_file('./data/set/test_text.txt'))
        # 拼接提取词典库
        contents = train_data + test_data
        # 根据文本获取词典
        dictionary = corpora.Dictionary(contents)
        # 词典创建语料库
        corpus = [dictionary.doc2bow(doc) for doc in train_data]
    	#调用LDA模型,请求潜在主题数30;训练语料库2次
        lda = gensim.models.ldamodel.LdaModel(corpus, num_topics=30, id2word=dictionary,
                                              passes=2)
        #导出模型分类数量
        data = lda.print_topics(num_topics=3, num_words=5)
        # 打印主题,10个主题,20个单词
        for item in data:
            print(item) 
            print("--------------------split line---------------------")
        # 测试数据转换
        test_vec = [dictionary.doc2bow(doc) for doc in test_data]
    	#预测并打印结果
        for i, item in enumerate(test_vec):
            topic = lda.get_document_topics(item)
            keys = target.keys()
            print('第',i+1,'条记录分类结果:',topic)
    
    
      if __name__ == '__main__':
        # 据集读取
        contents = read_text_file('./data/set/train_text.txt')
        # 文本处理
        contents = deal_words(contents)
        # LDAmodel
        lad_model(contents)
    
    

    text_deal.py代码如下:

    """
    自然语言处理---文本预处理
    """
    import jieba
    import pandas as pd
    
    """
    加载初始数据信息
    str:文件传输路径
    index:所需真实值索引列表
    """
    
    
    def read_data(str, index):
        dream_data = pd.read_csv(str)
        return dream_data.values[:, index]
    
    
    """
    去掉文本中的空格
    input:our_data为list文本数据
    output:去除空格后的文本list
    """
    
    
    def remove_blank_space(contents):
        contents_new = map(lambda s: s.replace(' ', ''), contents)
        return list(contents_new)
    
    
    """
    判断单词是否为中文
    input:word单个单词
    output:是中文True,不是中文False
    """
    
    
    def is_chinese(word):
        if word >= u'\u4e00' and word <= u'\u9fa5':
            return True
        else:
            return False
    
    
    """
    判断短句是否为纯中文
    input:words短句
    output:是中文True,不是中文False
    """
    
    
    def is_chinese_words(words):
        for word in words:
            if word >= u'\u4e00' and word <= u'\u9fa5':
                continue
            else:
                return False
        return True
    
    
    """
    将文本数据格式化去除非中文字符
    input:contents list结构的文本数据
    output:去除非中文字符的数据
    """
    
    
    def format_contents(contents):
        contents_new = []
        for content in contents:
            content_str = ''
            for i in content:
                if is_chinese(i):
                    content_str = content_str + i
            contents_new.append(content_str)
        return contents_new
    
    
    """
    对文本进行jieba分词
    input:contents文本list
    output:分词后的文本list
    """
    
    
    def cut_words(contents):
        cut_contents = map(lambda s: list(jieba.lcut(s)), contents)
        return list(cut_contents)
    
    
    """
    去除停用词/标点符号
    input:contents文本list(list中保存list)
    output:去除停用词后的文本list
    """
    
    
    def drop_stopwords(contents):
        # 初始化获取停用词表
        stop = open('./data/word_deal/stop_word_cn.txt', encoding='utf-8')
        stop_me = open('./data/word_deal/stop_one_mx.txt', encoding='utf-8')
        key_words = open('./data/word_deal/key_words.txt', encoding='utf-8')
        #分割停用词/自定义停用词/关键词
        stop_words = stop.read().split("\n")
        stop_me_words = stop_me.read().split("\n")
        key_words = key_words.read().split("\n")
        #定义返回后的结果
        contents_new = []
        #遍历处理数据
        for line in contents:
            line_clean = []
            for word in line:
                if (word in stop_words or word in stop_me_words) and word not in key_words:
                    continue
                if is_chinese_words(word):
                    line_clean.append(word)
            contents_new.append(line_clean)
        return contents_new
    
    

    运行效果

    (1, '0.023*"说" + 0.018*"怀孕" + 0.016*"父亲" + 0.014*"里" + 0.011*"岁"')
    --------------------split line---------------------
    (25, '0.023*"说" + 0.012*"办公室" + 0.010*"是不是" + 0.009*"朋友" + 0.009*"大门"')
    --------------------split line---------------------
    (20, '0.014*"同学" + 0.010*"跑" + 0.010*"培训" + 0.010*"骑" + 0.009*"机构"')
    --------------------split line---------------------
    第 1 条记录分类结果: [(4, 0.24392343), (8, 0.1395505), (10, 0.09619252), (18, 0.16527545), (21, 0.17173427), (23, 0.11055296)]
    第 2 条记录分类结果: [(5, 0.124014), (13, 0.28862998), (16, 0.099018164), (19, 0.09216843), (24, 0.12537746), (29, 0.22633219)]
    第 3 条记录分类结果: [(7, 0.101059936), (10, 0.37497482), (21, 0.15868592), (23, 0.19114888), (29, 0.12510397)]
    第 4 条记录分类结果: [(1, 0.082532495), (4, 0.17312291), (14, 0.072532885), (17, 0.38016438), (19, 0.050784156), (21, 0.21228231)]
    
    1. 文本处理根据自己需求一定要做好,清洗掉不必要的数据;否则影响主题分类。
    2. 语料库全面结果会更加友好吧,在语料库范围内分类效果还是比较好的,但是新数据效果一般。

    欢迎批评指正!

    展开全文
  • 无监督提取文档主题——LDA模型1.1 准备工作1.2 调用api实现模型2. LDA的可视化交互分析——pyLDAvis2.1 安装pyLDAvis2.2 结合gensim调用api实现可视化p.s. 保存结果为独立网页p.p.s. 加快prepare速度?2.3 如何...

    1. 无监督提取文档主题——LDA模型

    这个模型具体介绍、应用场景什么的就不谈了,你知道它能从一堆的文本中给你反馈出规定主题数的词语聚类就可以了。

    由于是无监督算法,意味着你不需要去准备训练集,不用去苦逼地打标签,在数据准备阶段任务量至少省掉了一半啊。

    而作为数学小白,其中具体原理如无必要我一向是不愿深究的,只要有人证明可行,那我拿来就用。聪明的脑袋要各尽其用嘛(笑

    但也许我之后始终逃不掉要学习原理吧,先把原理解释放在这里,之后需要时再看。

    故而本篇主要介绍的是如何上手实现如何分析结果这才是Data Scientist该干的事嘛

    1.1 准备工作

    书归正传。以本次工作为例,我需要分析爬取到500名用户每人50页微博,大概500* 50* 10=250000条微博文本的主题情况。也就是说想看看这些人的微博主要是在关心些什么,他们共同关注哪些方面。

    编程环境:
    python 3.6 + pycharm 2018,
    LDA实现使用的包是gensim
    分词还是用我们的老朋朋朋朋友jieba.

    数据准备:
    爬到的原始数据存在csv中,我想的是将所有的微博文本分行读到一个txt中,然后分词去停用词,就达到gensim的输入标准了。

    分词前:
    在这里插入图片描述
    分词后:
    在这里插入图片描述
    code
    用于处理原始文本。

    def stopwordslist(filepath):
        stopwords = [line.strip() for line in open(filepath, 'r', encoding='utf-8').readlines()]
        return stopwords
    
    # 对句子进行分词
    def seg_sentence(sentence):
        sentence = re.sub(u'[0-9\.]+', u'', sentence)
        jb.add_word('光线摄影学院')		# 这里是加入用户自定义的词来补充jieba词典。
        jb.add_word('曾兰老师')			# 同样,如果你想删除哪个特定的未登录词,就先把它加上然后放进停用词表里。
        jb.add_word('网页链接')
        jb.add_word('微博视频')
        jb.add_word('发布了头条文章')
        jb.add_word('青春有你')
        jb.add_word('青你')
        sentence_seged = jb.cut(sentence.strip())
        stopwords = stopwordslist('stopWords/stopwords.txt')  # 这里加载停用词的路径
        outstr = ''
        for word in sentence_seged:
            if word not in stopwords and word.__len__()>1:
                if word != '\t':
                    outstr += word
                    outstr += " "
        return outstr
    
    
    inputs = open('input/like_mi10_user_all_retweet.txt', 'r', encoding='utf-8')
    
    outputs = open('output1/mi10_user_retweet_fc.txt', 'w',encoding='utf-8')
    for line in inputs:
        line_seg = seg_sentence(line)  # 这里的返回值是字符串
        outputs.write(line_seg + '\n')
    outputs.close()
    inputs.close()
    

    1.2 调用api实现模型

    准备数据两小时,接口调用三分钟,等待结果两小时。

    gensim很友好,词典、词袋模型、lda模型都是一句话搞定。

    code

    
    from gensim import corpora
    from gensim.models import LdaModel
    from gensim.corpora import Dictionary
    
    
    train = []
    
    fp = codecs.open('output1/mi10_user_retweet_fc.txt','r',encoding='utf8')
    for line in fp:
        if line != '':
            line = line.split()
            train.append([w for w in line])
    
    dictionary = corpora.Dictionary(train)
    
    corpus = [dictionary.doc2bow(text) for text in train]
    
    lda = LdaModel(corpus=corpus, id2word=dictionary, num_topics=20, passes=60)
    # num_topics:主题数目
    # passes:训练伦次
    # num_words:每个主题下输出的term的数目
    
    for topic in lda.print_topics(num_words = 20):
        termNumber = topic[0]
        print(topic[0], ':', sep='')
        listOfTerms = topic[1].split('+')
        for term in listOfTerms:
            listItems = term.split('*')
            print('  ', listItems[1], '(', listItems[0], ')', sep='')
    

    最后的输出是

    0:
      "北京" (0.024)
      "疫情" ( 0.021)
      "中国联通" ( 0.019)
      "领券" ( 0.019)
      "购物" ( 0.016)
      "新冠" ( 0.016)
      "专享" ( 0.012)
      "元券" ( 0.012)
      "确诊" ( 0.012)
      "上海" ( 0.011)
      "优惠" ( 0.011)
      "肺炎" ( 0.010)
      "新闻" ( 0.010)
      "病例" ( 0.010)
      "汽车"( 0.009)
    1:
      "小米" (0.133)
      "Redmi" ( 0.019)
      "新浪" ( 0.019)
      "智慧" ( 0.018)
      "雷军" ( 0.014)
      "众测" ( 0.012)
      "体验" ( 0.012)
      "智能" ( 0.012)
      "MIUI" ( 0.012)
      "电视" ( 0.012)
      "红米" ( 0.011)
      "空调" ( 0.009)
      "产品" ( 0.009)
      "品牌" ( 0.009)
      "价格"( 0.008)
    2:
      "抽奖" (0.056)
      "平台" ( 0.032)
      "评测" ( 0.022)
      "生活" ( 0.013)
      "红包" ( 0.013)
      "关注" ( 0.012)
      "这条" ( 0.012)
      "视频" ( 0.012)
      "工具" ( 0.011)
      "获得" ( 0.011)
      "有效" ( 0.011)
      "进行" ( 0.010)
      "恭喜" ( 0.010)
      "用户" ( 0.010)
      "公正"( 0.010)
     .....
    

    这种。他只会返回给你规定主题数下的多少词,每个词后面的小数可认为是这个词属于这个主题的概率,主题下所有词的概率和为1;而这个主题应该是什么,就要靠你人工后面分析来定义了。

    那,盯着这一堆冷冰冰的词语和数字,也许你能通过概率衡量出这个词和这个主题的关系,但你能看出不同主题之间的关系吗?你能看出一个词和其他主题的关系吗?

    有点困难。这时就要引出我们的LDA可视化分析工具了。

    2. LDA的可视化交互分析——pyLDAvis

    先上效果图:
    在这里插入图片描述

    2.1 安装pyLDAvis

    > pip install pyldavis
    

    会安装很多依赖包。包括:
    在这里插入图片描述
    源码地址及文档
    直接上手的使用指南

    2.2 结合gensim调用api实现可视化

    pyLDAvis支持三种包内lda模型的直接传入:sklearn、gensim、graphlab,好像也可以自己算。这里当然紧接上文直接用gensim得到的lda模型了。

    pyLDAvis也很友好,同样一句话完成实现:

    import pyLDAvis.gensim
    
    '''插入之前的代码片段'''
    
    d=pyLDAvis.gensim.prepare(lda, corpus, dictionary)
    
    '''
    lda: 计算好的话题模型
    
    corpus: 文档词频矩阵
    
    dictionary: 词语空间
    '''
    
    pyLDAvis.show(d)		#展示在浏览器
    # pyLDAvis.displace(d) #展示在notebook的output cell中
    

    数据量很大,运行时间稍长。

    p.s. 保存结果为独立网页

    同时,如果你希望能够将这个结果保存为独立网页以便分享或放到web系统中,那么可以这样:

    d=pyLDAvis.gensim.prepare(lda, corpus, dictionary)
    
    pyLDAvis.save_html(d, 'lda_pass10.html')	# 将结果保存为该html文件
    

    就不用每次都等好久时间跑结果了。。

    p.p.s. 加快prepare速度?

    是的,这个可视化过程真的很慢。。我用time来计时了,测试时为节省时间,gensim只训练一遍,耗时58s,然后等待pyLDAvis的渲染。。等了足足一个多小时吧?4200s…才终于出来了。
    然后保存为网页很快。
    在这里插入图片描述
    期间电脑CPU利用率一直保持在100%, pycharm占比90%左右。结果出来气得我也没截图,马上试了试查到的新方案:

    在这里插入图片描述

    d=pyLDAvis.gensim.prepare(lda, corpus, dictionary, mds='mmds')
    

    酱紫。
    实际测试了,可以说,没有效果。。。。。

    同时这个选择算法的参数还可以为tsne,不同算法的区别还是看文档吧。

    2.3 如何分析pyLDAvis可视化结果

    出来的这个页面,说复杂也不复杂,左边的气泡分布是不同主题,右边就是主题内前30个特征词了。浅蓝色的表示这个词在整个文档中出现的频率(权重),深红色的表示这个词在这个主题中所占的权重。右上角可以调节一个参数λ,其作用接着往下看。
    比如

    于是我们最后回答LDAvis作者开发这个工具所要解决的三个问题:

    2.3.1. 每个主题表示什么意义?

    通过鼠标悬浮在左边的气泡上,我们可以选择查看具体的某个主题。选定后,右侧面板会相应地显示出跟这个主题相关的词汇,通过总结这些词汇表达的意义,我们就可以归纳出该主题的意义。

    同时,哪个词对主题的权重更高呢?某个词语主题的相关性,就由λ参数来调节。

    如果λ接近1,那么在该主题下更频繁出现的词,跟主题更相关;
    如果λ越接近0,那么该主题下更特殊、更独有(exclusive)的词,跟主题更相关(有点TF-IDF的意思了)。

    所以我们可以通过调节λ的大小来改变词语跟主题的相关性,探索更加sense的主题意义。

    2.3.2 每个主题有多么普遍?

    在跑完主题建模之后,我们就可以知道每个主题出现的频率。LDAvis的作者将这个数字,用圆圈的大小来表示,同时也按顺序标号为1~n。所以气泡的大小及编号即表示主题出现的频率。
    在这里插入图片描述

    2.3.3 主题之间有什么关联?

    这里作者用多维尺度分析,提取出主成分做维度,将主题分布到这两个维度上,主题相互之间的位置远近,就表达了主题之间的接近性。气泡距离采用的是JSD距离,(应该)可认为是主题间的差异度,气泡有重叠说明这两个话题里的特征词有交叉。

    知道这些后,就是看词说话了。看看这些词应该是在说些什么东西,提炼出不同的topic来,这才是有实际应用价值的结果。若无最后的结果输出,前面所做的一切都是废纸一张。

    先总结到这里吧,抛去理论层面,应该是够用了。

    展开全文
  • 无监督提取文档主题——LDA模型 1.1 准备工作 1.2 调用api实现模型 LDA的可视化交互分析——pyLDAvis 2.1 安装pyLDAvis 2.2 结合gensim调用api实现可视化 p.s. 保存结果为独立网页 p.p.s. 加快prepare速度? 2.3 ...

    主题模型LDA的实现及其可视化pyLDAvis

    1. 无监督提取文档主题——LDA模型
      1.1 准备工作
      1.2 调用api实现模型
    2. LDA的可视化交互分析——pyLDAvis
      2.1 安装pyLDAvis
      2.2 结合gensim调用api实现可视化
      p.s. 保存结果为独立网页
      p.p.s. 加快prepare速度?
      2.3 如何分析pyLDAvis可视化结果
      2.3.1. 每个主题表示什么意义?
      2.3.2 每个主题有多么普遍?
      2.3.3 主题之间有什么关联?
    3. 无监督提取文档主题——LDA模型
      这个模型具体介绍、应用场景什么的就不谈了,你知道它能从一堆的文本中给你反馈出规定主题数的词语聚类就可以了。

    由于是无监督算法,意味着你不需要去准备训练集,不用去苦逼地打标签,在数据准备阶段任务量至少省掉了一半啊。

    而作为数学小白,其中具体原理如无必要我一向是不愿深究的,只要有人证明可行,那我拿来就用。聪明的脑袋要各尽其用嘛(笑

    但也许我之后始终逃不掉要学习原理吧,先把原理解释放在这里,之后需要时再看。

    故而本篇主要介绍的是如何上手实现及如何分析结果,这才是Data Scientist该干的事嘛

    1. 无监督提取文档主题——LDA模型

    1.1 准备工作

    书归正传。以本次工作为例,我需要分析爬取到500名用户每人50页微博,大概500* 50* 10=250000条微博文本的主题情况。也就是说想看看这些人的微博主要是在关心些什么,他们共同关注哪些方面。

    编程环境:
    python 3.6 + pycharm 2018,
    LDA实现使用的包是gensim,
    分词还是用我们的老朋朋朋朋友jieba.

    数据准备:
    爬到的原始数据存在csv中,我想的是将所有的微博文本分行读到一个txt中,然后分词去停用词,就达到gensim的输入标准了。

    分词前:
    在这里插入图片描述
    分词后:
    在这里插入图片描述
    【code】
    用于处理原始文本。

    def stopwordslist(filepath):
        stopwords = [line.strip() for line in open(filepath, 'r', encoding='utf-8').readlines()]
        return stopwords
    
    # 对句子进行分词
    def seg_sentence(sentence):
        sentence = re.sub(u'[0-9\.]+', u'', sentence)
        jb.add_word('光线摄影学院')		# 这里是加入用户自定义的词来补充jieba词典。
        jb.add_word('曾兰老师')			# 同样,如果你想删除哪个特定的未登录词,就先把它加上然后放进停用词表里。
        jb.add_word('网页链接')
        jb.add_word('微博视频')
        jb.add_word('发布了头条文章')
        jb.add_word('青春有你')
        jb.add_word('青你')
        sentence_seged = jb.cut(sentence.strip())
        stopwords = stopwordslist('stopWords/stopwords.txt')  # 这里加载停用词的路径
        outstr = ''
        for word in sentence_seged:
            if word not in stopwords and word.__len__()>1:
                if word != '\t':
                    outstr += word
                    outstr += " "
        return outstr
    
    
    inputs = open('input/like_mi10_user_all_retweet.txt', 'r', encoding='utf-8')
    
    outputs = open('output1/mi10_user_retweet_fc.txt', 'w',encoding='utf-8')
    for line in inputs:
        line_seg = seg_sentence(line)  # 这里的返回值是字符串
        outputs.write(line_seg + '\n')
    outputs.close()
    inputs.close()
    

    1.2 调用api实现模型

    准备数据两小时,接口调用三分钟,等待结果两小时。

    gensim很友好,词典、词袋模型、lda模型都是一句话搞定。

    【code】

    from gensim import corpora
    from gensim.models import LdaModel
    from gensim.corpora import Dictionary
    
    
    train = []
    
    fp = codecs.open('output1/mi10_user_retweet_fc.txt','r',encoding='utf8')
    for line in fp:
        if line != '':
            line = line.split()
            train.append([w for w in line])
    
    dictionary = corpora.Dictionary(train)
    
    corpus = [dictionary.doc2bow(text) for text in train]
    
    lda = LdaModel(corpus=corpus, id2word=dictionary, num_topics=20, passes=60)
    # num_topics:主题数目
    # passes:训练伦次
    # num_words:每个主题下输出的term的数目
    
    for topic in lda.print_topics(num_words = 20):
        termNumber = topic[0]
        print(topic[0], ':', sep='')
        listOfTerms = topic[1].split('+')
        for term in listOfTerms:
            listItems = term.split('*')
            print('  ', listItems[1], '(', listItems[0], ')', sep='')
    

    最后的输出是

    0:
      "北京" (0.024)
      "疫情" ( 0.021)
      "中国联通" ( 0.019)
      "领券" ( 0.019)
      "购物" ( 0.016)
      "新冠" ( 0.016)
      "专享" ( 0.012)
      "元券" ( 0.012)
      "确诊" ( 0.012)
      "上海" ( 0.011)
      "优惠" ( 0.011)
      "肺炎" ( 0.010)
      "新闻" ( 0.010)
      "病例" ( 0.010)
      "汽车"( 0.009)
    1:
      "小米" (0.133)
      "Redmi" ( 0.019)
      "新浪" ( 0.019)
      "智慧" ( 0.018)
      "雷军" ( 0.014)
      "众测" ( 0.012)
      "体验" ( 0.012)
      "智能" ( 0.012)
      "MIUI" ( 0.012)
      "电视" ( 0.012)
      "红米" ( 0.011)
      "空调" ( 0.009)
      "产品" ( 0.009)
      "品牌" ( 0.009)
      "价格"( 0.008)
    2:
      "抽奖" (0.056)
      "平台" ( 0.032)
      "评测" ( 0.022)
      "生活" ( 0.013)
      "红包" ( 0.013)
      "关注" ( 0.012)
      "这条" ( 0.012)
      "视频" ( 0.012)
      "工具" ( 0.011)
      "获得" ( 0.011)
      "有效" ( 0.011)
      "进行" ( 0.010)
      "恭喜" ( 0.010)
      "用户" ( 0.010)
      "公正"( 0.010)
     .....
    

    这种。他只会返回给你规定主题数下的多少词,每个词后面的小数可认为是这个词属于这个主题的概率,主题下所有词的概率和为1;而这个主题应该是什么,就要靠你人工后面分析来定义了。

    那,盯着这一堆冷冰冰的词语和数字,也许你能通过概率衡量出这个词和这个主题的关系,但你能看出不同主题之间的关系吗?你能看出一个词和其他主题的关系吗?

    有点困难。这时就要引出我们的LDA可视化分析工具了。

    2. LDA的可视化交互分析——pyLDAvis

    先上效果图:
    在这里插入图片描述

    2.1 安装pyLDAvis

    pip install pyldavis
    

    2.2 结合gensim调用api实现可视化

    pyLDAvis支持三种包内lda模型的直接传入:sklearn、gensim、graphlab,好像也可以自己算。这里当然紧接上文直接用gensim得到的lda模型了。
    pyLDAvis也很友好,同样一句话完成实现:

    import pyLDAvis.gensim
    
    '''插入之前的代码片段'''
    
    d=pyLDAvis.gensim.prepare(lda, corpus, dictionary)
    
    '''
    lda: 计算好的话题模型
    
    corpus: 文档词频矩阵
    
    dictionary: 词语空间
    '''
    
    pyLDAvis.show(d)		#展示在浏览器
    # pyLDAvis.displace(d) #展示在notebook的output cell中
    

    数据量很大,运行时间稍长。

    p.s. 保存结果为独立网页

    同时,如果你希望能够将这个结果保存为独立网页以便分享或放到web系统中,那么可以这样

    d=pyLDAvis.gensim.prepare(lda, corpus, dictionary)
    
    pyLDAvis.save_html(d, 'lda_pass10.html')	# 将结果保存为该html文件
    

    就不用每次都等好久时间跑结果了。。

    p.p.s. 加快prepare速度?

    是的,这个可视化过程真的很慢。。我用time来计时了,测试时为节省时间,gensim只训练一遍,耗时58s,然后等待pyLDAvis的渲染。。等了足足一个多小时吧?4200s…才终于出来了。
    然后保存为网页很快。
    在这里插入图片描述

    d=pyLDAvis.gensim.prepare(lda, corpus, dictionary, mds='mmds')
    

    酱紫。
    实际测试了,可以说,没有效果。。。。。

    同时这个选择算法的参数还可以为tsne,不同算法的区别还是看文档吧。

    2.3 如何分析pyLDAvis可视化结果

    出来的这个页面,说复杂也不复杂,左边的气泡分布是不同主题,右边就是主题内前30个特征词了。浅蓝色的表示这个词在整个文档中出现的频率(权重),深红色的表示这个词在这个主题中所占的权重。右上角可以调节一个参数λ,其作用接着往下看。
    在这里插入图片描述
    于是我们最后回答LDAvis作者开发这个工具所要解决的三个问题:

    2.3.1. 每个主题表示什么意义?

    通过鼠标悬浮在左边的气泡上,我们可以选择查看具体的某个主题。选定后,右侧面板会相应地显示出跟这个主题相关的词汇,通过总结这些词汇表达的意义,我们就可以归纳出该主题的意义。

    同时,哪个词对主题的权重更高呢?某个词语主题的相关性,就由λ参数来调节。

    如果λ接近1,那么在该主题下更频繁出现的词,跟主题更相关;
    如果λ越接近0,那么该主题下更特殊、更独有(exclusive)的词,跟主题更相关(有点TF-IDF的意思了)。
    

    所以我们可以通过调节λ的大小来改变词语跟主题的相关性,探索更加sense的主题意义。

    2.3.2 每个主题有多么普遍?

    在跑完主题建模之后,我们就可以知道每个主题出现的频率。LDAvis的作者将这个数字,用圆圈的大小来表示,同时也按顺序标号为1~n。所以气泡的大小及编号即表示主题出现的频率。
    在这里插入图片描述

    2.3.3 主题之间有什么关联?

    这里作者用多维尺度分析,提取出主成分做维度,将主题分布到这两个维度上,主题相互之间的位置远近,就表达了主题之间的接近性。气泡距离采用的是JSD距离,(应该)可认为是主题间的差异度,气泡有重叠说明这两个话题里的特征词有交叉。

    知道这些后,就是看词说话了。看看这些词应该是在说些什么东西,提炼出不同的topic来,这才是有实际应用价值的结果。若无最后的结果输出,前面所做的一切都是废纸一张。

    先总结到这里吧,抛去理论层面,应该是够用了。

    展开全文
  • 主题模型目前广泛应用于机器学习与自然语言分析等领域,该模型自动分析一...大数据处理的内存迭代和分布式计算特性,实现了基于 LDA 模型的文本主题提取过程,并给 出了在新闻文本数据集上的主题抽取与分类预测结果。
  • 场景大量的文本留言,有短文本有长文本,我们如何搞笑提取文本主题?如上图 知道view 如何获取topics 解决办法: 1文本分类 2,主题提取 3,主题聚类 4,主题输出 from sklearn.cluster import DBSCAN import ...
  • 通过对交通事故中记录驾驶员违法行为的文本数据进行分析,提出了一种文本主题提取模型和技术,来挖掘交通事故中驾驶员风险驾驶因素,解决以往交通事故统计中交通违法行为难以挖掘的问题,计算出影响交通事故的最大...
  • 主题提取LDA

    2015-04-21 20:57:21
    了解使用LDA的资料,亲们可以多多下载,把文本主题提取整好
  • 提出了一种基于增量词集频率的文本主题提取算法,其核心思想是计算主题词集频率增量,算法从候选主题词集提取主题词时,计算单个候选主题词对主题词集频率的增量,若增量小于给定阈值,则主题词提取算法结束,否则...
  • 单文档摘要从给定的一个文档中生成摘要,多文档摘要从给定的一组主题相关的文档中生成摘要。按照输出类型可分为抽取式摘要和生成式摘要。 摘要:意思就是从一段文本 用几句话来概括这段话的意思 方法有很多 本文只讲...
  • lda主题提取模型 4. 词向量化word2vec 参考: http://zhuanlan.zhihu.com/textmining-experience/1963076 #!/usr/bin/env python # -*- coding:utf-8 -*- import MySQLdb import pandas as pd import pandas.io....
  • 本篇文章的呢主要写的使用spark ml 中的lda...使用lda算法对中文文本聚类并提取主题,大体上需要这么几个过程: 1.首先采用中文分词工具对中文分词,这里采用开源的IK分词。 2.从分词之后的词表中去掉停用词,生成新
  • 这里写自定义目录标题1、数据的提取分词与词向量学习如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一...
  • 主题模型+TF-IDF提取文本的关键词 背景 懒得说背景!以后想起来再补充!电脑硬盘坏过,本文代码也忘了参考谁的了!原作者发现可以联系我!立马改参考! Import Dependency Jar import gensim import math import...
  • 不知道我理解的对不对哈~你想要做的是,用一个已经训练出来的P(w|z)和P(z|d)去计算一个新文本的P(z|d)?如果是的话,其实还是有解的~首先P(z|d)也可以表示为但是P(z|w)并没有在原始的主题模型结果中,如何求得P(z|...
  • 从任何文本提取提及(@mention)和/或主题标签(#hashtag) 如何使用 const extract = require ( 'mention-hashtag' ) const mentions = extract ( 'Any text with @mention' ) ; // mentions == ['@mention'] ...
  • 今天的主题是介绍提取文本中关键词技术(有时候业务场景是需要从海量舆情数据中提取关键词,这个时候就需要进行分词求词频来先发现高频词),介绍最为简单的一种用jieba分词后,然后统计词频,词频高的我们就理解为...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 683
精华内容 273
关键字:

文本主题提取