如何在Python中从零实现几何均方根误差(GRMSE)函数
从零实现几何均方根误差(GRMSE)的Python函数
咱们先明确一下GRMSE的核心逻辑:它是专门用来衡量相对误差的指标,比起普通RMSE更适合关注比例差异的场景。计算思路是把预测值和真实值的比值转化为对数空间的绝对误差,算出均方根后再还原回原空间。公式可以写成这样:
GRMSE = exp( sqrt( (1/n) * Σ( ln(fᵢ) - ln(yᵢ) )² ) )
其中n是样本数量,fᵢ是预测值,yᵢ是真实值。
接下来咱们一步步实现可调用的grmse(ft, yt)函数,我会提供两种方案:纯Python实现(不依赖第三方库,适合理解底层逻辑)和numpy实现(更高效,适合处理大数据集)。
方案1:纯Python实现(无第三方依赖)
这个版本完全用Python标准库实现,适合想搞清楚每一步细节的同学:
import math def grmse(ft, yt): # 第一步:校验输入向量长度一致 if len(ft) != len(yt): raise ValueError("预测向量和真实向量的长度必须完全一致") n = len(ft) squared_log_diff_total = 0.0 # 遍历每个元素计算对数差的平方 for f_val, y_val in zip(ft, yt): # 必须确保所有值都是正数,不然对数会报错 if f_val <= 0 or y_val <= 0: raise ValueError("所有预测值和真实值都得是正数,因为要计算自然对数哦") # 计算单个样本的对数差并平方 log_diff = math.log(f_val) - math.log(y_val) squared_log_diff_total += log_diff ** 2 # 计算均值的平方根,再取指数得到最终结果 mean_squared_log = squared_log_diff_total / n rmse_log_space = math.sqrt(mean_squared_log) grmse_result = math.exp(rmse_log_space) return grmse_result
方案2:Numpy实现(高效简洁)
如果你的数据量比较大,用numpy会快很多,代码也更简洁:
import numpy as np def grmse(ft, yt): # 把输入转成numpy浮点数组 f_array = np.array(ft, dtype=np.float64) y_array = np.array(yt, dtype=np.float64) # 校验输入形状一致 if f_array.shape != y_array.shape: raise ValueError("预测向量和真实向量的长度必须完全一致") # 校验所有元素为正数 if np.any(f_array <= 0) or np.any(y_array <= 0): raise ValueError("所有预测值和真实值都得是正数,因为要计算自然对数哦") # 按公式一步到位计算 log_diffs = np.log(f_array) - np.log(y_array) mean_squared_log = np.mean(log_diffs ** 2) rmse_log_space = np.sqrt(mean_squared_log) grmse_result = np.exp(rmse_log_space) return grmse_result
测试一下给定的向量
用你提供的测试数据跑一下看看:
# 测试数据 ft = (2, 3, 4.5, 6, 4, 3, 2) yt = (2.1, 4.2, 4.5, 7, 3, 2, 2) # 调用函数 print(grmse(ft, yt))
运行后会得到大约1.17的结果,这个值说明整体预测值相对于真实值有一定程度的高估(因为GRMSE>1)。
额外说明
- 为什么要校验正数?因为自然对数
ln(x)在x≤0时是无意义的,提前校验能避免运行时抛出莫名其妙的错误。 - GRMSE的解读:如果结果等于1,说明预测和真实值的几何平均完全匹配;大于1表示整体预测偏高,小于1表示整体预测偏低。
内容的提问来源于stack exchange,提问作者PeCaDe




