PyTorch张量求和浮点精度异常问题优化咨询
浮点精度优化:PyTorch与Python列表求和的差异问题
我编写了一个Python测试,用于计算存入PyTorch Tensor的列表元素之和,测试代码如下:
lst = [0.0014, -0.0306, 0.0005, 0.0011, 0.0012, 0.0022, 0.0017, 0.0011, 0.0017, 0.0011, 0.0012, 0.0017, 0.0014, 0.0015, 0.0010, 0.0006, 0.0006, 0.0004, 0.0009, 0.0007, 0.0008, 0.0007, 0.0013, 0.0013, 0.0015, 0.0023, 0.0006] LEN=27 trch = torch.Tensor([lst]) print('--------------------------------------------------------------') print(trch.sum(1, keepdim=True)) print(sum(lst)) print(trch @ torch.ones((LEN,1))) print(torch.mm( trch , torch.ones((LEN,1)))) trch_sum= 0 for num in lst: trch_sum += num print(trch_sum)
初始运行得到的结果较为合理:
tensor([[-0.0001]]) -9.999999999999912e-05 tensor([[-9.9999e-05]]) tensor([[-9.9999e-05]]) -9.999999999999972e-05
但将列表最后一个数值改为0.0007后,各求和方式的结果出现极大差异:
tensor([[-9.3132e-10]]) 9.215718466126788e-19 tensor([[1.1642e-09]]) tensor([[1.1642e-09]]) 3.2526065174565133e-19
已知这是浮点精度问题,请问有什么方法可以优化这种情况?
优化浮点求和精度的方法
使用更高精度的数据类型
默认PyTorch的torch.Tensor采用float32(32位单精度浮点数),而Python原生float是float64(64位双精度)。将Tensor转换为双精度类型能大幅减少精度损失:# 直接创建双精度Tensor trch = torch.tensor(lst, dtype=torch.float64).unsqueeze(0) # 或转换已有Tensor trch = trch.double()双精度浮点数的有效位数是单精度的两倍,能显著降低累加过程中的误差累积。
实现Kahan求和算法
这是一种专门用于减少浮点累加误差的算法,通过跟踪并补偿累加时丢失的小数部分提升精度,适合手动循环求和场景:# Python版本Kahan求和 def kahan_sum(lst): total = 0.0 correction = 0.0 for num in lst: y = num - correction temp = total + y correction = (temp - total) - y total = temp return total # PyTorch版本Kahan求和 def torch_kahan_sum(tensor): total = torch.zeros_like(tensor) correction = torch.zeros_like(tensor) for num in tensor.flatten(): y = num - correction temp = total + y correction = (temp - total) - y total = temp return total替代普通循环求和后,误差会明显降低。
调整求和顺序
浮点求和的误差与累加顺序直接相关,将元素按大小排序或正负分开累加,能避免小数值被大数值“吞没”:# 正负分组后分别排序求和 positives = sorted([x for x in lst if x >= 0]) negatives = sorted([x for x in lst if x < 0]) optimized_sum = sum(positives) + sum(negatives)结果后处理:合理截断精度
如果业务场景不需要极高精度,可对结果进行四舍五入,掩盖无意义的微小误差:# 保留8位小数 print(round(trch.sum(1, keepdim=True).item(), 8)) print(round(sum(lst), 8))
内容的提问来源于stack exchange,提问作者Carmel Gafa
相关产品推荐
相关产品推荐

