目标检测(Object Detection)是计算机视觉领域中的核心研究方向之一,其目标是在图像或视频中同时完成目标类别识别 和目标位置定位。与图像分类只输出类别不同,目标检测需要输出目标的类别及其在图像中的边界框(Bounding Box),因此在自动驾驶、智能安防、视频监控、工业检测等领域具有广泛应用。
随着深度学习的发展,基于卷积神经网络(CNN)的目标检测算法取得了突破性进展。然而,目标检测模型通常结构复杂、参数量大,对训练数据规模和计算资源要求较高。迁移学习(Transfer Learning)通过利用在大规模数据集(如 ImageNet、COCO)上预训练的模型,将已有知识迁移到新任务中,显著降低了训练成本,提高了模型性能。PyTorch 作为主流深度学习框架,为目标检测与迁移学习提供了灵活高效的实现方式。
目标检测算法
1. 传统目标检测方法
早期目标检测主要基于人工特征与浅层分类器相结合的方法,例如:
- Haar 特征 + AdaBoost(如 Viola-Jones 人脸检测)
- HOG 特征 + SVM
- DPM(可变形部件模型)
这类方法依赖人工特征设计,鲁棒性和泛化能力有限,在复杂场景下效果较差。
2. 深度学习目标检测算法
深度学习引入后,目标检测进入端到端学习阶段,主流算法主要分为两类:
(1)两阶段检测算法(Two-stage)
典型代表为 R-CNN 系列:
- R-CNN
- Fast R-CNN
- Faster R-CNN
特点:
- 第一阶段生成候选区域(Region Proposal)
- 第二阶段对候选区域进行分类和边界框回归
- 检测精度高,但速度相对较慢
(2)单阶段检测算法(One-stage)
典型代表包括:
- YOLO(You Only Look Once)
- SSD(Single Shot Detector)
- RetinaNet
特点:
- 不显式生成候选框
- 直接在特征图上预测类别和位置
- 检测速度快,适合实时应用
迁移学习原理
1. 迁移学习的基本思想
迁移学习的核心思想是:将源任务中学到的知识迁移到目标任务中。在目标检测中,通常使用在大规模数据集上预训练的模型作为初始权重,而不是从零开始训练。
迁移学习的优势包括:
- 减少对大规模标注数据的依赖
- 加快模型收敛速度
- 提高小样本场景下的检测精度
- 降低过拟合风险
2. 迁移学习的常见策略
- 特征提取(Feature Extraction)
- 冻结 backbone(如 ResNet、VGG)
- 仅训练检测头(分类和回归层)
- 微调(Fine-tuning)
- 解冻部分或全部网络参数
- 使用较小学习率进行训练
- 分阶段训练
- 先冻结 backbone 训练检测头
- 再逐步解冻 backbone 进行整体微调
PyTorch 中的目标检测框架
PyTorch 官方在 torchvision 中提供了成熟的目标检测模型,便于快速实现迁移学习,包括:
- Faster R-CNN
- Mask R-CNN
- RetinaNet
- SSD
这些模型通常采用 ResNet、MobileNet 等作为 backbone,并提供 ImageNet 或 COCO 的预训练权重。
基于 PyTorch 的迁移学习实现流程
1. 数据集准备
目标检测数据集通常采用以下标注格式:
- VOC 格式(XML)
- COCO 格式(JSON)
- 自定义格式(需转换)
每条样本一般包含:
- 图像
- 边界框坐标(xmin, ymin, xmax, ymax)
- 类别标签
在 PyTorch 中,需要自定义 Dataset 类,返回如下数据结构:
- image:Tensor
- target:字典(包含 boxes、labels 等)
2. 模型加载与修改
以 Faster R-CNN 为例,迁移学习主要涉及:
- 加载预训练模型
- 替换分类头(预测类别数需与新任务一致)
常见 backbone:
- ResNet-50 / ResNet-101
- MobileNet(轻量化)
3. 冻结与解冻参数
通过设置 requires_grad 控制参数是否参与训练:
- 冻结 backbone:减少计算量,防止过拟合
- 微调 backbone:提升特定领域的特征表达能力
4. 损失函数与优化器
目标检测模型通常包含多种损失:
- 分类损失(Cross Entropy / Focal Loss)
- 边界框回归损失(Smooth L1 / GIoU)
常用优化器:
- SGD(带动量)
- AdamW
学习率策略对迁移学习效果影响显著,一般采用较小初始学习率。
5. 训练与评估
训练过程包括:
- 前向传播
- 损失计算
- 反向传播
- 参数更新
评估指标常用:
- mAP(mean Average Precision)
- Precision / Recall
- FPS(实时性评估)
PyTorch 目标检测迁移学习完整示例(Faster R-CNN)
1. 环境依赖
bash
pip install torch torchvision opencv-python numpy
PyTorch ≥ 1.10,torchvision ≥ 0.11
2. 数据集格式说明
假设数据集结构如下(VOC 风格):
yaml
dataset/
├── images/
│ ├── 0001.jpg
│ ├── 0002.jpg
├── labels/
│ ├── 0001.txt
│ ├── 0002.txt
每个 .txt 内容(YOLO 简化格式):
nginx
class_id xmin ymin xmax ymax
3. 自定义 Dataset
python
import os
import torch
import cv2
from torch.utils.data import Dataset
class DetectionDataset(Dataset):
def __init__(self, img_dir, label_dir, transforms=None):
self.img_dir = img_dir
self.label_dir = label_dir
self.transforms = transforms
self.images = os.listdir(img_dir)
def __len__(self):
return len(self.images)
def __getitem__(self, idx):
img_name = self.images[idx]
img_path = os.path.join(self.img_dir, img_name)
label_path = os.path.join(
self.label_dir, img_name.replace('.jpg', '.txt')
)
# 读取图像
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = torch.from_numpy(img).float() / 255.0
img = img.permute(2, 0, 1)
boxes = []
labels = []
with open(label_path) as f:
for line in f.readlines():
cls, xmin, ymin, xmax, ymax = map(float, line.split())
boxes.append([xmin, ymin, xmax, ymax])
labels.append(int(cls) + 1) # 0 保留给 background
target = {
"boxes": torch.tensor(boxes, dtype=torch.float32),
"labels": torch.tensor(labels, dtype=torch.int64),
}
return img, target
4. 加载预训练模型并修改检测头(迁移学习核心)
python
import torchvision
from torchvision.models.detection.faster_rcnn import FastRCNNPredictor
def get_model(num_classes):
# 加载 COCO 预训练模型
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(
weights="DEFAULT"
)
# 替换分类头
in_features = model.roi_heads.box_predictor.cls_score.in_features
model.roi_heads.box_predictor = FastRCNNPredictor(
in_features, num_classes
)
return model
num_classes = 目标类别数 + 1(background)
5. 冻结 Backbone(可选)
def freeze_backbone(model):
for name, param in model.backbone.body.named_parameters():
param.requires_grad = False
6. 训练代码
python
import torch
from torch.utils.data import DataLoader
from torch.optim import SGD
def collate_fn(batch):
return tuple(zip(*batch))
def train():
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
dataset = DetectionDataset(
"dataset/images",
"dataset/labels"
)
loader = DataLoader(
dataset,
batch_size=2,
shuffle=True,
collate_fn=collate_fn
)
num_classes = 2 # 1 类目标 + background
model = get_model(num_classes)
model.to(device)
freeze_backbone(model)
params = [p for p in model.parameters() if p.requires_grad]
optimizer = SGD(params, lr=0.005, momentum=0.9, weight_decay=0.0005)
model.train()
for epoch in range(10):
total_loss = 0.0
for imgs, targets in loader:
imgs = [img.to(device) for img in imgs]
targets = [{k: v.to(device) for k, v in t.items()} for t in targets]
loss_dict = model(imgs, targets)
losses = sum(loss for loss in loss_dict.values())
optimizer.zero_grad()
losses.backward()
optimizer.step()
total_loss += losses.item()
print(f"Epoch [{epoch+1}/10], Loss: {total_loss:.4f}")
torch.save(model.state_dict(), "detector.pth")
if __name__ == "__main__":
train()
7. 推理(Inference)示例
python
import torchvision.transforms as T
import matplotlib.pyplot as plt
def inference(img_path):
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = get_model(num_classes=2)
model.load_state_dict(torch.load("detector.pth"))
model.to(device)
model.eval()
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
transform = T.Compose([T.ToTensor()])
input_tensor = transform(img).unsqueeze(0).to(device)
with torch.no_grad():
outputs = model(input_tensor)
boxes = outputs[0]["boxes"].cpu().numpy()
scores = outputs[0]["scores"].cpu().numpy()
for box, score in zip(boxes, scores):
if score > 0.5:
x1, y1, x2, y2 = map(int, box)
cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 0), 2)
plt.imshow(img)
plt.axis("off")
plt.show()
结论
目标检测作为计算机视觉的重要研究方向,在深度学习和工程应用中占据核心地位。迁移学习通过复用预训练模型的特征表达能力,有效解决了目标检测模型训练成本高、数据需求大的问题。PyTorch 以其灵活的动态图机制和完善的生态,为目标检测迁移学习提供了高效、可扩展的实现平台。