基于 TensorFlow-Slim 对 CIFAR-10 进行 Fine-tuning

**基于 TensorFlow-Slim 对 CIFAR-10 进行 Fine-tuning 的完整步骤
选择的模型是 TensorFlow Slim 中的 ResNet_v2_50(ImageNet 预训练),因为:

  • 结构成熟,迁移效果好
  • Slim 自带 checkpoint
  • 易于替换最后一层

一、整体思路

CIFAR-10 特点:

  • 输入尺寸:32×32
  • 类别数:10
  • 数据量:5万训练 + 1万测试

ResNet_v2_50 原始输入是 224×224,因此:

👉 必须 resize
👉 替换最后一层 logits
👉 只 fine-tune 后几层(推荐)


二、环境准备

建议使用:

Python 3.9
TensorFlow 2.x
tf_slim

安装:

pip install tensorflow tf_slim

三、完整 Fine-tuning 代码(教学版)

1️⃣ 导入依赖

import tensorflow as tf
import tf_slim as slim
from tf_slim.nets import resnet_v2
import numpy as np

2️⃣ 加载 CIFAR-10 数据

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()

x_train = x_train.astype(np.float32) / 255.0
x_test = x_test.astype(np.float32) / 255.0

y_train = tf.keras.utils.to_categorical(y_train, 10)
y_test = tf.keras.utils.to_categorical(y_test, 10)

3️⃣ Resize 到 224×224

def preprocess(image, label):
    image = tf.image.resize(image, [224, 224])
    return image, label

train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.map(preprocess).batch(64).shuffle(1000)

test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_dataset = test_dataset.map(preprocess).batch(64)

4️⃣ 构建 Slim 模型(替换最后一层)

def build_model(num_classes=10, is_training=True):
    with slim.arg_scope(resnet_v2.resnet_arg_scope()):
        logits, endpoints = resnet_v2.resnet_v2_50(
            inputs,
            num_classes=num_classes,
            is_training=is_training,
            global_pool=True
        )
    return logits

⚠ 注意:
这里 num_classes=10 自动替换最后全连接层。


5️⃣ 加载预训练权重(关键)

假设你下载了 ImageNet 预训练权重:

resnet_v2_50.ckpt

恢复时:

variables_to_restore = slim.get_variables_to_restore(
    exclude=['resnet_v2_50/logits']
)

init_fn = slim.assign_from_checkpoint_fn(
    'resnet_v2_50.ckpt',
    variables_to_restore
)

这样可以:

✔ 加载 backbone
✖ 不加载最后分类层


6️⃣ 定义损失与优化器

loss = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-4)

7️⃣ 训练循环(简化版)

for epoch in range(10):
    for images, labels in train_dataset:
        with tf.GradientTape() as tape:
            logits = model(images, training=True)
            batch_loss = loss(labels, logits)

        gradients = tape.gradient(batch_loss, model.trainable_variables)
        optimizer.apply_gradients(zip(gradients, model.trainable_variables))

    print(f"Epoch {epoch}, Loss: {batch_loss.numpy()}")

四、推荐 Fine-tuning 策略(实战经验)

🔥 方法一:只训练最后一层(推荐起步)

for var in model.trainable_variables:
    if 'logits' not in var.name:
        var._trainable = False

优点:

  • 训练快
  • 不容易过拟合
  • CIFAR-10 通常 >85%

🔥 方法二:解冻后两层

训练 5 个 epoch 后:

for var in model.trainable_variables:
    var._trainable = True

学习率调小:

learning_rate = 1e-5

通常可以达到:

90%+ 准确率


五、效果对比

方法 CIFAR-10 准确率
从头训练 ResNet50 ~88%
ImageNet 迁移 + fine-tune 90~93%

六、为什么迁移有效?

CIFAR-10 和 ImageNet 都包含:

  • 动物
  • 交通工具
  • 物体边缘纹理

低层特征(卷积核)是通用的。


七、如果想更轻量?

推荐:

  • MobileNet
  • Inception_v3

它们在 Slim 中也有现成模型。


八、总结结构图

CIFAR10 (32x32)
        ↓
Resize 224x224
        ↓
ResNet_v2_50 Backbone (ImageNet Pretrained)
        ↓
Replace logits (10 classes)
        ↓
Fine-tune

posted @ 2026-02-22 12:28  kkman2000  阅读(18)  评论(0)    收藏  举报