关于EfficientNet B0输出维度与GlobalAveragePooling2D兼容报错的技术问询
嘿,我来帮你捋清楚这个问题的根源和解决办法!
你触发这个ValueError的关键问题出在**EfficientNetB0初始化时的include_top=True参数**:
当你设置include_top=True时,Keras会加载完整的预训练EfficientNetB0模型——这意味着它已经包含了原模型顶层的GlobalAveragePooling2D层和针对ImageNet 1000类的全连接分类层。此时这个模型的输出是二维张量(形状为(batch_size, 1000)),但你后续添加的GlobalAveragePooling2D层要求输入必须是4维张量(格式为(batch_size, height, width, channels)),维度不匹配自然就报错了。
根据你的自定义分类需求,推荐以下两种修复方式:
方案一:移除原模型顶层,自定义分类头(推荐)
如果你想使用自己写的全连接层结构(就像代码里那样),只需要把include_top改为False,这样EfficientNetB0会输出最后一个卷积层的特征图——也就是你在论文里看到的(*,7,7,1280)形状的4维张量,之后就能正常对接你的GlobalAveragePooling2D和后续层了:
model=Sequential() inputS=(height,width,depth) chanDim=-1 # 修改include_top为False,去掉原模型的顶层分类结构 model.add(EfficientNetB0(input_shape=inputS, include_top=False, weights='imagenet')) model.add(GlobalAveragePooling2D()) model.add(Dense(1024)) model.add(Activation("swish")) model.add(BatchNormalization(axis=chanDim)) model.add(Dropout(0.25)) model.add(Dense(256)) model.add(Activation("swish")) model.add(BatchNormalization(axis=chanDim)) model.add(Dropout(0.25)) model.add(Dense(32)) model.add(Activation("tanh")) model.add(BatchNormalization(axis=chanDim)) model.add(Dropout(0.25)) model.add(Dense(classes)) model.add(Activation("softmax")) return model
方案二:保留原模型顶层,删除自定义的池化层
如果你确实想基于原模型的顶层输出继续训练(这种场景比较少见,因为原顶层是针对1000类优化的,未必适配你的任务),那可以直接删除代码中的model.add(GlobalAveragePooling2D()),让原模型的二维输出直接对接你的全连接层。不过这种方式的效果通常不如方案一理想。
还有个细节要注意:当include_top=True时,你的input_shape必须严格匹配原模型的默认输入尺寸(EfficientNetB0是(224,224,3)),否则会触发其他错误;而设置include_top=False时,你可以使用任意符合要求的输入尺寸(只要是32的倍数,EfficientNet对输入大小的兼容性很强)。
内容的提问来源于stack exchange,提问作者cris tiano

