当前位置:   article > 正文

Python数据分析案例14——文本计算TF-IDF值和LDA主题模型_tf-idf lda

tf-idf lda

本次案例教大家怎么进行文本的TF-idf值的计算,并且使用这个相应的词向量进行LDA文本主题模型的构建,然后画出每个主题的重要词汇的词云图。

任何文本数据,只要是很多条文本,都能进行上面的建模操作。这一套流程对于文本大数据分析是非常实用的。

(部分图片打了马赛克是因为应该有敏感词汇不让显示.....)

需要这代码演示数据的同学可以参考:数据


文本读取 分词

导入包,读取停用词

  1. import pandas as pd
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. import seaborn as sns
  5. plt.rcParams['font.sans-serif'] = ['KaiTi'] #指定默认字体 SimHei黑体
  6. plt.rcParams['axes.unicode_minus'] = False #解决保存图像是负号'
  7. import jieba
  8. stop_list = pd.read_csv("停用词.txt",index_col=False,quoting=3,sep="\t",names=['stopword'], encoding='utf-8')

对我们的本文数据进行读取,然后使用jieba库进行分词操作

  1. #Jieba分词函数
  2. def txt_cut(juzi):
  3. lis=[w for w in jieba.lcut(juzi) if w not in stop_list.values]
  4. return (" ").join(lis)
  5. df=pd.read_excel('2022新闻.xlsx')
  6. df['cutword']=df['content'].astype('str').apply(txt_cut)

查看我们的数据前五行现在的样子:

df.head()

 我使用的数据是2022年所有的央视新闻的文本,day是日期,前五条都是2022年1月1日的,title是这个新闻的标题,content是新闻文本内容,cutword就是进行停用词去除,分词后的词汇。

可以看到分词后,每个词语中间都是空白连接,标点符号都去了,这样方便后面进行文本的词向量化。


jieba分析

首先使用jieba库统计一下,2022年所有新闻文本的词汇重要性排序。

  1. import jieba.analyse
  2. jieba.analyse.set_stop_words('停用词.txt')
  3. #合并一起
  4. text = ''
  5. for i in range(len(df['cutword'])):
  6. text += df['cutword'][i]+'\n'
  7. jieba.analyse.extract_tags(text,topK=20,withWeight=True)

 

我这里只输出了前20个最重要的词汇。既然是央视的新闻,那么央视网,新闻联播这些词显然都是出现得最多的。

发展,中国,国家,这些也都是新闻联播常见的用词了。

病例,新冠,疫情,在2022年,新闻对于这些东西也是播报频率很高的。


Tf-IDF分析

上面的词频统计(TF)分析其实都是新闻联播常用的词汇,那么经过逆词频(idf)计算后,真实的词语重要性排序是什么呢,下面进行TF-IDF计算,词向量化。

  1. from sklearn.feature_extraction.text import CountVectorizer,TfidfVectorizer
  2. from sklearn.decomposition import LatentDirichletAllocation
  1. tf_vectorizer = TfidfVectorizer()
  2. #tf_vectorizer = TfidfVectorizer(ngram_range=(2,2)) #2元词袋
  3. X = tf_vectorizer.fit_transform(df.cutword)
  4. #print(tf_vectorizer.get_feature_names_out())
  5. print(X.shape)

可以看到,这里将分词好了的文本变为了48265列数值型的特征变量X。这样就方便模型计算。

查看TF-IDF值排序

  1. data1 = {'word': tf_vectorizer.get_feature_names_out(),
  2. 'tfidf': X.toarray().sum(axis=0).tolist()}
  3. df1 = pd.DataFrame(data1).sort_values(by="tfidf" ,ascending=False,ignore_index=True)
  4. df1.head(20)

 

 TF-IDF值最高的前20个词汇排序如图,说明真实的最重要的词汇大概是:病例,发展,中国,m国,这些词汇。

像央视网,新闻联播这些几乎每个新闻都有的词汇就排名往下掉了。


LDA建模

LDA模型可以说类似于聚类模型,是一种无监督的算法,就是把文本数据自动划分为几类几类话题,然后每类话题都有一些高频词汇可以输出出来。

说白了就是一种专门针对文本数据的聚类方法。

由于是无监督,所以聚类效果也不好评价。聚类个数也不知道咋选.....

