Почему предварительная обработка 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"])
Другие вопросы по тегам