При инициализации SMOTE ожидаются n_neighbors <= n_samples, но n_samples <n_neighbors

Я уже предварительно очистил данные, и ниже показан формат верхних 4 строк:

     [IN] df.head()

    [OUT]   Year    cleaned
         0  1909    acquaint hous receiv follow letter clerk crown...
         1  1909    ask secretari state war whether issu statement...
         2  1909    i beg present petit sign upward motor car driv...
         3  1909    i desir ask secretari state war second lieuten...
         4  1909    ask secretari state war whether would introduc...

Я вызвал train_test_split() следующим образом:

     [IN] X_train, X_test, y_train, y_test = train_test_split(df['cleaned'], df['Year'], random_state=2)
   [Note*] `X_train` and `y_train` are now Pandas.core.series.Series of shape (1785,) and `X_test` and `y_test` are also Pandas.core.series.Series of shape (595,)

Затем я векторизовал данные обучения и тестирования X, используя следующие процедуры TfidfVectorizer и процедуры подгонки / преобразования:

     [IN] v = TfidfVectorizer(decode_error='replace', encoding='utf-8', stop_words='english', ngram_range=(1, 1), sublinear_tf=True)
          X_train = v.fit_transform(X_train)
          X_test = v.transform(X_test)

Сейчас я нахожусь на этапе, когда я обычно применяю классификатор и т. Д. (Если бы это был сбалансированный набор данных). Однако я инициализирую класс SMOTE() imblearn (для выполнения передискретизации)...

     [IN] smote_pipeline = make_pipeline_imb(SMOTE(), classifier(random_state=42))
          smote_model = smote_pipeline.fit(X_train, y_train)
          smote_prediction = smote_model.predict(X_test)

... но это приводит к:

     [OUT] ValueError: "Expected n_neighbors <= n_samples, but n_samples = 5, n_neighbors = 6.

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

-------------------------------------------------- -------------------------------------------------- --------------------------------

РЕДАКТИРОВАТЬ:

Полная трассировка

Набор данных / фрейм данных (df) содержит 2380 строк в двух столбцах, как показано на df.head() выше. X_train содержит 1785 из этих строк в формате списка строк (df['cleaned']) а также y_train также содержит 1785 строк в формате строк (df['Year']).

Поствекторизация с использованием TfidfVectorizer(): X_train а также X_test преобразованы из pandas.core.series.Series формы '(1785,)' и '(595,)' соответственно, чтобы scipy.sparse.csr.csr_matrix формы "(1785, 126459)" и "(595, 126459)" соответственно.

Что касается количества классов: использование Counter() Я подсчитал, что существует 199 классов (лет), каждый экземпляр класса привязан к одному элементу вышеупомянутого df['cleaned'] данные, которые содержат список строк, извлеченных из текстового корпуса.

Цель этого процесса состоит в том, чтобы автоматически определить / угадать год, десятилетие или столетие (подойдет любая степень классификации!) Входных текстовых данных на основе словарного запаса.

6 ответов

Решение

Поскольку в обучающем наборе приблизительно 200 классов и 1800 образцов, у вас в среднем 9 образцов на класс. Причиной появления сообщения об ошибке является то, что а) возможно, данные не идеально сбалансированы, и есть классы с менее чем 6 выборками и б) число соседей равно 6. Несколько решений для вашей проблемы:

  1. Рассчитайте минимальное количество выборок (n_samples) среди 199 классов и выберите n_neighbors параметр класса SMOTE меньше или равен n_samples.

  2. Исключить из передискретизации классов с n_samples ratio параметр SMOTE учебный класс.

  3. использование RandomOverSampler класс, который не имеет аналогичного ограничения.

  4. Объедините 3 и 4 решения: создайте конвейер, который использует SMOTE а также RandomOversampler таким образом, который удовлетворяет условию n_neighbors <= n_samples для сглаженных классов и использует случайную передискретизацию, когда условие не выполняется.

Попробуйте выполнить приведенный ниже код для SMOTE

oversampler=SMOTE(kind='regular',k_neighbors=2)

Это сработало для меня.

ПОЧЕМУ ЭТО ПРОИСХОДИТ:

В моем случае это произошло из-за того, что у меня было всего 1 выборок для некоторых значений / категорий. Поскольку SMOTE основан на концепции KNN, невозможно применить SMOTE к 1 выборочным значениям.

КАК Я ЭТО РЕШИЛ:

Поскольку эти 1 выборочные значения / категории были эквивалентны выбросам, я удалил их из набора данных, а затем применил SMOTE, и это сработало.

Также попробуйте уменьшить параметр, чтобы заставить его работать

      xr, yr = SMOTE(k_neighbors=3).fit_resample(x, y)

Это происходит, когда количество образцов в категории очень мало (меньше параметра).

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

Я смог решить эту проблему, следуя номеру 1 этого ответа.

      from collections import Counter

Count(df) # get the classes

# drop the classes with 1 as their value because it's lower than k_neighbors which has 2 as minimum value in my case

X_res, y_res = SMOTE(k_neighbors = 2).fit_resample(X, y)

Я думаю, что можно использовать код:

сэмплер = SMOTE(ratio={1: 1927, 0: 300},random_state=0)

Другие вопросы по тегам