目录
介绍
主题数确认
代码实现
普通关键词提取 TF-IDF,textRank 实现链接:gensim 实现 TF-IDF;textRank 关键词提取_gensim tfidf关键词-CSDN博客
它们是直接从文本中提取关键词,如果想基于一些潜在语义,可以用 LDA,但不是真正会识别语义,介绍如下。
介绍
LDA(Latent Dirichlet Allocation)确实是一个用于从大量文档中提取关键词的算法,但它并不是直接基于语义去提取关键词,而是通过建立文档主题的概率分布模型来间接揭示文档的关键词结构。LDA是一种统计模型,特别是一种主题模型,由David Blei、Andrew Ng和Michael Jordan在2003年提出。
LDA的工作原理是这样的:
-
假设: 每篇文档是由多个潜在主题(latent topics)按照一定概率混合而成,每个主题又对应着一组关键词的概率分布。同时,每个关键词在文档中出现的概率也是由这些主题共同决定的。
-
过程:
- LDA首先假定文档集合中的每个文档都由K个潜在主题的混合构成。
- 每个主题是一个概率分布,表示这个主题下各个单词出现的概率。
- 文档生成的过程是:先根据文档的主题分布选择一个主题,然后根据这个主题的概率分布生成相应的单词。
- 迭代优化:通过对文档中的词语计数数据进行统计分析,利用贝叶斯统计推断的方法,通过Gibbs抽样或者变分推断等手段估计出最优的主题分布和主题下的单词分布。
-
关键词提取:
- 当LDA模型训练完成后,每个主题会被赋予一系列相关的关键词,这些关键词就是在给定主题下具有高概率的词汇。
- 通过查看每个文档的主题分布,可以找出文档最显著的主题,进而确定文档的关键信息,即文档的关键词。
虽然LDA本身不是基于语义相似性的严格概念来直接抽取关键词,但因为它能够发现文本中隐含的结构和主题,因此可以被看作是一种基于统计意义上的语义聚类,有助于识别那些与文档主题密切相关的关键词。然而,LDA并未直接理解单个词的确切语义,而是通过统计规律捕捉到了主题级别的语义相关性。如果要进行更精细的语义分析,则可能需要结合其他基于深度学习的语义理解技术。
主题数确认
使用 LDA,那需要确定主题,也就是需要设计几个主题,原因有以下几点:
-
模型参数化: LDA作为一种概率图形模型,其核心参数之一就是主题数量K。在模型初始化阶段,需要设置K值,这意味着模型会尝试找出文档集合中K个不同的主题,并且为每个主题分配一组词语的概率分布。
-
模型复杂性与解释性: 主题数量决定了模型的复杂程度。如果主题数量过少,模型可能无法充分捕获数据集中的所有重要模式和结构,导致信息损失,使得主题过于宽泛,缺乏区分度;反之,如果主题数量过多,可能会产生很多高度重叠或者非常相似的主题,造成模型过度拟合,降低了模型的解释性和实用性。
-
模型评估与优化: 在实践中,选择合适的主题数量是为了得到最具解释力和预测能力的模型。常用的方法包括观察模型的困惑度(Perplexity)、主题间互信息(Coherence Score)等指标随主题数量变化的趋势,选择这些指标表现最优或者拐点处的主题数量作为最佳模型参数。
-
实际应用需求: 根据实际应用场景和分析目的,研究者也需要考虑主题的数量是否符合领域内专家的理解和期望,能否较好地概括和解读数据集的内容结构。
综上所述,确定合适的主题数是LDA主题建模过程中至关重要的一环,它直接影响到模型的有效性和可解释性。在实际操作中,往往需要通过实验对比不同主题数下模型的表现,从而确定最佳的主题数量。
代码实现
在代码中平均余弦相似度来寻找最优的主题数,在通过得到最优主题数后,手动设置主题数参数
当然也可以省略最优的主题数这一步,直接设置后使用 LDA:
用的数据是分词后的词语列表 posdata['word']
import pandas as pd
import numpy as np
import re
import itertools
import matplotlib.pyplot as plt
from gensim import corpora, models
from matplotlib.font_manager import FontProperties
plt.rcParams['font.sans-serif'] = ['SimHei'] # 解决中文乱码问题
plt.rcParams['axes.unicode_minus'] = False # 解决负号无法正常显示的问题
plt.style.use('Solarize_Light2') # 设置绘图样式# posdata['word'] 是分词后的词语
posdata = pd.read_csv("posdata.csv", encoding='utf-8')
pos_dict = corpora.Dictionary([[i] for i in posdata['word']]) # 正面
pos_corpus = [pos_dict.doc2bow(j) for j in [[i] for i in posdata['word']]] # 正面# 构造主题数寻优函数
def cos(vector1, vector2): # 余弦相似度函数dot_product = 0.0;normA = 0.0;normB = 0.0;for a, b in zip(vector1, vector2):dot_product += a * bnormA += a ** 2normB += b ** 2if normA == 0.0 or normB == 0.0:return (None)else:return (dot_product / ((normA * normB) ** 0.5))# 主题数寻优def lda_k(x_corpus, x_dict):# 初始化平均余弦相似度mean_similarity = []mean_similarity.append(1)# 循环生成主题并计算主题间相似度for i in np.arange(2, 11):lda = models.LdaModel(x_corpus, num_topics=i, id2word=x_dict) # LDA模型训练for j in np.arange(i):term = lda.show_topics(num_words=50)# 提取各主题词top_word = []for k in np.arange(i):top_word.append([''.join(re.findall('"(.*)"', i)) \for i in term[k][1].split('+')]) # 列出所有词# 构造词频向量word = sum(top_word, []) # 列出所有的词unique_word = set(word) # 去除重复的词# 构造主题词列表,行表示主题号,列表示各主题词mat = []for j in np.arange(i):top_w = top_word[j]mat.append(tuple([top_w.count(k) for k in unique_word]))p = list(itertools.permutations(list(np.arange(i)), 2))l = len(p)top_similarity = [0]for w in np.arange(l):vector1 = mat[p[w][0]]vector2 = mat[p[w][1]]top_similarity.append(cos(vector1, vector2))# 计算平均余弦相似度mean_similarity.append(sum(top_similarity) / l)return (mean_similarity)# 计算主题平均余弦相似度
pos_k = lda_k(pos_corpus, pos_dict)
# 绘制主题平均余弦相似度图形
font = FontProperties(size=14)fig = plt.figure(figsize=(10,8))
ax1 = fig.add_subplot(211)
ax1.plot(pos_k)
ax1.set_xlabel('正面评论LDA主题数寻优', fontproperties=font)
plt.show()# LDA主题分析
# 根据图表主题数为 3
pos_lda = models.LdaModel(pos_corpus, num_topics = 3, id2word = pos_dict)
pos_topic = pos_lda.print_topics(num_words = 10)
print(pos_topic)# 去掉权重
pos_theme = []
for p in pos_topic:word = re.findall('\*"(.*?)"',p[1])pos_theme.append(word)
print(pos_theme)
主题数图表,最低点为最优主题数
直接用 LDA 提取关键词,不确定主题数
import jieba
from gensim import corpora, models
import re# 文本预处理,将文档分为句子
text = '6月19日,《2012年度“中国爱心城市”公益活动新闻发布会》在京举行。' + \'中华社会救助基金会理事长许嘉璐到会讲话。基金会高级顾问朱发忠,全国老龄' + \'办副主任朱勇,民政部社会救助司助理巡视员周萍,中华社会救助基金会副理事长耿志远,' + \'重庆市民政局巡视员谭明政。晋江市人大常委会主任陈健倩,以及10余个省、市、自治区民政局' + \'领导及四十多家媒体参加了发布会。中华社会救助基金会秘书长时正新介绍本年度“中国爱心城' + \'市”公益活动将以“爱心城市宣传、孤老关爱救助项目及第二届中国爱心城市大会”为主要内容,重庆市' + \'、呼和浩特市、长沙市、太原市、蚌埠市、南昌市、汕头市、沧州市、晋江市及遵化市将会积极参加' + \'这一公益活动。中国雅虎副总编张银生和凤凰网城市频道总监赵耀分别以各自媒体优势介绍了活动' + \'的宣传方案。会上,中华社会救助基金会与“第二届中国爱心城市大会”承办方晋江市签约,许嘉璐理' + \'事长接受晋江市参与“百万孤老关爱行动”向国家重点扶贫地区捐赠的价值400万元的款物。晋江市人大' + \'常委会主任陈健倩介绍了大会的筹备情况。'
sentences = [sentence.strip() for sentence in text.split('。') if sentence.strip()]
word_lst = [jieba.lcut(s) for s in sentences]
words = []
for w in word_lst:for _ in w:words.append(_)
pos_dict = corpora.Dictionary([[i] for i in words]) # 正面
pos_corpus = [pos_dict.doc2bow(j) for j in [[i] for i in words]] # 正面# LDA主题分析
# 根据图表主题数为 3
pos_lda = models.LdaModel(pos_corpus, num_topics = 3, id2word = pos_dict)
pos_topic = pos_lda.print_topics(num_words = 10)
print(pos_topic)# 去掉权重
pos_theme = []
for p in pos_topic:word = re.findall('\*"(.*?)"',p[1])pos_theme.append(word)
print(pos_theme)