你是否需要一个关于用Python实现文本聚类(如K-means)的案例

访客 自然语言处理 1

本文目录导读:

  1. 完整实现案例
  2. 关键步骤说明
  3. 运行结果示例
  4. 重要提示

这是一个关于用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: 手机, 拍照, 华为, 苹果, 小米

重要提示

  1. 中文处理:如果是英文文本,可以直接使用TfidfVectorizer,无需分词

  2. 参数调优

    • max_features: 控制特征数量
    • n_init: K-means初始化次数
    • max_iter: 最大迭代次数
  3. 评估指标

    • 轮廓系数(Silhouette Score)
    • Calinski-Harabasz指数
    • Davies-Bouldin指数
  4. 改进方向

    • 使用Word2Vec/Embedding替代TF-IDF
    • 尝试层次聚类、DBSCAN等其他算法
    • 添加停用词过滤

这个案例提供了一个完整的文本聚类流程,你可以直接复制运行并根据实际数据调整参数。

标签: Kmeans

抱歉,评论功能暂时关闭!