使用 scikit-learn 估计器作为变压器

问题描述 投票:0回答:1

我想创建自己的 scikit-learn 转换器,用于编码包含分类的数字特征,例如邮政编码或行业代码(NAICS、MCC 等)。在这些类型的代码中有一个结构:例如MCC 3000-3999 是“旅行和娱乐”,它进一步细分为更细粒度的类别,例如“航空公司”、“汽车租赁”等。我们不能将它们用作序数特征,但如果我们将它们视为纯分类特征(例如,通过 One -Hot-Encoding)我们需要选择在代码结构的哪个级别应用特征编码。

为了解决这个问题,我创建了自己的 scikit-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.

显然,scikit-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']])
python machine-learning scikit-learn data-science
1个回答
0
投票

在您的

fit_transform
中,您需要使树适合整个数据集,以防您稍后调用
transform
。正如所写,您尝试时也会遇到错误

te = TaxonomyEncoder()
te.fit_transform(df[['mcc']], df['y'])
te.transform(df[['mcc']])

修复方法很简单:

def fit_transform(self, X, y=None):
    self.fit(X, y)
    return cross_val_predict(self.tree_, X, y, cv=self.cv).reshape(-1,1)

ColumnTransformer
有一点怪癖,导致使用它时出错:它实际上总是
fit_transform
是它的所有变压器(即使只是拟合列变压器本身),以确定输出是否稀疏从而判断 hstack 是否应该稀疏。

© www.soinside.com 2019 - 2024. All rights reserved.