LDA主题建模——基于鸿星尔克微博热搜评论

目录

项目背景

项目步骤

一、评论数据准备

二、使用步骤

1.将评论以日为单位合并

2.导包

3.TF-IDF提取关键词

 4.Word2Vec词向量训练

5.LDA模型评估指标与最佳主题数的选取

三、结果可视化和分析


项目背景

        在2021年7月,一起“鸿星尔克捐款5000万”的事件引发了网友们的强烈反响。年轻一代网友,即所谓的“Z世代”,涌入直播间,进行了所谓的“野性消费”,即疯狂地超额抢购产品,导致销量暴涨。为了探究这种“野性消费”对国产品牌带来的影响和引起的思考,本项目对该时间段关于鸿星尔克的微博评论进行了基于LDA模型的主题特征分析

项目步骤

一、评论数据准备

利用已经分词和清洗过后的评论数据作为项目数据来源,共有3500条评论。

二、使用步骤

1.将评论以日为单位合并

  1. 使用 drop_duplicates() 方法获得数据中的所有唯一时间戳。
  2. 对于每个唯一时间戳 time,使用 datas[datas["time"]==time]["tokenization_filtered"] 筛选出该时间段内的所有文档,然后使用 join() 方法将它们合并成一个字符串,并用空格分隔单词。同时,将合并后的字符串转化为单词列表(即按照空格切割)并存入 word_list 中,将字符串直接存入 comments_list 中。

代码如下:

import pandas as pd
from pandas import DataFrame 
from pandas import Series
datas = pd.read_csv("data_selected.csv", encoding='gbk', dtype={'tokenization_filtered': str, 'time': str})
word_list = []
comments_list = []
unique_time=datas["time"].drop_duplicates()

# 按时间段分组,将评论内容合并成一个长字符串,并转换为分词后的单词列表
for time, group in datas.groupby('time'):
    comments = group['tokenization_filtered'].str.cat(sep=' ')
    word_list.append(comments.split())
    comments_list.append(comments)

2.导包

代码如下:

import gensim
from gensim import corpora
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import warnings
warnings.filterwarnings('ignore')  # To ignore all warnings that arise here to enhance clarity
 
from gensim.models.coherencemodel import CoherenceModel
from gensim.models.ldamodel import LdaModel
from gensim import models

from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence

plt.rcParams['font.family'] = 'SimHei'  # 设置字体为中文宋体

3.TF-IDF提取关键词

        TF-IDF(term frequency–inverse document frequency,词频-逆向文件频率)是一种用于信息检索(information retrieval)与文本挖掘(text mining)的常用加权技术。它由两部分组成,TF和IDF。TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。本文通过TF-IDF算法提取出鸿星尔克7月3日到9月1日每天的微博评论词语的权重比和最关键的三个词语。其中7月4日博文词语权重见表2-1,7月4日至7月5日最关键Top3见表2-2

 

代码如下:

from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
time_list=list(unique_time)
# 示例文本集合
corpus = comments_list

# 将文本转化为词频矩阵
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(corpus)

# 计算tf-idf
transformer = TfidfTransformer()
tfidf = transformer.fit_transform(X)

# 输出每个词语对应的tf-idf值(该词重要程度)
feature_names = vectorizer.get_feature_names()
for i in range(tfidf.shape[0]):
    print(time_list[i])
    for j in tfidf[i].nonzero()[1]:
        print("  {} : {:.2f}".format(feature_names[j], tfidf[i, j]))
        
# 输出每个文档中前n个tf-idf值最大的词语
n = 3
for i in range(tfidf.shape[0]):
    print(time_list[i])
    top_n = sorted(zip(feature_names, tfidf[i].toarray()[0]), key=lambda x: -x[1])[:n]
    for word, score in top_n:
        print("  {}: {:.2f}".format(word, score))

        在原始的LDA模型中,对文本建模的方式采用的词袋模型,而词袋模型存在一个严重的问题就行,常用词的词频往往很高,专有名词的词频很低,这种建模方式存在一定的不合理性。TF-IDF 相对于词袋模型的优势在于,它可以更准确地体现出文档中关键词的重要性。词袋模型只考虑了每个单词在文档中的出现频率,而没有考虑到该单词在整个文集中的重要性。相比之下,TF-IDF 还考虑了文集中某个词的普遍重要程度。

代码如下:

