当其中一个numpy数组含np.nan时,如何计算两个数组的MSE
解决方案
方案1:用布尔掩码提前过滤样本(最优,无nan兼容问题)
不需要给真值赋值nan,直接通过布尔索引筛选出需要计算损失的样本即可,性能最高也不会出现报错:
import numpy as np from sklearn.metrics import mean_squared_error a = np.random.normal(size=(4,4)) # 真值 b = np.random.normal(size=(4,4)) # 预测值 threshold = 0.5 # 自定义阈值,低于该值的真值不计入损失 # 生成掩码:仅保留真值绝对值大于阈值的位置 mask = np.abs(a) > threshold # 仅计算符合条件位置的MSE filtered_a = a[mask] filtered_b = b[mask] mse = np.square(np.subtract(filtered_a, filtered_b)).mean()
如果要使用sklearn的mean_squared_error,也可以直接传入过滤后的两个数组:
mse = mean_squared_error(filtered_a, filtered_b)
方案2:兼容你现有nan赋值的写法
如果你不想改赋值nan的逻辑,只需要把原来普通的均值计算换成numpy提供的忽略nan的均值函数即可:
# 你的原有逻辑:给低于阈值的真值赋值nan,注意加copy避免修改原数组a c = a.copy() c[np.abs(c) <= 0.5] = np.nan # 方法1修改:用np.nanmean替代普通mean difference_array = np.subtract(c,b) squared_array = np.square(difference_array) mse = np.nanmean(squared_array) # 如果要用sklearn接口,可以先手动过滤掉nan位置 mask = ~np.isnan(c) mse = mean_squared_error(c[mask], b[mask])
方案3:用样本权重适配sklearn接口
如果需要保留完整数组结构,也可以通过sample_weight参数实现忽略指定样本:
threshold = 0.5 # 符合条件的样本权重为1,不符合的为0 sample_weight = (np.abs(a) > threshold).astype(float) # 计算时自动忽略权重为0的样本 mse = mean_squared_error(a, b, sample_weight=sample_weight)
神经网络损失函数适配
如果是要在PyTorch/TensorFlow框架中实现该自定义损失,逻辑和上面一致,以PyTorch为例:
import torch import torch.nn as nn def custom_mse(y_true, y_pred, threshold=0.5): mask = torch.abs(y_true) > threshold # 仅计算符合条件的位置的平方误差均值 return torch.mean(torch.square(y_true[mask] - y_pred[mask]))
内容的提问来源于stack exchange,提问作者McM
相关产品推荐
相关产品推荐

