自然语言处理--基于截断的 SVD (TruncatedSVD)的短消息语义分析:提取主题向量

它可以处理稀疏矩阵,所以如果我们正在处理大规模数据集,那么无论如何都要使用TruncatedSVD而非 PCA。
TruncatedSVD 的 SVD 部分将 TF-IDF 矩阵分解为 3 个矩阵,其截断部分将丢弃包含 TF-IDF 矩阵最少信息的维度。这些被丢弃的维度表示文档集中变化最小的主题(词的线性组合),它们可能对语料库的总体语义没有意义。它们可能会包含许多停用词和其他词,这些词在所有文档中均匀分布。

使用 TruncatedSVD 仅仅保留 16 个主题,这些主题在 TF-IDF 向量中所占的方差最大:

import pandas as pd
from nlpia.data.loaders import get_data
from sklearn.feature_extraction.text import TfidfVectorizer
from nltk.tokenize.casual import casual_tokenize
from sklearn.decomposition import TruncatedSVD

# 从 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))

# 计算每条消息的 TF-IDF 向量
tfidf = TfidfVectorizer(tokenizer=casual_tokenize)
tfidf_docs = tfidf.fit_transform(raw_documents=sms.text).toarray()
# 来自分词器(casual_tokenize)的 9232 个不同的1-gram 词条
print(len(tfidf.vocabulary_))
tfidf_docs = pd.DataFrame(tfidf_docs)
# 减去平均值对向量化的文档(词袋向量)进行中心化处理
tfidf_docs = tfidf_docs - tfidf_docs.mean()
# 4837 条短消息
print(tfidf_docs.shape)
# 有 638 条(13%)被标记为垃圾短消息
print(sms.spam.sum())
print("词汇表:\n", tfidf.vocabulary_)

# svd
svd = TruncatedSVD(n_components=16, n_iter=100)
svd_topic_vectors = svd.fit_transform(tfidf_docs.values)
columns = ['topic{}'.format(i) for i in range(svd.n_components)]
svd_topic_vectors = pd.DataFrame(svd_topic_vectors, columns=columns, index=index)
# TruncatedSVD 的这些主题向量与 前面PCA 生成的主题向量完全相同!这个结果是因为我们非
# 常谨慎地使用了很多的迭代次数(n_iter),并且还确保每个词项(列)的 TF-IDF 频率都做了
# 基于零的中心化处理(通过减去每个词项上的平均值)。
print(svd_topic_vectors.round(3).head(6))

猜你喜欢

转载自blog.csdn.net/fgg1234567890/article/details/112438678
SVD