本文主观的将聚类个数定为10,即将文本数据划分为10个主题类别。

  1. n_topics = 10 #分为10类
  2. lda = LatentDirichletAllocation(n_components=n_topics, max_iter=100,
  3. learning_method='batch',
  4. learning_offset=100,
  5. # doc_topic_prior=0.1,
  6. # topic_word_prior=0.01,
  7. random_state=0)
  8. lda.fit(X)

 模型拟合好后,查看结果前先定义一个函数,让结果输出更好看一下。

  1. def print_top_words(model, feature_names, n_top_words):
  2. tword = []
  3. tword2 = []
  4. tword3=[]
  5. for topic_idx, topic in enumerate(model.components_):
  6. print("Topic #%d:" % topic_idx)
  7. topic_w = [feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]]
  8. topic_pro=[str(round(topic[i],3)) for i in topic.argsort()[:-n_top_words - 1:-1]] #(round(topic[i],3))
  9. tword.append(topic_w)
  10. tword2.append(topic_pro)
  11. print(" ".join(topic_w))
  12. print(" ".join(topic_pro))
  13. print(' ')
  14. word_pro=dict(zip(topic_w,topic_pro))
  15. tword3.append(word_pro)
  16. return tword3

选择每个主题输出前20个重要词汇;

  1. ##输出每个主题对应词语和概率
  2. n_top_words = 20
  3. feature_names = tf_vectorizer.get_feature_names_out()
  4. word_pro = print_top_words(lda, feature_names, n_top_words)

可以看到,输出了10个主题,每个主题对应输出20个重要词汇和他们的重要性数值。

那么每条新闻属于哪类话题,可以通过下面代码得到每篇文章对应主题

  1. #输出每篇文章对应主题
  2. topics=lda.transform(X)
  3. topic=np.argmax(topics,axis=1)
  4. df['topic']=topic
  5. #df.to_excel("data_topic.xlsx",index=False)
  6. print(topics.shape)
  7. print(topics[0])
  8. topic[0]

 如图预测的类别是一个(5337,10)的数据,5337是样本个数,即5337条新闻,10是分为10类,每一类的概率值。

我们查看第一条数据的10的类别概率值,发现它是第0类话题的概率是0.0213,第1类话题的概率是0.1518,第2类话题的概率是0.52......以此类推。

由于它是第2类话题的概率0.52最大,所以第一条新闻被认为是第2类话题。


词云图

打印出来每个话题关键词不够直观,画出每类话题的词云图看。

先定义一个随机颜色的函数。能随机返回颜色。

  1. import random #定义随机生成颜色函数
  2. def randomcolor():
  3. colorArr = ['1','2','3','4','5','6','7','8','9','A','B','C','D','E','F']
  4. color ="#"+''.join([random.choice(colorArr) for i in range(6)])
  5. return color
  6. [randomcolor() for i in range(3)]

 词语图设置

  1. from collections import Counter
  2. from wordcloud import WordCloud
  3. from matplotlib import colors
  4. #from imageio import imread #形状设置
  5. #mask = imread('爱心.png')
  6. def generate_wordcloud(tup):
  7. color_list=[randomcolor() for i in range(10)] #随机生成10个颜色
  8. wordcloud = WordCloud(background_color='white',font_path='simhei.ttf',#mask = mask, #形状设置
  9. max_words=20, max_font_size=50,random_state=42,
  10. colormap=colors.ListedColormap(color_list) #颜色
  11. ).generate(str(tup))
  12. return wordcloud

画多子图

  1. dis_cols = 4 #一行几个
  2. dis_rows = 3
  3. dis_wordnum=20
  4. plt.figure(figsize=(5 * dis_cols, 5 * dis_rows),dpi=128)
  5. kind=len(df['topic'].unique())
  6. for i in range(kind):
  7. ax=plt.subplot(dis_rows,dis_cols,i+1)
  8. most10 = [ (k,float(v)) for k,v in word_pro[i].items()][:dis_wordnum] #高频词
  9. ax.imshow(generate_wordcloud(most10), interpolation="bilinear")
  10. ax.axis('off')
  11. ax.set_title("第{}类话题 前{}词汇".format(i,dis_wordnum), fontsize=30)
  12. plt.tight_layout()
  13. plt.show()

 可以看到每一类话题的重要性词汇都画出来了,词语越大说明这个词越重要。

可以看到LDA模型效果还是不错的,比如第2类话题出现了很多中国,合作,发展,人民,全面等词汇,说明第2类话题就是那些新闻联播里面老生常谈的些描述国家发展的新闻。

第7类话题出现了很多病例,输入,确诊,新增,本土,新冠等这些词汇,说明第7类话题就是那些天天报道新冠疫情情况的新闻。

第4类话题出现了很多冬奥会,运动员,滑雪,选手,比赛等这些词汇,说明第4类话题就是描述冬奥会比赛情况的新闻。

其他话题也有各自的主题和道理。

这是2022的央视网新闻,换成任何一个其他的文本都可以进行上述的分析,比如可以分析股吧评论,电影标语,微博热搜等等。最终可以得到每个文本的类别和词云图。


创作不易,看官觉得写得还不错的话点个关注和赞吧,本人会持续更新python数据分析领域的代码文章~(需要定制代码可私信)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/289996
推荐阅读
相关标签
  

闽ICP备14008679号