我想创建我自己的SCRKIT-学习转换器,用于编码包含分类的数字特征,如邮政编码或行业代码(NAICS,MCC等).在这类代码中有一种 struct :例如,MCC 3000-3999是"旅行和娱乐",它被进一步细分为更细粒度的类别,如"航空公司"、"汽车租赁"等.我们不能将它们用作顺序特征,但如果我们将它们视为纯粹的分类特征(例如,通过一热编码),我们需要 Select 在代码 struct 的哪个级别应用特征编码.
为了解决这个问题,我创建了我自己的SCRICKIT-LEARN转换器,它是使用决策树的TargetEncoder的变体.代码如下所示.重要的是要认识到,在模型训练过程中,应该使用样本外的决策树回归分数,以避免过度拟合.出于这个原因,我实现了自己的fit_transform
函数,该函数从样本分数中生成以下分数:
from sklearn.tree import DecisionTreeRegressor
from sklearn.base import TransformerMixin, BaseEstimator
from sklearn.model_selection import cross_val_predict
class TaxonomyEncoder(TransformerMixin, BaseEstimator):
def __init__(self, n_leafs=10, cv=3):
self.n_leafs = n_leafs
self.cv = cv
def fit(self, X, y=None):
self.tree_ = DecisionTreeRegressor(max_leaf_nodes=self.n_leafs).fit(X,y)
return self
def transform(self, X):
return self.tree_.predict(X).reshape(-1,1)
def fit_transform(self, X, y=None):
self.tree_ = DecisionTreeRegressor(max_leaf_nodes=self.n_leafs)
return cross_val_predict(self.tree_, X, y, cv=self.cv).reshape(-1,1)
变压器工作正常,但在ColumnTransformer
范围内使用时除外:
from sklearn.compose import ColumnTransformer
transformer = ColumnTransformer([('taxonomy', TaxonomyEncoder(), ['mcc'])])
transformer.fit(df[['mcc']], df['y'])
transformer.transform(df[['mcc']])
然后,我得到的错误是决策树还不适合:
NotFittedError: This DecisionTreeRegressor instance is not fitted yet. Call 'fit' with appropriate arguments before using this estimator.
显然,SCRICKIT-LEARN会在表面之下进行一些判断,从而导致这个错误.请注意,实际上没有理由具有适合的决策树,因为该树是在cross_val_predict
函数中重新设置的.我怎么才能解决这个问题呢?
下面是一个完整的工作示例来重现错误:
import pandas as pd
df = pd.DataFrame({'mcc':[3000,3500,7339], 'y':[0,0,1]})
te = TaxonomyEncoder().fit(df[['mcc']], df['y'])
te.transform(df[['mcc']])
提供:
array([[0.],
[0.],
[1.]])
FIT_Transform也提供了预期的结果:
te.fit_transform(df[['mcc']], df['y'])
array([[0.],
[0.],
[0.]])
但当包装在ColumnTransformer中时,事情就出错了:
transformer = ColumnTransformer([('taxonomy', TaxonomyEncoder(), ['mcc'])])
transformer.fit(df[['mcc']], df['y'])
transformer.transform(df[['mcc']])