赞
踩
本次案例教大家怎么进行文本的TF-idf值的计算,并且使用这个相应的词向量进行LDA文本主题模型的构建,然后画出每个主题的重要词汇的词云图。
任何文本数据,只要是很多条文本,都能进行上面的建模操作。这一套流程对于文本大数据分析是非常实用的。
(部分图片打了马赛克是因为应该有敏感词汇不让显示.....)
需要这代码演示数据的同学可以参考:数据
导入包,读取停用词
- import pandas as pd
- import numpy as np
- import matplotlib.pyplot as plt
- import seaborn as sns
- plt.rcParams['font.sans-serif'] = ['KaiTi'] #指定默认字体 SimHei黑体
- plt.rcParams['axes.unicode_minus'] = False #解决保存图像是负号'
- import jieba
- stop_list = pd.read_csv("停用词.txt",index_col=False,quoting=3,sep="\t",names=['stopword'], encoding='utf-8')
对我们的本文数据进行读取,然后使用jieba库进行分词操作
- #Jieba分词函数
- def txt_cut(juzi):
- lis=[w for w in jieba.lcut(juzi) if w not in stop_list.values]
- return (" ").join(lis)
- df=pd.read_excel('2022新闻.xlsx')
- df['cutword']=df['content'].astype('str').apply(txt_cut)
查看我们的数据前五行现在的样子:
df.head()
我使用的数据是2022年所有的央视新闻的文本,day是日期,前五条都是2022年1月1日的,title是这个新闻的标题,content是新闻文本内容,cutword就是进行停用词去除,分词后的词汇。
可以看到分词后,每个词语中间都是空白连接,标点符号都去了,这样方便后面进行文本的词向量化。
首先使用jieba库统计一下,2022年所有新闻文本的词汇重要性排序。
- import jieba.analyse
- jieba.analyse.set_stop_words('停用词.txt')
- #合并一起
- text = ''
- for i in range(len(df['cutword'])):
- text += df['cutword'][i]+'\n'
- jieba.analyse.extract_tags(text,topK=20,withWeight=True)
我这里只输出了前20个最重要的词汇。既然是央视的新闻,那么央视网,新闻联播这些词显然都是出现得最多的。
发展,中国,国家,这些也都是新闻联播常见的用词了。
病例,新冠,疫情,在2022年,新闻对于这些东西也是播报频率很高的。
上面的词频统计(TF)分析其实都是新闻联播常用的词汇,那么经过逆词频(idf)计算后,真实的词语重要性排序是什么呢,下面进行TF-IDF计算,词向量化。
- from sklearn.feature_extraction.text import CountVectorizer,TfidfVectorizer
- from sklearn.decomposition import LatentDirichletAllocation
- tf_vectorizer = TfidfVectorizer()
- #tf_vectorizer = TfidfVectorizer(ngram_range=(2,2)) #2元词袋
- X = tf_vectorizer.fit_transform(df.cutword)
- #print(tf_vectorizer.get_feature_names_out())
- print(X.shape)
可以看到,这里将分词好了的文本变为了48265列数值型的特征变量X。这样就方便模型计算。
查看TF-IDF值排序
- data1 = {'word': tf_vectorizer.get_feature_names_out(),
- 'tfidf': X.toarray().sum(axis=0).tolist()}
- df1 = pd.DataFrame(data1).sort_values(by="tfidf" ,ascending=False,ignore_index=True)
- df1.head(20)
TF-IDF值最高的前20个词汇排序如图,说明真实的最重要的词汇大概是:病例,发展,中国,m国,这些词汇。
像央视网,新闻联播这些几乎每个新闻都有的词汇就排名往下掉了。
LDA模型可以说类似于聚类模型,是一种无监督的算法,就是把文本数据自动划分为几类几类话题,然后每类话题都有一些高频词汇可以输出出来。
说白了就是一种专门针对文本数据的聚类方法。
由于是无监督,所以聚类效果也不好评价。聚类个数也不知道咋选.....
本文主观的将聚类个数定为10,即将文本数据划分为10个主题类别。
- n_topics = 10 #分为10类
- lda = LatentDirichletAllocation(n_components=n_topics, max_iter=100,
- learning_method='batch',
- learning_offset=100,
- # doc_topic_prior=0.1,
- # topic_word_prior=0.01,
- random_state=0)
- lda.fit(X)
模型拟合好后,查看结果前先定义一个函数,让结果输出更好看一下。
- def print_top_words(model, feature_names, n_top_words):
- tword = []
- tword2 = []
- tword3=[]
- for topic_idx, topic in enumerate(model.components_):
- print("Topic #%d:" % topic_idx)
- topic_w = [feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]]
- topic_pro=[str(round(topic[i],3)) for i in topic.argsort()[:-n_top_words - 1:-1]] #(round(topic[i],3))
- tword.append(topic_w)
- tword2.append(topic_pro)
- print(" ".join(topic_w))
- print(" ".join(topic_pro))
- print(' ')
- word_pro=dict(zip(topic_w,topic_pro))
- tword3.append(word_pro)
- return tword3
选择每个主题输出前20个重要词汇;
- ##输出每个主题对应词语和概率
- n_top_words = 20
- feature_names = tf_vectorizer.get_feature_names_out()
- word_pro = print_top_words(lda, feature_names, n_top_words)
可以看到,输出了10个主题,每个主题对应输出20个重要词汇和他们的重要性数值。
那么每条新闻属于哪类话题,可以通过下面代码得到每篇文章对应主题
- #输出每篇文章对应主题
- topics=lda.transform(X)
- topic=np.argmax(topics,axis=1)
- df['topic']=topic
- #df.to_excel("data_topic.xlsx",index=False)
- print(topics.shape)
- print(topics[0])
- topic[0]
如图预测的类别是一个(5337,10)的数据,5337是样本个数,即5337条新闻,10是分为10类,每一类的概率值。
我们查看第一条数据的10的类别概率值,发现它是第0类话题的概率是0.0213,第1类话题的概率是0.1518,第2类话题的概率是0.52......以此类推。
由于它是第2类话题的概率0.52最大,所以第一条新闻被认为是第2类话题。
打印出来每个话题关键词不够直观,画出每类话题的词云图看。
先定义一个随机颜色的函数。能随机返回颜色。
- import random #定义随机生成颜色函数
- def randomcolor():
- colorArr = ['1','2','3','4','5','6','7','8','9','A','B','C','D','E','F']
- color ="#"+''.join([random.choice(colorArr) for i in range(6)])
- return color
- [randomcolor() for i in range(3)]
词语图设置
- from collections import Counter
- from wordcloud import WordCloud
- from matplotlib import colors
- #from imageio import imread #形状设置
- #mask = imread('爱心.png')
-
- def generate_wordcloud(tup):
- color_list=[randomcolor() for i in range(10)] #随机生成10个颜色
- wordcloud = WordCloud(background_color='white',font_path='simhei.ttf',#mask = mask, #形状设置
- max_words=20, max_font_size=50,random_state=42,
- colormap=colors.ListedColormap(color_list) #颜色
- ).generate(str(tup))
- return wordcloud
画多子图
- dis_cols = 4 #一行几个
- dis_rows = 3
- dis_wordnum=20
- plt.figure(figsize=(5 * dis_cols, 5 * dis_rows),dpi=128)
- kind=len(df['topic'].unique())
-
- for i in range(kind):
- ax=plt.subplot(dis_rows,dis_cols,i+1)
- most10 = [ (k,float(v)) for k,v in word_pro[i].items()][:dis_wordnum] #高频词
- ax.imshow(generate_wordcloud(most10), interpolation="bilinear")
- ax.axis('off')
- ax.set_title("第{}类话题 前{}词汇".format(i,dis_wordnum), fontsize=30)
- plt.tight_layout()
- plt.show()
可以看到每一类话题的重要性词汇都画出来了,词语越大说明这个词越重要。
可以看到LDA模型效果还是不错的,比如第2类话题出现了很多中国,合作,发展,人民,全面等词汇,说明第2类话题就是那些新闻联播里面老生常谈的些描述国家发展的新闻。
第7类话题出现了很多病例,输入,确诊,新增,本土,新冠等这些词汇,说明第7类话题就是那些天天报道新冠疫情情况的新闻。
第4类话题出现了很多冬奥会,运动员,滑雪,选手,比赛等这些词汇,说明第4类话题就是描述冬奥会比赛情况的新闻。
其他话题也有各自的主题和道理。
这是2022的央视网新闻,换成任何一个其他的文本都可以进行上述的分析,比如可以分析股吧评论,电影标语,微博热搜等等。最终可以得到每个文本的类别和词云图。
创作不易,看官觉得写得还不错的话点个关注和赞吧,本人会持续更新python数据分析领域的代码文章~(需要定制代码可私信)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。