为什么 sklearn 预处理 LabelEncoder inverse_transform 只适用于一列?

Why does sklearn preprocessing LabelEncoder inverse_transform apply from only one column?

我有一个用 sklearn 构建的随机森林模型。该模型构建在一个文件中,我有第二个文件,我在其中使用 joblib 加载模型并将其应用于新数据。数据具有通过 sklearn 的预处理 LabelEncoder.fit_transform 转换的分类字段。做出预测后,我将尝试使用 LabelEncoder.inverse_transform 反转此转换。

代码如下:

 #transform the categorical rf inputs
 df["method"] = le.fit_transform(df["method"])
 df["vendor"] = le.fit_transform(df["vendor"])
 df["type"] = le.fit_transform(df["type"])
 df["name"] = le.fit_transform(df["name"])
 dups["address"] = le.fit_transform(df["address"])

 #designate inputs for rf model
 inputs = ["amt","vendor","type","name","address","method"]

 #load rf model and run it on new data
 from sklearn.externals import joblib
 rf = joblib.load('rf.pkl')
 predict = rf.predict(df[inputs])

 #reverse LabelEncoder fit_transform
 df["method"] = le.inverse_transform(df["method"])
 df["vendor"] = le.inverse_transform(df["vendor"])
 df["type"] = le.inverse_transform(df["type"])
 df["name"] = le.inverse_transform(df["name"])
 df["address"] = le.inverse_transform(df["address"])

 #convert target to numeric to make it play nice with SQL Server
 predict = pd.to_numeric(predict)

 #add target field to df
 df["prediction"] = predict

 #write results to SQL Server table
 import sqlalchemy
 engine = sqlalchemy.create_engine("mssql+pyodbc://<username>:<password>@UserDSN")
 df.to_sql('TABLE_NAME', engine, schema='SCHEMANAME', if_exists='replace', index=False)

没有 inverse_transform 部分,结果如预期:用数字代码代替分类值。对于 inverse_transform 部分,结果很奇怪:对应于 "address" 字段的分类值被 returned 用于 all 分类字段。

因此,如果 1600 Pennsylvania Avenue 编码为数字 1,则 所有 分类值编码为数字 1(无论字段如何)现在 return 1600 Pennsylvania Avenue。为什么 inverse_transform 选择一列来反转所有 fit_transform 代码?

这是预期的行为。

当你调用le.fit_transform()时,LabelEncoder的内部参数(类学习)被重新初始化。 le 对象适合您提供的列的值。

在上面的代码中,您使用同一个对象来转换所有列,您提供的最后一列是 address。因此,le 会忘记之前调用 fit()(或在本例中为 fit_transform())的所有信息,并再次学习新数据。因此,当您对其调用 inverse_transform() 时,它只会 returns 与 address 相关的值。希望我说清楚了。

要对所有列进行编码,您需要初始化不同的对象,每列一个。如下所示:

 df["method"] = le_method.fit_transform(df["method"])
 df["vendor"] = le_vendor.fit_transform(df["vendor"])
 df["type"] = le_type.fit_transform(df["type"])
 df["name"] = le_name.fit_transform(df["name"])
 df["address"] = le_address.fit_transform(df["address"])

然后在适当的编码器上调用 inverse_transform()

我知道这是一个老问题,但是对于每个喜欢方便的人来说:

apply,结合 lambda can 轻松转换 multiple/all 列

df = df.apply(lambda col: le.fit_transform(col))

我鄙视非别名、非动态代码(你也应该如此),除非真的有必要:

 df["method"] = le_method.fit_transform(df["method"])
 df["vendor"] = le_vendor.fit_transform(df["vendor"])
 df["type"] = le_type.fit_transform(df["type"])
 df["name"] = le_name.fit_transform(df["name"])
 df["address"] = le_address.fit_transform(df["address"])