1. 项目背景与核心价值
猫狗图像分类是计算机视觉领域的经典入门项目,2012年AlexNet在ImageNet竞赛中一战成名,首次证明深度学习在图像识别领域的巨大潜力。这个项目看似简单,却涵盖了数据预处理、模型构建、训练调优等深度学习全流程关键技术点。
我选择复现这个项目有三个原因:首先,AlexNet作为CNN里程碑式模型,其设计思想至今仍影响现代网络架构;其次,猫狗数据集规模适中(约2.5万张图片),适合快速验证模型效果;最重要的是,通过这个项目可以掌握图像分类任务的完整技术栈,为后续更复杂的CV任务打下基础。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境配置与数据准备
2.1 开发环境搭建
推荐使用Python 3.8+和PyTorch 1.12+环境,硬件配置至少需要4GB显存的GPU(如GTX 1060)。安装核心依赖:
bash复制pip install torch torchvision pillow matplotlib
注意:如果使用CUDA加速,需确保驱动版本与PyTorch版本匹配。可通过
torch.cuda.is_available()验证GPU是否可用。
2.2 数据集处理
Kaggle提供的Dogs vs Cats数据集包含12500张猫和12500张狗的图像。建议按以下结构组织数据:
code复制data/
train/
cat/
dog/
val/
cat/
dog/
使用torchvision.datasets.ImageFolder加载数据时,会自动根据目录结构生成标签。典型的数据增强配置:
python复制from torchvision import transforms
train_transform = transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
技巧:在验证集上不要使用随机裁剪,建议用
transforms.Resize(256)+transforms.CenterCrop(224)保持评估一致性。
3. AlexNet模型实现详解
3.1 网络架构解析
原始AlexNet包含5个卷积层和3个全连接层,由于现代GPU显存更大,我们可以简化部分设计:
python复制import torch.nn as nn
class AlexNet(nn.Module):
def __init__(self, num_classes=2):
super().__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(64, 192, kernel_size=5, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(192, 384, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(384, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
)
self.avgpool = nn.AdaptiveAvgPool2d((6, 6))
self.classifier = nn.Sequential(
nn.Dropout(),
nn.Linear(256*6*6, 4096),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Linear(4096, num_classes),
)
def forward(self, x):
x = self.features(x)
x = self.avgpool(x)
x = torch.flatten(x, 1)
x = self.classifier(x)
return x
关键改进点:
- 移除了原始论文中的LRN层(现代实践表明效果有限)
- 使用AdaptiveAvgPool替代固定尺寸池化,增强输入尺寸灵活性
- 输出层改为2个神经元(猫/狗二分类)
3.2 模型初始化技巧
使用Kaiming初始化能有效解决ReLU网络的梯度问题:
python复制def init_weights(m):
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
if m.bias is not None:
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
nn.init.normal_(m.weight, 0, 0.01)
nn.init.constant_(m.bias, 0)
model.apply(init_weights)
4. 模型训练与调优
4.1 训练参数配置
使用交叉熵损失和带动量的SGD优化器:
python复制criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.005, momentum=0.9)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1)
推荐batch size设为128(根据显存调整),训练30-50个epoch。添加早停机制(patience=5)防止过拟合。
4.2 训练过程监控
使用TensorBoard记录关键指标:
python复制from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter()
for epoch in range(epochs):
# 训练代码...
writer.add_scalar('Loss/train', train_loss, epoch)
writer.add_scalar('Accuracy/train', train_acc, epoch)
# 验证代码...
writer.add_scalar('Loss/val', val_loss, epoch)
writer.add_scalar('Accuracy/val', val_acc, epoch)
常见问题:如果验证准确率波动大,尝试减小学习率(如0.001)或增加batch size
5. 模型评估与部署
5.1 性能评估指标
除了准确率,还应计算混淆矩阵和分类报告:
python复制from sklearn.metrics import classification_report
with torch.no_grad():
outputs = model(images)
_, preds = torch.max(outputs, 1)
print(classification_report(labels.cpu(), preds.cpu(),
target_names=['cat', 'dog']))
优质模型应达到验证集准确率>90%。如果出现严重过拟合(训练准确率>>验证准确率),可尝试:
- 增加Dropout比例(如0.5)
- 添加L2正则化(weight_decay=1e-4)
- 使用更多数据增强
5.2 模型部署示例
使用Flask创建简易API服务:
python复制from flask import Flask, request, jsonify
from PIL import Image
import io
app = Flask(__name__)
model.eval()
@app.route('/predict', methods=['POST'])
def predict():
file = request.files['file']
img_bytes = file.read()
img = Image.open(io.BytesIO(img_bytes))
img_tensor = test_transform(img).unsqueeze(0)
with torch.no_grad():
output = model(img_tensor)
pred = torch.argmax(output).item()
return jsonify({'class': 'dog' if pred else 'cat'})
6. 进阶优化方向
6.1 模型轻量化
将全连接层替换为全局平均池化:
python复制self.classifier = nn.Sequential(
nn.Dropout(0.5),
nn.Linear(256, num_classes)
)
def forward(self, x):
x = self.features(x)
x = self.avgpool(x)
x = torch.flatten(x, 1)
x = self.classifier(x)
return x
6.2 迁移学习实践
使用预训练模型快速收敛:
python复制from torchvision.models import alexnet
model = alexnet(pretrained=True)
# 替换最后一层
model.classifier[6] = nn.Linear(4096, 2)
这种方法通常只需训练5-10个epoch就能达到较好效果。
6.3 可视化分析
使用Grad-CAM观察模型关注区域:
python复制from torchcam.methods import GradCAM
cam_extractor = GradCAM(model, 'features.10')
with torch.no_grad():
out = model(input_tensor)
activation_map = cam_extractor(out.squeeze(0).argmax().item(), out)
可视化结果能帮助理解模型是否真正学会了识别动物特征,而非背景噪声。
