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

使用Sklearn GridSearchCV调优HDBSCAN时DBCV得分偏低问题排查

问题分析
  • 核心错误:make_scorer生成的评分器默认要求函数接收y_true和y_pred两个参数,但无监督聚类没有真实标签y_true,而hdbscan.validity.validity_index的签名是(X, labels),参数不匹配触发TypeError。
  • GridSearchCV总是选第一个参数的原因:评分函数未正确计算有效得分,所有参数组合的得分可能为默认值(或相同值),因此返回第一个条目。
解决方案

1. 适配无监督场景的DBCV评分器

sklearn的无监督评分器要求函数签名为(estimator, X),我们可以基于HDBSCAN拟合后的labels_属性自定义评分器:

def dbcv_scorer(estimator, X):
    # 从拟合后的模型中获取聚类标签,计算DBCV
    labels = estimator.labels_
    return hdbscan.validity.validity_index(X, labels)

# 生成符合sklearn规范的评分器
validity_scorer = make_scorer(dbcv_scorer, greater_is_better=True)

2. 修正GridSearchCV的初始化逻辑

不要提前拟合HDBSCAN模型,GridSearchCV会自动为每个参数组合重新拟合模型:

# 错误写法:hdb = hdbscan.HDBSCAN(...).fit(coordinates)
# 正确写法:仅初始化未拟合的模型实例
hdb = hdbscan.HDBSCAN(gen_min_span_tree=True)

3. 完整修正代码

from sklearn.model_selection import GridSearchCV
import hdbscan
from sklearn.metrics import make_scorer
import logging

logging.captureWarnings(True)

# 初始化未拟合的HDBSCAN模型
hdb = hdbscan.HDBSCAN(gen_min_span_tree=True)

# 定义参数网格
grid = {
    'min_samples': [50,55,60,65,70,75,80,90,100,110],
    'min_cluster_size': [40,45,50,55,60,65,75,80,85,90,95,100],
    'cluster_selection_method': ['eom','leaf'],
    'metric': ['euclidean','manhattan']
}

# 自定义DBCV评分器
def dbcv_scorer(estimator, X):
    labels = estimator.labels_
    return hdbscan.validity.validity_index(X, labels)

validity_scorer = make_scorer(dbcv_scorer, greater_is_better=True)

# 初始化GridSearchCV
grid_search = GridSearchCV(
    estimator=hdb,
    param_grid=grid,
    scoring=validity_scorer,
    # 可选:指定交叉验证策略,无监督场景推荐用ShuffleSplit
    # cv=ShuffleSplit(n_splits=5, test_size=0.2, random_state=42)
)

# 执行网格搜索
grid_search.fit(coordinates)

# 输出最优结果
print(f"Best Parameters {grid_search.best_params_}")
print(f"Cross-validated DBCV score :{grid_search.best_score_}")

4. RandomizedSearchCV的参数记录方案

用RandomizedSearchCV时,开启return_train_score=True,将所有参数组合的得分保存到DataFrame,方便回溯最优参数:

from sklearn.model_selection import RandomizedSearchCV
import pandas as pd

random_search = RandomizedSearchCV(
    estimator=hdb,
    param_distributions=grid,
    n_iter=20,  # 随机采样20组参数
    scoring=validity_scorer,
    return_train_score=True,
    random_state=42
)

random_search.fit(coordinates)

# 转换结果为DataFrame并按得分排序
results_df = pd.DataFrame(random_search.cv_results_)
results_df_sorted = results_df.sort_values(by='mean_test_score', ascending=False)

# 查看Top5最优参数组合
print(results_df_sorted[['params', 'mean_test_score']].head())
关键说明
  • 无监督聚类的评分器必须适配sklearn的无监督接口,不能直接用默认的make_scorer包装有监督风格的函数。
  • 提前拟合模型会导致GridSearchCV复用已训练的模型,无法正确测试不同参数组合,必须传入未拟合的模型实例。
  • grid_search.best_score_是交叉验证后的平均DBCV得分,和手动单次拟合的得分可能略有差异,但能更客观反映参数的稳定性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:35:04