我想对一组超参数进行网格搜索来调整聚类模型。
GridSearchCV
为无监督学习提供了一堆评分函数,但我想使用其中不存在的函数,例如剪影分数.
关于如何实现我的自定义函数的文档不清楚我们应该如何定义我们的评分函数。该示例显示了简单地导入自定义评分器并使用 make_scorer
创建自定义评分函数。然而,
make_scorer
似乎需要真实值(这在无监督学习中不存在),所以不清楚如何使用它。这是我到目前为止所拥有的:
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 my_custom_function(model, X):
preds = model.predict(X)
return silhouette_score(X, preds)
Z, _ = make_blobs()
model = DBSCAN()
pgrid = {'eps': [0.1*i for i in range(1,6)]}
gs = GridSearchCV(model, pgrid, scoring=my_custom_function)
gs.fit(Z)
best_score = gs.score(Z)
但是它抛出了两个错误:
TypeError: my_custom_function() takes 2 positional arguments but 3 were given
和
AttributeError: 'DBSCAN' object has no attribute 'predict'
如何正确定义我的自定义评分函数?
.fit_predict()
方法来获取标签(使用
.labels_
不起作用)。那么您的记分器函数必须返回一个值,其中值越大越好1。 scikit-learn 上的所有聚类算法都实现了
.fit_predict()
,所以在这方面没有问题。例如,要将轮廓分数实现为 DBSCAN 的评分指标,请按如下方式定义它,并将其直接传递到
GridSearchCV
作为评分参数。请注意,如果只有一个标签,轮廓分数将无法正常工作,因此我们需要对此进行检查。
def my_silhouette_score(model, X, y=None):
preds = model.fit_predict(X)
return silhouette_score(X, preds) if len(set(preds)) > 1 else float('nan')
model = DBSCAN()
pgrid = {
'eps': np.linspace(0.01, 0.5, 10),
'min_samples': np.arange(2, 10)
}
gs = GridSearchCV(model, pgrid, scoring=my_silhouette_score).fit(Z)
best_estimator = gs.best_estimator_
highest_silhouette_score = gs.score(Z)
1:这确实不是问题;简单地改变结果的符号应该使函数最小化或最大化。