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

如何在TensorFlow与Keras迁移学习中防止过拟合?

解决TensorFlow Hub预训练层微调过拟合的标准方案

遇到这种封装好的预训练层没法直接修改内部结构的情况,业内有一套成熟的处理思路,我帮你拆解下最实用的几个方案,按优先级来:

1. 分层解冻(渐进式微调)—— 最推荐的核心方案

直接全开trainable=True过拟合,本质是预训练的通用权重被你的小数据集带偏了。正确的做法是先冻结预训练层,只训练你自己加的顶层,等顶层收敛后,再逐步解冻预训练层的后几层(靠近输出的层,这些层的特征更偏向任务无关到任务相关的过渡),同时用极小的学习率训练,避免破坏预训练的通用特征。

举个代码例子:

# 第一步:冻结预训练层,先训练自定义顶层
hub_layer = hub.KerasLayer("你的预训练模型地址", trainable=False)
model = tf.keras.Sequential([
    hub_layer,
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 先训顶层,用正常学习率
model.fit(train_ds, validation_data=val_ds, epochs=10)

# 第二步:渐进式解冻,只让预训练层的最后5层可训练(数量按需调整)
hub_layer.trainable = True
# 遍历预训练层的内部子层,冻结前面的大部分
for layer in hub_layer.layers[:-5]:
    layer.trainable = False

# 用极小的学习率继续训练,比如比之前小10-100倍
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-5),
              loss='binary_crossentropy', metrics=['accuracy'])
# 接着之前的epoch继续训
model.fit(train_ds, validation_data=val_ds, epochs=30, initial_epoch=10)

2. 给模型加全局正则化—— 无需修改预训练层内部

你说的对,没法给每个hub子层加kernel_regularizer,但可以给所有可训练权重统一加L2正则化,在自定义训练循环里手动计算正则化损失就行,不管权重来自哪里:

loss_fn = tf.keras.losses.BinaryCrossentropy(from_logits=True)
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-5)
l2_lambda = 1e-4  # 正则化强度,按需调

@tf.function
def train_step(x, y):
    with tf.GradientTape() as tape:
        logits = model(x, training=True)
        # 基础损失
        base_loss = loss_fn(y, logits)
        # 收集所有可训练权重的L2损失,统一乘正则化系数
        l2_loss = tf.add_n([tf.nn.l2_loss(w) for w in model.trainable_weights]) * l2_lambda
        total_loss = base_loss + l2_loss
    
    gradients = tape.gradient(total_loss, model.trainable_weights)
    optimizer.apply_gradients(zip(gradients, model.trainable_weights))
    return total_loss

# 然后用这个train_step循环训练就行
for epoch in range(epochs):
    for x_batch, y_batch in train_ds:
        loss = train_step(x_batch, y_batch)
    # 验证逻辑...

3. 在预训练层外部加正则化层—— 简单直接的补充

虽然没法改hub层内部,但可以在它的输出后面加Dropout、BatchNormalization这类正则化层,同样能有效缓解过拟合:

model = tf.keras.Sequential([
    hub_layer,
    tf.keras.layers.Dropout(0.3),  # 给预训练特征加Dropout
    tf.keras.layers.BatchNormalization(),  # 稳定特征分布
    tf.keras.layers.Dense(128, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(1e-4)),
    tf.keras.layers.Dropout(0.5),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

关于FTRL优化器的使用

TF2里FTRL确实支持内置的L2正则化,但它的参数调起来和Adam不一样,尤其是学习率——FTRL适合用稍大一点的学习率(比如1e-3到1e-2),同时正则化强度要和数据集匹配。如果之前用不好,试试调整这两个参数:

optimizer = tf.keras.optimizers.Ftrl(
    learning_rate=0.01,
    l2_regularization_strength=1e-4,
    learning_rate_power=-0.5  # 这个参数控制学习率衰减,默认值就行
)

不过要注意,FTRL更适合稀疏特征场景(比如文本的one-hot特征),如果你的数据集是图像这类稠密特征,还是Adam加全局L2的组合效果更稳定。

必加的辅助手段:早停(Early Stopping)

不管用哪个方案,都一定要加早停回调,一旦验证集损失不再下降就停止训练,直接用最优的权重:

early_stopping = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss',
    patience=5,  # 5个epoch没提升就停
    restore_best_weights=True  # 自动恢复到最优权重
)
model.fit(train_ds, validation_data=val_ds, epochs=50, callbacks=[early_stopping])

内容的提问来源于stack exchange,提问作者Lukáš Lánský

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:23:53