本文目录导读:
这是一个关于用Python实现文本聚类(K-means)的完整案例,我将使用scikit-learn库,从数据准备到可视化逐步展示。
完整实现案例
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.metrics import silhouette_score
import jieba # 用于中文分词
import warnings
warnings.filterwarnings('ignore')
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 1. 准备示例数据(中文文本)
documents = [
"我喜欢吃苹果和香蕉",
"今天天气真好适合出去运动",
"苹果手机发布了新款很漂亮",
"香蕉和苹果都是水果",
"运动可以增强体质保持健康",
"华为手机拍照效果非常好",
"水果富含维生素对身体有益",
"小米手机性价比很高",
"跑步游泳都是很好的运动方式",
"OPPO手机自拍效果很棒"
]
# 2. 中文分词函数
def chinese_word_segmentation(text):
"""使用jieba进行中文分词"""
words = jieba.cut(text)
return ' '.join(words)
# 3. 文本预处理和特征提取
print("正在预处理文本...")
# 对每个文档进行分词
segmented_docs = [chinese_word_segmentation(doc) for doc in documents]
# 使用TF-IDF向量化
vectorizer = TfidfVectorizer(max_features=100, # 限制特征数量
stop_words=None) # 可以添加停用词表
X = vectorizer.fit_transform(segmented_docs)
print(f"TF-IDF矩阵形状: {X.shape}")
# 4. 确定最佳聚类数(使用肘部法则和轮廓系数)
def find_optimal_k(X, max_k=6):
"""使用肘部法则和轮廓系数确定最佳K值"""
inertias = []
silhouette_scores = []
K_range = range(2, min(max_k, X.shape[0]))
for k in K_range:
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
kmeans.fit(X)
inertias.append(kmeans.inertia_)
# 轮廓系数(需要足够样本)
if X.shape[0] > k and X.shape[0] > 1:
sil_score = silhouette_score(X, kmeans.labels_)
silhouette_scores.append(sil_score)
else:
silhouette_scores.append(0)
# 绘图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
ax1.plot(K_range, inertias, 'bo-')
ax1.set_xlabel('聚类数K')
ax1.set_ylabel('惯性值')
ax1.set_title('肘部法则')
ax1.grid(True)
ax2.plot(K_range, silhouette_scores, 'ro-')
ax2.set_xlabel('聚类数K')
ax2.set_ylabel('轮廓系数')
ax2.set_title('轮廓系数分析')
ax2.grid(True)
plt.tight_layout()
plt.show()
# 建议最佳K值
best_k = K_range[np.argmax(silhouette_scores)]
print(f"建议最佳聚类数: K = {best_k} (基于轮廓系数)")
return best_k
# 5. 训练K-means模型
print("\n正在执行K-means聚类...")
optimal_k = find_optimal_k(X, max_k=6)
# 使用最佳K值进行聚类
kmeans = KMeans(n_clusters=optimal_k, random_state=42, n_init=10)
kmeans.fit(X)
# 6. 结果分析
print("\n聚类结果分析:")
print("-" * 50)
# 输出每个聚类的中心关键词
def get_cluster_keywords(vectorizer, kmeans, n_words=5):
"""获取每个聚类的重要关键词"""
order_centroids = kmeans.cluster_centers_.argsort()[:, ::-1]
terms = vectorizer.get_feature_names_out()
cluster_keywords = {}
for i in range(optimal_k):
keywords = [terms[ind] for ind in order_centroids[i, :n_words]]
cluster_keywords[i] = keywords
print(f"聚类 {i}: {', '.join(keywords)}")
return cluster_keywords
cluster_keywords = get_cluster_keywords(vectorizer, kmeans)
# 7. 分配聚类标签并显示结果
df_results = pd.DataFrame({
'文本': documents,
'聚类标签': kmeans.labels_
})
print("\n详细聚类结果:")
print(df_results.to_string(index=False))
# 8. 可视化聚类结果(使用PCA降维)
def visualize_clusters(X, labels):
"""使用PCA降维可视化聚类结果"""
# PCA降维到2D
pca = PCA(n_components=2, random_state=42)
X_pca = pca.fit_transform(X.toarray())
plt.figure(figsize=(10, 8))
# 为每个聚类绘制不同颜色
colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b']
for i in range(optimal_k):
mask = labels == i
plt.scatter(X_pca[mask, 0], X_pca[mask, 1],
c=colors[i % len(colors)],
label=f'聚类 {i}',
s=100, alpha=0.7, edgecolors='k')
plt.title('K-means文本聚类结果可视化 (PCA降维)', fontsize=14)
plt.xlabel('主成分1')
plt.ylabel('主成分2')
plt.legend()
plt.grid(True, alpha=0.3)
# 添加文本标签
for i, (x, y) in enumerate(X_pca):
plt.annotate(f'文档{i+1}', (x, y),
xytext=(5, 5), textcoords='offset points',
fontsize=8, alpha=0.7)
plt.tight_layout()
plt.show()
visualize_clusters(X, kmeans.labels_)
# 9. 对新文档进行聚类预测
print("\n对新文档聚类预测:")
new_docs = [
"今天天气很好适合跑步",
"苹果和香蕉都是美味的水果",
"新款手机照相功能很强大"
]
# 预处理新文档
new_segmented = [chinese_word_segmentation(doc) for doc in new_docs]
new_X = vectorizer.transform(new_segmented)
# 预测聚类
predicted_labels = kmeans.predict(new_X)
for doc, label in zip(new_docs, predicted_labels):
print(f"'{doc}' -> 属于聚类 {label}")
关键步骤说明
数据准备
- 准备了10条中文文本,涵盖水果、运动、手机等主题
中文分词
- 使用
jieba进行中文分词(英文文本可跳过此步)
特征提取
- 使用
TfidfVectorizer将文本转换为TF-IDF特征矩阵
确定最佳K值
- 肘部法则:惯性值下降趋缓的点
- 轮廓系数:衡量聚类效果(-1到1,越大越好)
训练K-means模型
- 使用最佳K值进行聚类
结果分析
- 获取每个聚类的关键词
- 展示文本的聚类标签
可视化
- 使用PCA降维到2D空间进行可视化
运行结果示例
建议最佳聚类数: K = 3 (基于轮廓系数)
聚类 0: 运动, 天气, 跑步, 游泳, 健康
聚类 1: 水果, 苹果, 香蕉, 维生素, 身体
聚类 2: 手机, 拍照, 华为, 苹果, 小米
重要提示
-
中文处理:如果是英文文本,可以直接使用
TfidfVectorizer,无需分词 -
参数调优:
max_features: 控制特征数量n_init: K-means初始化次数max_iter: 最大迭代次数
-
评估指标:
- 轮廓系数(Silhouette Score)
- Calinski-Harabasz指数
- Davies-Bouldin指数
-
改进方向:
- 使用Word2Vec/Embedding替代TF-IDF
- 尝试层次聚类、DBSCAN等其他算法
- 添加停用词过滤
这个案例提供了一个完整的文本聚类流程,你可以直接复制运行并根据实际数据调整参数。
标签: Kmeans