【问题标题】:One-hot-encoding with missing categories缺少类别的单热编码
【发布时间】:2018-07-31 04:27:32
【问题描述】:

我有一个包含类别列的数据集。为了使用线性回归,我对这一列进行了 1-hot 编码。

我的集合有 10 列,包括类别列。删除该列并附加 1-hot 编码矩阵后,我最终得到 14 列 (10 - 1 + 5)。

所以我用形状为 (n, 14) 的矩阵训练(拟合)我的 LinearRegression 模型。

在训练之后,我想在训练集的一个子集上对其进行测试,所以我先只取 5 个,然后将它们通过相同的管道。但是这 5 个首先只包含 3 个类别。因此,在通过管道之后,我只剩下一个形状为 (n, 13) 的矩阵,因为它缺少 2 个类别。

如何强制 1-hot 编码器使用 5 个类别?

我正在使用来自 sklearn 的 LabelBinarizer。

【问题讨论】:

  • 您应该只对新数据使用 LabelBinarizer.transform()。永远不适合()。显示代码,我们将根据需要对其进行修改。
  • 就是这样@VivekKumar - 一旦安装了变压器(在本例中为 LabelBinarizer),就不应重新安装。谢谢!

标签: python scikit-learn one-hot-encoding


【解决方案1】:

错误是“将测试数据通过同一管道”。基本上我在做:

data_prepared = full_pipeline.fit_transform(train_set)

lin_reg = LinearRegression()
lin_reg.fit(data_prepared, labels)

some_data = train_set.iloc[:5]
some_data_prepared = full_pipeline.fit_transform(some_data)

lin_reg.predict(some_data_prepared)
# => error because mismatching shapes

有问题的行是:

some_data_prepared = full_pipeline.fit_transform(some_data)

通过执行fit_transform,我会将 LabelBinarizer 安装到仅包含 3 个标签的集合中。相反,我应该这样做:

some_data_prepared = full_pipeline.transform(some_data)

这样我就使用了全套(train_set)安装的管道,并以相同的方式对其进行转换。

谢谢@Vivek Kumar

【讨论】:

    【解决方案2】:

    我遇到了这个问题,通过scikit-learn找不到解决办法。

    我正在使用 pandas .get_dummies() 做类似于 OneHotEncoder 的事情。

    下面是我为处理这个确切问题而制作的一个函数,请随意使用并改进它(如果您发现任何错误,请告诉我,实际上我只是从一个更具体的函数中制作的在我的代码库中)

    import numpy as np
    import pandas as pd
    
    def one_hot_encoding_fixed_columns(pandas_series, fixed_columns):
    
        # Creates complete fixed columns list (with nan and 'other')
        fixed_columns = list(fixed_columns)
        fixed_columns.extend([np.nan, 'other'])
    
        # Get dummies dataset
        ohe_df = pd.get_dummies(pandas_series, dummy_na=True)
    
        # Create blank 'other' column
        ohe_df['other'] = 0
    
        # Check if columns created by get_dummies() are in 'fixed_columns' list.
        for column in ohe_df.columns:
    
            if column not in fixed_columns:
                # If not in 'fixed_columns', transforms exceeding column into 'other'.
                ohe_df['other'] = ohe_df['other'] + ohe_df[column]
                ohe_df.drop(columns=[column])
    
        # Check if elements in 'fixed_columns' are in the df generated by get_dummies()
        for column in fixed_columns:
    
            if column not in ohe_df.columns:
                # If the element is not present, create a new column with all values set to 0.
                ohe_df['column'] = 0
    
        # Reorders columns according to fixed columns
        ohe_df = ohe_df[fixed_columns]
    
        return ohe_df
    

    基本上,您可以创建一个包含将始终使用的列的列表。如果test 样本没有给定类别的任何元素,则会创建具有values = 0 的对应列。如果test 具有不在train 样本中的新值,则将其归类为other

    我已将代码注释掉,希望它可以理解,如果您有任何问题,请告诉我,我会澄清它。

    此函数的输入是pandas_series = df['column_name'],您可以在训练集上执行fixed_columns = df[selected_column].str[0].value_counts().index.values 之类的操作,以生成也将用于测试集的值。

    【讨论】:

      【解决方案3】:

      基本上,首先我们需要对基础数据应用 fit_transform,然后对样本数据应用变换,因此样本数据也将获得与基础数据相对应的确切列数。

      【讨论】:

        猜你喜欢
        • 2018-01-06
        • 2021-02-23
        • 2023-03-06
        • 2011-03-07
        • 2016-12-14
        • 1970-01-01
        • 2018-02-16
        • 2018-12-17
        • 2020-11-21
        相关资源
        最近更新 更多