CNN猫狗图像分类报错:target与output维度不匹配
猫狗分类CNN模型训练报错:维度不匹配
错误日志
File "c:\Users\UserPC\Downloads\image-classification-using-cnn-master\image-classification-using-cnn-master\Code\main.py", line 164, in <module> history = model.fit( ^^^^^^^^^^ File "C:\Users\UserPC\AppData\Local\Programs\Python\Python311\Lib\site-packages\keras\src\utils\traceback_utils.py", line 122, in error_handler raise e.with_traceback(filtered_tb) from None File "C:\Users\UserPC\AppData\Local\Programs\Python\Python311\Lib\site-packages\keras\src\backend\tensorflow\nn.py", line 694, in binary_crossentropy raise ValueError( ValueError: Arguments `target` and `output` must have the same rank (ndim). Received: target.shape=(50,), output.shape=(50, 2)
问题核心
这个错误的本质是模型输出、损失函数、标签格式三者不匹配:
- 模型最后一层为
Dense(2, activation='softmax'),输出形状是(batch_size, 2),对应2类多分类输出 - 但使用的损失函数是
binary_crossentropy,该损失函数为二分类任务设计,要求模型输出是(batch_size, 1)(搭配sigmoid激活),标签为(batch_size,)的整数/浮点值
修复方案
方案一:调整模型适配标准二分类逻辑(推荐)
将模型最后一层和损失函数改为二分类专属配置,无需修改标签格式:
def get_model(): # ... 其余卷积、池化层保持不变 ... # 替换最后一层为单输出sigmoid激活 model.add(Dense(1, activation='sigmoid')) # 二分类仅需1个输出单元 # 保留binary_crossentropy损失函数 model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) print('Model prepared...') return model
方案二:调整损失函数适配当前多分类输出
如果想保留Dense(2, softmax)的输出层,有两种可选方式:
选项1:使用sparse_categorical_crossentropy(无需修改标签)
该损失函数直接支持整数标签与多分类输出的组合:
def get_model(): # ... 其余层保持不变 ... # 保留Dense(2, softmax)输出层 model.add(Dense(2, activation='softmax')) # 替换损失函数 model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy']) print('Model prepared...') return model
选项2:使用categorical_crossentropy(需将标签转为独热编码)
- 取消
to_categorical的导入注释:
from keras._tf_keras.keras.utils import to_categorical
- 修改模型损失函数:
def get_model(): # ... 其余层保持不变 ... model.add(Dense(2, activation='softmax')) # 切换为categorical_crossentropy model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) print('Model prepared...') return model
- 在主函数中转换标签格式:
if __name__ == "__main__": # ... 加载数据的代码保持不变 ... train_labels = np.array([i[1] for i in train_data]) train_labels = to_categorical(train_labels, num_classes=2) # 转为独热编码 test_labels = np.array([i[1] for i in test_data]) test_labels = to_categorical(test_labels, num_classes=2) # 转为独热编码 # ... 后续训练代码保持不变 ...
内容的提问来源于stack exchange,提问作者Luis Cruz
相关产品推荐
相关产品推荐

