Как рассчитать тестовые данные с вмененными значениями обучающих данных с помощью GridSearchCV и sklearn Pipeline - PullRequest
0 голосов
/ 23 декабря 2018

Я пытаюсь улучшить свои заявки на участие в конкурсе цен на дома в Каггле здесь .Я работаю с доступными данными Айовы здесь .Я пытаюсь обучить и протестировать мою модель с использованием конвейера (sklearn.pipeline.Pipeline), перекрестной проверки с помощью GridSearchCV (sklearn.model_selection.GridSearchCV) и использования и использования XGBRegressor (xgboost.XGBRegressor).Выбранные объекты имели категориальные данные и значения NaN, которые должны были быть вменены (sklearn.impute.SimpleImputer (). Начальная настройка:

import pandas as pd
from xgboost import XGBRegressor
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.impute import SimpleImputer

# Path of the file to read.
iowa_file_path = '../input/train.csv'

original_home_data = pd.read_csv(iowa_file_path)

home_data = original_home_data.copy()

# delete rows where SalePrice is Nan
home_data.dropna(axis=0, subset=['SalePrice'], inplace=True)

# Create a target object and call it y
y = home_data.SalePrice

# Create X
features = ['LotArea', 'YearBuilt', '1stFlrSF', '2ndFlrSF', 'FullBath', 'BedroomAbvGr', 'TotRmsAbvGrd']
extra_features = ['OverallCond', 'GarageArea', 'LotFrontage', 'OverallQual', 'BsmtFinSF1', 'BsmtUnfSF', 'TotalBsmtSF', 'GrLivArea', 'MoSold']
categorical_data = ['LotShape', 'MSZoning', 'Neighborhood', 'BldgType', 'HouseStyle', 'Foundation', 'KitchenQual']

features.extend(extra_features)
features.extend(categorical_data)

X = home_data[features]

Категориальными данными были одно горячее кодирование:

X = pd.get_dummies(X, prefix='OHE', columns=categorical_data)

Столбцы с пропущенными значениями были собраны:

cols_with_missing = (col for col in X.columns if X[col].isnull().any())
for col in cols_with_missing:
    X[col + '_was_missing'] = X[col].isnull()

Затем данные обучения и проверки были разделены:

train_X, val_X, train_y, val_y = train_test_split(X, y, random_state=1, test_size=0.25)
train_X, val_X = train_X.align(val_X, join='left', axis=1)

Затем был создан конвейер для вычисления среднего для NaN срегрессор

    my_pipeline = Pipeline([('imputer', SimpleImputer()), ('xgbrg', XGBRegressor())])
param_grid = {
    'xgbrg__n_estimators': [10, 50, 100, 500, 1000], 
    'xgbrg__learning_rate': [0.01, 0.04, 0.05, 0.1, 0.5, 1]
}
fit_params = {
    'xgbrg__early_stopping_rounds': 10,
    'xgbrg__verbose': False,
    'xgbrg__eval_set': [(np.array(val_X), val_y)]
}

Затем я инициализировал перекрестный валидатор:

searchCV = GridSearchCV(my_pipeline, cv=5, param_grid=param_grid, return_train_score=True, scoring='neg_mean_absolute_error')

Затем я установил мой перекрестный валидатор:

searchCV = GridSearchCV(my_pipeline, cv=5, param_grid=param_grid, return_train_score=True, scoring='neg_mean_absolute_error')

и соответствовал модели (обратите внимание на следующую строку ):

searchCV.fit(X=np.array(train_X), y=train_y, **fit_params)

Затем я сделал то же самое для тестовых данных (одно горячее кодирование, получение столбцов с NaN,)

# path to file you will use for predictions
test_data_path = '../input/test.csv'

# read test data file using pandas
test_data = pd.read_csv(test_data_path)

# create test_X which comes from test_data but includes only the columns you used for prediction.
original_test_X = test_data[features]

test_X = original_test_X.copy()

# to one hot encode the data
test_X = pd.get_dummies(test_X, prefix='OHE', columns=categorical_data)

for col in cols_with_missing:
    test_X[col + '_was_missing'] = test_X[col].isnull()

# to align the training and test data and discard columns not in the training data
X, test_X = X.align(test_X, join='inner', axis=1)

Iзатем попытался преобразовать данные теста со средним значением из данных обучения для вменения значений NaN в данные теста:

test_X = my_pipeline.named_steps['imputer'].transform(test_X)

Затем я получил эту ошибку:

NotFittedError: This SimpleImputer instance is not fitted yet. Call 'fit' with appropriate arguments before using this method.

Так что яне могу даже использовать эту строку для прогноза:

test_preds = searchCV.predict(test_X)
  1. Что мможет быть, здесь не так?

  2. Как я могу использовать свой конвейер для преобразования другого набора данных после подгонки?

Если я пытаюсь создать новый SimpleImputer () экземпляр для тестовых данных и вменения для NaN и выполнения fit_transform:

test_pipeline = SimpleImputer()
test_X = test_pipeline.fit_transform(test_X)

, и я добавляю и запускаю:

test_preds = searchCV.predict(test_X)

Я получаю следующую ошибку:

ValueError: X has 72 features per sample, expected 74
Что здесь не так?

1 Ответ

0 голосов
/ 10 апреля 2019

У меня была та же ошибка "Этот экземпляр SimpleImputer еще не установлен" при уточнении моей модели на этапе "Пропавшие данные".После долгих проб и ошибок мне помогло следующее:

Подготовьте свои тестовые данные в том же цикле, где вы готовите тренировочные данные.По сути, цикл for col in cols_with_missing должен выполняться одновременно для обучения и проверки данных.Я также новичок в этой области (только что начал на прошлой неделе), но я предполагаю, что эта ошибка может возникать из-за несоответствия в столбцах, если вы запустите этот цикл col отдельно для обучения и тестирования данных.

мой фрагмент кода, который работал:

cols_with_missing = (col for col in X_train.columns 
                                 if X_train[col].isnull().any())
for col in cols_with_missing:
    imputed_X_train_plus[col + '_was_missing'] = imputed_X_train_plus[col].isnull()
    imputed_X_test_plus[col + '_was_missing'] = imputed_X_test_plus[col].isnull()
    imputed_final_test_plus[col + 'was_missing'] = imputed_final_test_plus[col].isnull()
...