You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keras中VGG16替换全连接层后出现形状不兼容错误求助

Keras VGG16替换全连接层后训练报错:形状不兼容问题

问题描述

我正在用Keras做VGG16模型的迁移学习练习,已加载预训练模型,需要将原模型最后3个全连接层替换为3个新层:前两层分别为50和20个神经元,采用ReLU激活函数,最后一层为对应类别的神经元数量。

我执行的代码如下:

# 冻结预训练模型层的权重
for layer in base_model.layers:
    layer.trainable = False

# 替换最后3个全连接层为新层
x = base_model.output
x = Dense(50, activation='relu')(x)
x = Dense(20, activation='relu')(x)
x = Dense(num_classes, activation='softmax')(x)

# 拼接VGG16基础模型和新层,创建新模型
model = Model(inputs=base_model.input, outputs=x)

运行model.summary()输出如下:

=================================================================

 input_13 (InputLayer)       [(None, 224, 224, 3)]     0          
                                                                 
 block1_conv1 (Conv2D)       (None, 224, 224, 64)      1792       
                                                                 
 block1_conv2 (Conv2D)       (None, 224, 224, 64)      36928      
                                                                 
 block1_pool (MaxPooling2D)  (None, 112, 112, 64)      0          
                                                                 
 block2_conv1 (Conv2D)       (None, 112, 112, 128)     73856      
                                                                 
 block2_conv2 (Conv2D)       (None, 112, 112, 128)     147584     
                                                                 
 block2_pool (MaxPooling2D)  (None, 56, 56, 128)       0          
                                                                 
 block3_conv1 (Conv2D)       (None, 56, 56, 256)       295168     
                                                                 
 block3_conv2 (Conv2D)       (None, 56, 56, 256)       590080     
                                                                 
 block3_conv3 (Conv2D)       (None, 56, 56, 256)       590080     
                                                                 
 block3_pool (MaxPooling2D)  (None, 28, 28, 256)       0          
                                                                 
 block4_conv1 (Conv2D)       (None, 28, 28, 512)       1180160    
                                                                 
 block4_conv2 (Conv2D)       (None, 28, 28, 512)       2359808    
                                                                 
 block4_conv3 (Conv2D)       (None, 28, 28, 512)       2359808    
                                                                 
 block4_pool (MaxPooling2D)  (None, 14, 14, 512)       0          
                                                                 
 block5_conv1 (Conv2D)       (None, 14, 14, 512)       2359808    
                                                                 
 block5_conv2 (Conv2D)       (None, 14, 14, 512)       2359808    
                                                                 
 block5_conv3 (Conv2D)       (None, 14, 14, 512)       2359808    
                                                                 
 block5_pool (MaxPooling2D)  (None, 7, 7, 512)         0          
                                                                 
 dense_6 (Dense)             (None, 7, 7, 50)          25650      
                                                                 
 dense_7 (Dense)             (None, 7, 7, 20)          1020       
                                                                 
 dense_8 (Dense)             (None, 7, 7, 21)          441        
                                                                 
=================================================================

Total params: 14,741,799
Trainable params: 27,111
Non-trainable params: 14,714,688
_________________________________________________________________

训练时出现以下错误:

ValueError: Shapes (None, 21) and (None, 7, 7, 21) are incompatible

问题原因

从模型summary可以看到,base_model.output的形状是*(None,7,7,512)*——这是VGG16最后一个池化层的输出,保留了7x7的空间维度和512个通道。直接在这个输出上叠加Dense层时,Keras会将Dense层的计算应用到每个空间位置,导致每一层的输出都保留7x7的空间维度,最终模型输出形状为*(None,7,7,21)*。而你的训练标签是*(None,21)*(单样本对应一个类别概率向量),两者维度不匹配,因此触发形状兼容错误。

解决方法

在添加Dense层之前,需要将空间维度的特征压缩为一维向量,可通过以下两种方式实现:

方法1:使用Flatten层(完整保留特征)

将7x7x512的特征展平为一维向量,保留所有空间特征信息:

x = base_model.output
x = Flatten()(x)  # 将(None,7,7,512)转换为(None,25088)
x = Dense(50, activation='relu')(x)
x = Dense(20, activation='relu')(x)
x = Dense(num_classes, activation='softmax')(x)

方法2:使用全局池化层(减少参数,缓解过拟合)

通过全局平均池化或全局最大池化,将每个通道的空间特征压缩为单个值,大幅减少后续全连接层的参数数量:

x = base_model.output
x = GlobalAveragePooling2D()(x)  # 输出形状为(None,512)
# 也可替换为GlobalMaxPooling2D()实现全局最大池化
x = Dense(50, activation='relu')(x)
x = Dense(20, activation='relu')(x)
x = Dense(num_classes, activation='softmax')(x)

修改后,模型最终输出形状会变为*(None,21)*,与训练标签的形状匹配,即可正常训练。


内容的提问来源于stack exchange,提问作者JLL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 01:12:55