scikit-learn:如何使用管道组合 LabelEncoder 和 OneHotEncoder?
Posted
技术标签:
【中文标题】scikit-learn:如何使用管道组合 LabelEncoder 和 OneHotEncoder?【英文标题】:scikit-learn: How to compose LabelEncoder and OneHotEncoder with a pipeline? 【发布时间】:2018-08-02 09:42:20 【问题描述】:在为机器学习分类任务预处理标签时,我需要对采用字符串值的标签进行热编码。碰巧来自sklearn.preprocessing
的OneHotEncoder
或来自kera.np_utils
的to_categorical
需要int
输入。这意味着我需要在一个热编码器之前加上LabelEncoder
。我用自定义类手工完成了它:
class LabelOneHotEncoder():
def __init__(self):
self.ohe = OneHotEncoder()
self.le = LabelEncoder()
def fit_transform(self, x):
features = self.le.fit_transform( x)
return self.ohe.fit_transform( features.reshape(-1,1))
def transform( self, x):
return self.ohe.transform( self.la.transform( x.reshape(-1,1)))
def inverse_tranform( self, x):
return self.le.inverse_transform( self.ohe.inverse_tranform( x))
def inverse_labels( self, x):
return self.le.inverse_transform( x)
我相信在 sklearn API 中必须有一种使用sklearn.pipeline
的方法,但是在使用时:
LabelOneHotEncoder = Pipeline( [ ("le",LabelEncoder), ("ohe", OneHotEncoder)])
我从OneHotEncoder
收到错误ValueError: bad input shape ()
。我的猜测是LabelEncoder
的输出需要通过添加一个微不足道的第二个轴来重塑。我不确定如何添加此功能。
【问题讨论】:
【参考方案1】:这不是针对提出的问题,而是仅将 LabelEncoder 应用于所有列,您可以使用以下格式
df_non_numeric =df.select_dtypes(['object'])
non_numeric_cols = df_non_numeric.columns.values
from sklearn.preprocessing import LabelEncoder
for col in non_numeric_cols:
df[col] = LabelEncoder().fit_transform(df[col].values)
df.head()
【讨论】:
【参考方案2】:我使用了一个自定义类来包装我的标签编码器函数,它会返回整个更新的数据集。
class CustomLabelEncode(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
return self
def transform(self, X ,y=None):
le=LabelEncoder()
for i in X[cat_cols]:
X[i]=le.fit_transform(X[i])
return X
cat_cols=['Family','Education','Securities Account','CDAccount','Online','CreditCard']
le_ct=make_column_transformer((CustomLabelEncode(),cat_cols),remainder='passthrough')
pd.DataFrame(ct3.fit_transform(X)) #This will show you your changes
Final_pipeline=make_pipeline(le_ct)
[我已经实现了你可以看我的github链接] [1]:https://github.com/Ayushmina-20/sklearn_pipeline
【讨论】:
【参考方案3】:从 scikit-learn 0.20 开始,OneHotEncoder
接受字符串,因此您不再需要 LabelEncoder
之前。您可以在管道中使用它。
【讨论】:
感谢您的更新,更新后可能会使用此信息。【参考方案4】:奇怪的是他们不能很好地一起玩......我很惊讶。我会扩展该类以按照您的建议返回重塑后的数据。
class ModifiedLabelEncoder(LabelEncoder):
def fit_transform(self, y, *args, **kwargs):
return super().fit_transform(y).reshape(-1, 1)
def transform(self, y, *args, **kwargs):
return super().transform(y).reshape(-1, 1)
然后使用管道应该可以工作。
pipe = Pipeline([("le", ModifiedLabelEncoder()), ("ohe", OneHotEncoder())])
pipe.fit_transform(['dog', 'cat', 'dog'])
https://github.com/scikit-learn/scikit-learn/blob/a24c8b46/sklearn/preprocessing/label.py#L39
【讨论】:
感谢您的意见。我首先接受了您的答案,因为它看起来很明显它会起作用,但是在实施它时我遇到了错误。首先,管道构造函数接受类而不是实例,因此它必须是ModifiedLabelEncoder
而不是ModifiedLabelEncoder()
。其次,reshape 参数应该是(-1,1)
。之后,ModifiedLabelEncoder
将自行工作,但不在管道中。我在拨打fit_transform
时收到TypeError: super(type, obj): obj must be an instance or subtype of type
。
@Learningisamess 错误。管道接受实例,而不是类。
@Learningisamess 我已经更正了上面的代码,请立即检查。如果仍然有错误,请在问题中发布完整的错误堆栈跟踪。
@VivekKumar:确实我在关于管道的实例与类上错了。将很快检查新代码并报告。
添加对额外参数的支持后,代码确实可以工作 (*args, **kwargs
)。采纳答案,谢谢!以上是关于scikit-learn:如何使用管道组合 LabelEncoder 和 OneHotEncoder?的主要内容,如果未能解决你的问题,请参考以下文章
当最后一个估计器不是转换器时,如何使用 scikit-learn 管道进行转换?
如何在 scikit-learn 管道中将时代添加到 Keras 网络
如何在 scikit-learn 中使用管道调整自定义内核函数的参数