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

自定义模型最后一层冻结及ResNet50权重替换与单层训练方案

解决方案:加载自定义权重并冻结最后一层以外的层

我来帮你一步步搞定这个问题,咱们拆成两个核心环节来操作:加载你的自定义权重到模型,然后冻结大部分层只训练最后一层。

1. 加载自定义权重到mini_XCEPTION模型

首先你得确保手里有训练好的权重文件(一般是.h5格式),先创建模型实例,再加载你的权重:

from tensorflow.keras.layers import Input, Conv2D, BatchNormalization, Activation, SeparableConv2D, MaxPooling2D, add, GlobalAveragePooling2D
from tensorflow.keras.models import Model
from tensorflow.keras.regularizers import l2

# 保留你原有的模型定义
def mini_XCEPTION(input_shape, num_classes, l2_regularization=0.01):
    regularization = l2(l2_regularization)
    # base
    img_input = Input(input_shape)
    x = Conv2D(8, (3, 3), strides=(1, 1), kernel_regularizer=regularization, use_bias=False)(img_input)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = Conv2D(8, (3, 3), strides=(1, 1), kernel_regularizer=regularization, use_bias=False)(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    # module 1
    residual = Conv2D(16, (1, 1), strides=(2, 2), padding='same', use_bias=False)(x)
    residual = BatchNormalization()(residual)
    x = SeparableConv2D(16, (3, 3), padding='same', kernel_regularizer=regularization, use_bias=False)(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = SeparableConv2D(16, (3, 3), padding='same', kernel_regularizer=regularization, use_bias=False)(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
    x = add([x, residual])
    # module 2
    residual = Conv2D(32, (1, 1), strides=(2, 2), padding='same', use_bias=False)(x)
    residual = BatchNormalization()(residual)
    x = SeparableConv2D(32, (3, 3), padding='same', kernel_regularizer=regularization, use_bias=False)(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = SeparableConv2D(32, (3, 3), padding='same', kernel_regularizer=regularization, use_bias=False)(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
    x = add([x, residual])
    # module 3
    residual = Conv2D(64, (1, 1), strides=(2, 2), padding='same', use_bias=False)(x)
    residual = BatchNormalization()(residual)
    x = SeparableConv2D(64, (3, 3), padding='same', kernel_regularizer=regularization, use_bias=False)(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = SeparableConv2D(64, (3, 3), padding='same', kernel_regularizer=regularization, use_bias=False)(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
    x = add([x, residual])
    # module 4
    residual = Conv2D(128, (1, 1), strides=(2, 2), padding='same', use_bias=False)(x)
    residual = BatchNormalization()(residual)
    x = SeparableConv2D(128, (3, 3), padding='same', kernel_regularizer=regularization, use_bias=False)(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = SeparableConv2D(128, (3, 3), padding='same', kernel_regularizer=regularization, use_bias=False)(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
    x = add([x, residual])
    x = Conv2D(num_classes, (3, 3), padding='same')(x)
    x = GlobalAveragePooling2D()(x)
    output = Activation('softmax', name='predictions')(x)
    model = Model(img_input, output)
    return model

# 创建模型实例(要和你权重对应的输入形状、类别数匹配)
input_shape = (224, 224, 3)
num_classes = 你的数据集类别数  # 替换成你实际的类别数量
model = mini_XCEPTION(input_shape, num_classes)

# 加载你的自定义权重(替换成你的权重文件路径)
model.load_weights('你的权重文件路径.h5')

2. 冻结最后一层以外的所有层,仅训练最后一层

接下来我们要把模型大部分层冻结,只让最后一层(或分类头)可训练,这里分两种场景:

场景一:仅训练最后的softmax输出层

如果你的“最后一层”特指名称为predictions的激活层,这么操作:

# 先冻结所有层
for layer in model.layers:
    layer.trainable = False

# 解冻最后的predictions层
model.get_layer('predictions').trainable = True

# 关键:必须重新编译模型,Keras才会更新训练参数配置
model.compile(optimizer='adam',  # 微调建议用小学习率,比如tf.keras.optimizers.Adam(1e-4)
              loss='categorical_crossentropy',  # 二分类任务换成binary_crossentropy
              metrics=['accuracy'])

场景二:训练整个分类头(含前面的卷积和池化层)

看你的模型结构,最后三个层组成了分类头:Conv2D(num_classes) → GlobalAveragePooling2D → Activation('predictions'),如果要训练整个分类头,这么做:

# 冻结所有层
for layer in model.layers:
    layer.trainable = False

# 解冻最后三个层(分类头部分)
for layer in model.layers[-3:]:
    layer.trainable = True

# 重新编译模型
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4),
              loss='categorical_crossentropy',
              metrics=['accuracy'])

额外提醒

  • 确保你的自定义权重和当前模型结构完全匹配(输入形状、层数、参数数量一致),否则加载权重会报错。
  • 微调时用小学习率,避免破坏预训练好的权重。
  • 如果是二分类任务,记得把num_classes设为1,loss换成binary_crossentropy,输出层激活函数改成sigmoid。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 06:28:52