如何在预测时从测试数据中处理onehotencoding后的类别不匹配?

Posted

技术标签:

【中文标题】如何在预测时从测试数据中处理onehotencoding后的类别不匹配?【英文标题】:How to handle category mismatch after onehotencoding from test data while predicting? 【发布时间】:2018-05-26 23:10:57 【问题描述】:

对不起,如果问题的标题不是那么清楚,我无法将问题总结在一行中。

这里是用于解释的简化数据集。基本上,训练集中的类别数量远大于测试集中的类别数量,因此 OneHotEncoding 后的测试和训练集中的列数存在差异。我该如何处理这个问题?

训练集

+-------+----------+
| Value | Category |
+-------+----------+
| 100   | SE1      |
+-------+----------+
| 200   | SE2      |
+-------+----------+
| 300   | SE3      |
+-------+----------+

OneHotEncoding 之后的训练集

+-------+-----------+-----------+-----------+
| Value | DummyCat1 | DummyCat2 | DummyCat3 |
+-------+-----------+-----------+-----------+
| 100   | 1         | 0         | 0         |
+-------+-----------+-----------+-----------+
| 200   | 0         | 1         | 0         |
+-------+-----------+-----------+-----------+
| 300   | 0         | 0         | 1         |
+-------+-----------+-----------+-----------+

测试集

+-------+----------+
| Value | Category |
+-------+----------+
| 100   | SE1      |
+-------+----------+
| 200   | SE1      |
+-------+----------+
| 300   | SE2      |
+-------+----------+

OneHotEncoding 之后的测试集

+-------+-----------+-----------+
| Value | DummyCat1 | DummyCat2 |
+-------+-----------+-----------+
| 100   | 1         | 0         |
+-------+-----------+-----------+
| 200   | 1         | 0         |
+-------+-----------+-----------+
| 300   | 0         | 1         |
+-------+-----------+-----------+

如您所见,OneHotEncoding 之后的训练集形状为 (3,4),而 OneHotEncoding 之后的测试集形状为 (3,3)。 因此,当我执行以下代码时(y_train 是形状为(3,) 的列向量)

from sklearn.linear_model import LinearRegression
regressor = LinearRegression()
regressor.fit(x_train, y_train)

x_pred = regressor.predict(x_test)

我在预测函数中得到错误。如您所见,与基本示例不同,误差中的维度非常大。

  Traceback (most recent call last):

  File "<ipython-input-2-5bac76b24742>", line 30, in <module>
    x_pred = regressor.predict(x_test)

  File "/Users/parthapratimneog/anaconda3/lib/python3.6/site-packages/sklearn/linear_model/base.py", line 256, in predict
    return self._decision_function(X)

  File "/Users/parthapratimneog/anaconda3/lib/python3.6/site-packages/sklearn/linear_model/base.py", line 241, in _decision_function
    dense_output=True) + self.intercept_

  File "/Users/parthapratimneog/anaconda3/lib/python3.6/site-packages/sklearn/utils/extmath.py", line 140, in safe_sparse_dot
    return np.dot(a, b)

ValueError: shapes (4801,2236) and (4033,) not aligned: 2236 (dim 1) != 4033 (dim 0)

【问题讨论】:

您需要x_trainx_test 中的相同功能集。如果您的训练数据中的因子具有更多级别,请在您的测试数据中明确表示它们,或者从x_train 中删除那些无法应用于您的测试集的因子。 @andrew_reece 是否有任何直接的方法可以从x_train 中删除额外的级别? 如果你在拆分为训练和测试之前进行哑化,你可以避免这个问题。但如果由于某种原因你不能这样做,x_train.drop(x_train.columns[~x_train.columns.isin(x_test.columns)], 1) 之类的东西应该可以工作。 我没有拆分数据,它们已经以不同的 CSV 格式出现。让我试试这段代码。 在这种情况下,只需使用与转换火车数据相同的对象并使用transform(x_test)。我假设您目前在测试数据上使用fit_transform(),但它fit()fit_transform() 只能用于训练数据,并且只能在测试数据上使用transform()。如果您共享用于编码 x_train 和 x_test 的代码,我可以添加一个答案来帮助您。 【参考方案1】:

您必须像转换 x_train 一样转换 x_test

x_test = onehotencoder.transform(x_test)
x_pred = regressor.predict(x_test)

确保使用与 x_train 上的 fit() 相同的 onehotencoder 对象。

我假设您当前正在对测试数据使用 fit_transform()。 执行fit()fit_transform() 会忘记之前学习的数据并重新拟合 oneHotEncoder。它现在会认为列中只有两个不同的值,因此会改变输出的形状。

【讨论】:

ValueError: unknown categorical feature present [462 61 462 ..., 61 61 462] during transform. 你是怎么处理这个问题的?这是在另一个数据集上,我认为现在测试集中有更多的分类数据。 @ParthapratimNeog 是的。就是这样。在这种情况下,您需要考虑在新的非种子数据包含您尚未了解的内容的现实世界中您将做什么。那你怎么处理它们?然后您是否放弃这些案例或再次对整个数据进行训练。 理想情况下,我想再次训练它们,但是训练数据中没有它们,那我该怎么做呢?我试着暂时忽略它们。对不起,我对此真的很陌生:) @ParthapratimNeog 您需要将它们包含在训练中,然后再次训练。现在,您可以删除那些存在此类数据的行。也只是在虚拟值的情况下,在整个数据集上使用 OneHotEncoder,然后将它们分成训练和测试。它不会损害性能或过度拟合。 @VivekKumar:在整个数据集上使用 OneHotEncoder 然后拆分为训练和测试时的问题是测试数据中存在新值(但这些值不在训练数据中)。还是把训练数据和测试数据分开转换比较好。

以上是关于如何在预测时从测试数据中处理onehotencoding后的类别不匹配?的主要内容,如果未能解决你的问题,请参考以下文章

OneHotEncoding 训练数据和测试数据之间的映射问题

测试数据特征与 OneHotEncoder 的训练数据特征不匹配

python如何预测下一年的数据

如何在 sklearn 中使用 OneHotEncoder 的输出?

考虑到我已经使用 OneHotEncoder 对数据进行了预处理,当我在 ANN 中添加输入层时,输入形状编号应该是多少?

如何在 pandas 系列列表中使用 OneHotEncoder?