silhouette_score 返回 NaN 或报错的主因是标签无效:如labels=None、全零、单类或含-1未处理;需确保标签为含≥2类的整数数组,输入X为稠密特征或合规预计算距离矩阵,且数据通常需标准化。

silhouette_score 为什么返回 NaN 或报错?
常见错误是传入了未聚类的标签,比如用 labels=None、全零标签、或标签数等于样本数(每个点自成一类)。这时轮廓系数数学上无定义,silhouette_score 直接返回 NaN 或抛出 ValueError: Number of labels is 1。
- 确保
labels是长度为 n_samples 的整数数组,且至少有 2 个不同类别(即len(set(labels)) > 1) - 别把距离矩阵误当原始特征:若传入
metric="precomputed",必须确认输入X是对称的、非负的成对距离矩阵,且形状为 (n, n) - 避免用稀疏矩阵直接喂给
silhouette_score—— 它不支持scipy.sparse输入,会静默转成稠密并可能爆内存
该用 silhouette_score 还是 silhouette_samples?
silhouette_score 返回单个平均值,适合快速对比不同 k 值下的整体聚类质量;silhouette_samples 返回每个样本的轮廓值,才能看出哪些簇拖了后腿、是否存在异常离群点。
- 调参选 k 时,用
silhouette_score+ 循环遍历k=2..10最稳妥 - 诊断具体问题时,必须用
silhouette_samples配合直方图或按簇分组看分布 —— 比如某簇均值低但标准差大,说明内部结构混乱,不是简单“k 太大”能解释的 - 注意:两者默认都用欧氏距离;若数据已标准化或用了其他度量,得显式传
metric="manhattan"等,否则结果不可比
标准化对 silhouette_score 影响有多大?
轮廓系数本身不归一化输入,但它的计算依赖样本间距离。特征量纲差异大会让距离被高量纲维度主导,导致系数失真 —— 即使数值上看“很高”,也可能是假象。
- 几乎所有实际场景下,都该在聚类前用
StandardScaler或MinMaxScaler处理X,再算silhouette_score - 文本 TF-IDF 向量例外:本身已近似归一化,强行
StandardScaler反而破坏稀疏性,此时更适合用metric="cosine" - 别在聚类后补标准化 —— 轮廓系数只认你喂给它的那个
X,和你心里想的“应该标准化”无关
sklearn 1.2+ 的 silhouette_score 有什么兼容性变化?
新版加了 random_state 参数(仅当 sample_size 不为 None 时生效),但更关键的是默认行为收紧:旧版容忍部分无效标签(如 -1 表示噪声),新版直接报错。
- 用 DBSCAN 时,
labels常含 -1,必须先过滤掉或映射为连续正整数(如labels[labels != -1] += 1)再喂给silhouette_score -
sample_size设太小(如 100)虽快,但估计偏差大,尤其当簇大小极不均衡时;建议只在 n_samples > 10000 且只是粗筛时启用 - 旧项目升级后报
ValueError: Found array with 0 sample(s),八成是传了空子集或全 -1 标签,得检查预处理逻辑
轮廓系数不是万能指标,它偏好球形、等大小、密度均匀的簇。如果数据里有长条形簇或明显嵌套结构,就算 score 接近 0.8,聚类结果也可能完全不符合业务直觉。

















