文本聚类工程实践:KMeans 能跑,但分词策略决定聚类质量
2026/7/11 2:54:26 网站建设 项目流程

文本聚类工程实践:KMeans 能跑,但分词策略决定聚类质量

一、聚类结果不好时,先别调算法参数,先查分词和向量

文本聚类是NLP工程里最常见的任务之一:把大量文档、评论或日志分成若干组,发现主题结构和异常模式。KMeans是最常用的聚类算法,参数少、速度快、实现简单。但实际工程中,KMeans跑完后的聚类结果经常不可用:有的簇包含几百条文本毫无共性,有的簇只有两条文本却被强行分开,有的簇的主题描述完全是噪音词。原因通常不在KMeans的k值或初始化方式,而在更前面的步骤——分词策略和向量表示。分词粒度决定了特征空间的结构,见证奇迹的时刻是把jieba换成领域定制分词后,轮廓系数从0.15跳到0.42。

文本聚类的完整链路不是"分词→向量化→KMeans"三步走,而是"分词→停用词→词频→向量→距离→聚类→评估"七步走,每一步都可能成为瓶颈。

二、聚类链路:分词策略到聚类评估的七步管道

flowchart TD A[原始文本] --> B[分词策略选择] B --> C[停用词与低频词过滤] C --> D[向量化方法选择] D --> E[向量归一化与降维] E --> F[距离度量选择] F --> G[聚类算法执行] G --> H[聚类质量评估] H --> I{轮廓系数≥阈值} I -- 否 --> B I -- 是 --> J[输出聚类结果]

分词策略的影响远比想象中大。通用分词(jieba默认模式)把"大模型推理服务"分成["大", "模型", "推理", "服务"],丢失了"大模型"这个关键概念;领域定制分词把同一个句子分成["大模型", "推理服务"],保留了两个核心技术概念。分词粒度直接影响TF-IDF和词向量特征的质量,进而影响聚类结果。

向量化方法的选择也很关键。TF-IDF简单但忽略语义,Word2Vec/GloVe考虑语义但忽略词频重要性,BERT向量语义最强但维度高、计算慢。工程上通常用BERT向量做语义聚类,TF-IDF做主题聚类,FastText做折中方案。

距离度量需要匹配向量类型:TF-IDF适合用余弦距离(因为向量是词频比例),BERT向量也适合余弦距离(因为语义向量方向比长度更重要),归一化后的向量可以用欧氏距离(归一化后欧氏距离和余弦距离等价)。

三、聚类管道实现:分词策略与向量方法的可配置组合

下面是文本聚类管道的核心逻辑。代码注释解释了关键设计选择。

