Функция, которая возвращает предсказанные пропущенные значения с оценкой предсказания.

Если вы занимаетесь традиционным машинным обучением, вы, вероятно, сталкиваетесь с продолжающейся битвой с пропущенными значениями (NaN) в ваших данных.
Это имеет место практически в каждом соревновании Kaggle, а также в большинстве наборов табличных данных. там.

Здесь я рассмотрю некоторые жизнеспособные подходы. Затем я попытаюсь коснуться аспектов, которые я разработал и которые я вижу отличными от других.

Спойлер: в этой статье я подробно расскажу о проблеме, но если вам просто нужно однострочное решение:

$ pip install verstack

Общая практика

Большинство практикующих специалистов по данным захотят быстро избавиться от недостающих значений и начать подгонку моделей для получения результата.

Следовательно, быстрое решение состоит в том, чтобы просто заполнить NaN определенными константами для каждого типа столбца с отсутствующими значениями:

numeric — среднее/медиана столбца:

df[col].fillna(df[col].mean(), inplace = True)

двоичный/категориальный (независимо от типа данных в столбце)

  • самая распространенная категория:
most_common_category = df[col].value_counts().index[0]
df[col].fillna(most_common_category, inplace = True)
  • ввести новую категорию

Несмотря на простоту, этот подход жизнеспособен, поскольку отсутствующие данные могут появиться по определенной причине, и создание этой «причины» новой категории может привести к определенным знаниям

new_category = -999 # this can also be a string
df[col].fillna(new_category, inplace = True)

text — постоянная строка

df[col].fillna('Missing_data', inplace = True)

Несмотря на то, что все эти варианты жизнеспособны и широко используются, последствия этого подхода добавляют к вашим данным необъективность.

Один из самых сложных моментов для меня здесь — это невозможность измерить, правильный процесс наполнения или нет. Например, я подумал, если бы мне пришлось заполнять столбец1, столбец2.. столбец (n) отдельно для каждого и какой из них я получил бы более точные результаты. Я разработал для этого функцию. Для будущей работы я хочу превратить его в пакет Python.

Набор данных

У нас есть 4 непрерывные и 1 бинарная переменная в наборе данных. Нам нужно обработать нулевые значения перед запуском ML для нашей двоичной переменной. Мы можем попробовать методы, которые я упомянул выше. Но если мы не можем это измерить, мы не можем этим управлять. Итак, я расскажу вам о своем подходе.

Мой подход

Первым шагом в моем подходе является выбор объектов для заполнения. Затем я создаю отдельную модель LightGBM для каждого заполняемого столбца. Каждая модель воспринимает другие столбцы как поезд и воспринимает заполняемый столбец как цель. Причина, по которой я использую LighGBM, заключается в том, что он такой быстрый. Потому что может быть слишком много столбцов для заполнения, и этот процесс может занять слишком много времени в других алгоритмах.

hyper_params = {
    'boosting_type': 'gbdt',
    'objective': 'regression',
    'metric': 'l1',
    'learning_rate': 0.005, 
    "num_iterations": 800
}
lgbm_dict = dict()
colmns = ["feature_1","feature_2","feature_3","feature_4"]
for col in colmns:
    lgbm_dict['y'+ str(col)] = df[df[[col]].notna().any(axis=1)][col]
    lgbm_dict['df_test'+ str(col)] = df[df[[col]].isna().any(axis=1)]
    df_train = df[df[[col]].notna().any(axis=1)]
    df_train.drop([col], axis=1, inplace=True)
    lgbm_dict['df_test'+ str(col)].drop([col], axis=1, inplace=True)
    lgbm_dict['X_train'+ str(col)], X_test, lgbm_dict['y_train'+ str(col)], lgbm_dict['y_test'+ str(col)] = train_test_split(df_train, lgbm_dict['y'+ str(col)], test_size=0.25, random_state=42)
    lgbm_dict['gbm'+ str(col)]= lgb.LGBMRegressor(**hyper_params)
    lgbm_dict['gbm'+ str(col)].fit(lgbm_dict['X_train'+ str(col)], lgbm_dict['y_train'+ str(col)],
        eval_set=[(X_test, lgbm_dict['y_test'+ str(col)])],
        eval_metric='l1',
        early_stopping_rounds=60,verbose=100)

Затем я создал каждую часть информации, которая появляется здесь, и записал ее в словарь.

lgbm_dict["gbmfeature_1"]
Output: LGBMRegressor(learning_rate=0.005, metric='l1', num_iterations=800,
              objective='regression')

Оценка прогноза для каждого столбца

После этих операций я вычисляю баллы прогноза для каждого столбца.

colmns = ["feature_1","feature_2","feature_3","feature_4"]
for col in colmns:
    lgbm_dict['y_pred'+ str(col)] = lgbm_dict['gbm'+ str(col)].predict(lgbm_dict['X_train'+ str(col)], num_iteration=lgbm_dict['gbm'+ str(col)].best_iteration_)
    print('The R2 Score of prediction of',col + str(":"), round(r2_score(lgbm_dict['y_train'+ str(col)], lgbm_dict['y_pred'+ str(col)]) ** 0.5, 5))

Выход:

The R2 Score of prediction of feature_1: 0.9024
The R2 Score of prediction of feature_2: 0.65733
The R2 Score of prediction of feature_3: 0.52101
The R2 Score of prediction of feature_4: 0.9136

Как видите, мои оценки прогнозов для feature2 и feature3 низкие. Я мог бы рассмотреть возможность применения других операций к этим функциям. Например, я могу попробовать другой алгоритм или, если оценка все еще слишком низкая, я могу напрямую удалить пустые строки.

Визуализации

Давайте оценим наши процессы до этого этапа.
1- Мы восполнили недостающие значения с помощью LightGBM. Мы выбрали его, потому что он быстрый.
2- После этого мы оценили результат. Мы оценили дальнейшие исследования для столбцов с низкими прогностическими показателями.
3- И, наконец, мы можем визуализировать отсутствующие значения для каждого столбца, чтобы увидеть, как они распределялись до и после их заполнения. Вы можете увидеть 2 примера ниже.

Подведение итогов / Будущая работа?

Я думаю, что это исследование может внести свой вклад в экосистему машинного обучения с точки зрения измерения и оценки. Поэтому я планирую сделать функцию пакетом Python. Я также хочу добавить к нему несколько модулей.

Спасибо за чтение.

Автор:

Что вы думаете об отсутствующих значениях и их влиянии на машинное обучение? Свяжитесь со мной на моем LinkedIn или прокомментируйте здесь ниже, чтобы обсудить!