PyTorch初探:利用AlexNet神经网络开启猫狗判别之旅

文章标题:

PyTorch浅探:利用AlexNet神经网络开启猫犬识别之旅

文章内容:基于之前的博客 pytorch入门 - AlexNet神经网络,并借助Kaggle 的 Dogs vs Cats Redux 数据集,实现一个基于 AlexNet 的二分类模型来识别猫与狗。

完整流程包含数据准备、归一化处理、模型定义、训练增强、验证以及结果可视化。

一、数据集准备与预处理

import os
import shutil

def separate_data(ROOT_TRAIN):
    cat_directory = os.path.join(ROOT_TRAIN, "cat")
    dog_directory = os.path.join(ROOT_TRAIN, "dog")
    os.makedirs(cat_directory, exist_ok=True)
    os.makedirs(dog_directory, exist_ok=True)

    for file_name in os.listdir(ROOT_TRAIN):
        if file_name.startswith("cat") and file_name.endswith(".jpg"):
            shutil.move(os.path.join(ROOT_TRAIN, file_name), 
                        os.path.join(cat_directory, file_name))
        elif file_name.startswith("dog") and file_name.endswith(".jpg"):
            shutil.move(os.path.join(ROOT_TRAIN, file_name), 
                        os.path.join(dog_directory, file_name))

​优化原因​ ​:
分类任务需要明确标签与数据的对应关系。通过创建cat/dog子目录并移动图片,可直接利用PyTorch的ImageFolder自动生成标签,避免手动标注出错。

二、数据归一化参数计算

def compute_normalization_parameters(dataset_path):
    transform_sequence = transforms.Compose([
        transforms.Resize((227, 227)),
        transforms.ToTensor()
    ])
    data_collection = ImageFolder(dataset_path, transform=transform_sequence)
    data_loader_obj = DataLoader(data_collection, batch_size=32, num_workers=4, shuffle=False)

    mean_value = 0.0
    std_value = 0.0
    for data_batch, _ in data_loader_obj:
        batch_item_count = data_batch.size(0)
        data_batch = data_batch.view(batch_item_count, data_batch.size(1), -1)
        mean_value += data_batch.mean(2).sum(0)
        std_value += data_batch.std(2).sum(0)
    return mean_value / len(data_collection), std_value / len(data_collection)

​关键点​ ​:

  1. ​输入尺寸统一​:AlexNet要求固定输入尺寸227×227,需提前调整图像大小
  2. ​通道级归一化​:对RGB三通道分别计算均值和标准差,消除光照差异影响,加快模型收敛
  3. ​离线计算​:不在训练时实时计算,提升数据加载效率

三、AlexNet模型针对性修改

class AlexNetVariant(nn.Module):
    def __init__(self):
        super().__init__()
        # 修改1:输入通道调整为3 (RGB)
        self.conv_first_layer = nn.Conv2d(3, 96, kernel_size=11, stride=4) 
        # ... (中间层省略)
        # 修改2:输出层调整为2分类
        self.fc_last_layer = nn.Linear(4096, 2)  

        # 修改3:降低Dropout比例
        self.dropout_layer = nn.Dropout(0.2)  # 原论文为0.5

​优化逻辑​

  1. ​输入通道适配​:原始AlexNet针对ImageNet的1000类设计,此处为猫狗二分类,修改输出层维度为2
  2. ​降低过拟合风险​
    • 猫狗数据集(25k张)远小于ImageNet(1400万张)
    • 降低Dropout比例(0.5→0.2)保留更多特征信息,避免欠拟合
  3. ​权重初始化​:采用Kaiming初始化,适配ReLU激活函数特性,缓解梯度消失

四、数据增强策略

train_transformation = transforms.Compose([
    transforms.RandomHorizontalFlip(p=0.5),
    transforms.RandomRotation(10),
    transforms.RandomResizedCrop(227, scale=(0.8, 1.0)),
    transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.488, 0.455, 0.417], 
                         std=[0.226, 0.221, 0.221])
])

​增强目的​

  1. ​提升泛化能力​:通过旋转、裁剪、色彩扰动模拟真实场景多样性,防止模型记忆固定模式
  2. ​克服数据局限​:小数据集易过拟合,增强等效扩大数据规模
  3. ​对齐测试环境​:测试阶段用相同预处理,保证输入分布一致

五、训练过程优化

# 1. 学习率调整
optimizer = optim.Adam(model.parameters(), lr=1e-4)  # 原常用值0.001

# 2. 训练-验证集拆分
train_data_set_part, val_data_set_part = random_split(dataset, [0.8, 0.2])

# 3. 早停机制
if val_acc > best_acc:
    best_model_weights = copy.deepcopy(model.state_dict())

​关键技术点​

  1. ​低学习率策略​
    • 预训练模型特征完备,低学习率(1e-4)避免破坏已有特征
    • 微调阶段需精细调整,高学习率易震荡
  2. ​验证集独立划分​
    • 20%数据作验证集,监控泛化能力
    • 测试集不参与训练,保证评估客观
  3. ​混合精度训练(可选)​
    使用torch.cuda.amp自动混合精度,提升训练速度30%+(需GPU支持)

关键优化总结

优化点 原始值 调整值 作用
输入通道 1 (灰度) 3 (RGB) 适配彩色图像
输出维度 1000 2 二分类需求
Dropout率 0.5 0.2 防欠拟合
学习率 0.001 0.0001 稳定微调
数据增强 5种变换 提升泛化性

相关文章

暂无评论

暂无评论...