基于Stanford cars196数据集的迁移学习/微调代码实现方法问询
关于该迁移学习代码的实现逻辑说明
首先明确结论:该实现并非仅作为特征提取器,属于直接开启微调阶段的迁移学习实现,和官方两步流程的差异仅在于跳过了单独训练顶层分类头的特征提取阶段
官方标准两步迁移学习流程的逻辑
- 第一步(特征提取阶段):冻结整个预训练base_model的所有权重,仅训练后接的自定义分类头,让随机初始化的分类头先收敛,避免后续微调时大梯度破坏预训练权重
- 第二步(微调阶段):解冻base_model的部分顶层权重,使用更小的学习率联合训练解冻的base层和已经收敛的分类头,进一步拟合目标数据集
你提供的代码的运行逻辑
代码完整逻辑如下:
def fine_tune_densenet169(dropout, num_classes, fine_tune_at): base_model = tf.keras.applications.DenseNet169(input_shape=(224, 224, 3), include_top=False, weights='imagenet') x = base_model.output x = tf.keras.layers.GlobalAveragePooling2D()(x) x = Dropout(dropout)(x) prediction_layer = tf.keras.layers.Dense(num_classes, activation='softmax')(x) model=Model(inputs=base_model.input,outputs=prediction_layer) # unfreez base model #x = base_model.trainable = True # Let's take a look to see how many layers are in the base model print("Number of layers in the base model: ", len(base_model.layers)) learning_rate = 0.0001 # Fine-tune from this layer onwards for layer in model.layers[:fine_tune_at]: layer.trainable=False for layer in model.layers[fine_tune_at:]: layer.trainable=True return model
它的核心设置是:直接将整个模型fine_tune_at索引之前的所有层全部冻结,索引之后的层(包含base_model的顶层部分 + 自定义的GAP、Dropout、分类层)全部设为可训练。调用一次fit时会同时训练这两部分可训练权重,属于直接执行微调阶段的逻辑,跳过了单独训练分类头的步骤。
该写法常见于Kaggle的原因
- 使用的学习率极低(代码中给出的参考值为0.0001,仅为特征提取阶段常用学习率的1/10),不会大幅破坏预训练权重的特征提取能力
- 省略单独训练分类头的步骤,节省训练时间
- 当目标数据集(如Stanford Cars196)数据量足够时,最终训练效果和官方两步法差距极小,部分场景下甚至拟合效果更好
纯特征提取器的实现差异
如果需要该代码仅作为特征提取器使用,只需要将fine_tune_at参数设置为base_model的总层数即可,此时整个预训练base_model完全冻结,仅训练后接的自定义分类层,就是标准的特征提取实现。
内容的提问来源于stack exchange,提问作者deny
相关产品推荐
相关产品推荐

