Использование конвейера для предотвращения утечки данных как для X, так и для Y - PullRequest
0 голосов
/ 14 марта 2019

Я очень внимательно следовал примеру по этой ссылке: https://scikit -learn.org / stable / auto_examples / compose / plot_column_transformer_mixed_types.html , но использовал другой набор данных (находится здесь: https://archive.ics.uci.edu/ml/datasets/Adult)

В отличие от примера набора данных, мой набор данных также содержит пару нулей в столбце y (он же «цель»). Мне интересно, как бы я построил конвейер, аналогичный тому, который описан в документации по 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" vs "<= 50K". Но если яЕсли вы хотите вменять значение y в его среднее значение, вмененное значение будет зависеть от конкретного выбора y_train, что приведет к некоторой утечке данныхвозраст.</p>

Как бы я мог использовать библиотеку конвейеров, чтобы сделать это эффективно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...