You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

np.random.choice报概率和不为1错误,已归一化仍异常求助

问题原因与解决方案

这个错误的核心原因几乎都是浮点数精度误差,再加上你处理全小值行的逻辑存在小漏洞,咱们一步步拆解:

1. L1归一化后的浮点数舍入误差

F.normalize(outputs, p=1, dim=1)做L1归一化时,由于浮点数的二进制表示限制,很多时候无法得到精确的"和为1"的结果——比如某行的元素经过除法后,累加和可能是0.9999999999999998或者1.0000000000000002,这在np.random.choice的严格检查下(它要求概率和必须精确等于1,哪怕差一点点都会报错)就会触发错误。

2. 全小值行的处理可能有遗漏

你用prob.max(1) < 1e-6来筛选需要填充均匀分布的行,但如果outputs中某行全为0,那么L1归一化后该行的所有元素都会是NaN(因为除以0了),这时候prob.max(1)会得到NaN,而NaN < 1e-6的结果是False,导致这些行没有被填充均匀分布,后续用np.random.choice时,p参数包含NaN或者和不为1的数组,同样会报错。

修复方案

针对这两个问题,你可以调整代码如下:

步骤1:先处理全0行,再做归一化

先检查outputs中哪些行的L1范数为0(全0),提前处理这些行,避免归一化产生NaN:

import numpy as np
import torch.nn.functional as F

# 先计算每行的L1范数和行内最大值
l1_norm = outputs.norm(p=1, dim=1)
row_max = outputs.max(dim=1)[0]
# 找出全0行(L1范数为0)和行内最大值小于1e-6的行
problem_rows = torch.where((l1_norm == 0) | (row_max < 1e-6))[0]

# 先对非问题行做归一化
prob = F.normalize(outputs, p=1, dim=1).clone().data.cpu().numpy()
# 为问题行填充均匀分布
prob[problem_rows] = np.full(prob.shape[1], 1.0 / prob.shape[1])

步骤2:强制修正每行的概率和为1

在调用np.random.choice前,对每行的概率做一次最后的归一化,彻底解决浮点数精度问题:

for j in range(14):
    # 确保概率和精确为1
    p = prob[j]
    p = p / p.sum()
    # 兜底处理可能的NaN(比如之前遗漏的行)
    p = np.nan_to_num(p, nan=1.0 / len(p))
    sample = np.random.choice(6890, 4, replace=False, p=p)

额外优化:批量处理概率修正

如果不想在循环里重复计算,也可以一次性修正所有行:

# 按行归一化,确保每行和为1
prob = prob / prob.sum(axis=1, keepdims=True)
# 处理NaN(如果有的话)
prob = np.nan_to_num(prob, nan=1.0 / prob.shape[1])

这样处理后,就能彻底避免"概率和不为1"的错误了。

内容的提问来源于stack exchange,提问作者Rani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:28:52