用于提取日期特征的 Sklearn 自定义转换器在管道中不起作用
Sklearn custom transformer to extract date features doesn't work in a Pipeline
我输入的数据是字符串数据类型,我想从该字符串中提取一些与预测时间相关的日期。
例如:
Date
City
2015-07-12
Barcelona
2015-07-13
Brussels
我希望它成为
Day
Month
7
12
7
13
等等
from sklearn.base import BaseEstimator, TransformerMixin
class DateTransformer(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
return self
def transform(Self, X, y = None):
X.date = pd.to_datetime(X.date)
X["year"] = X.date.dt.year
X["month"] = X.date.dt.month
X["day"] = X.date.dt.day
X["dow"] = X.date.dt.dayofweek
X["quarter"] = X.date.dt.quarter
X = X.drop("date", axis=1)
X = X.astype(str)
return X
在以下流水线中使用
naiveBaseline = Pipeline([
('dates', DateTransformer()),
('onehot', OneHotEncoder()),
('regression', RidgeCV())
])
像这样使用时,流水线实际工作:
naiveBaseline2.fit(X_train,y_train)
naiveBaseline2.predict(X_test)
但理想情况下,我使用以下函数来对多个模型的性能进行基准测试:
def evaluate(model, X, y, cv):
cv_results = cross_validate(
model,
X,
y,
cv=cv,
scoring=["neg_mean_absolute_error", "neg_root_mean_squared_error"],
)
mae = -cv_results["test_neg_mean_absolute_error"]
rmse = -cv_results["test_neg_root_mean_squared_error"]
print(
f"Mean Absolute Error: {mae.mean():.3f} +/- {mae.std():.3f}\n"
f"Root Mean Squared Error: {rmse.mean():.3f} +/- {rmse.std():.3f}"
)
如果我 运行 通过这样的评估函数:evaluate(naiveBaseline2, X, y, TimeSeriesSplit())
我只是得到了两个指标的 NaN。我已经检查了几个小时,但似乎真的不明白出了什么问题,你们知道吗?
已解决,问题出在 oneHotEncoder 上,在使用 TimeSeriesSplit()
并向前交叉验证时,它看不到所有日期标签(例如第一次拆分中的 2020 年),因此它抛出了一个错误。 oneHotEncoder 需要参数 handle_unknown=True
.
我输入的数据是字符串数据类型,我想从该字符串中提取一些与预测时间相关的日期。
例如:
Date | City |
---|---|
2015-07-12 | Barcelona |
2015-07-13 | Brussels |
我希望它成为
Day | Month |
---|---|
7 | 12 |
7 | 13 |
等等
from sklearn.base import BaseEstimator, TransformerMixin
class DateTransformer(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
return self
def transform(Self, X, y = None):
X.date = pd.to_datetime(X.date)
X["year"] = X.date.dt.year
X["month"] = X.date.dt.month
X["day"] = X.date.dt.day
X["dow"] = X.date.dt.dayofweek
X["quarter"] = X.date.dt.quarter
X = X.drop("date", axis=1)
X = X.astype(str)
return X
在以下流水线中使用
naiveBaseline = Pipeline([
('dates', DateTransformer()),
('onehot', OneHotEncoder()),
('regression', RidgeCV())
])
像这样使用时,流水线实际工作:
naiveBaseline2.fit(X_train,y_train)
naiveBaseline2.predict(X_test)
但理想情况下,我使用以下函数来对多个模型的性能进行基准测试:
def evaluate(model, X, y, cv):
cv_results = cross_validate(
model,
X,
y,
cv=cv,
scoring=["neg_mean_absolute_error", "neg_root_mean_squared_error"],
)
mae = -cv_results["test_neg_mean_absolute_error"]
rmse = -cv_results["test_neg_root_mean_squared_error"]
print(
f"Mean Absolute Error: {mae.mean():.3f} +/- {mae.std():.3f}\n"
f"Root Mean Squared Error: {rmse.mean():.3f} +/- {rmse.std():.3f}"
)
如果我 运行 通过这样的评估函数:evaluate(naiveBaseline2, X, y, TimeSeriesSplit())
我只是得到了两个指标的 NaN。我已经检查了几个小时,但似乎真的不明白出了什么问题,你们知道吗?
已解决,问题出在 oneHotEncoder 上,在使用 TimeSeriesSplit()
并向前交叉验证时,它看不到所有日期标签(例如第一次拆分中的 2020 年),因此它抛出了一个错误。 oneHotEncoder 需要参数 handle_unknown=True
.