问题现象
训练分类模型时,标签经常以「类别下标」的形式给出,比如[1, 0, 3]表示三个样本分别属于第 1、0、3 类。但损失函数通常要求标签是 one-hot 形式。转换过程看着简单,动手却常出错。
现象一:用循环逐行赋值写了十几行代码,数据量一大就跑得极慢,几万条标签要等半天。
现象二:用np.eye(n)[a]的思路取出来,结果形状不对:输入是一维数组时得到的是二维结果没问题,但输入本身是二维批次时,输出维度多了一层,送进模型就报维度不匹配。
现象三:硬编码了类别数(比如写死 10),一旦某个批次的标签没覆盖到全部类别,或者换了个类别数不同的数据集,代码立刻失效甚至越界报错。
现象四:在 TensorFlow 或 PyTorch 里想做同样的事,用np.eye生成的数组 dtype 默认是 float64,与模型的 float32 不兼容,出现类型转换告警或显存占用翻倍。
现象五:标签里出现了-1(表示忽略该样本),直接用-1做下标会触发「负索引」语义,不但不报错,还会在最后一列偷偷置 1,污染训练目标。
原因分析
要理解正确写法,先看清两件事:花式索引的规则与广播机制。
花式索引指的是用数组做下标。当用两个等长的一维数组分别作为行下标和列下标时,NumPy 会把它们配对:(row[0], c