缺少类别的单热编码

One-hot-encoding with missing categories

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

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

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

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

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

我正在使用 sklearn 中的 LabelBinarizer。

我已经 运行 解决了这个问题,但我无法通过 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 的操作以生成也将在测试集上使用的值。

错误是"put the test data through the same pipeline"。基本上我在做:

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

基本上,首先我们需要对基础数据应用 fit_transform,然后对样本数据应用转换,因此样本数据也将获得准确的 no.of 列 w.r.t 基础数据.