Почему предварительная обработка sklearn LabelEncoder inverse_transform применяется только из одного столбца?
У меня есть случайная модель леса, построенная из 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
часть, результаты странные: категориальные значения, соответствующие полю "адреса", возвращаются для всех категориальных полей.
Таким образом, если 1600 Пенсильвания-авеню кодируется как число 1, все категориальные значения, закодированные как номер 1 (независимо от поля), теперь возвращают 1600 Пенсильвания-авеню. Почему inverse_transform
выбирая один столбец, из которого можно обратить все fit_transform
коды?
1 ответ
Это ожидаемое поведение.
Когда вы звоните 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()
на соответствующем кодере.
Я знаю, что это старый вопрос, но для всех, кто любит удобство:
apply в сочетании с лямбда может легко преобразовывать несколько / все столбцы
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"])