MobileViT二分类训练报logits与labels形状不匹配错误
问题根因
这个形状不匹配报错是二分类任务的输出层、激活函数、损失函数、标签编码三套配置逻辑混用导致的,你现在的配置既不符合单神经元二分类的规范,也不符合双输出多分类式二分类的规范,同时你写的tf.one_hot标签处理逻辑实际没有生效,传入训练的标签实际还是形状为(None,1)的单值0/1标签,和你设置的2维输出层形状完全对不上。
快速修复方案(改动最小,推荐)
选择单神经元二分类的标准配置即可,不需要做独热编码,收敛速度更快:
- 把分类头最后一层从
Dense(2, activation='sigmoid')改成Dense(1, activation='sigmoid'),输出形状变为(None,1) - 删掉标签预处理阶段
depth=2的tf.one_hot逻辑,直接使用原始0/1标签;如果取batch打印标签形状是(None,),就加一步labels = tf.expand_dims(labels, axis=-1)把标签形状转成(None,1)和输出对齐 - 损失函数保持
keras.losses.BinaryCrossentropy()不用改,直接启动训练就不会再报形状错误 - 推理时直接判断输出值:大于0.5为正类,小于等于0.5为负类
2维输出适配方案(非必要不选)
如果一定要用2维输出的结构,需要把整套配置换成双输出分类的逻辑,不能混用BinaryCrossentropy:
- 分类头最后一层保持
Dense(2),激活函数换成softmax,也可以不加激活直接输出原始logits - 修正数据集预处理逻辑:先取一个训练batch执行
imgs, labels = next(iter(train_dataset)),打印labels.shape,排查one_hot未生效的原因——常见问题包括数据集加载时label_mode配置不对、map处理函数没正确返回one_hot后的标签、one_hot后误加了squeeze操作压缩了维度,最终要确保标签形状为(None,2) - 损失函数替换为
keras.losses.CategoricalCrossentropy():如果最后一层没加激活函数,就加参数from_logits=True;如果加了softmax激活就保持默认from_logits=False - 不要用
BinaryCrossentropy搭配2维输出,这个损失函数是为单神经元二分类设计的,搭配2维输出会对每个神经元单独计算二分类损失,不符合任务目标。
必做排查项
不管选哪种方案,改完之后先取一个batch的数据,分别打印模型预测的输出形状、标签形状,确认两者完全一致再启动全量训练,避免浪费算力和时间。
内容的提问来源于stack exchange,提问作者Nephilim700
相关产品推荐
相关产品推荐

