
在第一篇内容中,我们介绍了 LDA 主题模型,这一篇,我们将介绍经典的 KMeans 聚类算法在文本上的表现。为了方便和前面 LDA 主题模型对比,我们依然使用同一份数据集,对数据的前期处理保持一致。
二、KMeans 聚类
2.1 加载数据集
df = pd.read_csv('/content/drive/My Drive/cnews.train.txt', delimiter="\t", header=None, names=["label", "data"])
print(df.label.unique())
['体育' '娱乐' '家居' '房产' '教育' '时尚' '时政' '游戏' '科技' '财经']
2.2 数据清洗
中间几个步骤略,与上一篇处理方式完全一致。
data_words_bigrams = make_bigrams(train_st_text)
为了方便后续的处理,我们将分词后的数组拼接起来
corpus = [' '.join(line) for line in data_words_bigrams]
['马晓旭 意外 受伤 国奥 警惕 无奈 大雨 格外 青睐 殷家 傅亚雨 沈阳 报道 来到 沈阳 国奥队 依然 摆脱 雨水 困扰 下午 国奥队 日常 训练 再度 大雨 干扰 无奈_之下 队员 慢跑 分钟 草草收场 上午 国奥队 奥体中心 外场 训练 阴沉沉 气象预报 显示 当天 下午 沈阳 大雨 幸好 队伍 上午 训练 干扰 下午 点当 球队 抵达 训练场 大雨 几个 小时 丝毫 停下来 试一试 态度 球队 当天 下午 例行_训练 分钟 天气 转好 迹象 保护 球员 国奥队 中止 当天 训练 全队 返回 酒店 训练 足球队 来说 稀罕 奥运会 即将 全队 变得 娇贵 沈阳 一周 训练 国奥队 保证 现有 球员 不再 出现意外 伤病 情况 影响 正式 比赛 这一 阶段 控制 训练 受伤 控制 感冒 疾病 队伍 放在 位置 抵达 沈阳 后卫 冯萧霆 训练 冯萧霆 长春 患上_感冒 参加 塞尔维亚 热身赛 队伍 介绍 冯萧霆 发烧_症状 两天 静养 休息 感冒 恢复 训练 冯萧霆 例子 国奥队 对雨中 训练 显得 特别 谨慎 担心 球员 受凉 引发 感冒 非战斗 减员 女足 队员 马晓旭 热身赛 受伤 导致 无缘 奥运 前科 沈阳 国奥队 格外 警惕 训练 嘱咐 队员 动作 再出 事情 工作人员 长春_沈阳 雨水 一路 伴随 国奥队 长春 几次 训练 大雨 搅和 没想到 沈阳 碰到 事情 国奥 球员 雨水 青睐 不解']
2.3 文本向量化
文本的向量化表示采用三种方式:使用 IDF 权重的哈希向量化表示、不使用 IDF 权重的哈希向量化表示以及 TFIDF 向量化表示,由于文本词量较大,因此在做 hash 处理的时候,我们把特征数设定为 25 万,TFIDF 中我们没设定,使用全部词量。
from sklearn.pipeline import make_pipeline
from sklearn.feature_extraction.text import TfidfTransformer
# Perform an IDF normalization on the output of HashingVectorizer
hasher = HashingVectorizer(n_features=250000, alternate_sign=False, norm=None)
vectorizer_hash_idf = make_pipeline(hasher, TfidfTransformer())
vectorizer_hash = HashingVectorizer(n_features=250000, alternate_sign=False, norm='l2')
vectorizer_tfidf = TfidfVectorizer(max_df=0.5, min_df=2, use_idf=True)
X_hash_idf = vectorizer_hash_idf.fit_transform(corpus)
X_hash = vectorizer_hash.fit_transform(corpus)
X_tfidf = vectorizer_tfidf.fit_transform(corpus)
print(X_hash_idf.shape)
print(X_hash.shape)
print(X_tfidf.shape)
(50000, 250000)
(50000, 250000)
(50000, 207705)
对于数据维度过高,我们可以使用一些维度压缩技术进行处理,如 PCA、SVD 等,此处我们使用的是 SVD 及正则化处理,此处的输出维度我们限定到 100,如果压缩的目的是为了可视化,那么最常见的是压缩到 2 维。
from sklearn.decomposition import TruncatedSVD
from sklearn.preprocessing import Normalizer
print("Performing dimensionality reduction using LSA")
# Vectorizer results are normalized, which makes KMeans behave as
# spherical k-means for better results. Since LSA/SVD results are
# not normalized, we have to redo the normalization.
svd = TruncatedSVD(100)
normalizer = Normalizer(copy=False)
lsa = make_pipeline(svd, normalizer)
X_hash_idf_lsa = lsa.fit_transform(X_hash_idf)
X_hash_lsa = lsa.fit_transform(X_hash)
X_tfidf_lsa = lsa.fit_transform(X_tfidf)
explained_variance = svd.explained_variance_ratio_.sum()
print("Explained variance of the SVD step: {}%".format(
int(explained_variance * 100)))
print()
Performing dimensiona