CNN模型拟合报错:ValueError: logits与labels形状不匹配求助
问题解决:CNN二分类中logits与labels形状不匹配错误
错误根源
报错ValueError: logits and labels must have the same shape, received ((None, 3) vs (None, 2))的核心原因有两点:
- 模型最后输出层的单元数设置错误:你用了
units=3,但你的标签是二分类的one-hot编码(维度[260,2]),输出维度和标签维度不匹配 - 损失函数与输出层激活函数搭配错误:当前用了
softmax激活+binary_crossentropy损失,这不符合二分类的标准配置
修正方案(两种可选)
方案1:保持one-hot标签,适配softmax激活
这种方案适合用one-hot编码的标签(也就是你当前的trainlabels):
- 将最后一层全连接层的单元数改为2,匹配二分类的类别数
- 损失函数替换为
categorical_crossentropy,和softmax激活搭配
修改后的模型代码:
model <- keras_model_sequential() model %>% layer_conv_2d(filters = 32, kernel_size = c(3,3), activation = 'relu', input_shape = c(250, 250, 3)) %>% layer_conv_2d(filters = 32, kernel_size = c(3,3), activation = 'relu') %>% layer_max_pooling_2d(pool_size = c(2,2)) %>% layer_dropout(rate = 0.25) %>% layer_conv_2d(filters = 64, kernel_size = c(3,3), activation = 'relu') %>% layer_conv_2d(filters = 64, kernel_size = c(3,3), activation = 'relu') %>% layer_max_pooling_2d(pool_size = c(2,2)) %>% layer_dropout(rate = 0.25) %>% layer_flatten()%>% layer_dense(units = 256, activation = 'relu',) %>% layer_dropout(rate = 0.25) %>% # 修正:输出单元数改为2 layer_dense(units = 2, activation = 'softmax')%>% compile(loss = 'categorical_crossentropy', # 修正:替换损失函数 optimizer = optimizer_sgd(lr = 0.01, decay = 1e-6, momentum = 0.9, nesterov = TRUE), metrics = c('accuracy'))
方案2:用原始标签,适配sigmoid激活
这种方案不需要one-hot编码,直接用原始的trainy(0/1数组):
- 最后一层全连接层单元数设为1,用
sigmoid激活 - 损失函数保持
binary_crossentropy,标签直接传入trainy而非trainlabels
修改后的关键代码:
# 不需要to_categorical,直接用原始标签 trainlabels <- trainy testlabels <- testy model <- keras_model_sequential() model %>% # 前面的卷积、池化层保持不变 layer_conv_2d(filters = 32, kernel_size = c(3,3), activation = 'relu', input_shape = c(250, 250, 3)) %>% layer_conv_2d(filters = 32, kernel_size = c(3,3), activation = 'relu') %>% layer_max_pooling_2d(pool_size = c(2,2)) %>% layer_dropout(rate = 0.25) %>% layer_conv_2d(filters = 64, kernel_size = c(3,3), activation = 'relu') %>% layer_conv_2d(filters = 64, kernel_size = c(3,3), activation = 'relu') %>% layer_max_pooling_2d(pool_size = c(2,2)) %>% layer_dropout(rate = 0.25) %>% layer_flatten()%>% layer_dense(units = 256, activation = 'relu',) %>% layer_dropout(rate = 0.25) %>% # 修正:输出单元数1,sigmoid激活 layer_dense(units = 1, activation = 'sigmoid')%>% compile(loss = 'binary_crossentropy', optimizer = optimizer_sgd(lr = 0.01, decay = 1e-6, momentum = 0.9, nesterov = TRUE), metrics = c('accuracy')) # 拟合时传入原始标签trainy history <- model %>% fit(train, trainy, epochs = 50, batch_size = 32, validation_split = 0.2)
额外建议
- 你之前尝试调整图片尺寸到100×100,这个操作本身没问题,但和当前错误无关,错误根源是输出层和损失函数的配置
- 可以考虑在输入层前添加
layer_resizing来统一图片尺寸,比如:
model %>% layer_resizing(height = 100, width = 100) %>% # 新增这一行 layer_conv_2d(filters = 32, kernel_size = c(3,3), activation = 'relu', input_shape = c(100, 100, 3)) %>% # 后续层保持不变
内容的提问来源于stack exchange,提问作者Fjoralb
相关产品推荐
相关产品推荐

