#python-3.x #machine-learning #scikit-learn
Вопрос:
Я хочу понять, почему sklearn.metrics.mean_squared_error()
возвращают отрицательное число? Я знаю, что это невозможно, но это то, что происходит на моей машине, на самом деле 2 машины. Я использую Python 3.6 и sklearn(0.0).
Код:
from sklearn.metrics import mean_squared_error
predictions = [96271]
test = [35241]
mse = mean_squared_error(test, predictions)
print('MSE: %.3f' % mse)
Ouput: MSE: -570306396.000
Вот скриншот отладчика, показывающий отрицательное значение:
введите описание изображения здесь
Комментарии:
1. Не удается воспроизвести; получение
MSE: 3724660900.000
, как указано @StupidWolf в их ответе ниже. Голосование закрыть как невоспроизводимое.
Ответ №1:
С новым кодом проблема, похоже, заключается просто в переполнении int
>>> from sklearn.metrics import mean_squared_error
>>> predictions = [96271]
>>> test = [35241]
>>> mean_squared_error(test, predictions)
-570306396.0
>>> np.float32(96271 - 35241)**2
3724660900
>>> np.int32(96271 - 35241)**2
-570306396
Естественный вопрос в том, когда он сломается, поскольку встроенный python int не будет переполняться
>>> (96271 - 35241)**2
3724660900
Таким образом, проблема возникает, когда scikit learn обертывает ваши данные в массив numpy в
y_type, y_true, y_pred, multioutput = _check_reg_targets(
y_true, y_pred, multioutput)
который определяет ваш тип данных как int32 и выводит np.массив(…, dtype=np.int32), который затем переполняется.
Обратите внимание, что просто убедитесь, что все выглядит как поплавки, тоже будет работать
>>> from sklearn.metrics import mean_squared_error
>>> predictions = [96271.] # Note the dot!
>>> test = [35241.]
>>> mean_squared_error(test, predictions)
3724660900
Комментарии:
1. Да, это сработало ! Спасибо. Будучи новичком в Python и ML, такое поведение удивительно, это где-то задокументировано или это просто то, как работает Python ?
2. Вот как работает арифметика с фиксированной точностью для целых чисел. Встроенное целое число Python имеет гибкий размер, поэтому не потерпит неудачу таким образом, но numpy-это, по сути, кусок кода c , который более … строг и его легко взломать. Вы можете прочитать больше о типах numpy и переполнениях здесь: numpy.org/doc/stable/user/…
Ответ №2:
Единственный способ, которым MSE может быть отрицательным, — это если вы указали sample_weights
(или multioutput
), что это отрицательно. например
mean_squared_error([0, 0], [1, 0], sample_weight=[-1, 1.2])
-5.000000000000001
поскольку то, что делает sklearn, — это сначала берет квадрат разностей, а затем взвешенное среднее с использованием
avg = sum(a * weights) / sum(weights)
что может быть отрицательным, если некоторый вес отрицателен, но сумма положительна.
Из первоисточника:
y_type, y_true, y_pred, multioutput = _check_reg_targets(
y_true, y_pred, multioutput)
check_consistent_length(y_true, y_pred, sample_weight)
output_errors = np.average((y_true - y_pred) ** 2, axis=0,
weights=sample_weight)
if not squared:
output_errors = np.sqrt(output_errors)
if isinstance(multioutput, str):
if multioutput == 'raw_values':
return output_errors
elif multioutput == 'uniform_average':
# pass None as weights to np.average: uniform mean
multioutput = None
return np.average(output_errors, weights=multioutput)
В частности, обратите внимание на
output_errors = np.average((y_true - y_pred) ** 2, axis=0,
weights=sample_weight)
строка, которая показывает, откуда может исходить отрицательный вывод.
Есть тема, обсуждающая сомнительный выбор авторов numpy для принятия отрицательных весов при усреднении https://github.com/numpy/numpy/issues/9825, но сейчас, в 2021 году, средний показатель все еще принимает эти веса и действует таким образом, что это может удивить людей.
Комментарии:
1. Спасибо за разъяснение, но я не предоставил sample_weights (или multioutput), просто пару списков положительных чисел. Потратил некоторое время, пытаясь понять это, но не смог, в настоящее время используя mean_absolute_error.
2. пожалуйста, приведите воспроизводимый пример, поскольку это действительно кажется невозможным из кода. Команда Scikit learn также выиграла бы от сообщения об ошибке, если это действительно происходит.
Ответ №3:
Я не могу воспроизвести вашу ошибку, я на Python 3.8.5, sklearn 0.24.1, numpy 1.20.1 Я получаю:
mse = mean_squared_error(test, predictions)
print('MSE: %.3f' % mse)
MSE: 3724660900.000
Глядя на цифры, я предполагаю, что при расчете они по умолчанию имеют значение np.int32, поэтому квадрат ваших значений превышает 2 147 483 647. Вы можете попробовать:
mean_squared_error(np.float64(test),np.float64(predictions))
Возможно, было бы неплохо проверить вашу версию numpy / scikit-learn
Комментарии:
1. Не может воспроизвести ни то, ни другое; голосование за закрытие как таковое.