Scikit-Learn中为GridSearchCV自定义损失函数的相关问题
解答:Kaggle房价预测自定义评分函数的两个问题
问题1:自定义损失函数应返回单值还是样本级数组?
在scikit-learn的make_scorer机制里,传入的损失/评分函数必须返回单个标量值(所有样本的总损失或平均得分),而不是每个样本的得分数组。
原因很直接:GridSearchCV这类交叉验证工具需要用单一数值来评估模型在某一折上的表现,进而计算交叉验证的平均得分。如果返回数组,要么会触发报错,要么无法正确完成交叉验证的分数统计。
你的RMSE计算本身就是全局统计量(所有样本的平方差平均后开根号),所以返回单值的方向是对的——只是代码里最后一行多了个没必要的np.sum(np.sqrt(numerator / len(truth))本身就是单值,sum之后结果不变,但可以简化掉)。
问题2:为什么best_score_是负数?
这个问题的核心是make_scorer的greater_is_better参数:
- 你设置了
greater_is_better=False,相当于告诉scikit-learn:你的自定义函数返回的是损失值(越小越好),而非常规的得分值(越大越好)。 - 但GridSearchCV的逻辑是默认寻找「最高得分」的模型,所以它会自动把你的损失值取反——比如实际RMSE是0.12137,就会被转成-0.12137,这样「最接近0的负数」就对应了最优模型(最小损失)。
所以你看到的负数best_score_,它的绝对值就是你真正需要的RMSE(log(真实值), log(预测值))。
顺便给你修正一下自定义损失函数,让逻辑更清晰准确:
import numpy as np from sklearn.metrics import make_scorer def custom_rmse_log(truth, preds): # 注意:要确保truth和preds都是正数,避免log(0)报错 truth_log = np.log(truth) preds_log = np.log(preds) mse = np.mean(np.square(truth_log - preds_log)) return np.sqrt(mse) # 因为RMSE是损失,越小越好,所以greater_is_better=False custom_scorer = make_scorer(custom_rmse_log, greater_is_better=False)
内容的提问来源于stack exchange,提问作者anon_swe
相关产品推荐
相关产品推荐

