KNN: n_neighbors больше обучающей выборки — как исправить
KNeighborsClassifier обучился без ошибки, но predict завершился сообщением, что n_neighbors превышает число обучающих объектов. Поиск соседей фактически происходит при прогнозе, поэтому успешный fit ещё не проверил допустимость запроса.
Считать объекты после разделения
Ограничение относится к числу объектов, которые получил конкретный estimator при fit. Размер исходного файла может быть больше, но после разбиения или внутри отдельного fold обучающих строк меньше. Поэтому k следует сравнивать с минимальным размером обучающей части среди планируемых запусков.
В примере KFold создаёт три разбиения для девяти объектов. В каждом обучении остаётся шесть строк. Из кандидатов 1, 3 и 7 допустимы только 1 и 3. Список разбиений сохраняем, затем используем для проверки и обучения: так вычисление предела соответствует фактическим индексам.
Отделить техническую допустимость от выбора модели
Фильтрация сетки решает техническую ошибку запуска. Она не выбирает лучший k по качеству. После удаления невозможных значений обычный процесс подбора может сравнить оставшиеся кандидаты. Не уменьшайте k молча внутри predict: тогда фактическая модель будет меняться в зависимости от случайного размера входного обучения.
Код действительно обучает KNN на каждом разбиении и получает прогноз на его проверочной части. Здесь важно, что все допустимые конфигурации выполняются. Результат прогноза не используется как доказательство качества.
from sklearn.model_selection import KFold
from sklearn.neighbors import KNeighborsClassifier
X = [[i] for i in range(9)]
y = [0, 0, 0, 0, 1, 1, 1, 1, 1]
splits = list(KFold(n_splits=3).split(X))
smallest_training = min(len(train) for train, _ in splits)
candidates = [1, 3, 7]
valid = [k for k in candidates if k <= smallest_training]
assert smallest_training == 6
assert valid == [1, 3]
completed = 0
for k in valid:
for train, test in splits:
model = KNeighborsClassifier(n_neighbors=k).fit(
[X[i] for i in train], [y[i] for i in train])
prediction = model.predict([X[i] for i in test])
assert len(prediction) == len(test)
completed += 1
assert completed == 6
print("allowed k:", valid, "completed fits:", completed)Что сделать в маленьком рабочем наборе
Если обучающих строк меньше ожидаемого, сначала проверьте фильтры и отбор данных. Возможно, ошибка в том, что в fit передан один сегмент вместо полного разрешённого набора. Если малый размер правильный, ограничьте k явно и сохраните фактический размер рядом с параметрами обучения.
Для очень маленького набора модель по соседям может быть нестабильной даже при допустимом k. Техническое исправление позволяет выполнить эксперимент; основание для использования прогноза появляется после проверки на подходящих данных. Не скрывайте исходное ограничение переключением на случайное большое значение n_neighbors.
Закрепить базовую операцию
Открытая практика fit и predict показывает две отдельные операции. Повторите их на небольшом наборе, затем добавьте проверку размера обучающей части перед выбором параметра KNN. Откройте урок «Первый fit и predict на своих данных». Затем вернитесь к сценарию статьи и проверьте его на своём небольшом наборе. Посмотрите программу курса первой ML-модели, чтобы пройти путь от обучения к использованию результата.
Продолжить на практике
- Машинное обучение с нуля на Python: первая модель ↗
Бесплатный курс машинного обучения на Python: обучите первую модель в scikit-learn, проверьте её качество и решите 106 задач в браузере.
