迁移学习实战:基于预训练模型 ResNet50 微调实现自定义图像分类
迁移学习通过复用预训练模型的知识,显著提升新任务的训练效率和性能。ResNet50 是一个在 ImageNet 数据集上预训练的深度残差网络,包含 50 层结构,具有强大的图像特征提取能力。以下我将逐步指导您如何微调 ResNet50 实现自定义图像分类任务,整个过程包括数据准备、模型修改、训练和评估。代码基于 TensorFlow/Keras 框架实现。
·
迁移学习实战:基于预训练模型 ResNet50 微调实现自定义图像分类
迁移学习通过复用预训练模型的知识,显著提升新任务的训练效率和性能。ResNet50 是一个在 ImageNet 数据集上预训练的深度残差网络,包含 50 层结构,具有强大的图像特征提取能力。以下我将逐步指导您如何微调 ResNet50 实现自定义图像分类任务,整个过程包括数据准备、模型修改、训练和评估。代码基于 TensorFlow/Keras 框架实现。
步骤 1: 环境准备
确保安装必要库:
- Python 3.7+
- TensorFlow 2.x
- Keras
- NumPy
- OpenCV 或 Pillow(图像处理)
使用 pip 安装:
pip install tensorflow numpy opencv-python
步骤 2: 数据准备
自定义数据集需组织为以下目录结构(以类别分文件夹):
custom_dataset/
├── train/
│ ├── class1/
│ ├── class2/
│ └── ...
└── val/
├── class1/
├── class2/
└── ...
- 图像预处理:统一调整为 $224 \times 224$ 像素(ResNet50 输入尺寸),并归一化像素值到 $[0, 1]$。
- 数据增强:防止过拟合,使用旋转、缩放等变换。
步骤 3: 加载并修改 ResNet50 模型
预训练 ResNet50 的顶层(全连接层)需替换为自定义分类层:
import tensorflow as tf
from tensorflow.keras.applications import ResNet50
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# 定义数据集路径和参数
train_dir = 'custom_dataset/train'
val_dir = 'custom_dataset/val'
batch_size = 32
num_classes = 10 # 替换为您的类别数
# 数据生成器(含增强)
train_datagen = ImageDataGenerator(
rescale=1./255,
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip=True,
validation_split=0.2
)
train_generator = train_datagen.flow_from_directory(
train_dir,
target_size=(224, 224),
batch_size=batch_size,
class_mode='categorical',
subset='training'
)
val_generator = train_datagen.flow_from_directory(
val_dir,
target_size=(224, 224),
batch_size=batch_size,
class_mode='categorical',
subset='validation'
)
# 加载预训练 ResNet50(不含顶层)
base_model = ResNet50(
weights='imagenet',
include_top=False,
input_shape=(224, 224, 3)
)
# 冻结所有卷积层(保留特征提取能力)
for layer in base_model.layers:
layer.trainable = False
# 添加自定义顶层
x = base_model.output
x = GlobalAveragePooling2D()(x) # 全局平均池化替代全连接
x = Dense(1024, activation='relu')(x) # 新增全连接层
predictions = Dense(num_classes, activation='softmax')(x) # 输出层
# 构建最终模型
model = Model(inputs=base_model.input, outputs=predictions)
步骤 4: 编译模型
- 使用 Adam 优化器,学习率设为 $0.0001$(微调时宜小)。
- 损失函数为分类交叉熵:$ \text{loss} = -\sum_{i} y_i \log(\hat{y}_i) $。
- 评估指标为准确率。
model.compile(
optimizer=Adam(learning_rate=0.0001),
loss='categorical_crossentropy',
metrics=['accuracy']
)
步骤 5: 训练模型
- 训练周期(epochs)根据数据集大小调整(建议 10-50)。
- 使用验证集监控过拟合。
epochs = 20
history = model.fit(
train_generator,
steps_per_epoch=train_generator.samples // batch_size,
epochs=epochs,
validation_data=val_generator,
validation_steps=val_generator.samples // batch_size
)
步骤 6: 评估与预测
- 评估性能:在测试集计算准确率。
- 预测新图像:预处理后输入模型。
# 评估模型
test_loss, test_acc = model.evaluate(val_generator)
print(f'测试准确率: {test_acc:.4f}')
# 预测单张图像
import cv2
import numpy as np
def predict_image(image_path):
img = cv2.imread(image_path)
img = cv2.resize(img, (224, 224))
img = img / 255.0 # 归一化
img = np.expand_dims(img, axis=0) # 添加批次维度
pred = model.predict(img)
class_idx = np.argmax(pred)
return f'预测类别: {class_idx}, 置信度: {np.max(pred):.2f}'
注意事项
- 数据质量:确保数据集平衡,每类样本不少于 100 张。
- 微调策略:
- 初始训练时冻结卷积层(如上代码),后期可解冻部分层进一步微调。
- 学习率使用余弦退火等调度策略,公式可表示为:$$ \eta_t = \eta_{\min} + \frac{1}{2}(\eta_{\max} - \eta_{\min})(1 + \cos(\frac{t}{T}\pi)) $$。
- 过拟合处理:添加 Dropout 层或 L2 正则化。
- 硬件需求:GPU 加速训练(如 NVIDIA CUDA)。
通过以上步骤,您能高效实现自定义图像分类任务。完整代码可在 Colab 或本地运行,实际准确率可达 90%+(取决于数据集)。如需优化,可尝试不同预训练模型(如 VGG 或 EfficientNet)或调整超参数。
更多推荐
所有评论(0)