我正在编写一个使用线性回归的应用程序。在我的例子中 sklearn.linear_model.Ridge
。我无法为 Ridge
带来我喜欢预测的正确形状的数据点。我简要描述我的两个应用程序以及问题是如何出现的:
第一个申请:
我的数据点每个只有 1 个特征,它们都是字符串,所以我使用 One-Hot-Encoding 以便能够将它们与 Ridge
一起使用。之后,数据点 (X_hotEncoded
) 每个都有 9 个特征:
import pandas as pd
X_hotEncoded = pd.get_dummies(X)
将 Ridge
拟合到 X_hotEncoded
和标签 y
之后,我将训练好的模型保存为:
from sklearn.externals import joblib
joblib.dump(ridge, "ridge.pkl")
第二次申请:
现在我已经在磁盘上保存了一个经过训练的模型,我想在我的第二个应用程序中检索它并预测一个数据点的 y
(标签)。这就是我遇到上述问题的地方:
# X = one datapoint I like to predict y for
ridge= joblib.load("ridge.pkl")
X_hotEncoded = pd.get_dummies(X)
ridge.predict(X_hotEncoded) # this should give me the prediction
最后一行代码出现以下错误:
ValueError:形状 (1,1) 和 (9,) 未对齐:1 (dim 1) != 9 (dim 0)
Ridge
由于使用了我在所有数据点上使用的 One-Hot-Encoding,因此使用 9 个特征进行了训练。现在,当我只想预测一个数据点(只有 1 个特征)时,我很难将这个数据点设置为正确的形状,以便 Ridge 能够处理它。 One-Hot-Encoding 对只有一个特征的一个数据点没有影响。
有人知道这个问题的巧妙解决方案吗?
一个可能的解决方案可能是在第一个应用程序中将列名写入磁盘并在第二个应用程序中检索它,然后在那里重建数据点。 one-hot-encoded 数组的列名可以像这里声明的那样被检索:Reversing 'one-hot' encoding in Pandas
最佳答案
这里发生的事情如下:
在训练阶段,您决定使用一种编码将单个分类特征转换为 9 个数字特征(One Hot)。你用这个编码训练了你的回归算法。因此,为了将其用于未知(测试)数据,您必须以与训练期间完全相同的方式转换此数据。
不幸的是,我认为您不能保存 pd.get_dummies
使用的编码并重新使用它。你应该使用 sklearn.preprocessing.OneHotEncoder()
反而。所以在训练期间:
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder()
X_hotEncoded = enc.fit_transform(X)
fit_transform()
首先将编码器拟合到您的训练数据,然后使用它来转换数据。与 pd.get_dummies()
的不同之处在于,您现在拥有一个编码器对象,您可以将其保存并在以后重用:
joblib.dump(enc, "encoder.pkl")
在测试期间,您可以像这样应用在训练期间使用的相同编码:
enc = joblib.load("encoder.pkl")
X_hotEncoded = enc.transform(X)
请注意,您不想再次适合编码器(这是 pd.get_dummies()
会做的)因为对训练和测试数据使用相同的编码是至关重要的.
注意:
如果测试数据包含训练数据中不存在的值,您将遇到问题(因为编码器不知道如何编码这些未知值)。为避免这种情况,您可以:
- 为
OneHotEncoder()
提供categories
参数,将所有类别的列表传递给它。 - 为
OneHotEncoder()
提供handle_unknown
参数设置为ignore
。这避免了错误,只是将所有列设置为零。 - 在将数据拆分为训练集和测试集之前执行一次热编码。
- 为
OneHotEncoder()
提供n_values
参数,告诉编码器每个输入特征需要多少个不同的类别[编辑:自版本 0.20 起已弃用]。
关于python - 在训练中使用 One-Hot-Encoding 后获得数据点的正确形状以使用回归模型进行预测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45012271/