Использование SMOTE со значениями NaN

Есть ли способ использовать SMOTE с NaNs?

Вот фиктивная прога, чтобы попробовать использовать SMOTE при наличии значений NaN

# Imports
from collections import Counter
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import Imputer
from imblearn.over_sampling import SMOTE
from imblearn.pipeline import make_pipeline
from imblearn.combine import SMOTEENN

# Load data
bc = load_breast_cancer()
X, y = bc.data, bc.target

# Initial number of samples per class
print('Number of samples for both classes: {} and {}.'.format(*Counter(y).values()))

# SMOTEd class distribution
print('Dataset has %s missing values.' % np.isnan(X).sum())
_, y_resampled = SMOTE().fit_sample(X, y)
print('Number of samples for both classes: {} and {}.'.format(*Counter(y_resampled).values()))

# Generate artificial missing values
X[X > 1.0] = np.nan
print('Dataset has %s missing values.' % np.isnan(X).sum())
#_, y_resampled = make_pipeline(Imputer(), SMOTE()).fit_sample(X, y)


sm = SMOTE(ratio = 'auto',k_neighbors = 5, n_jobs = -1)
smote_enn = SMOTEENN(smote = sm)

x_train_res, y_train_res = smote_enn.fit_sample(X, y)

print('Number of samples for both classes: {} and {}.'.format(*Counter(y_resampled).values()))

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

Number of samples for both classes: 212 and 357.
Dataset has 0 missing values.
Number of samples for both classes: 357 and 357.
Dataset has 6051 missing values.

ValueError: Input contains NaN, infinity or a value too large for dtype('float64').

2 ответа

Вы уже включили ответ. Заметить, что fit_resample используется вместо fit_sample, Вы должны использовать make_pipeline следующее:

# Imports
import numpy as np
from collections import Counter
from sklearn.datasets import load_breast_cancer
from sklearn.impute import SimpleImputer
from imblearn.over_sampling import SMOTE
from imblearn.pipeline import make_pipeline
from imblearn.combine import SMOTEENN

# Load data
bc = load_breast_cancer()
X, y = bc.data, bc.target
X[X > 1.0] = np.nan

# Over-sampling 
smote = SMOTE(ratio='auto',k_neighbors=5, n_jobs=-1)
smote_enn = make_pipeline(SimpleImputer(), SMOTEENN(smote=smote))
_, y_res = smote_enn.fit_resample(X, y)

# Class distribution
print('Number of samples for both classes: {} and {}.'.format(*Counter(y_res).values()))

Проверьте также свою несбалансированную версию обучения.

Как правило, нет, SMOTE готовит набор данных для дальнейшей подгонки модели.

Обычные модели (например, случайный лес и т. Д.) Не работают с NAв переменной label, потому что вы на самом деле предсказываете здесь? То же самое касается NAв переменных предиктора, где большинство алгоритмов либо не работают, либо просто игнорируют случаи с NA,

Таким образом, ошибка в значительной степени преднамеренная, поскольку у вас не может быть и не должно быть пропущенных значений в наборе обучающих данных для алгоритма, и логически вы не хотите "балансировать" случаи с пропущенными значениями, вам нужно только УДАЛИТЬ случаи с допустимыми метками.

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

Обновление 1:

Еще один способ - сначала пропустить пропущенные значения, чтобы у вас было три шага по подгонке вашей модели:

  1. Ввод пропущенных значений (используя MICE или аналогичный)
  2. SMOTE, чтобы сбалансировать тренировочный набор
  3. Подходящий алгоритм / модель
Другие вопросы по тегам