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

时间:2017-03-30 20:47:43

标签: python python-3.x pandas scikit-learn random-forest

我有一个用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块,结果是奇数:对应于&#34;地址&#34;的分类值。 所有分类字段都会返回字段。

因此,如果将1600宾夕法尼亚大道编码为数字1,则所有分类值编码为数字1(无论字段)现在返回1600宾夕法尼亚大道。为什么inverse_transform选择一列来反转所有fit_transform代码?

2 个答案:

答案 0 :(得分:3)

这是预期的行为。

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

在上面的代码中,您使用相同的对象来转换所有列,并且您提供的最后一列是address。因此,le会忘记之前调用fit()(或在此情况下为fit_transform())的所有信息,并再次获知新数据。因此,当您在其上调用inverse_transform()时,它只会返回与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()

答案 1 :(得分:1)

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

应用,结合 lambda 可以轻松转换多个/所有列

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"])