Почему моя точность обучения KNeighborsRegressor снижается, а точность тестирования увеличивается?

Краткое описание проблемы

Я использую набор данных 1,88 миллиона лесных пожаров в США и использую KNeighborsRegressor от SciKit Learn для регрессии по «FIRE_SIZE». Я получаю следующий вывод и немного смущен тем, почему точность моего обучения снижается, а точность тестов увеличивается. Ищу здесь некоторое представление о том, что может происходить за кулисами.

Выходной фрагмент


Test RMSE:  7495.765269614677
Train Accuracy:  0.9995951877448755
Test Accuracy:  0.04561166544992734 

--x--

3-Nearest Neighbor(s) Results:

Test RMSE:  5798.419599886992
Train Accuracy:  0.5157901853607345
Test Accuracy:  0.4288996249038137 

--x--

5-Nearest Neighbor(s) Results:

Test RMSE:  4370.705370544834
Train Accuracy:  0.3818744943896586
Test Accuracy:  0.6755138015850977 

--x--

7-Nearest Neighbor(s) Results:

Test RMSE:  5234.077626536805
Train Accuracy:  0.32715455088444
Test Accuracy:  0.5346566791409124 

--x--

9-Nearest Neighbor(s) Results:

Test RMSE:  4833.210891971975
Train Accuracy:  0.2925369697746403
Test Accuracy:  0.603206401422826 

--x--

11-Nearest Neighbor(s) Results:

Test RMSE:  4662.668487875189
Train Accuracy:  0.27812301457721345
Test Accuracy:  0.6307145104081042 

--x--

13-Nearest Neighbor(s) Results:

Test RMSE:  4475.217632469529
Train Accuracy:  0.2623128334766227
Test Accuracy:  0.659810044524328 

--x--

Код, который выполняет регрессию

def k_nearest_neighbors(X, y, n):
  
  # Get training and testing splits.

  X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.01, random_state=42)

  # Initialize a LinearRegr model and return scores/results in a dictionary.
  classifier = KNeighborsRegressor(n_neighbors=n, n_jobs=-1)
  classifier.fit(X_train, y_train)

  y_pred = classifier.predict(X_test)
  mse_test = mean_squared_error(y_test, y_pred) # Mean-squared error, test
  
  test_predictions = classifier.predict(X_test) # prediction accuracy, test
  test_score = r2_score(y_test, test_predictions)
  
  train_predictions = classifier.predict(X_train) # prediction accuracy, train
  train_score = r2_score(y_train, train_predictions)

  return {'rmse': sqrt(mse_test), 'train': train_score, 'test': test_score}

Код, создающий фрагмент вывода

for i in range(1, 15, 2):
  print(f'{i}-Nearest Neighbor(s) Results:\n')
  
  X, y = get_prediction_df(conn, cols_with_log, 'FIRE_SIZE', 700000, geohash_precision=2)
  result = k_nearest_neighbors(X, y, i)

  print('Test RMSE: ', result['rmse'])
  print('Train Accuracy: ', result['train'])
  print('Test Accuracy: ', result['test'], '\n')
  print('--x--\n')

Я голосую за то, чтобы закрыть этот вопрос, потому что речь идет не о программировании, как это определено в справочном центре , а о теории и/или методологии машинного обучения — см. вступление и ПРИМЕЧАНИЕ в информации тега machine-learning.

desertnaut 15.12.2020 13:34
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
1 131
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Похоже, что ваша модель переоснащена — по мере того, как вы включаете в модель больше соседей, вы даете ей возможность изучить все более и более сложную функцию, но когда вы проверяете модель на своем тестовом наборе, она не работает. не так хорошо. Это связано с тем, что ваша модель начала изучать отношения, которых нет в данных, с которыми она не обучалась (и, вероятно, отношения, которых не существует). Судя по вашим результатам, кажется, что между версиями с 3 соседями и 5 соседями начинает происходить переоснащение. Возможно, попробуйте версию с 4 соседями и посмотрите, обеспечивает ли она наилучшую точность теста в целом?

=====

Редактировать: основываясь на разговоре в комментариях, мне интересно, происходит ли здесь что-то большее, чем просто переобучение. По совету по этому ответу

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

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

Когда происходит переобучение, не увеличивается ли точность обучения и снижается точность теста? Это означает, что модель теперь слишком многому учится на тренировочном наборе и работает очень хорошо, но не может обобщать на тестовом наборе?

sharathnatraj 15.12.2020 03:06

Вы поднимаете очень хорошие вопросы, спасибо за понимание! Вот результаты 4 соседей. 4-Nearest Neighbor(s) Results: Test RMSE: 4524.328935384681 Train Accuracy: 0.42028669564300813 Test Accuracy: 0.6523025460837525 Не могли бы вы объяснить, почему, если модель изучила отношения к переобучению, то есть отношения, которые не существуют, она так хорошо работает с новыми данными, то есть с точностью теста?

AbdulSohu 15.12.2020 03:09

оформить заказ - stats.stackexchange.com/questions/59630/…

sharathnatraj 15.12.2020 03:10

