Python3-LDA主题模型+TF/IDF gensim实现,中文案例

LDA主题模型+TF/IDF gensim实现

  2020年8月7日,上班无事,写博客打发时间,我的第一篇博客
  数据的清洗和LDA和TF/IDF的实现,原理写起来太长了,懒得写了

文本预处理

  当我们拿到文本数据时,我们需要将其转化为词袋,才能进行标准化处理,但是往往在这些数据中存在着一些噪音数据,如“的、我、吗、需要”这些对我们结果没有意义的词语,同时在进行切词时可能将一个词切成多个,如将“泸州老窖”切成“泸州”,“老窖”两个词,其次繁体字英文也会对结果进行一些干扰,综上所述我们将进行数据清晰,生成规范的数据。

#导入库
from gensim import corpora
from gensim.models import LdaModel
from gensim import models
from gensim.corpora import Dictionary
import pandas as pd
import jieba.posseg as jp, jieba
import opencc

#读取数据
texts=pd.read_excel(r'data.xlsx',encoding='utf-8',usecos=[0,1]).astype(str)

#繁体转化为简体
texts.iloc[:,0].apply(lambda x:opencc.OpenCC('t2s').convert(x))

#通过jieba进行切词生成词袋
text=[jp.cut(i) for i in texts]

#添加停用词性
flags = ('n', 'nr','v','ns', 'nt','d')
#停用词列表,这里“cn_stopwords.txt”使用哈工大停用词表
stoplist=open('cn_stopwords.txt','r',encoding='utf-8').read().split('\n')+['一定','个人','企业','没','做','说','非常','可能','原','美国','中国','产品','问题']

#将于停用词性中相同词性的词和停用词表中的词剔除,并剔除长度为1的词
data = [[w.word for w in words if (w.word not in stoplist and w.flag in flags and len(w.word)>1)] for words in text]

#将清洗后的数据转化为 Corpora_Dictionary
dictionary = corpora.Dictionary(data)
#压缩词向量,去掉出现的文章小于2的词,和在50%的文章都出现的词,整体长度限制在500
dictionary.filter_extremes(no_below=2, no_above=0.5, keep_n=500)
corpus = [ dictionary.doc2bow(text) for text in data]

TF/IDF+LDA

#进行TF/IDF编码
tfidf = models.TfidfModel(corpus)
corpus_tfidf = tfidf[corpus]

#主题个数
num_topics=5
#训练LDA模型,passes为迭代次数
lda = LdaModel(corpus=corpus, id2word=dictionary, num_topics=num_topics,passes=100) 

#打印主题
for topic in lda.print_topics(num_words=num_topics,num_topics=num_topics):
    print(topic)

#out_put:
#(0, '0.027*"液体" + 0.027*"啤酒" + 0.027*"成分" + 0.027*"解热" + 0.027*"面包"')
#(1, '0.032*"觉得" + 0.026*"没有" + 0.020*"产业" + 0.018*"其实" + 0.016*"比较"')
#(2, '0.036*"创新" + 0.020*"全球" + 0.019*"方面" + 0.017*"觉得" + 0.016*"技术"')
#(3, '0.129*"茅台" + 0.024*"板块" + 0.021*"股价" + 0.018*"指数" + 0.018*"疫情"')
#(4, '0.029*"银行" + 0.023*"其实" + 0.019*"包括" + 0.014*"觉得" + 0.014*"东西"')

文章归类

#生成主题列表
topic_list=[i for i in range(num_topics)]
article_class = defaultdict()
for i in topic_list:
    article_class[i]=[]
#将同主题文章放在一个Key对应Value中
for i in range(len(doc_topic)):
    article_class[topic_list[doc_topic[i][0][0]]].append(pd.DataFrame(texts).iloc[i,0])

#将主题替换成关键词
ls=list(article_class.items())
article_class_list=[]
for i in ls:
    s=[]
    s.append(key_word[i[0]])
    s=s+i[1]
    article_class_list.append(s)

函数封装

 上面的代码为了方便理解没有进行函数封装,了方便在业务场景中方便调用,下面是进行封装后的代码

from gensim import corpora
from gensim.models import LdaModel
from gensim import models
from gensim.corpora import Dictionary
import pandas as pd
import jieba.posseg as jp, jieba
import opencc
from collections import defaultdict

#数据清洗
def deal_row_text(row_data,add_stoplist,whitelist,flags):
    #繁转简
    texts=row_data.iloc[:,0].apply(lambda x:opencc.OpenCC('t2s').convert(x))
    #逐句分词
    text=[jp.cut(i) for i in texts]
    #去停用词
    stoplist=open('cn_stopwords.txt','r',encoding='utf-		 8').read().split('\n')+add_stoplist
    #加白名单
    for i in whitelist:
        jieba.add_word(i)
    data = [[w.word for w in words if (w.word not in stoplist and w.flag in flags and len(w.word)>1)] for words in text]
    return data

#词频统计
def words_frequent(data):
    frequency = defaultdict(int)
    for i in data:
        for j in i:
            frequency[j] += 1
    sort_frequency=list(frequency.items())
    sort_frequency.sort(key=lambda x:x[1],reverse=True)
    return sort_frequency
 
#词袋编码
def record_data(data):
    global dictionary,corpus,corpus_tfidf
    dictionary = corpora.Dictionary(data)
    dictionary.filter_extremes(no_below=3, no_above=0.4, keep_n=500)
    corpus = [ dictionary.doc2bow(text) for text in data]
    tfidf = models.TfidfModel(corpus)
    corpus_tfidf = tfidf[corpus]
    
#训练模型
def model_result(num_topics=5,passes=100):
    global lda,doc_topic
    lda = LdaModel(corpus=corpus, id2word=dictionary, num_topics=num_topics,passes=passes)
    doc_topic = [a for a in lda[corpus]]

#标准化结果展示
def format_result(on_of=False,num_topics=5,num_words=5):
    key_word=[]
    on_of=True
    for i in lda.show_topics(num_topics=num_topics, num_words=num_words, log=False, formatted=False):
        word=[]
        for j in i[1]:
            word.append(j[0])
            if on_of==True:
                word.append(j[1])
        key_word.append(word)
    return key_word

#文章分类
def  classify_article(num_topics):
    topic_list=[i for i in range(num_topics)]
    article_class = defaultdict()
    for i in topic_list:
        article_class[i]=[]
    for i in range(len(doc_topic)):
        doc_topic[i].sort(key=lambda x:x[1],reverse=True)
        article_class[topic_list[doc_topic[i][0][0]]].append(texts.iloc[i,0])
    return article_class


if __name__=='__main__':
    num_topics=15
    texts=pd.read_excel('past.xlsx',encoding='utf-8',header=None).astype(str)
    flags = ['n', 'nr','v','ns', 'nt','d']
    add_stoplist=['知道','了解','感受','矿泉水','公司','东北','案例','包装','作者','看到','转载','商品','日本','消费者','心理','使用','越来越','购买','一定','个人','企业','没','做','说','非常','可能','原','美国','中国','产品','问题']
    whitelist=['iPhone 11','泸州老窖']
    data=deal_row_text(texts,add_stoplist,whitelist,flags)
    record_data(data)
    model_result(num_topics=num_topics,passes=100)
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值