缺少类别的单热编码
Posted
技术标签:
【中文标题】缺少类别的单热编码【英文标题】: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),就不应重新安装。谢谢! 【参考方案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,然后对样本数据应用变换,因此样本数据也将获得与基础数据相对应的确切列数。
【讨论】:
以上是关于缺少类别的单热编码的主要内容,如果未能解决你的问题,请参考以下文章