from dataclasses import dataclass, field from typing import Literal, Callable import math TokenMethod = Literal["jieba_default", "jieba_search", "custom_domain"] VectorMethod = Literal["tfidf", "fasttext", "bert"] DistanceMetric = Literal["cosine", "euclidean"] @dataclass class ClusterPipelineConfig: """聚类管道配置:分词、向量、距离三步联合决定聚类质量""" token_method: TokenMethod = "jieba_default" custom_dict: list[str] = field(default_factory=list) # 设计原因:领域定制词表比通用分词更关键, # 例如"大模型"在通用分词里被拆成两个无意义词 vector_method: VectorMethod = "tfidf" stop_words: list[str] = field(default_factory=list) min_doc_freq: int = 3 # 最低文档频率过滤 max_doc_freq_ratio: float = 0.8 # 最高文档频率过滤 # 设计原因:min_doc_freq去掉噪音词(只出现1-2次的低频词), # max_doc_freq_ratio去掉无区分力词(出现在80%文档的通用词) distance_metric: DistanceMetric = "cosine" n_clusters: int = 10 reduce_dim: int = 0 # 是否降维,0表示不降维 # 见证奇迹的时刻:领域定制词表+BERT向量+余弦距离的组合 def tokenize(text: str, method: TokenMethod, custom_dict: list[str] = []) -> list[str]: """分词:不同策略对同一文本产生不同粒度""" # 实际工程中这里调用jieba或领域分词器 # 此处展示策略逻辑而非具体库调用 if method == "jieba_default": # 默认模式:精确分词,偏向短词 pass # 实际调用jieba.cut(text) elif method == "jieba_search": # 搜索模式:保留更多长词组合 pass # 实际调用jieba.cut_for_search(text) elif method == "custom_domain": # 领域定制:先匹配领域词表,再对剩余文本做通用分词 # 设计原因:领域词表保证技术概念不被拆散 pass return [] # 占位返回 def filter_tokens(tokens: list[str], stop_words: list[str], min_freq: int, max_freq_ratio: float, doc_freq_map: dict[str, int], total_docs: int) -> list[str]: """停用词和频率过滤:去掉无区分力的词""" filtered = [] for token in tokens: if token in stop_words: continue freq = doc_freq_map.get(token, 0) if freq < min_freq: # 低频词是噪音,在聚类中增加维度但不增加区分力 continue if freq / total_docs > max_freq_ratio: # 高频词没有区分力,所有簇都包含这些词 continue filtered.append(token) return filtered def silhouette_score(cluster_labels: list[int], distances: list[list[float]]) -> float: """轮廓系数:衡量聚类质量的标准指标 设计原因:轮廓系数同时考虑簇内紧密度和簇间分离度, 比单一指标(如簇内距离)更全面""" n = len(cluster_labels) scores = [] for i in range(n): own_cluster = cluster_labels[i] # 簇内平均距离:a_i own_dists = [distances[i][j] for j in range(n) if cluster_labels[j] == own_cluster and j != i] a_i = sum(own_dists) / len(own_dists) if own_dists else 0.0 # 最近其他簇的平均距离:b_i other_clusters = set(cluster_labels) - {own_cluster} b_i = float('inf') for c in other_clusters: c_dists = [distances[i][j] for j in range(n) if cluster_labels[j] == c] avg = sum(c_dists) / len(c_dists) if c_dists else 0.0 b_i = min(b_i, avg) # 轮廓系数:越接近1越好,接近0表示边界模糊,负值表示错聚类 s_i = (b_i - a_i) / max(a_i, b_i) if max(a_i, b_i) > 0 else 0.0 scores.append(s_i) return sum(scores) / len(scores)

四、聚类权衡:分词粒度、向量维度和簇数的三方影响

文本聚类工程的核心权衡有三个维度。第一是分词粒度vs特征维度:细粒度分词产生更多特征维度,每个维度信息更少,聚类需要更多数据才能稳定;粗粒度分词产生更少维度,每个维度信息更多,但可能丢失关键概念。领域定制词表是折中方案:保留关键长词,其余用通用分词。

第二是向量方法vs计算成本:TF-IDF维度等于词表大小(可能数万维),计算快但语义弱;BERT向量768维或1024维,语义强但每条文本需要一次模型推理,万级文档的向量化成本很高。折中方案是FastText:比TF-IDF语义更强,比BERT计算更快,适合中等规模文本聚类。

第三是簇数选择vs业务需求:KMeans的k值没有通用最优解。轮廓系数可以辅助选择,但业务需求可能要求特定数量的簇(如客服分类必须对应已有工单类别)。k值太小会强行合并不同主题,k值太大会把同一主题拆成多个小簇。工程上建议先用轮廓系数找k的范围,再按业务约束微调。

降维也影响聚类质量。高维向量做聚类时,距离度量会退化(所有点距离趋于相同),这是维度灾难的表现。PCA或UMAP降维到50-100维通常能改善聚类效果,但降维本身丢失信息,降维后的距离不再精确反映原始语义差异。

五、总结

文本聚类的瓶颈通常不在KMeans算法参数,而在分词策略和向量表示。分词粒度决定特征空间结构,领域定制词表保证技术概念不被拆散;停用词和频率过滤去掉无区分力词;向量方法按语义需求和计算成本选择TF-IDF、FastText或BERT;距离度量应匹配向量类型;轮廓系数评估聚类质量应同时考虑簇内紧密度和簇间分离度;高维向量建议降维到50-100维缓解维度灾难。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询