SMOTE in r значительно уменьшает размер выборки

У меня есть набор данных с около 130000 записей. Записи, разделенные на два класса целевых переменных, 0 и 1. 1 содержат только 0,09% от общей доли.

Я выполняю свой анализ в R-3.5.1 в Windows 10. Я использовал алгоритм SMOTE для работы с этим несбалансированным набором данных.

Я использовал следующий код для обработки несбалансированного набора данных

library(DMwR)
data_code$target=as.factor(data_code$target) #Converted to factor as 
# SMOTE works with factor data type
smoted_data <- SMOTE(target~., data_code, perc.over=100)

Но после выполнения кода я вижу, что счет для 0 равен 212, а 1 также равен 212, что значительно уменьшает размер моей выборки. Можете ли вы предложить мне, как мне обрабатывать этот несбалансированный набор данных с помощью SMOTE без изменения размера данных?


person Sonia    schedule 11.02.2019    source источник
comment
Пожалуйста, приведите пример кода, воспроизводящий вашу проблему, чтобы люди могли попробовать и предложить решение. См. stackoverflow.com/help/mcve.   -  person denis    schedule 11.02.2019
comment
Привет @denis, я уже дал код, который использую в своем посте. Что еще вы хотите?   -  person Sonia    schedule 11.02.2019
comment
То, что люди хотят, как подробно описано в ссылке, которую я дал, — это примеры данных. Если я скопирую и вставлю ваш код, я ничего не получу, потому что я не знаю data_code. Если я предлагаю решение, я не могу его проверить. Мне пришлось бы создать пример самому, но здесь предполагается, что это ваша часть работы. Создайте поддельный набор data_code, который воспроизводит проблему, и опубликуйте его в своем вопросе (избегайте внешней ссылки).   -  person denis    schedule 11.02.2019
comment
Извините, я не могу поделиться с вами data_code, так как он содержит данные клиента.   -  person Sonia    schedule 11.02.2019
comment
Опять же, я/мы не прошу вас делиться набором данных: создайте поддельный набор данных, который воспроизводит вашу проблему.   -  person denis    schedule 11.02.2019


Ответы (3)


Вам нужно немного поиграть с двумя параметрами, доступными из функции: perc.over и perc.under.

Согласно документу от SMOTE:

Параметры perc.over и perc.under управляют количеством избыточной выборки класса меньшинства и недостаточной выборки классов большинства соответственно.

So:

perc.over обычно будет числом выше 100. С этим типом значений для каждого наблюдения в исходном наборе данных, принадлежащем классу меньшинства, будет создано perc.over/100 новых примеров этого класса.

Я не вижу ваших данных, но если ваш класс меньшинства имеет 100 случаев и perc.over=100, алгоритм сгенерирует 100/100 = 1 новых случаев из этого класса.

Параметр perc.under управляет долей наблюдений мажоритарного класса, которые будут случайным образом выбраны для окончательного «сбалансированного» набора данных. Эта пропорция рассчитывается по отношению к количеству вновь созданных дел класса меньшинства.

Так, например, значение perc.under=100 будет выбирать из класса большинства исходных данных такое же количество наблюдений, которое было сгенерировано для класса меньшинства.

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

Я предлагаю использовать значения выше 100 для perc.over и даже более высокие значения для perc.under (по умолчанию 100 и 200).

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

Числовой пример:

set.seed(123)

data <- data.frame(var1 = sample(50),
                   var2 = sample(50),
                   out = as.factor(rbinom(50, 1, prob=0.1)))

table(data$out)
#  0  1 
# 43  7 # 50 rows total (original data)
smote_data <- DMwR::SMOTE(out ~ var1, data, perc.over = 200, perc.under = 400)
table(smote_data$out)
#  0  1 
# 56 21 # 77 rows total (smote data)
person RLave    schedule 11.02.2019
comment
очень красивое объяснение. Большое спасибо - person Sonia; 11.02.2019

Альтернативой пакету DMwR является пакет smotefamily, который не уменьшает размер выборки.

Вместо этого он создает дополнительные данные (= синтезированные данные) из класса меньшинства и добавляет их к исходным данным. Итак, вывод в аргументе $data готов к обучению. Чтобы настроить количество синтезируемых данных, вы можете изменить параметр dup_size. Однако значение по умолчанию dup_size = 0 уже оптимизирует вывод для достижения сбалансированных классов, поэтому его не нужно настраивать.

Это подробно объясняется в этом сообщении в блоге Ричарда Ричарда.

Пример кода (с функциями в первых двух столбцах):

smote1 <- smotefamily::SMOTE(features, target, K = 4, dup_size = 0)
formula1 <- "class ~ ." %>% as.formula
model.smote <- caret::train(formula1, method = "rpart", smote1$data)
predictions.smote <- predict(model.smote, smote1$data[,1:2]) %>% print
cv2 <- confusionMatrix(smote1$data$class %>% as.factor, predictions.smote)

Я нахожу smotefamily::SMOTE более удобным, потому что вам не нужно настраивать два параметра perc_over и perc_under, пока вы не получите приемлемый размер выборки, а DMwR::SMOTE часто генерирует значения NA.

person Agile Bean    schedule 01.11.2019