Использование 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:
Еще один способ - сначала пропустить пропущенные значения, чтобы у вас было три шага по подгонке вашей модели:
- Ввод пропущенных значений (используя MICE или аналогичный)
- SMOTE, чтобы сбалансировать тренировочный набор
- Подходящий алгоритм / модель