如何在无监督学习的GridSearchCV中使用自定义评分函数
无监督聚类模型GridSearchCV自定义评分函数解决方案
问题背景
想用GridSearchCV调优DBSCAN这类无监督聚类模型的超参数,自定义轮廓系数作为评分指标,但遇到两个报错:
TypeError: my_custom_function() takes 2 positional arguments but 3 were givenAttributeError: 'DBSCAN' object has no attribute 'predict'
错误原因与修复方法
TypeError 修复
GridSearchCV会给评分函数传递3个参数:模型实例、特征数据X、标签y(无监督场景下y为None),哪怕你用不上y,自定义函数也必须把它作为参数声明。AttributeError 修复
DBSCAN属于无监督密度聚类算法,没有predict方法,要获取聚类标签,得先让模型拟合当前数据,再通过labels_属性提取结果。
完整可运行代码
from sklearn.datasets import make_blobs from sklearn.model_selection import GridSearchCV from sklearn.cluster import DBSCAN from sklearn.metrics import silhouette_score, make_scorer # 自定义轮廓系数评分函数 def silhouette_scorer(estimator, X, y=None): # 拟合数据获取聚类标签 estimator.fit(X) labels = estimator.labels_ # 处理全噪声的极端情况,避免silhouette_score报错 unique_labels = set(labels) if len(unique_labels) == 1 and -1 in unique_labels: return -1.0 return silhouette_score(X, labels) # 用make_scorer包装自定义函数,明确评分越高越好 custom_scorer = make_scorer(silhouette_scorer, greater_is_better=True) # 生成测试数据集 X, _ = make_blobs(n_samples=500, centers=3, random_state=42) # 初始化模型与待调参网格 dbscan = DBSCAN() param_grid = {'eps': [0.1*i for i in range(1,6)], 'min_samples': [2,3,4]} # 初始化网格搜索,传入自定义评分器 grid_search = GridSearchCV(estimator=dbscan, param_grid=param_grid, scoring=custom_scorer, cv=3) grid_search.fit(X) # 输出最优结果 print("最优参数组合:", grid_search.best_params_) print("最优轮廓系数得分:", grid_search.best_score_)
关键细节说明
- 用
make_scorer包装是scikit-learn的标准操作,通过greater_is_better=True告诉网格搜索:轮廓系数越高,模型效果越好。 - 增加了全噪声场景的判断:如果所有样本都被标记为噪声(labels全是-1),直接返回最低分-1.0,避免
silhouette_score因聚类数量为1抛出异常。 - GridSearchCV会自动完成交叉验证的数据集拆分,无需手动处理。
内容的提问来源于stack exchange,提问作者cottontail
相关产品推荐
相关产品推荐

