在训练和测试数据中保持相同的虚拟变量

Posted

技术标签:

【中文标题】在训练和测试数据中保持相同的虚拟变量【英文标题】:Keep same dummy variable in training and testing data 【发布时间】:2017-05-11 04:22:50 【问题描述】:

我正在 python 中构建一个预测模型,其中包含两个单独的训练和测试集。训练数据包含数字类型的分类变量,例如邮政编码,[91521,23151,12355, ...],还有字符串分类变量,例如,城市 ['Chicago', 'New York', 'Los Angeles', ...]。

为了训练数据,我首先使用 'pd.get_dummies' 来获取这些变量的虚拟变量,然后用转换后的训练数据拟合模型。

我对我的测试数据进行相同的转换,并使用经过训练的模型预测结果。但是,我得到了错误

ValueError: Number of features of the model must  match the input. Model n_features is 1487 and  input n_features is 1345

原因是测试数据中的虚拟变量较少,因为它的“城市”和“邮政编码”较少。

我该如何解决这个问题?例如,'OneHotEncoder' 只会对所有数值类型的分类变量进行编码。 'DictVectorizer()' 只会对所有字符串类型的分类变量进行编码。我在网上搜索并看到一些类似的问题,但没有一个能真正解决我的问题。

Handling categorical features using scikit-learn

https://www.quora.com/If-the-training-dataset-has-more-variables-than-the-test-dataset-what-does-one-do

https://www.quora.com/What-is-the-best-way-to-do-a-binary-one-hot-one-of-K-coding-in-Python

【问题讨论】:

【参考方案1】:

您也可以只获取缺失的列并将它们添加到测试数据集中:

# Get missing columns in the training test
missing_cols = set( train.columns ) - set( test.columns )
# Add a missing column in test set with default value equal to 0
for c in missing_cols:
    test[c] = 0
# Ensure the order of column in the test set is in the same order than in train set
test = test[train.columns]

此代码还确保将删除从测试数据集中的类别产生但不存在于训练数据集中的列

【讨论】:

最后一行也可以使用train, test = train.align(test, axis=1) 如果使用get dummies完成训练并保存模型,稍后我们加载模型和新的测试数据(只有一条记录),此时如何获取测试中的新列名基于其值的数据【参考方案2】:

假设您在训练和测试数据集中具有相同的特征名称。您可以从训练和测试中生成连接数据集,从连接数据集中获取假人并将其拆分以进行训练和测试。

你可以这样做:

import pandas as pd
train = pd.DataFrame(data = [['a', 123, 'ab'], ['b', 234, 'bc']],
                     columns=['col1', 'col2', 'col3'])
test = pd.DataFrame(data = [['c', 345, 'ab'], ['b', 456, 'ab']],
                     columns=['col1', 'col2', 'col3'])
train_objs_num = len(train)
dataset = pd.concat(objs=[train, test], axis=0)
dataset_preprocessed = pd.get_dummies(dataset)
train_preprocessed = dataset_preprocessed[:train_objs_num]
test_preprocessed = dataset_preprocessed[train_objs_num:]

结果,训练数据集和测试数据集的特征数量相等。

【讨论】:

看不见的测试数据呢?连接和重新训练模型?似乎不是一个可行的选择 @randomSampling 你找到解决方案了吗?如果是的话,请你看看这个question【参考方案3】:
train2,test2 = train.align(test, join='outer', axis=1, fill_value=0)

train2 和 test2 具有相同的列。 fill_value 表示用于缺失列的值。

【讨论】:

在训练数据中,如果列名是“Marital_Status”,它变成“Marital_Status_Single, Marital_Status_Married, Marital_Status_Divorced”,但在测试数据中它仍然是“Marital_Status”并且说值是“Single”,所以如何将精确列“Marital_Status_Single”归为 1,将其他 2 归为 0。 @hanzgs,很晚了,但对其他人有帮助::- 在执行训练测试连接之前,对测试数据执行 one-hot 编码以及“pd.get_dummies(test))”【参考方案4】:

这是一个相当老的问题,但如果你打算使用 scikit learn API,你可以使用以下 DummyEncoder 类:https://gist.github.com/psinger/ef4592492dc8edf101130f0bf32f5ff9

它的作用是利用类别 dtype 来指定要创建的虚拟对象,此处也详细说明:Dummy creation in pipeline with different levels in train and test set

【讨论】:

【参考方案5】:

我过去在训练集和测试集上运行 get_dummies 后遇到过这种情况

X_test = X_test.reindex(columns = X_train.columns, fill_value=0)

显然对个别情况进行了一些调整。但是,它会丢弃测试集中的新值,并填充测试中缺失的值,在本例中为全零。

【讨论】:

以上是关于在训练和测试数据中保持相同的虚拟变量的主要内容,如果未能解决你的问题,请参考以下文章

R语言使用caret包的predict函数对模型在测试集上的表现进行推理和预测predict函数对测试数据集进行数据预处理(和训练集的初始方式保持一致):缺失值填充数值变量最小最大缩放独热编码

R语言使用caret包的predict函数对测试数据集进行数据预处理(和训练集的处理方式保持一致):缺失值填充数值变量最小最大缩放因子变量独热编码等

QDA |训练和测试数据集的长度 |如何拆分训练数据和测试数据?

机器学习训练和测试数据拆分方法

scikit learn 的训练测试拆分导致训练数据中只有一个唯一值的特征

拆分训练测试数据集将相似的值保持在一起