При инициализации 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. Несколько решений для вашей проблемы:
Рассчитайте минимальное количество выборок (n_samples) среди 199 классов и выберите
n_neighbors
параметр класса SMOTE меньше или равен n_samples.Исключить из передискретизации классов с n_samples
ratio параметр SMOTE
учебный класс.использование
RandomOverSampler
класс, который не имеет аналогичного ограничения.Объедините 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)