Практическое руководство по Kickstarter.

В предыдущих статьях я обещал обсудить, как исправить недостающие значения!

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

Вступление

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

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

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

  • В доме с 1 спальней не будет ответа на вопрос, Насколько велика вторая спальня.
  • Владелец дома может не захотеть делиться своим заработком.

Библиотеки Python представляют отсутствующие числа как nan, что является сокращением от не числа. Однако наборы данных, содержащие значения nan, не согласуются с оценками Sklearn, которые предполагают, что все значения в массиве являются числовыми и что все они имеют и сохраняют значение, поэтому математические операции могут применяться к ним.

Основная стратегия использования наборов данных, содержащих пропущенные значения, состоит в том, чтобы отбросить целые строки и / или столбцы, состоящие из пропущенных значений. Однако это происходит за счет потери ценных данных, которые могут быть важными (даже если они неполные). Лучшая стратегия - заполнить недостающие значения - это оценить их из той части данных, которая не пропущена.

Вы можете выяснить, в каких ячейках отсутствуют значения и какой процент значений отсутствует в каждом столбце, с помощью команды:

def missingcheck(data):
 total = data.isnull().sum().sort_values(ascending=False)
 percent_1 = data.isnull().sum()/data.isnull().count()*100
 percent_2 = (np.round(percent_1, 1)).sort_values(ascending=False)
 missing_data = pd.concat([total, percent_2], axis=1, keys=[‘Total’, ‘%’])
 return missing_data

Весь этот код присутствует в репозитории Github MLin10Minutes!

Кроме того, разделите числовые атрибуты и категориальные атрибуты.

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

Функция оценки точности каждого подхода

Мы определяем функцию score_dataset () для сравнения различных подходов к работе с отсутствующими значениями. Эта функция сообщает среднюю абсолютную ошибку (MAE) для модели случайного леса.

from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error
# Function for comparing different approaches
def score_dataset(X_train, X_valid, y_train, y_valid):
 RFr = RandomForestRegressor(n_estimators=150, random_state=42)
 RFr.fit(X_train, y_train)
 preds = RFr.predict(X_valid)
 return mean_absolute_error(y_valid, preds)

1) Наивный подход: отбросьте столбцы с пропущенными значениями

Самый простой вариант - удалить столбцы с пропущенными значениями.

Если большинство значений в отброшенных столбцах не отсутствует, модель теряет доступ к большому количеству (возможно, полезной!) Информации при таком подходе. В качестве крайнего примера рассмотрим набор данных из 20 000 строк, в котором в одном важном столбце отсутствует только одна запись. Такой подход приведет к удалению всего столбца!

#get names of columns with missing values
cols_with_missing = [col for col in X_train.columns
 if X_train[col].isnull().any()]
# drop columns in training and validation data
reduced_X_train = X_train.drop(cols_with_missing, axis=1)
reduced_X_valid = X_valid.drop(cols_with_missing, axis=1)

2) Превосходная альтернатива: одномерное вменение

Вменение заменяет пропущенные значения некоторым числом. Например, мы можем ввести среднее значение в каждый столбец.

Вмененное значение в большинстве случаев не совсем правильное, но обычно приводит к лучшим моделям, чем если бы вы полностью удалили столбец.

Один из типов алгоритма вменения, приведенный в sklearn, является одномерным,

«который вменяет значения в i-м измерении объекта, используя только не пропущенные значения в этом измерении объекта» (например, impute.SimpleImputer).

SimpleImputer из пакета sklearn предоставляет базовые стратегии для вменения пропущенных значений. Пропущенные значения могут быть рассчитаны с помощью предоставленного постоянного значения или с помощью статистики (среднего, медианного или наиболее частого) каждого столбца, в котором находятся пропущенные значения.

Следующий фрагмент демонстрирует, как заменить отсутствующие значения:

from sklearn.impute import SimpleImputer
# imputation
simple_imputer = SimpleImputer()
imputed_X_train= pd.DataFrame(simple_imputer.fit_transform(X_train))
imputed_X_valid = pd.DataFrame(simple_imputer.transform(X_valid))
# imputation removed column names; put them back
imputed_X_train.columns = X_train.columns
imputed_X_valid.columns = X_valid.columns

Помните, я говорил вам, что наша стратегия для числового и категориального атрибута будет другой. Обратите внимание: если в столбце есть категориальные данные, такие как «высокий», «средний», «низкий», нельзя использовать среднее значение.

Класс SimpleImputer также поддерживает категориальные данные, представленные в виде строковых значений или категорий pandas при использовании стратегии ‘most_frequent’ или ‘constant’.

3) Другой вариант: многомерное вменение

Как определено в документации Sklearn, «многомерный импьютер, который оценивает каждую функцию по сравнению со всеми остальными. Стратегия для вменения отсутствующих значений путем моделирования каждой функции с пропущенными значениями как функции других функций в раунде. -робин мода. "

