Спасибо, что пришли на ТАК, чтобы задать свой вопрос!
Работа с несбалансированными данными (определяемыми, как правило, как данные, в которых число случаев для одного или нескольких классов очень отличается от других - асимметричное распределение какого-либо рода) является постоянной проблемой, которая побудило много онлайн писать. Мне нравится эта статья в качестве отправной точки. Я приведу примеры в Python, хотя аналогичные идеи применимы и в R
.
Для краткого изложения: Выборка важна по ряду причин, не в последнюю очередь из-за правильного разделения ваших данных для обучения и тестирования. Чтобы упростить задачу, вы можете либо изменить способ рисования примеров из набора данных (образца), чтобы у вас был примерно равный шанс получить каждый класс, либо вы можете попытаться смоделировать новые примеры класса с меньшим количеством случаев, чтобы снова достичь этого равного вероятность рисования класса, когда вы делаете свое расщепление.
Для ясности, скажем, есть два случая для переменной X
: X = 0
и X = 1
. И давайте назовем X = 1
случай, когда происходит какое-то событие, присутствует некоторая характеристика c, наблюдается некоторый отклик и т. Д. c. Мы назовем это «позитивным классом». Наконец, допустим, у вас есть 100 000 наблюдений, из которых только 1000 случаев X = 1
, остальные - X = 0
. Таким образом, ваш класс меньшинства является положительным классом, а ваш дисбаланс (положительный к отрицательному) составляет 1/100.
Если вы рисуете 50 000 случайных выборок и хотите, чтобы доля составляла примерно 50/50 положительного и отрицательного классов, вы можете сделать пару вещей.
- Пересмотреть класс меньшинства
Этот метод позволяет вам получить больше примеров из данных, где X = 1
. Чтобы достичь баланса 50/50, вам нужно (случайным образом) вытянуть из положительного класса больше, чтобы получить 25 000 примеров.
Чтобы сделать это с sci-kit learn
, вы можете сделать что-то вроде следующего.
Предполагая, что X
- это фрейм данных с вашими данными:
from sklearn.utils import resample
# make two dataframes, each with only one class
majority_df = X[X['outcome']==0]
minority_df = X[X['outcome']==1]
# Oversampling the minority
oversampled_minority_df = resample(minority_df,
replace=True,
n_samples=len(majority_df),
random_state=123)
Несколько комментариев:
Теперь, когда вы знаете о передискретизации класса меньшинства, это как раз наоборот. Вместо многократной выборки класса меньшинства до тех пор, пока у вас не будет того же числа примеров, что и у большинства, здесь вы берете столько образцов выборки, сколько у вас есть примеров класса меньшинства.
Вы можете изменить приведенный выше код следующим образом. Все еще предполагая, что X
ваши данные:
# Oversampling the minority
undersampled_majority_df = resample(majority_df,
replace=False,
n_samples=len(minority_df),
random_state=123)
Пара замечаний:
- Это все еще "повторная выборка", только берется меньше образцов
replace
теперь ложно, так как вы не хотите повторять данные, если вам не нужно (что вам пришлось делать для передискретизации) n_samples
теперь соответствует длине minority_df
так что имеется одинаковое количество примеров
Как классы избыточной, так и недостаточной выборки несут статистические проблемы, которые вы можете посмотреть в другом месте.
Другой вариант - синтезировать данные. Это, опять же, чтобы упростить статистический процесс, возмущает имеющиеся у вас данные таким образом, чтобы создавать «новые» примеры, которые выглядят аналогично вашим существующим данным, но вносят некоторый (полезный) шум в процесс.
Один популярный пакет для работы с несбалансированными данными и синтетического c создания данных - imblearn
. В этом пакете много отличной работы, но еще лучше то, насколько он похож на sklearn
и насколько хорошо они работают вместе.
imblearn
предоставляет популярный метод SMOTE или Syntheti c TEchnique с избыточной выборкой меньшинств и многие другие. В этом случае, однако, вместо прямой работы с вашими фреймами данных, imblearn
использует SMOTE как собственный процесс подгонки.
from imblearn.over_sampling import SMOTE
from sklearn.model_selection import train_test_split
y = base_df['outcome']
X = base_df.drop('outcome', axis=1)
# setting up testing and training sets
X_train, X_test, y_train, y_test = train_test_split(X,
y,
test_size=0.20,
random_state=123)
sm = SMOTE(random_state=123, ratio=1.0)
X_train, y_train = sm.fit_sample(X_train, y_train)
Вы заметите, что у объекта sm
есть метод fit_sample
, и что вы устанавливаете соотношение положительного / отрицательного (до ratio
) при его создании. Результатом являются кадры данных, которые сбалансированы и могут использоваться при подгонке модели.