在python中是否有用于均方根误差(RMSE)的库函数?

我知道我可以实现这样一个均方根误差函数:

def rmse(predictions, targets):
return np.sqrt(((predictions - targets) ** 2).mean())

如果这个rmse函数是在某个库中实现的,可能是在scipy或scikit-learn中,我在寻找什么?

448883 次浏览

这个可能更快?:

n = len(predictions)
rmse = np.linalg.norm(predictions - targets) / np.sqrt(n)

Sklearn >= 0.22.0

sklearn.metrics有一个带有squared kwarg的mean_squared_error函数(默认为True)。将squared设置为False将返回RMSE。

from sklearn.metrics import mean_squared_error


rms = mean_squared_error(y_actual, y_predicted, squared=False)

sklearn & lt;0.22.0

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, RMD或RMS。它能解决什么问题?

如果你理解RMSE:(均方根误差),MSE:(均方误差)RMD(均方根偏差)和RMS:(均方根平方),那么要求一个库来为你计算这是不必要的过度工程。所有这些都可以直观地写在一行代码中。Rmse mse rmd和RMS是同一事物的不同名称。

RMSE回答:“平均而言,list1中的数字与list2中的数字有多相似?”两个列表的大小必须相同。洗掉任意两个给定元素之间的噪声,洗掉收集到的数据的大小,得到一个单一的数字结果”。

RMSE的直观和ELI5。它能解决什么问题?:

想象一下你正在学习在飞镖板上投掷飞镖。每天练习一小时。你想知道你是变好了还是变坏了。所以你每天投10次,然后测量靶心和你的飞镖击中的地方之间的距离。

你将这些数字list1列成一个列表。使用第一天的距离和包含全0的list2之间的均方根误差。在第2天和第n天做同样的事情。你得到的是一个随时间递减的数字。当你的RMSE为零时,你每次都能击中靶心。如果rmse值上升,情况就会变得更糟。

在python中计算均方根误差的例子:

import numpy as np
d = [0.000, 0.166, 0.333]   #ideal target distances, these can be all zeros.
p = [0.000, 0.254, 0.998]   #your performance goes here


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

数学符号:

均方根偏差解释 .

字形的传说: n是一个正整数,表示投掷的次数。i表示枚举sum的整个正整数计数器。d代表理想距离,在上面的例子中,list2包含所有的零。p代表性能,上面例子中的list1。上标2代表数字的平方。d <子> < /子>d的第i个索引。i0是p的第i个索引。

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         #absolute distance between 8 and 5 is +3
-20 - 10 = -30    #absolute distance between -20 and 10 is +30

如果你用任何一个数乘以它自己,结果总是正的,因为负数乘以负数是正的:

3*3     = 9   = positive
-30*-30 = 900 = positive

把它们都加起来,但是等一下,一个有很多元素的数组会比一个小数组有更大的误差,所以用它们的元素数量求平均值。

但是我们之前把它们都平方了,使它们都是正的。用平方根消除伤害。

这样就只剩下一个数字,它平均表示list1的每个值与其对应的list2的元素值之间的距离。

如果RMSE值随着时间的推移而下降,我们很高兴,因为方差正在减少。“缩小方差”;这是一种原始的机器学习算法。

RMSE不是最精确的直线拟合策略,总最小二乘是:

均方根误差测量点和线之间的垂直距离,所以如果你的数据形状像香蕉,底部平坦,顶部陡峭,那么RMSE将报告到高点的距离更大,但到低点的距离更短,而实际上距离是相等的。这就导致了一个倾斜,即该线更倾向于接近高的点而不是低的点。

如果这是一个问题,总最小二乘法解决这个问题: https://mubaris.com/posts/linear-regression < / p >

可以破坏RMSE函数的陷阱:

如果输入列表中有空值或无穷大,那么输出的rmse值是没有意义的。有三种策略可以处理任意一个列表中的空值/缺失值/无穷大:忽略该组件,将其归零或在所有时间步骤中添加最佳猜测或统一随机噪声。每种补救方法都有其优点和缺点,这取决于您的数据意味着什么。一般来说,忽略任何缺少值的组件是可取的,但这会使RMSE偏向于零,使您认为性能得到了改善,而实际上并没有。如果有很多缺失值,最好在最佳猜测上添加随机噪声。

为了保证RMSE输出的相对正确性,必须从输入中消除所有null /无穷大。

RMSE对不属于它的异常数据点具有零容忍

均方根误差平方依赖于所有数据都是正确的,并且都被视为相等。这意味着在左外野的一个偏离点将完全破坏整个计算。要处理异常值数据点并在某个阈值后消除它们的巨大影响,请参见鲁棒估计器,该估计器构建了一个阈值,将异常值排除为极端罕见事件,不需要其古怪的结果来改变我们的行为。

有一个库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

引用:

下面是一个示例代码,计算两种多边形文件格式PLY之间的RMSE。它同时使用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])

或者只使用NumPy函数:

def rmse(y, y_pred):
return np.sqrt(np.mean(np.square(y - y_pred)))

地点:

  • Y是我的目标
  • Y_pred是我的预测

注意,rmse(y, y_pred)==rmse(y_pred, y)由于平方函数。

  1. 不,有一个library Scikit Learn for machine learning,它可以通过使用Python语言轻松使用。它有一个函数的均方误差,我分享下面的链接:

https://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_squared_error.html

  1. 函数名为mean_squared_error,如下所示,其中y_true将是数据元组的真实类值,y_pred将是预测值,由您使用的机器学习算法预测:

< em > mean_squared_error (y_true y_pred) < / em >

    你必须修改它以获得RMSE(通过使用Python的sqrt函数)。这个过程在这个链接中描述: 李https://www.codeastar.com/regression-model-rmsd/ < / >

所以,最终代码是这样的:

从sklearn < p >。度量导入mean_squared_error 从数学导入根号

RMSD = sqrt(mean_squared_error(testing_y, prediction))

打印(RMSD)

在scikit-learn 0.22.0中,你可以将参数squared=False传递给mean_squared_error()来返回RMSE。

from sklearn.metrics import mean_squared_error
mean_squared_error(y_actual, y_predicted, squared=False)

sklearn的mean_squared_error本身包含一个参数squared,默认值为True。如果我们将其设置为False,相同的函数将返回RMSE而不是MSE。

from sklearn.metrics import mean_squared_error
rmse = mean_squared_error(y_true, y_pred , squared=False)
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中编写函数。更重要的是,如果你频繁调用它,你可以使用numba来加快它的速度。

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)

额外注意:在我的用例中,numbanp.sqrt(((y1-y2)**2).mean())上给出的结果略有不同,但可以忽略不计,其中没有numba,结果将等于scipy结果。你自己试试。

是的,它是由SKLearn提供的,我们只需要在参数中提到squared = False

from sklearn.metrics import mean_squared_error


mean_squared_error(y_true, y_pred, squared=False)