Python中移除测试标签y_test零值解决MAPE计算inf问题及准确率优化
零值样本清理的代码实现
针对你已经构造的合并数组erry,不需要逐一定位零值索引做删除操作,用numpy布尔索引就能快速筛掉y_test为0的配对条目:
- 第一步:构造有效位置掩码,识别
erry第二行(存储y_test的行)中的非零值位置valid_mask = erry[1] != 0 - 第二步:用掩码按列筛选合并数组(数组每一列对应一组「误差值、测试标签值」的配对),得到无零值的配对数据集
filtered_erry = erry[:, valid_mask]
筛选完成后,filtered_erry[0]是和非零标签一一对应的误差值,filtered_erry[1]是清理后的非零测试标签,直接代入原MAPE计算逻辑就不会出现无穷值。
操作提示:如果不构造合并数组也可以直接实现同样的效果,用
valid_idx = np.where(y_test != 0)[0]拿到非零标签的索引,再分别从errors和y_test中索引提取对应值即可,比合并数组再筛选的流程更精简。
适配零值场景的准确率计算方案
原方案使用的标准MAPE指标本身存在数学局限性,要求真实值不能为0才能逐点计算误差率,除了直接删除零值样本的操作,还有三类鲁棒性更强的方案可以适配这类存在零值标签的场景:
- 对称MAPE(sMAPE):将逐点计算的分母替换为真实值和预测值的绝对值平均值,只要预测值和真实值不同时为0就不会出现除零错误。计算逻辑为:
smape = np.mean(2 * np.abs(errors) / (np.abs(y_test) + np.abs(y_pred) + 1e-8)) * 100
最终准确率换算为100 - smape,对小值、零值样本的敏感度远低于标准MAPE。 - 加权MAPE(wMAPE):跳过逐点计算单样本误差率的步骤,先汇总所有非零标签对应的绝对误差总和,再除以所有非零标签的总和计算整体误差率。计算逻辑为:
最终准确率为valid_idx = y_test != 0 wmape = (np.sum(np.abs(errors[valid_idx])) / np.sum(y_test[valid_idx])) * 100100 - wmape,从根源上避免了逐点除零的问题,同时不会因为单样本误差过大拉高整体均值,对样本分布波动的鲁棒性更强。 - 平滑修正版MAPE:如果一定要保留原有的逐点计算逻辑,可以给分母增加一个极小的平滑偏移值,从计算规则上规避除零问题:
mape = 100 * np.abs(errors) / (np.abs(y_test) + 1e-8)
这种方案不需要删除任何样本,就算标签值为0,也能正常计算对应样本的误差率,不会出现inf值拉垮整体计算结果。
注意事项:如果测试标签中的零值是真实的有效观测,并非缺失值,直接删除这类样本会引入统计偏差,这种场景下优先选择sMAPE、wMAPE或者带平滑修正的MAPE方案,不要直接剔除零值样本。
内容的提问来源于stack exchange,提问作者HoOman
相关产品推荐
相关产品推荐