# 根据文本列表创建一个语料库,每个词与一个整型索引值对应
word_dict = corpora.Dictionary(word_list) 
# 词频统计,转化成空间向量格式
corpus_list = [word_dict.doc2bow(text) for text in word_list] 
tfidf = models.TfidfModel(corpus_list)
corpus_tfidf = tfidf[corpus_list]

 4.Word2Vec词向量训练

利用Word2Vec构建词向量相对于词袋模型的优势在于:

  • Word2Vec 不仅能够将单词表示成独立的向量,还能够学习到单词之间的语义关系。因此,通过计算向量之间的余弦相似度,可以精确地捕捉单词之间的距离和相关性,而不是简单地计数单词出现的次数。
  • Word2Vec 能够处理未见过的单词。在许多自然语言处理任务中,经常会遇到未见过的单词。而词袋模型只能依靠上下文中出现过的单词来预测未知单词的含义,这可能导致低效或不准确的结果。相比之下,Word2Vec 能够对未见过的单词进行推断,并返回合理的向量表示。
  • Word2Vec 可以提高语言处理效率。与词袋模型相比,Word2Vec 使用浅层神经网络,例如多层感知器或卷积神经网络等,可大幅提高自然语言处理的效率。这种方法还允许自动学习词向量,而无需人工干预或手动维护词表和规则库。

因此,利用Word2Vec构建词向量相对于词袋模型具有更好的表征能力、更高的泛化能力以及更高的处理效率。

代码如下:

from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
data=  LineSentence(open('news_Corpus.txt', 'r',encoding="utf-8"))
model = Word2Vec(
    data,
    sg = 0,
    size = 100,
    window = 3,
    min_count = 1,
    workers=8
)
 
# 词向量保存
model.wv.save_word2vec_format('news_data.vector', binary=False)
 
# 模型保存
model.save('news_test.model')

import gensim

 
# 1通过模型加载词向量(recommend)
model = gensim.models.Word2Vec.load('news_test.model')
 
# 获取训练好的单词向量和单词列表
word_vectors = model.wv
words = list(word_vectors.vocab.keys())

# 将单词向量转换为字典,并为每个单词分配ID以供LDA模型使用
dictionary_vec = corpora.Dictionary([list(word_vectors.vocab.keys())])
corpus_vec = [dictionary_vec.doc2bow(text) for text in data]

5.LDA模型评估指标与最佳主题数的选取

        主题一致性是指主题内部单词之间的联系程度,也被称为主题连贯度。在大多数关于主题建模的文章中,常用主题连贯度或主题连贯度指标来表示整体主题的可解释性,用于评估主题的质量。通常情况下,主题一致性越高,表示主题的连贯性越好,主题的可解释性也更高。

        困惑度是衡量语言模型好坏的指标,也可以用于评估主题模型的质量。它反映了模型对新样本的泛化能力。困惑度越小,意味着模型对新样本的预测效果越好。在LDA中,可以通过计算每个主题下的单词概率来计算困惑度。

        总的来说,主题一致性和困惑度是两种常用的评估LDA模型质量的指标。主题一致性主要关注主题内部单词之间的联系程度,而困惑度则更关注模型的泛化能力。

        在项目中采用主题一致性来评估模型性能,本文采用TF-IDF和word2vec对文本建模,并绘制主题——一致性曲线来确定最佳主题个数,从而判断TF-IDF和word2vec是否对主题建模质量有所提高。并通过matplotlib绘制“主题-coherence”曲线来确定最优主题数。具体来说,首先在不同主题数下构建LDA模型,然后计算每个主题的一致性得分,最后将得分平均作为整个模型的一致性得分。通过不断改变主题数并计算一致性得分,得到一系列主题-coherence数据点,根据曲线的趋势选择最优主题数,从而确定模型的最佳主题数为7,且TF-IDF 主题建模的质量更好。

代码如下:

#计算困惑度
def perplexity(num_topics):
    """
    计算主题数为num_topics时的困惑度

    参数:
    num_topics: int,主题数目

    返回:
    ldamodel.log_perplexity(corpus): float,困惑度大小
    """
    ldamodel = LdaModel(corpus_list, num_topics=num_topics, id2word=word_dict, passes=30)
    return ldamodel.log_perplexity(corpus_list)

#计算coherence
def coherence(num_topics):
    """
    计算主题数为num_topics时的一致性(coherence)

    参数:
    num_topics: int,主题数目

    返回:
    ldacm.get_coherence(): float,一致性大小
    """
    ldamodel = LdaModel(corpus_list, num_topics=num_topics, id2word=word_dict, passes=30, random_state=1)
    ldacm = CoherenceModel(model=ldamodel, texts=word_list, dictionary=word_dict, coherence='c_v')
    return ldacm.get_coherence()

