python - sklearn 使用带有自定义指标的 RandomizedSearchCV 并捕获异常

标签 python scikit-learn random-forest cross-validation

我在 sklearn 中使用 RandomizedSearchCV 函数和随机森林分类器。 为了查看不同的指标,我使用自定义评分

from sklearn.metrics import make_scorer, roc_auc_score, recall_score, matthews_corrcoef, balanced_accuracy_score, accuracy_score

acc = make_scorer(accuracy_score)

auc_score = make_scorer(roc_auc_score)
recall = make_scorer(recall_score)
mcc = make_scorer(matthews_corrcoef)
bal_acc = make_scorer(balanced_accuracy_score)

scoring = {"roc_auc_score": auc_score, "recall": recall, "MCC" : mcc, 'Bal_acc' : bal_acc, "Accuracy": acc }

这些自定义评分器用于随机搜索

rf_random = RandomizedSearchCV(estimator=rf, param_distributions=random_grid, n_iter=100, cv=split, verbose=2,
                               random_state=42, n_jobs=-1, error_score=np.nan, scoring = scoring, iid = True, refit="roc_auc_score")

现在的问题是,当我使用自定义拆分时,AUC 会引发异常,因为这一精确拆分只有一个类标签。

我不想更改分割,因此是否有可能在 RandomizedSearchCV 或 make_scorer 函数中捕获这些异常? 所以例如如果其中一个指标未计算(由于异常),只需输入 NaN 并继续下一个模型。

编辑: 显然,error_score 不包括模型训练,但不包括度量计算。如果我使用例如准确性,一切都会正常,我只会在只有一个类标签的折叠处收到警告。如果我使用 AUC 作为指标,我仍然会抛出异常。

很高兴能在这里得到一些想法!

解决方案: 定义一个自定义记分器,但有异常(exception):

def custom_scorer(y_true, y_pred, actual_scorer):
score = np.nan

try:
  score = actual_scorer(y_true, y_pred)
except ValueError: 
  pass

return score

这导致了一个新的指标:

acc = make_scorer(accuracy_score)
recall = make_scorer(custom_scorer, actual_scorer=recall_score)
new_auc = make_scorer(custom_scorer, actual_scorer=roc_auc_score)
mcc = make_scorer(custom_scorer, actual_scorer=matthews_corrcoef)
bal_acc = make_scorer(custom_scorer,actual_scorer=balanced_accuracy_score)

scoring = {"roc_auc_score": new_auc, "recall": recall, "MCC" : mcc, 'Bal_acc' : bal_acc, "Accuracy": acc }

这又可以传递给 RandomizedSearchCV 的评分参数

我发现的第二个解决方案是:

def custom_auc(clf, X, y_true):
score = np.nan
y_pred = clf.predict_proba(X)
try:
    score = roc_auc_score(y_true, y_pred[:, 1])
except Exception:
    pass

return score

也可以传递给评分参数:

scoring = {"roc_auc_score": custom_auc, "recall": recall, "MCC" : mcc, 'Bal_acc' : bal_acc, "Accuracy": acc }

(改编自 this answer )

最佳答案

您可以拥有一个通用记分器,它可以将其他记分器作为输入,检查结果,捕获它们抛出的任何异常并返回固定值。

def custom_scorer(y_true, y_pred, actual_scorer):
    score = np.nan

    try:
      score = actual_scorer(y_true, y_pred)
    except Exception: 
      pass

    return score

然后你可以使用以下方式调用它:

acc = make_scorer(custom_scorer, actual_scorer = accuracy_score)
auc_score = make_scorer(custom_scorer, actual_scorer = roc_auc_score, 
                        needs_threshold=True) # <== Added this to get correct roc
recall = make_scorer(custom_scorer, actual_scorer = recall_score)
mcc = make_scorer(custom_scorer, actual_scorer = matthews_corrcoef)
bal_acc = make_scorer(custom_scorer, actual_scorer = balanced_accuracy_score)

重现示例:

import numpy as np
def custom_scorer(y_true, y_pred, actual_scorer):
    score = np.nan

    try:
      score = actual_scorer(y_true, y_pred)
    except Exception: 
      pass

    return score


from sklearn.metrics import make_scorer, roc_auc_score, accuracy_score
acc = make_scorer(custom_scorer, actual_scorer = accuracy_score)
auc_score = make_scorer(custom_scorer, actual_scorer = roc_auc_score, 
                        needs_threshold=True) # <== Added this to get correct roc

from sklearn.datasets import load_iris
X, y = load_iris().data, load_iris().target

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV, KFold
cvv = KFold(3)
params={'criterion':['gini', 'entropy']}
gc = GridSearchCV(DecisionTreeClassifier(), param_grid=params, cv =cvv, 
                  scoring={"roc_auc": auc_score, "accuracy": acc}, 
                  refit="roc_auc", n_jobs=-1, 
                  return_train_score = True, iid=False)
gc.fit(X, y)
print(gc.cv_results_)

关于python - sklearn 使用带有自定义指标的 RandomizedSearchCV 并捕获异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53705966/

相关文章:

python - 为多个类创建图像数据集

python - SKlearn SGD 部分拟合

pyspark - 使用 Pyspark 从 Spark DataFrame 创建标记点

python - 如何在 python 中绘制图形,如 R 中的 varImpPlot() 方法图,用于绘制随机森林中的重要变量?

python - 如何使用漂亮的汤和重新找到包含特定文本的特定类的跨度?

Python:UnicodeWarning:Unicode 相等比较未能将两个参数转换为 Unicode - 将它们解释为不相等

python - 如何从 gridSearchCV 的输出中获取特征名称

keras - 如何使用 KerasClassifier 验证拆分和使用 scitkit 学习 GridSearchCV

machine-learning - 用于检测周期性时间序列模式中的异常的随机森林砍伐

Python pandas tz_localize throws NonExistentTimeError,然后无法丢弃错误的时间