向AgglomerativeClustering传入稀疏距离矩阵触发TypeError的解决方案咨询
解决思路与方案
你的问题核心是:scikit-learn的AgglomerativeClustering不支持预计算的稀疏距离矩阵,而转成稠密矩阵又会内存爆炸。下面是几个实用的替代方案:
方案1:直接用归一化特征做层次聚类(最推荐)
你完全没必要提前计算全量距离矩阵——AgglomerativeClustering支持直接以特征向量为输入,并用余弦距离作为相似度度量,内存占用仅为embeddings本身的大小,10万样本完全没问题。
步骤:
- 先对embeddings做L2归一化(余弦距离计算要求特征向量归一化):
from sklearn.preprocessing import normalize embeddings_norm = normalize(embeddings, norm='l2')
- 直接用归一化后的特征做聚类:
clustering = AgglomerativeClustering( n_clusters=None, distance_threshold=1 - similarity_threshold, # 余弦距离 = 1 - 余弦相似度,和你之前的逻辑一致 affinity='cosine', linkage=linkage ) clustering.fit(embeddings_norm)
这个方案彻底避免了生成10万×10万的巨型矩阵,直接解决内存和稀疏矩阵不兼容的问题。
方案2:用Scipy层次聚类处理稀疏距离对
如果你一定要基于已生成的稀疏距离矩阵聚类,可以用scipy.cluster.hierarchy工具,它支持处理压缩形式的距离数据:
- 从稀疏矩阵中提取有效距离对(排除对角线和重复对):
import scipy.cluster.hierarchy as sch # 获取非零元素的行、列索引和距离值 rows, cols = sm_matrix.nonzero() dists = sm_matrix.data # 过滤自身到自身的距离,只保留上三角部分避免重复 valid_mask = (rows != cols) & (rows < cols) rows_valid = rows[valid_mask] cols_valid = cols[valid_mask] dists_valid = dists[valid_mask] # 用单链接(适合稀疏场景)生成聚类树,再根据阈值生成标签 Z = sch.linkage(dists_valid, method=linkage) labels = sch.fcluster(Z, t=1 - similarity_threshold, criterion='distance')
注:这个方案仅适合稀疏度极高的场景,且不同linkage方法的兼容性不同,操作较繁琐,优先选方案1。
方案3:换用支持稀疏矩阵的聚类算法
如果可以接受非层次聚类的结果,DBSCAN支持稀疏矩阵作为预计算距离输入:
from sklearn.cluster import DBSCAN # 调整eps为你的距离阈值0.35,min_samples根据业务需求设置 dbscan = DBSCAN(eps=0.35, min_samples=3, metric='precomputed', n_jobs=-1) cluster_labels = dbscan.fit_predict(sm_matrix)
DBSCAN是密度聚类,和层次聚类的聚类逻辑差异较大,需要根据你的业务场景判断是否适用。
内容的提问来源于stack exchange,提问作者Salihcan
相关产品推荐
相关产品推荐

