Среднеквадратическая ошибка в питоне
Я знаю, что мог бы реализовать функцию среднеквадратичной ошибки следующим образом:
def rmse(predictions, targets):
return np.sqrt(((predictions - targets) ** 2).mean())
Что я ищу, если эта функция rmse реализована где-то в библиотеке, возможно, в scipy или scikit-learn?
16 ответов
sklearn.metrics
имеет mean_squared_error
функция. RMSE - это просто квадратный корень того, что он возвращает.
from sklearn.metrics import mean_squared_error
from math import sqrt
rms = sqrt(mean_squared_error(y_actual, y_predicted))
Что такое RMSE? Также известный как MSE или RMS. Какую проблему это решает?
Если вы понимаете RMSE: (среднеквадратическая ошибка), MSE: (среднеквадратичная ошибка) и RMS: (среднеквадратическое значение), то запрос библиотеки для ее расчета для вас является излишней чрезмерной инженерией. Все эти метрики представляют собой одну строку кода Python длиной не более 2 дюймов. Три метрики rmse, mse и rms являются концептуально идентичными.
RMSE отвечает на вопрос: "Насколько в среднем похожи числа в списке от 1 до 2?". Два списка должны быть одинакового размера. Я хочу "стереть шум между любыми двумя заданными элементами, вымыть размер собранных данных и почувствовать изменение единого числа во времени".
Интуиция и ELI5 для RMSE:
Представьте, что вы учитесь бросать дротики в дартс. Каждый день вы тренируетесь в течение одного часа. Вы хотите выяснить, становится ли вам лучше или хуже. Поэтому каждый день вы делаете 10 бросков и измеряете расстояние между яблочком и местом удара дротика.
Вы делаете список этих чисел. Используйте среднеквадратичную ошибку между расстояниями в день 1 и списком, содержащим все нули. Сделайте то же самое на 2-й и 9-й день. То, что вы получите, это одно число, которое, мы надеемся, со временем уменьшается. Когда ваш RMSE номер равен нулю, вы каждый раз ударяете по буллисам. Если число увеличивается, вам становится хуже.
Пример расчета среднеквадратичной ошибки в Python:
import numpy as np
d = [0.000, 0.166, 0.333]
p = [0.000, 0.254, 0.998]
print("d is: " + str(["%.8f" % elem for elem in d]))
print("p is: " + str(["%.8f" % elem for elem in p]))
def rmse(predictions, targets):
return np.sqrt(((predictions - targets) ** 2).mean())
rmse_val = rmse(np.array(d), np.array(p))
print("rms error is: " + str(rmse_val))
Какие отпечатки:
d is: ['0.00000000', '0.16600000', '0.33300000']
p is: ['0.00000000', '0.25400000', '0.99800000']
rms error between lists d and p is: 0.387284994115
Математическая запись:
Rmse выполняется небольшими шагами, чтобы его можно было понять:
def rmse(predictions, targets):
differences = predictions - targets #the DIFFERENCEs.
differences_squared = differences ** 2 #the SQUAREs of ^
mean_of_differences_squared = differences_squared.mean() #the MEAN of ^
rmse_val = np.sqrt(mean_of_differences_squared) #ROOT of ^
return rmse_val #get the ^
Как работает каждый шаг RMSE:
Вычитание одного числа из другого дает вам расстояние между ними.
8 - 5 = 3 #distance between 8 and 5 is 3
-20 - 10 = -30 #distance between -20 and 10 is +30
Если вы умножаете любое число раз на себя, результат всегда будет положительным, потому что отрицательное время отрицательным будет положительным:
3*3 = 9 = positive
-30*-30 = 900 = positive
Добавьте их все, но подождите, тогда массив с множеством элементов будет иметь большую ошибку, чем маленький массив, поэтому усредните их по количеству элементов.
Но подождите, мы поставили их в квадрат раньше, чтобы заставить их позитивно настроиться. Отмените урон квадратным корнем!
Это оставляет вас с одним числом, которое представляет в среднем расстояние между каждым значением list1 и соответствующим значением элемента list2.
Если значение RMSE уменьшается со временем, мы счастливы, потому что дисперсия уменьшается.
RMSE - не самая точная стратегия подгонки линии, общее количество наименьших квадратов:
Среднеквадратическая ошибка измеряет вертикальное расстояние между точкой и линией, поэтому, если ваши данные имеют форму банана, плоского у дна и крутого у вершины, то среднеквадратическое отклонение будет сообщать о больших расстояниях до высоких точек, но о небольших расстояниях до указывает низко, когда на самом деле расстояния эквивалентны. Это вызывает перекос, когда линия предпочитает быть ближе к точкам выше, чем ниже.
Если это проблема, метод общих наименьших квадратов исправляет это: https://mubaris.com/2017-09-28/linear-regression-from-scratch
Поправка, которая может нарушить эту функцию RMSE:
Если в любом из входных списков есть нули или бесконечность, то выходное значение rmse не будет иметь смысла. Есть три стратегии, чтобы иметь дело с нулями / отсутствующими значениями / бесконечностями в любом списке: игнорировать этот компонент, обнулять его или добавлять наилучшее предположение или равномерный случайный шум для всех временных шагов. Каждое лекарство имеет свои плюсы и минусы в зависимости от того, что означают ваши данные. В общем, предпочтительным является игнорирование любого компонента с отсутствующим значением, но это смещает RMSE к нулю, заставляя вас думать, что производительность улучшилась, хотя на самом деле это не так. Добавление случайного шума по наилучшему предположению может быть предпочтительным, если имеется много пропущенных значений.
Чтобы гарантировать относительную правильность выходных данных RMSE, вы должны исключить все нули / бесконечности из входных данных.
RMSE имеет нулевой допуск для посторонних точек данных, которые не принадлежат
Среднеквадратичные квадраты ошибок основаны на правильности всех данных, и все они считаются равными. Это означает, что одна случайная точка в левом поле полностью испортит весь расчет. Чтобы обработать точки данных выбросов и отклонить их огромное влияние после определенного порога, см. Надежные оценки, которые строят порог для отклонения выбросов.
В scikit-learn 0.22.0 вы можете пройти mean_squared_error()
Аргумент squared=False
вернуть RMSE.
from sklearn.metrics import mean_squared_error
mean_squared_error(y_actual, y_predicted, squared=False)
Это наверное быстрее?
n = len(predictions)
rmse = np.linalg.norm(predictions - targets) / np.sqrt(n)
Вы не можете найти функцию RMSE непосредственно в SKLearn. Но вместо выполнения sqrt вручную есть другой стандартный способ использования sklearn. По-видимому, само значение mean_squared_error в Sklearn содержит параметр, называемый "в квадрате" со значением по умолчанию как true. Если мы установим его в false, та же функция вернет RMSE вместо MSE.
# code changes implemented by Esha Prakash
from sklearn.metrics import mean_squared_error
rmse = mean_squared_error(y_true, y_pred , squared=False)
Или просто используя только функции NumPy:
def rmse(y, y_pred):
return np.sqrt(np.mean(np.square(y - y_pred)))
Куда:
- у моя цель
- y_pred - мой прогноз
Обратите внимание, что rmse(y, y_pred)==rmse(y_pred, y)
из-за функции квадрата.
На всякий случай, если кто-то найдет эту ветку в 2019 году, есть библиотека под названием ml_metrics
который доступен без предварительной установки в ядрах Kaggle, довольно легкий и доступен через pypi
(это может быть установлено легко и быстро с pip install ml_metrics
):
from ml_metrics import rmse
rmse(actual=[0, 1, 2], predicted=[1, 10, 5])
# 5.507570547286102
У него есть несколько других интересных метрик, которые недоступны в sklearn
, лайк mapk
,
Рекомендации:
Да, это предоставляется SKLearn, нам просто нужно упомянуть
squared = False
в аргументах
from sklearn.metrics import mean_squared_error
mean_squared_error(y_true, y_pred, squared=False)
На самом деле, я написал кучу из них в качестве служебных функций для statsmodels
http://statsmodels.sourceforge.net/devel/tools.html
и http://statsmodels.sourceforge.net/devel/generated/statsmodels.tools.eval_measures.rmse.html
В основном один или два лайнера и не очень много проверок ввода, и в основном они предназначены для простого получения некоторой статистики при сравнении массивов. Но у них есть модульные тесты для аргументов оси, потому что именно здесь я иногда делаю небрежные ошибки.
from sklearn import metrics
import numpy as np
print(np.sqrt(metrics.mean_squared_error(y_test,y_predict)))
from sklearn.metrics import mean_squared_error
rmse = mean_squared_error(y_actual, y_predicted, squared=False)
or
import math
from sklearn.metrics import mean_squared_error
rmse = math.sqrt(mean_squared_error(y_actual, y_predicted))
Возможно, вы захотите добавить абсолютное значение
np.abs
если вы имеете дело с комплексными числами.
import numpy as np
rms = np.sqrt(np.mean(np.abs(x-y)**2))
Обратите внимание, что если вы используете
np.linalg.norm
он уже заботится о комплексных числах.
import numpy as np
rms = np.linalg.norm(x-y)/np.sqrt(len(x))
Ориентир
Для конкретного случая использования, когда вам не нужен обработчик служебных данных и всегда ожидается ввод массива numpy, самый быстрый способ - вручную написать функцию в
numpy
. Более того, вы можете использовать его для ускорения, если вы часто его вызываете.
import numpy as np
from numba import jit
from sklearn.metrics import mean_squared_error
%%timeit
mean_squared_error(y[i],y[j], squared=False)
445 µs ± 90.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
def euclidian_distance(y1, y2):
"""
RMS Euclidean method
"""
return np.sqrt(((y1-y2)**2).mean())
%%timeit
euclidian_distance(y[i],y[j])
28.8 µs ± 2.54 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
@jit(nopython=True)
def jit_euclidian_distance(y1, y2):
"""
RMS Euclidean method
"""
return np.sqrt(((y1-y2)**2).mean())
%%timeit
jit_euclidian_distance(y[i],y[j])
2.1 µs ± 234 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
@jit(nopython=True)
def jit2_euclidian_distance(y1, y2):
"""
RMS Euclidean method
"""
return np.linalg.norm(y1-y2)/np.sqrt(y1.shape[0])
%%timeit
jit2_euclidian_distance(y[i],y[j])
2.67 µs ± 60.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Дополнительное примечание: в моем случае дайте немного другой, но незначительный результат на
np.sqrt(((y1-y2)**2).mean())
, где без
numba
, результат будет равен
scipy
результат. Попробуй сам.
Вот пример кода, который вычисляет RMSE между двумя форматами файлов полигонов PLY
, Он использует как ml_metrics
либ и np.linalg.norm
:
import sys
import SimpleITK as sitk
from pyntcloud import PyntCloud as pc
import numpy as np
from ml_metrics import rmse
if len(sys.argv) < 3 or sys.argv[1] == "-h" or sys.argv[1] == "--help":
print("Usage: compute-rmse.py <input1.ply> <input2.ply>")
sys.exit(1)
def verify_rmse(a, b):
n = len(a)
return np.linalg.norm(np.array(b) - np.array(a)) / np.sqrt(n)
def compare(a, b):
m = pc.from_file(a).points
n = pc.from_file(b).points
m = [ tuple(m.x), tuple(m.y), tuple(m.z) ]; m = m[0]
n = [ tuple(n.x), tuple(n.y), tuple(n.z) ]; n = n[0]
v1, v2 = verify_rmse(m, n), rmse(m,n)
print(v1, v2)
compare(sys.argv[1], sys.argv[2])
from sklearn import metrics
import bumpy as np
print(no.sqrt(metrics.mean_squared_error(actual,predicted)))
- Нет, для машинного обучения существует библиотека Scikit Learn, и ее можно легко использовать с помощью языка Python. Он имеет функцию для среднеквадратичной ошибки, которой я делюсь ссылкой ниже:
https://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_squared_error.html
- Функция называется mean_squared_error, как указано ниже, где y_true будет реальными значениями класса для кортежей данных, а y_pred - предсказанными значениями, предсказанными алгоритмом машинного обучения, который вы используете:
mean_squared_error (y_true, y_pred)
- Вы должны изменить его, чтобы получить RMSE (используя функцию sqrt с использованием Python). Этот процесс описан по этой ссылке: https://www.codeastar.com/regression-model-rmsd/
Итак, окончательный код будет примерно таким:
из sklearn.metrics импортировать mean_squared_error из математического импорта sqrt
RMSD = sqrt(mean_squared_error(test_y, прогноз))
печать (RMSD)