#python #encoding #scikit-learn #one-hot-encoding #imputation
#python #кодирование #scikit-learn #one-hot-encoding #вменение
Вопрос:
Я очень внимательно следил за примером по этой ссылке: https://scikit-learn.org/stable/auto_examples/compose/plot_column_transformer_mixed_types.html но использовался другой набор данных (найден здесь:https://archive.ics.uci.edu/ml/datasets/Adult )
В отличие от примера dataset, мой dataset также содержит пару нулей в столбце y (он же ‘target’). Мне интересно, как бы я построил конвейер, подобный тому, что указан в документации sklearn, который преобразует столбцы в X и y, а не только в X. Это то, что я пробовал, но, конечно, это не работает, потому что функция ‘target’ была удалена из X, чтобы разрешить train_test_split:
import os
import pandas as pd
import numpy as np
os.listdir()
df_train = pd.read_csv('data_train.txt', header=None)
df_test = pd.read_csv('data_test.txt', header=None)
names = ['age', 'workclass', 'fnlwgt', 'education', 'education-num', 'marital-status',
'occupation', 'relationship', 'race', 'sex', 'capital-sign', 'capital-loss',
'hours-per-week', 'native-country', 'target']
df = pd.concat([df_train, df_test], axis=0)
df.head()
df.columns = names
Data Leakage Example - Preprocessing is done on the entire dataset
df_leakage = df.copy()
#Exploring nulls:
df_leakage[df_leakage.isnull().any(axis=1)]
There are only two nulls so it would be safe to discard them but for the purposes of this demo we will impute values
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder, OrdinalEncoder, LabelEncoder
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
#Defining numeric features and the transformations we will apply to them
numeric_features = ['capital-sign', 'capital-loss', 'hours-per-week', 'education-num']
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='mean')),
('scaler', StandardScaler())])
#Defining categorical features and the transformations we will apply to them
categorical_features = ['marital-status', 'occupation', 'relationship', 'race', 'sex', 'native-country']
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(handle_unknown='ignore'))])
#Defining categorical ordinal features and the transformations we will apply to them
#Note: we already have a education-continuous feature available but we will demo how to apply an ordinal transformation:
ordinal_features = ['education']
ordinal_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('ordinal', OrdinalEncoder())])
#Defining categorical ordinal features and the transformations we will apply to them
#Note: we already have a education-continuous feature available but we will demo how to apply an ordinal transformation:
ordinal_features = ['education']
label_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('label', LabelEncoder())])
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features),
('ord', ordinal_transformer, ordinal_features),
('lab', label_transformer, label_features),
])
# Append classifier to preprocessing pipeline.
# Now we have a full prediction pipeline.
clf = Pipeline(steps=[('preprocessor', preprocessor),
('classifier', LogisticRegression(solver='lbfgs'))])
X = df_leakage.drop('target', axis=1)
y = df_leakage['target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
clf.fit(X_train, y_train)
print("model score: %.3f" % clf.score(X_test, y_test))
Error log (partial):
658 columns = list(key)
659
--> 660 return [all_columns.index(col) for col in columns]
661
662 elif hasattr(key, 'dtype') and np.issubdtype(key.dtype, np.bool_):
ValueError: 'y' is not in list
Очевидно, я мог бы легко применить преобразование к y отдельно, прежде чем произойдет какое-либо из этих других преобразований. Я думаю, было бы неплохо обрабатывать ошибки символьных строк, например «.<=50K» против «<=50K». Но если я захочу приписать значение y его среднему значению, вменяемое значение будет зависеть от конкретного выбора y_train — таким образом, вызывая некоторую утечку данных.
Как бы я мог использовать библиотеку конвейера, чтобы сделать это эффективно?
Комментарии:
1. Мои 2 цента на это заключаются в том, что если у вас есть значения y, которые вам нужно вменить, тогда вам лучше отказаться от них из вашего обучающего набора, и все. Какой смысл обучать модель на основе вмененных значений? Скорее всего, в конечном итоге это только повредит вашей модели.
2. Это очень хороший момент! У меня есть только две строки с нулевым целевым значением var, поэтому я обязательно это сделаю. Просто из любопытства, что, если бы у меня было еще много нулей в y? Например, 50% набора данных. Что бы вы сделали в этой ситуации?
3. Я бы все равно отбросил недостающие данные. Если у вас действительно очень мало помеченных данных, то вы могли бы начать думать о обучении под присмотром, но это совершенно другой способ продолжения.
4. Рад, что это помогло! 🙂