def coherence_tfidf(num_topics):
    ldamodel = LdaModel(corpus_tfidf, num_topics=num_topics, id2word=word_dict, passes=30, random_state=1)
    ldacm = CoherenceModel(model=ldamodel, texts=word_list, dictionary=word_dict, coherence='c_v')
    return ldacm.get_coherence()

def coherence_word2vec(num_topics):
    ldamodel = LdaModel(corpus_vec, num_topics=num_topics, id2word=dictionary_vec, passes=30, random_state=1)
    ldacm = CoherenceModel(model=ldamodel, texts=word_list, dictionary=dictionary_vec, coherence='c_v')
    return ldacm.get_coherence()

x = range(1,13)
y = []
y_tfidf = []
y_word2vec = []

for i in x:
    y.append(coherence(i))
    y_tfidf.append(coherence_tfidf(i))
    y_word2vec.append(coherence_word2vec(i))

# 创建画布
fig, ax = plt.subplots(figsize=(8,8))

ax.plot(x, y, color='b', label='coherence')
ax.plot(x, y_tfidf, color='g', label='tfidf coherence')
ax.plot(x, y_word2vec, color='r', label='word2vec coherence')
# 设置轮廓线和图例
for spine in ['left','bottom']:
    ax.spines[spine].set_linewidth(1.5)
for spine in ['top','right']:
    ax.spines[spine].set_visible(False)

ax.legend() 
ax.set_title('主题-coherence变化情况')
ax.set_xlabel('主题数目')
ax.set_ylabel('coherence大小')

plt.show()

三、结果可视化和分析

选择TF-IDF作为构建词向量的方法,输出每天最有可能的主题,结果如下

 代码如下:

#设定主题数为7,并输出每个文档最有可能对应的主题
lda = LdaModel(corpus=corpus_tfidf, id2word=word_dict, num_topics=7, passes = 30,random_state=1)
topic_list=lda.print_topics()
 
for i in lda.get_document_topics(corpus_list)[:]:
    listj=[]
    for j in i:
        listj.append(j[1])
    bz=listj.index(max(listj))
    print("主题{}".format(i[bz][0]+1),end=" ")

        pyLDAvis库是一个用于对LDA模型结果进行可视化的Python库,可以通过交互式的方式呈现主题模型的结果,pyLDAvis生成的LDA可视化结果图可以帮助我们直观地理解主题之间的相似度和每个主题的重要性。在这个图中,每个圆圈代表一个主题,圆圈的面积表示该主题在整个文集中占比大小,而圆圈之间的距离表示主题之间的距离,距离越近表示它们之间的关联程度越高。从每个圆圈的中心可以看到该主题的具体词频排名,这些词是该主题区别于其他主题的特征性词汇。

        本项目基于词此库对LDA模型结果进行可视化。作者分别对TF-IDF、word2vec,和词袋模型训练的LDA模型进行可视化,对可视化结果和各个主题下特征词进行分析,TF-IDF训练的LDA模型结果不同主题特征词差异性良好,一定程度上可以说明主题分类效果较好,但是结果主要集中在某个特定主题,其他主题圆圈非常小,很难区分不同的主题。可能是因为采集的是某个事件下的评论数据,导致评论数据主题过于接近,word2vec训练的LDA模型的三个主题具有包含关系,说明它们之间的相关性和相似性过高。词袋模型训练的LDA模型结果较为分散,但是通过人为分析每个主题下的特征词,发现不同主题特征词相似性和重复率很高,一定程度上说明主题区分度不是很高。

TF-IDF

word2vec

词袋

代码如下:

import pyLDAvis.gensim_models
from gensim import corpora, models 
# 最终模型
## corpus: 文档词频矩阵
## num_topics:主题数目
## passes:训练伦次
lda = models.LdaModel(corpus = corpus_tfidf, id2word = word_dict, random_state = 1, num_topics = 7 , passes = 30, alpha='auto')# 结果展示

## lda: 训练好的模型
d = pyLDAvis.gensim_models.prepare(lda, corpus_tfidf, word_dict, mds = 'pcoa', sort_topics = True)

pyLDAvis.save_html(d, 'lda_show.html') # 将结果保存为html文件

# 展示在notebook的output cell中 
pyLDAvis.enable_notebook()
vis = pyLDAvis.gensim_models.prepare(lda, corpus_list, word_dict)
vis

  • 18
    点赞
  • 148
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值