Выполните 10-кратную перекрестную проверку и снова проверьте свои результаты.

sharathnatraj 15.12.2020 03:13

@sharathnatraj не очень хорошо знаком с CV, так что бы вы порекомендовали? Должен ли я использовать ванильный cross_val_score из sklearn или что-то еще в той же библиотеке?

AbdulSohu 15.12.2020 03:19

Кроме того, вы делаете здесь 99% поезд и 1% тест? Рекомендуется разделение 90-10 или 80-20 и т.д. Есть ли конкретная причина делать 99:1?

sharathnatraj 15.12.2020 03:20

Хорошая мысль stackoverflow.com/users/13628883/sharathnatraj относительно обратного ожидаемого результата. Я обновлю свой ответ, чтобы включить нашу неопределенность в этот ответ.

Matthew Cox 15.12.2020 03:21

Я собрал свои мысли в виде нового ответа, в который я также включил ссылку для резюме - @AbdulSohu

sharathnatraj 15.12.2020 03:28

@sharathnatraj Я повторял модель по разным разбиениям тестовых поездов и получил результаты, которые показали снижение точности тестирования более чем на 1%, например: The train-test split: 99.0%-1.0% Test Accuracy: 0.10377409618872824 --x-- The train-test split: 97.0%-3.0% Test Accuracy: 0.07242578496681529 --x-- The train-test split: 95.0%-5.0% Test Accuracy: 0.06685114199694864 --x-- The train-test split: 93.0%-6.999999999999999% Test Accuracy: 0.06976801027832258 --x-- The train-test split: 91.0%-8.999999999999998% Test Accuracy: 0.05168511650970986

AbdulSohu 15.12.2020 03:30

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

sharathnatraj 15.12.2020 03:38

Взгляните на изображение ниже (взято из здесь):

Это общее представление компромисса смещения и дисперсии в машинном обучении. Нижняя из двух кривых представляет вашу ошибку обучения, а верхняя кривая представляет ошибку тестирования (или проверки).

Когда ваша модель имеет низкую сложность, например, небольшое количество предикторов, обе ошибки высоки, но по мере добавления данных они обе начинают уменьшаться, но до определенного момента. Ошибка обучения будет продолжать уменьшаться по мере усложнения модели и может продолжаться бесконечно. Проще говоря, когда вы добавляете в модель много данных, алгоритм теперь может еще лучше «запоминать» все обучающие данные и точно предсказывать их.

Но в то же время ошибка проверки начинает увеличиваться из-за переобучения — теперь ваша модель очень хорошо «запоминает» обучающие данные, но это ухудшает ее способность делать прогнозы на новых данных.

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

Ответ принят как подходящий

Это подробно обсуждается в теме ниже, https://stats.stackexchange.com/questions/59630/test-accuracy-higher-than-training-how-to-interpret

В вашем случае разделение на поезд-тест составляет 99: 1, что не рекомендуется, и это может быть одной из причин странных результатов. Перейдите на разделение 90-10 или 80-20 и используйте перекрестную проверку K-кратности (с K 10 или 20), а затем снова оцените свои результаты.

Выполнение перекрестной проверки хорошо объясняется здесь: https://towardsdatascience.com/building-a-k-nearest-neighbours-k-nn-model-with-scikit-learn-51209555453a

Я сделал перекрестную складку, где cv = 10, и еще одну, где cv = 6, и получил массив оценок с отрицательными значениями с плавающей запятой. Статья, на которую вы мне указали, показывает на самом деле лучшие (положительные) оценки прогноза для модели. Есть идеи, что вызывает мои отрицательные значения?

AbdulSohu 15.12.2020 08:52

Итак, вы пробовали CV = 10, для какого значения «K»? Каково было среднее значение массива для CV-10 для обучения и тестирования?

sharathnatraj 15.12.2020 09:04

Отрицательные значения для точности? @АбдулСоху

sharathnatraj 15.12.2020 10:12

Проблема ОП - это проблема регрессии, где, конечно, понятие точности бессмысленно; то, что здесь называют «точностью», на самом деле является показателем R^2.

desertnaut 15.12.2020 13:49

О, верно. Отрицательный R2 указывает на то, что подгонка модели довольно плохая. Пожалуйста, дважды проверьте подгонку модели @AbdulSohu

sharathnatraj 15.12.2020 16:31

@sharathnatraj Я полагаю, что единственный способ проверить соответствие модели - это вызвать model.predict(), и результаты этого находятся под вопросом. Я могу ошибаться здесь, и если да, дайте мне знать, как еще мы можем проверить соответствие модели ..?

AbdulSohu 15.12.2020 17:57

Я не имею в виду вызов model.predict(). Проверьте, есть ли у вас правильные черты, правильно ли выполнено масштабирование и т. д. и т. д., все девять ярдов. Похоже, вы напрямую подключаете входные данные без какой-либо предварительной обработки? Ознакомьтесь с шагами предварительной обработки ML, на которые уходит 80% тяжелой работы.

sharathnatraj 16.12.2020 00:32

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