Этот более продвинутый подход реализован в классе IterativeImputer, который моделирует каждую функцию с пропущенными значениями в зависимости от других функций и использует эту оценку для вменения. Это происходит в итеративном циклическом режиме: на каждом шаге столбец функций обозначается как выходные y, а другие столбцы функций обрабатываются как входные X. Регрессор подходит для (X, y) для известного y. Затем регрессор используется для прогнозирования отсутствующих значений y. Это итеративно выполняется для каждой функции, а затем повторяется для раундов вменения max_iteration. Возвращаются результаты последнего раунда вменения.

Вот фрагмент кода:

br_imputer = IterativeImputer(BayesianRidge()) 
imputed_X_train = pd.DataFrame(br_imputer.fit_transform(X_train))
imputed_X_valid = pd.DataFrame(br_imputer.transform(X_valid))
# imputation removed column names; put them back
imputed_X_train.columns = X_train.columns
imputed_X_valid.columns = X_valid.columns

Некоторые из оценщиков, которые мы можем использовать в IterativeImputer:

В экосистеме R data science есть множество хорошо зарекомендовавших себя пакетов вменения: Amelia, mi, mice, missForest и т. Д.

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

В случае популярного метода missForest этим регрессором является случайный лес.

4) Вменение ближайших соседей

Алгоритм k ближайших соседей может использоваться для вменения отсутствующих данных путем нахождения k ближайших соседей для наблюдения с отсутствующими данными, а затем вменения их на основе непропущенных значений в соседи.

Для этого есть несколько возможных стратегий. Можно использовать 1NN, где мы ищем наиболее похожего соседа, а затем используем его значение для замены отсутствующих данных.

В качестве альтернативы мы можем использовать kNN с k соседями и вычислить среднее соседей или средневзвешенное, где расстояния до соседей используются как веса, поэтому чем ближе сосед, тем больший вес он имеет при вычислении среднего значения. Чаще всего используется метод взвешенного среднего.

Класс KNNimputer обеспечивает вменение для заполнения пропущенных значений с использованием подхода k-ближайших соседей. Он использует метрику евклидова расстояния, которая поддерживает пропущенные значения. Он известен как nan_euclidean_distance и используется для поиска ближайших соседей.

Примечание в соответствии с официальной документацией: « sklearn.neighbors.KNeighborsRegressor отличается от вменения KNN, которое учится на выборках с пропущенными значениями, используя метрику расстояния, которая учитывает пропущенные ценности, а не приписывать их. "

Вот фрагмент кода:

knn_imputer = KNNImputer(n_neighbors=2, weights=”uniform”)
imputed_X_train = pd.DataFrame(knn_imputer.fit_transform(X_train))
imputed_X_valid = pd.DataFrame(knn_imputer.transform(X_valid))
# imputation removed column names; put them back
imputed_X_train.columns = X_train.columns
imputed_X_valid.columns = X_valid.columns

5) За гранью вменения

Вменение - это общепринятый подход, и в целом он хорошо работает. Однако условно исчисленные значения могут располагаться ниже или выше их фактических значений (которые не были собраны в наборе данных). Или значения отсутствующих строк могут отличаться по-другому. В этом случае ваша модель будет работать лучше, если учесть, какие значения изначально отсутствовали.

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

imputed_X_train_plus = X_train.copy()
imputed_X_test_plus = X_valid.copy()
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()
#see what happend to the dataset
imputed_X_train_plus.head()
# And now we Imputation
my_imputer = SimpleImputer()
imputed_X_train_plus = my_imputer.fit_transform(imputed_X_train_plus)
imputed_X_test_plus = my_imputer.transform(imputed_X_test_plus)

В некоторых случаях это значительно улучшит результаты. В других случаях это совсем не помогает.

6) Значение не может быть пропущенным!

Чего ждать?

Да, вполне возможно, что то, что вы считаете недостающим значением, не может быть пропущенным значением. Это могло произойти из-за путаницы в кодировке NA (недоступно), или мы неправильно ее интерпретируем. Например:

PoolQC: в описании данных указано, что NA означает «Нет пула». Это имеет смысл, учитывая огромное соотношение пропущенных значений (+ 99%) и большинство домов вообще не имеют пула.

То же самое касается Забора и Разного элемента, так как в этих домах не может быть никаких ограждений или других элементов.

В чем же тогда загвоздка?

Специалисты в области науки о данных считают, что это зависит от критического «стиля» исследователя, как с этим справляться. «В целом» не существует правильного или неправильного, даже если кто-то хочет произвести резкую замену среднего / медианного / режима или удалить их. Ничего страшного.

Можно сравнить MAE, чтобы выбрать лучший результат. Могут быть выполнены множественные вменения, и каждый результат вариации должен быть проанализирован. Например, вне среднего значения, медианы или режима, что следует выбрать. Какую оценку следует использовать в итеративном импьютере, или даже в KNNimputer, каким должно быть значение k?

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

Все это зависит от набора данных и предметной области. Просто ваша интуиция поможет вам выбрать наиболее подходящий метод!

Если вам понравился этот пост, нажмите кнопку хлопка. Заинтересованы в следующих публикациях? Обязательно следите за этой серией MLin10Minutes.

Не стесняйтесь оставлять комментарии, чтобы задать вопросы! Вы также можете DM свои сомнения.

Подтверждение: