You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用scikit-learn HDBSCAN计算medoid时触发ValueError错误求助

问题描述

我有一个预计算的方形距离矩阵,想通过HDBSCAN计算medoid。按照scikit-learn文档,设置store_centers="medoid"并调用.medoids_属性,但运行时触发以下错误:

Traceback (most recent call last):
  File "C:\Users\Desktop\Clustering\Model.py", line 163, in <module>
    cluster(df, 'test.txt')
  File "C:\Users\Desktop\Clustering\Model.py", line 139, in cluster
    clustering = hdb.fit(distance_matrix.tocsr())
  File "C:\Users\Desktop\Clustering\venv\lib\site-packages\sklearn\cluster\_hdbscan\hdbscan.py", line 854, in fit
    self._weighted_cluster_center(X)
 in _weighted_cluster_center
    dist_mat = pairwise_distances(
  File "C:\Users\Desktop\Clustering\venv\lib\site-packages\sklearn\metrics\pairwise.py", line 2157, in pairwise_distances
    X, _ = check_pairwise_arrays(
  File "C:\Users\Desktop\Clustering\venv\lib\site-packages\sklearn\metrics\pairwise.py", line 184, in check_pairwise_arrays
    raise ValueError(
ValueError: Precomputed metric requires shape (n_queries, n_indexed). Got (9, 2292) for 9 indexed.

我搞不懂为什么自己的方形预计算矩阵会变成9×2292的数组。除此之外模型运行正常,我也能手动通过MSE操作获取medoid。我希望通过这种方式获取每个簇的可变eps,从而把更多数据拟合到簇中。

补充代码示例:

from fuzzywuzzy import fuzz
from sklearn.cluster import HDBSCAN
from scipy.sparse import lil_matrix
import itertools

def dis_matrix(word_list):
    count = 0
    kw_index = {}
    index_kw = {}
    n = len(word_list)
    distance_matrix = lil_matrix((n, n))

    for kw in word_list:
        kw_index[kw] = count
        index_kw[count] = kw
        count += 1

    for x, y in itertools.product(word_list,word_list):
        d = fuzz.ratio(x,y) / 100
        distance = 1 - d if d <= 1 else 0.00000000000001
        index1 = kw_index[x]
        index2 = kw_index[y]
        distance_matrix[index1, index2] = distance
        distance_matrix[index2, index1] = distance

    return distance_matrix, index_kw

CLUSTERING_MIN_SAMPLES = 2
x = ['apple', 'app', 'banana', 'bannana', 'applesauce', 'peaches', 'peach', "appban"]
distance_matrix, index_kw = dis_matrix(x)
hdb = HDBSCAN(cluster_selection_epsilon=.1, metric='precomputed', n_jobs=8, min_samples=CLUSTERING_MIN_SAMPLES,store_centers='medoid')
clustering = hdb.fit(distance_matrix.tocsr())
print(clustering.medoids_)
问题分析与解决

错误原因

HDBSCAN的store_centers='medoid'逻辑存在设计缺陷:当使用预计算距离矩阵时,它不会直接复用已有的距离数据,反而会尝试基于原始特征重新计算距离。但你传入的是距离矩阵而非原始特征,这导致它误将距离矩阵当成特征矩阵,进而在计算medoid时尝试对这个"特征矩阵"重新计算距离,最终出现形状不匹配的错误。

解决方案

有两种可行途径:

  • 手动计算medoid:遍历每个簇内的样本,找到使簇内平均距离最小的样本作为medoid。这种方式完全避开HDBSCAN的内置medoid计算逻辑,不会触发错误,也是你当前已验证可行的方案。
  • 适配HDBSCAN内置逻辑:如果坚持要用.medoids_属性,需要在拟合时同时传入原始特征矩阵和预计算的距离矩阵。具体操作:
    1. 将你的单词列表转换为可计算距离的特征矩阵(比如TF-IDF向量、词嵌入向量等,不能直接传字符串列表)
    2. 修改拟合代码为:
      clustering = hdb.fit(X=原始特征矩阵, X_precomputed=distance_matrix.tocsr())
      

关于可变eps的需求

HDBSCAN的cluster_selection_epsilon参数本身用于控制簇的最小密度阈值,结合medoid计算可辅助调整簇范围。如果用手动计算medoid的方式,可以基于每个medoid的簇内距离分布,动态调整对应簇的eps值,从而纳入更多相似样本。


内容的提问来源于stack exchange,提问作者sadboy_hdbscan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 04:02:15