python 中是否有均方根误差(RMSE)的库函数?
- 2025-04-15 09:20:00
- admin 原创
- 39
问题描述:
我知道我可以实现这样的均方根误差函数:
def rmse(predictions, targets):
return np.sqrt(((predictions - targets) ** 2).mean())
如果这个 rmse 函数在某个库中实现,比如在 scipy 或 scikit-learn 中,我正在寻找什么?
解决方案 1:
sklearn >= 1.4
sklearn.metrics.root_mean_squared_error
from sklearn.metrics import root_mean_squared_error
rms = root_mean_squared_error(y_actual, y_predicted)
sklearn >= 0.22.0 且 < 1.4
sklearn.metrics
有一个mean_squared_error
带有squared
kwarg 的函数(默认为True
)。设置squared
为False
将返回 RMSE。
from sklearn.metrics import mean_squared_error
rms = mean_squared_error(y_actual, y_predicted, squared=False)
解决方案 2:
什么是 RMSE?也称为 MSE、RMD 或 RMS。它能解决什么问题?
如果您了解 RMSE(均方根误差)、MSE(均方误差)、RMD(均方根偏差)和 RMS(均方根),那么要求一个库帮您计算这些参数就完全是多余的。所有这些参数都可以直观地用一行代码写出来。rmse、mse、rmd 和 rms 是同一个概念的不同名称。
RMSE 回答的是:“平均而言, 中的数字与 的相似度如何list1
?list2
”。两个列表的大小必须相同。消除任意两个给定元素之间的噪声,消除所收集数据的大小,最终得到一个单一的数字结果。
直觉和 ELI5 的 RMSE。它解决了什么问题?
想象一下,你正在学习向镖靶投掷飞镖。你每天练习一小时。你想看看自己的水平是提高了还是降低了。所以你每天投掷10次,并测量靶心和飞镖命中点之间的距离。
你把这些数字列成一个列表list1
。用第一天的距离和包含所有零的距离之间的均方根误差来计算list2
。第二天和第 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
表示一个枚举总和的正整数计数器。 d
代表理想距离,list2
即上例中全包含零的。 p
代表性能,即list1
上例中的。 上标 2 代表数字平方。 d i是的第 i 个索引d
。 p i是的第 i 个索引p
。
均方根误差以小步骤完成,以便于理解:
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
可能破坏此 RMSE 函数的陷阱:
如果任一输入列表中存在空值或无穷大,则输出均方根误差 (RMSE) 值将毫无意义。处理任一列表中的空值/缺失值/无穷大有三种策略:忽略该分量、将其清零,或向所有时间步添加最佳猜测或均匀随机噪声。每种补救措施都有其优缺点,具体取决于您的数据含义。通常,忽略任何含有缺失值的分量是首选,但这会使 RMSE 偏向于零,使您认为性能有所提升,而实际上并没有。如果存在大量缺失值,则在最佳猜测上添加随机噪声可能是首选。
为了保证 RMSE 输出的相对正确性,您必须从输入中消除所有零值/无穷大。
RMSE 对不属于的异常数据点具有零容忍度
均方根误差平方依赖于所有数据都正确且均视为相等。这意味着,一个偏离正负值的点就会彻底毁掉整个计算。为了处理异常数据点并在达到一定阈值后消除其巨大影响,请参阅稳健估计器,它内置了一个阈值,将异常值视为极端罕见事件,不需要其异常结果来改变我们的行为。
解决方案 3:
在 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)
解决方案 4:
这可能更快吗?:
n = len(predictions)
rmse = np.linalg.norm(predictions - targets) / np.sqrt(n)
解决方案 5:
sklearn本身包含一个默认值为 的mean_squared_error
参数。如果我们将其设置为,则同一函数将返回 RMSE 而不是 MSE。squared
`True`False
from sklearn.metrics import mean_squared_error
rmse = mean_squared_error(y_true, y_pred , squared=False)
解决方案 6:
或者仅使用 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)
是由于平方函数。
解决方案 7:
Kaggle 内核中有一个ml_metrics
无需预先安装即可使用的库,非常轻量级且可通过以下方式访问pypi
(可以使用以下方式轻松快速地安装pip install ml_metrics
):
from ml_metrics import rmse
rmse(actual=[0, 1, 2], predicted=[1, 10, 5])
# 5.507570547286102
它还有一些其他有趣的指标,但在 中不可用sklearn
,例如mapk
。
参考:
解决方案 8:
是的,它由 SKLearn 提供,我们只需要squared = False
在参数中提及
from sklearn.metrics import mean_squared_error
mean_squared_error(y_true, y_pred, squared=False)
解决方案 9:
from sklearn import metrics
import numpy as np
print(np.sqrt(metrics.mean_squared_error(y_test,y_predict)))
解决方案 10:
不,有一个用于机器学习的库 Scikit Learn,可以用 Python 语言轻松使用。它有一个用于均方误差的函数,我分享的链接如下:
https://scikit-learn.org/stable/modules/ generated/sklearn.metrics.mean_squared_error.html
该函数名为 mean_squared_error,如下所示,其中 y_true 是数据元组的实际类值,y_pred 是预测值,由您正在使用的机器学习算法预测:
均方误差(y_true,y_pred)
您必须修改它以获取 RMSE(通过使用 Python 的 sqrt 函数)。此过程在此链接中描述:
https://www.codeastar.com/regression-model-rmsd/
因此,最终的代码将是这样的:
from sklearn.metrics import mean_squared_error
from math import sqrt
RMSD = sqrt(mean_squared_error(testing_y, prediction))
print(RMSD)
解决方案 11:
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))
解决方案 12:
下面是计算两种多边形文件格式之间 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])
解决方案 13:
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))
解决方案 14:
基准
对于不需要开销处理程序且始终需要 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)
补充说明:在我的用例中,numba
对 给出略有不同但可忽略不计的结果np.sqrt(((y1-y2)**2).mean())
,而如果没有numba
,结果将等于scipy
result。您可以自己尝试一下。
扫码咨询,免费领取项目管理大礼包!