您好,关于 sklearn.Pipeline 的两个问题,带有用于时间序列的自定义转换器 [关闭]
Posted
技术标签:
【中文标题】您好,关于 sklearn.Pipeline 的两个问题,带有用于时间序列的自定义转换器 [关闭]【英文标题】:Hello, two questions about sklearn.Pipeline with custom transformer for timeseries [closed] 【发布时间】:2020-12-26 23:36:33 【问题描述】:我应该如何修改下面的代码以使其工作:
目标,预测 = pipe.fit_predict(df)
编辑:
target, predicted = pipe.fit_transform(df, df)
我的代码:
import numpy as np
import pandas as pd
from sklearn.base import BaseEstimator
from sklearn.base import TransformerMixin
from sklearn.pipeline import Pipeline
np.random.seed(1)
rows,cols = 100,1
data = np.random.randint(100, size = (rows,cols))
tidx = pd.date_range('2019-01-01', periods=rows, freq='20min')
df = pd.DataFrame(data, columns=['num_orders'], index=tidx)
class MakeFeatures(BaseEstimator, TransformerMixin):
def __init__(self, X, y = None, max_lag = None, rolling_mean_day = None, rolling_mean_month = None):
self.X = X.resample('1H').sum()
self.max_lag = max_lag
self.rolling_mean_day = rolling_mean_day
self.rolling_mean_month = rolling_mean_month
def fit(self, X, y = None):
return self
def transform(self, X, y = None):
data = pd.DataFrame(index = self.X.index)
data['num_orders'] = self.X['num_orders']
data['year'] = self.X.index.year
data['month'] = self.X.index.month
data['day'] = self.X.index.day
data['dayofweek'] = self.X.index.dayofweek
data['detrend'] = self.X.shift() - self.X
if self.max_lag:
for lag in range(1, self.max_lag + 1):
data['lag_'.format(lag)] = data['detrend'].shift(lag)
if self.rolling_mean_day:
data['rolling_mean_24'] = data.detrend.shift().rolling(self.rolling_mean_day).mean()
if self.rolling_mean_month:
data['rolling_mean_24'] = data['detrend'].shift().rolling(self.rolling_mean_month).mean()
if data['year'].mean() == data['year'][1]:
data = data.drop('year', axis = 1)
data = data.dropna()
y = data.num_orders
data = data.drop('num_orders', 1)
return data, y
pipe = Pipeline([
('features', MakeFeatures(df, df, 2 , 24)),
('scaler', StandardScaler())
])
target, predicted = pipe.fit_transform(df, df) # where ‘Target’ is y - the output from the Class
输出:
ValueError: could not broadcast input array from shape (9,7) into shape (9).
Pipeline 中的每个函数都运行良好。
我可以毫无问题地运行 MakeFeatures(df, df) 和 StandardScaler().fit_transform(df, df)。
我可以将 MakeFeatures(df,df) 的乘积插入到 StandardScaler 中,没有错误。
【问题讨论】:
您好,您当前的问题很难理解。您能否提供数据的样本/虚拟对象,以便使用您的代码对其进行测试? @Kim Tang,感谢您的评论。至少现在我明白所有的缺点来自哪里。这是我的第一个问题,我还在学习如何提问。 那么欢迎来到 Stack Overflow!看看这里***.com/tour 的导览,然后用您的代码的“最小可重现示例”(***.com/help/minimal-reproducible-example) 更新您的问题以重现您的问题,以便其他人可以更好地帮助您。 让我们看看这是否可行。谢谢指导 【参考方案1】:你不能用
目标,预测 = pipe.fit_predict(df)
使用您定义的管道,因为只有在估计器也实现了这样的方法时才能使用 fit_predict() 方法。 Reference in documentation
仅当最终估计器实现 fit_predict 时才有效。
另外,它只会返回预测,所以你不能使用target,predicted =
,而应该使用predicted =
你得到了错误
ValueError: 使用序列设置数组元素。
因为您提供的是 StandardScaler()
和 pandas.TimeSeries
。
这是因为通过您的方法调用pipe.fit_predict(df)
,您只向管道提供了“X”而不是“y”。这对于管道“MakeFeatures”的第一个组件很好,因为它接受“X”并返回“数据”和“y”,但在管道中不会使用“y”,因为“y”必须在 fit_predict() 调用的开头定义。
在此处查看该方法的文档:https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html#sklearn.pipeline.Pipeline.fit_predict
它说明了“y”参数
训练目标。必须满足所有步骤的标签要求 管道。
因此“y”将用作管道所有部分的“y”,但您的未定义,所以None
。
因此,您当前的管道基本上会发生以下情况:
makeF = MakeFeatures(df, 2 , 24)
transformed_df = makeF.fit_transform(df)
sc = StandardScaler()
sc.fit(transformed_df)
并导致ValueError: setting an array element with a sequence.
所以我建议你像这样更新你的代码:
import numpy as np
import pandas as pd
from sklearn.base import BaseEstimator
from sklearn.base import TransformerMixin
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
np.random.seed(1)
rows,cols = 100,1
data = np.random.randint(100, size = (rows,cols))
tidx = pd.date_range('2019-01-01', periods=rows, freq='20min')
df = pd.DataFrame(data, columns=['num_orders'], index=tidx)
class MakeFeatures(BaseEstimator, TransformerMixin):
def __init__(self, X, max_lag = None, rolling_mean_day = None, rolling_mean_month = None):
self.X = X.resample('1H').sum()
self.max_lag = max_lag
self.rolling_mean_day = rolling_mean_day
self.rolling_mean_month = rolling_mean_month
def fit(self, X):
return self
def transform(self, X):
data = pd.DataFrame(index = self.X.index)
data['num_orders'] = self.X['num_orders']
data['year'] = self.X.index.year
data['month'] = self.X.index.month
data['day'] = self.X.index.day
data['dayofweek'] = self.X.index.dayofweek
data['detrend'] = self.X.shift() - self.X
if self.max_lag:
for lag in range(1, self.max_lag + 1):
data['lag_'.format(lag)] = data['detrend'].shift(lag)
if self.rolling_mean_day:
data['rolling_mean_24'] = data.detrend.shift().rolling(self.rolling_mean_day).mean()
if self.rolling_mean_month:
data['rolling_mean_24'] = data['detrend'].shift().rolling(self.rolling_mean_month).mean()
if data['year'].mean() == data['year'][1]:
data = data.drop('year', axis = 1)
data = data.dropna()
y = data.num_orders
data = data.drop('num_orders', 1)
return data, list(y)
pipe = Pipeline([
('scaler', StandardScaler()),
('Model' , LinearRegression())
])
makeF = MakeFeatures(df, 2 , 24)
makeF.fit(df)
data,y = makeF.transform(df)
pipe.fit(data,y) # where ‘Target’ is y - the output from the Class
然后您可以使用管道来预测数据并评估性能,例如使用 r2_score:
from sklearn.metrics import r2_score
predictions = pipe.predict(data)
r2_score(y,predictions)
【讨论】:
Kim Tang,谢谢你的回答,但 StandardScaler 和 Pipeline 都接受 label 参数,所以如果我将我的 Class 修改为 MakeFeature(self, X , y,..) 然后调用 pipe.fit_transform(df,df) (其中 pipe = Pipeline([ ('features', MakeFeatures(df,df), (')缩放器', StandardScaler())]) ? 我在这里看不到你完整的更新代码,但是通过查看这个,我认为错误是 StandardScaler 将使用'df'作为'y'参数来调用,因为你调用 pipe.fit_transform(df,df)。但 StandardScaler 不能将 'df' 用作 'y'。 首先-感谢您的患者,不确定政策,但我的问题与您已经回答的主要问题不同。 StandardScaler().fit_transform(df,df) 可以正常工作,MakeFeatures(df,df) 也可以。但一起: pipe = Pipeline([ ('features', MakeFeatures(df,df), ('scaler', StandardScaler())]), pipe.fit_transform(df,df) 它没有'不工作 好的,就你的问题提出一个新问题,包括代码和一些数据来重现和理解你的问题。这样其他人也可以帮助你。以上是关于您好,关于 sklearn.Pipeline 的两个问题,带有用于时间序列的自定义转换器 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
使用 sklearn Pipeline 和 MultiOutputRegressor 访问属性