训练CK+48数据集自定义CNN时logits与labels可广播性错误如何解决?
问题原因
你遇到的报错核心原因有2个:
- 中间隐藏层错误使用
softmax激活,导致特征传递异常,进而出现输出维度和标签维度不匹配的问题 - 手动设置
steps_per_epoch可能存在计算偏差,导致样本和标签对齐错误
修复步骤
1. 修改模型全连接层配置
中间全连接层属于隐藏层,应当使用relu作为激活函数,禁止使用softmax。如果保持from_logits=True的配置,输出层不需要加激活函数,修改后的全连接部分代码如下:
model.add(layers.Flatten()) # 把原来的softmax改成relu model.add(layers.Dense(64, activation='relu')) model.add(layers.Dense(len(set(traing.classes))))
如果你习惯输出层加softmax,可以同步修改损失函数配置:
# 模型部分 model.add(layers.Flatten()) model.add(layers.Dense(64, activation='relu')) model.add(layers.Dense(len(set(traing.classes)), activation='softmax')) # 损失函数部分,把from_logits改成False loss = tf.keras.losses.CategoricalCrossentropy(from_logits=False)
2. 删除手动设置的steps_per_epoch参数
Keras会自动根据数据生成器的样本数和batch size计算训练步数,手动计算容易出现整除导致的剩余样本丢失问题,修改训练代码如下:
history = model.fit(train_generator, epochs=500, validation_data=valid_generator)
建议补充validation_data参数,方便训练过程中监控过拟合情况。
3. 可选:排查数据生成器输出(如果上述修改仍报错)
执行以下代码确认数据生成器输出形状是否符合预期:
batch_x, batch_y = train_generator.next() print(batch_x.shape) # 应当输出 (64, 48, 48, 3) print(batch_y.shape) # 应当输出 (64, 7)
如果标签形状不是(batch_size,7),可以将flow_from_directory的class_mode参数显式设置为categorical;如果不想用one-hot编码,可以设置class_mode='sparse',同时将损失函数换成SparseCategoricalCrossentropy(from_logits=True)。
内容的提问来源于stack exchange,提问作者Wtow
相关产品推荐
相关产品推荐

