自然语言处理--基于 LDiA 主题模型的短消息语义分析:提取主题向量

当需要计算可解释的主题向量时,请使用 LDiA:在为消息分配主题时,会出现很多 0,因此主题之间分隔得更加清晰。
LDiA 假设每篇文档都由某个任意数量的主题混合(线性组合)而成,该数量是在开始训练LDiA 模型时选择的。LDiA 还假设每个主题都可以用词的分布(词项频率)来表示。文档中每个主题的概率或权重,以及某个词被分配到一个主题的概率,都假定一开始满足狄利克雷概率分布。

from sklearn.feature_extraction.text import CountVectorizer
from nltk.tokenize import casual_tokenize
import numpy as np
import pandas as pd
from nlpia.data.loaders import get_data
from nltk.tokenize.casual import casual_tokenize
from sklearn.decomposition import LatentDirichletAllocation as LDiA

# 从 nlpia 包中的 DataFrame 加载短消息数据
pd.options.display.width = 120
sms = get_data('sms-spam')
# 向短消息的索引号后面添加一个感叹号,以使垃圾短消息更容易被发现
index = ['sms{}{}'.format(i, '!'*j) for (i,j) in zip(range(len(sms)), sms.spam)]
sms.index = index
print(sms.head(6))

# 计算词袋向量
np.random.seed(42)
counter = CountVectorizer(tokenizer=casual_tokenize)
bow_docs = pd.DataFrame(counter.fit_transform(raw_documents=sms.text).toarray(), index=index)
column_nums, terms = zip(*sorted(zip(counter.vocabulary_.values(), counter.vocabulary_.keys())))
bow_docs.columns = terms
# 看看对标记为“sms0”的第一条短消息
print(sms.loc['sms0'].text)
print( bow_docs.loc['sms0'][bow_docs.loc['sms0'] > 0].head())

ldia = LDiA(n_components=16, learning_method='batch')
ldia = ldia.fit(bow_docs)
# 将 9232 个词(词项)分配给 16 个主题(成分)
print(ldia.components_.shape)

# 看看开头的几个词,我们了解一下它们是如何分配到 16 个主题中的。
pd.set_option('display.width', 75)
columns = ['topic{}'.format(i) for i in range(ldia.n_components)]
components = pd.DataFrame(ldia.components_.T, index=terms, columns=columns)
# 感叹号(!)被分配到大多数主题中,但它其实是 topic3 中一个特别重要的部分,
# 在该主题中引号(")几乎不起作用。
print(components.round(2).head(3))
# 该主题的前十个词条似乎是在要求某人做某事或支付某事的强调指令中可能使用的词类型。
print(components.topic3.sort_values(ascending=False)[:10])

# 生成主题向量
ldia16_topic_vectors = ldia.transform(bow_docs)
ldia16_topic_vectors = pd.DataFrame(ldia16_topic_vectors, index=index, columns=columns)
# 对比于pca,svd,ldia产生的主题之间分隔得更加清晰
print(ldia16_topic_vectors.round(2).head())

猜你喜欢

转载自blog.csdn.net/fgg1234567890/article/details/112439123