我正在参加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
,我从nan
语句中得到print
。查看三个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)
),那么它就会很好地返回。
我确信我错过了一些关于渐变增强的简单方法;为什么这个评分方法不适用于梯度增强回归量?
答案 0 :(得分:4)
我建议你对此进行矢量化
def rmsle(y, y0):
return np.sqrt(np.mean(np.square(np.log1p(y) - np.log1p(y0))))
基准可以在这里找到
答案 1 :(得分:3)
首先,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。希望这可以帮助 !最适合您的比赛。