为什么ColumnTransformer中的SimpleImputer会创建额外的列?

2024-09-27 00:23:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在学习奥雷利昂·杰隆的机器学习书籍

我正在试验ColumnTransformer类。当我包含SimplerImputer时,创建了一个额外的列。我知道SimplerImputer用于填充列total_bedrooms(结果中的列索引4)中缺少的值,因此我不清楚它为什么要在结果中添加新列(列索引:10)

当我不包括 来自ColumnTransformerSimplerImputer,但创建一个实例,以及fit_transformColumnTransformer的输出,我将不会获得额外的列。请告知

category_att = X.select_dtypes(include='object').columns
num_att = X.select_dtypes(include='number').columns

transformer = ColumnTransformer(
    [
    ('adder', AttributeAdder(), num_att ),
    ('imputer', SimpleImputer(strategy='median'), ['total_bedrooms']),
    ('ohe', OneHotEncoder(), category_att)
    ],
    remainder = 'passthrough'
)

用于添加两个新功能/列的自定义类

class AttributeAdder(BaseEstimator, TransformerMixin):
    
    def __init__(self, add_bed_room = False):
        self.add_bed_room = add_bed_room
    
    def fit(self,y=None):
        return self
    
    def transform(self,X,y=None):
        
        room_per_household = X.iloc[: , t_room ] / X.iloc[: , t_household ]
        population_per_household = X.iloc[: , t_population ] / X.iloc[: , t_household ]
        return np.c_[X,room_per_household,population_per_household]

结果 enter image description here


Tags: selfadddefattfittotalroompopulation
1条回答
网友
1楼 · 发布于 2024-09-27 00:23:20

为什么

确切地说,这不是SimpleImputer;这是ColumnTransformer本身ColumnTransformer并行应用其转换器,而不是按顺序应用(另请参见[1][2]),因此,如果将一列传递给多个转换器,您将在输出中多次使用该列。在您的例子中,输出列4来自total_bedrooms上的"adder"(它什么也没做,所以仍然缺少值),而输出列10来自"imputer"(因此将没有缺少值)

修复

在这种特殊情况下,两种方法似乎最简单

归咎于一切

任何没有缺失的数字功能都不会受到影响。但是,如果希望管道在缺少值的未来数据上出错,则不要这样做

num_pipe = Pipeline([
    ("add_feat", AttributeAdder()),
    ("impute", SimpleImputer(strategy="median")),
])
transformer = ColumnTransformer(
    [
        ('num', num_pipe, num_att),
        ('cat', OneHotEncoder(), category_att),
    ],
    remainder = 'passthrough',
)

小型变压器柱组

因为您的AttributeAdder实际上不需要您的total_bedrooms列,所以您不需要将它传递到该转换器中。具体细节将取决于您如何使用t_roomst_households等,但通常:

transformer = ColumnTransformer(
    [
        ('adder', AttributeAdder(), [["total_rooms", "households", "population"]]),
        ('imputer', SimpleImputer(strategy='median'), ['total_bedrooms']),
        ('ohe', OneHotEncoder(), category_att)
    ],
    remainder = 'passthrough'  # now you're relying on this one much more
)

在相关方法中,您可以更灵活地计算添加的特征。更改AttributeAdder以返回新特性(不要在transform的最后一步连接到X),并依赖ColumnTransformer传递这些特性。(注意,我们不能依赖于remainder实现这些功能,但我们可以使用"passthrough"作为变压器之一。)

class AttributeAdder(BaseEstimator, TransformerMixin):
    ...
    def transform(self,X,y=None):
        ...
        return np.c_[room_per_household,population_per_household]


transformer = ColumnTransformer(
    [
        ('adder', AttributeAdder(), num_att),
        ('num', "passthrough", num_att.drop(['total_bedrooms'])),
        ('imputer', SimpleImputer(strategy='median'), ['total_bedrooms']),
        ('ohe', OneHotEncoder(), category_att)
    ],
    passthrough=True,  # if you have columns in neither of num_att and category_att that you want kept
)

相关问题 更多 >

    热门问题