【问题标题】:Root mean log squared error issue with scitkit-learn.ensemble.GradientBoostingRegressorscikit-learn.ensemble.GradientBoostingRegressor 的均方根误差问题
【发布时间】:2018-02-22 10:35:45
【问题描述】:

我正在参加 Kaggle 比赛 (data here),但我在使用 scikit-learn 的 GradientBoostingRegressor 时遇到了问题。比赛使用均方根对数平方误差 (RMLSE) 来评估预测。


为了一个 MWE,这里是我用来清理上面链接中的train.csv 的代码:

import datetime
import pandas as pd

train = pd.read_csv("train.csv", index_col=0)

train.pickup_datetime = pd.to_datetime(train.pickup_datetime)
train["pickup_month"] = train.pickup_datetime.apply(lambda x: x.month)
train["pickup_day"] = train.pickup_datetime.apply(lambda x: x.day)
train["pickup_hour"] = train.pickup_datetime.apply(lambda x: x.hour)
train["pickup_minute"] = train.pickup_datetime.apply(lambda x: x.minute)
train["pickup_weekday"] = train.pickup_datetime.apply(lambda x: x.weekday())
train = train.drop(["pickup_datetime", "dropoff_datetime"], axis=1)
train["store_and_fwd_flag"] = pd.get_dummies(train.store_and_fwd_flag, drop_first=True)

X_train = train.drop("trip_duration", axis=1)
y_train = train.trip_duration

为了说明工作,如果我使用随机森林,那么 RMSLE 计算得很好:

import numpy as np
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.metrics import make_scorer
from sklearn.model_selection import cross_val_score


def rmsle(predicted, real):
    sum=0.0
    for x in range(len(predicted)):
        p = np.log(predicted[x]+1)
        r = np.log(real[x]+1)
        sum = sum + (p - r)**2
    return (sum/len(predicted))**0.5

rmsle_score = make_scorer(rmsle, greater_is_better=False)

rf = RandomForestRegressor(random_state=1839, n_jobs=-1, verbose=2)
rf_scores = cross_val_score(rf, X_train, y_train, cv=3, scoring=rmsle_score)
print(np.mean(rf_scores))

这运行得很好。 然而,梯度提升回归器抛出RuntimeWarning: invalid value encountered in log,我从print 语句中得到nan。查看三个 RMSLE 分数的数组,都是nan

gb = GradientBoostingRegressor(verbose=2)
gbr_scores = cross_val_score(gb, X_train, y_train, cv=3, scoring=rmsle_score)
print(np.mean(gbr_scores))

我认为这是因为我在某个不应该出现的地方得到了负值。 Kaggle 告诉我,当我在那里上传我的预测以查看它是否与我的代码有关时,它也遇到了零或非负 RMSLE。梯度提升不能用于这个问题有什么原因吗?如果我使用mean_squared_error 作为记分员(mse_score = make_scorer(mean_squared_error, greater_is_better=False)),它会返回就好了。

我确定我错过了一些关于梯度提升的简单内容;为什么这种评分方法适用于梯度提升回归器?

【问题讨论】:

  • (我也是一个主要的 R 用户,所以如果有人对代码有 Python 的一般批评,请分享,如果你愿意的话)。
  • 您可以在rmsle 函数中添加print(predicted) 以检查预测数组中是否存在负值。顺便说一句,rmsle 函数中的for 循环可以写成np.sqrt(np.mean(np.power(np.log(np.array(predicted)+1) - np.log(np.array(real)+1), 2))),这应该比遍历数组更快。
  • @σηγ宾果游戏,就是这样。谢谢!也感谢分数的矢量化代码。
  • 马克你能用这个新的得分手来试穿吗?使用 RandomizedSearchCV,无论我做什么,它都不起作用。如果我设置greater_is_better=False,它会否定它并开始最小化否定值。如果greater_is_better=True,就是最大化损失,两者都是错误的。怎么办??

标签: python machine-learning scikit-learn


【解决方案1】:

首先,make_scorer 为您的函数采用的语法如下:

def metric(real,predictions)

没有

def metric(predictions,real)

因此,您需要在代码中打印 real 值,以获取回归器的实际 predicted 值。

只需如下更改功能,它应该可以正常工作:

def rmsle(real, predicted):
    sum=0.0
    for x in range(len(predicted)):
        if predicted[x]<0 or real[x]<0: #check for negative values
            continue
        p = np.log(predicted[x]+1)
        r = np.log(real[x]+1)
        sum = sum + (p - r)**2
    return (sum/len(predicted))**0.5

其次,您的回归器在预测行号时给出了错误的值。第一个交叉验证集中的 399937。希望这可以帮助 !祝您的比赛一切顺利。

【讨论】:

    【解决方案2】:

    我建议你将这个向量化

    def rmsle(y, y0):
        return np.sqrt(np.mean(np.square(np.log1p(y) - np.log1p(y0))))
    

    可以在这里找到基准

    https://www.kaggle.com/jpopham91/rmlse-vectorized

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-23
      • 2020-08-10
      • 2014-03-22
      • 2017-05-07
      相关资源
      最近更新 更多