You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ResNet在CIFAR-10上的原论文实现与训练配置问题咨询

ResNet CIFAR-10原始实现训练配置答疑

首先是引用的论文训练配置原文:

我们设置weight decay为0.0001、momentum为0.9,采用文献[13]提出的权重初始化方法与BN[16],不使用dropout。模型在2张GPU上以minibatch size=128训练:初始learning rate为0.1,训练至32k、48k iterations时将学习率除以10,训练至64k iterations时终止,上述迭代步数设置基于45k/5k的train/val split确定。训练阶段采用文献[24]的简易data augmentation方案:图像每侧padding 4像素,从padding后的图像或其horizontal flip结果中随机裁剪32×32尺寸的区域作为输入;测试阶段仅对原始32×32尺寸的图像做单视图评估。


问题1:2张GPU下minibatch size=128的具体含义

是的,这里的128指全局总batch size,2张GPU并行训练时单卡承载的batch size为64。训练时两张卡分别计算各自64个样本的梯度,做跨卡聚合后统一更新模型权重,训练动态和单卡跑128 batch size完全一致。如果用PyTorch的DDP做分布式训练,直接给单卡设置batch size=64即可。

问题2:iterations与epochs的换算规则、总训练epoch计算

先明确两个单位的标准定义:

  • 1个iteration:完成1次「前向传播-反向传播-权重更新」全流程,单次处理的样本数等于全局batch size,本配置下为128
  • 1个epoch:遍历完整份训练集(本配置下为划分后的45k训练样本)的过程

你计算的总等价epoch数是正确的,即64000 * 128 / 45000 ≈ 182.04。注意原论文的训练调度完全以iteration为计数单位,没有用epoch作为调度节点,不需要硬套整数epoch的训练逻辑。

问题3:PyTorch实现逻辑、剩余样本处理、非整数epoch节点调度

各细节的实现方案如下:

  • 剩余样本处理:原实现会丢弃每个epoch最后凑不够128个的72个剩余样本,对应PyTorch中只需将DataLoader的drop_last参数设为True,设置后每个epoch固定跑45000 // 128 = 351个iteration。
  • 学习率调整与训练终止:不要将32k、48k、64k的节点舍入到最近的整数epoch,原实现是精确按iteration数触发调整和终止的,完全可以在某个epoch的训练中途修改学习率、直接结束训练,不需要等当前epoch跑完。
  • 其他配置对齐:论文提到的He初始化就是PyTorch卷积、全连接层默认的kaiming_normal_初始化,BN层默认参数(权重初始为1、偏置初始为0)也和要求一致,模型结构中不要添加Dropout层即可;对应的数据增强方案可以直接通过torchvision的transforms接口实现,和原方案完全匹配。

核心训练循环参考实现(按iteration计数,最不容易出错):

import torch
from torch.optim import SGD
from torchvision import transforms
from torch.utils.data import DataLoader

# 1. 数据增强与数据集加载
train_transform = transforms.Compose([
    transforms.RandomCrop(32, padding=4),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010]) # CIFAR-10数据集原生统计值,和原实现对齐
])
test_transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010])
])
# 注意train_dataset是你按45k/5k划分好的训练子集
train_loader = DataLoader(
    train_dataset, batch_size=128, shuffle=True, num_workers=4, drop_last=True
)

# 2. 模型、优化器初始化
model = resnet_cifar(depth=20) # 自行实现的CIFAR版本ResNet
optimizer = SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=1e-4)
model = model.cuda()
# 多卡训练就这里包一层DDP即可,单卡batch size设64全局凑128

# 3. 按iteration计数的训练循环
total_iter = 0
max_iter = 64000
# 学习率节点:初始0.1,到32k变0.01,到48k变0.001
lr_schedule = {32000: 0.01, 48000: 0.001}

model.train()
while total_iter < max_iter:
    for x, y in train_loader:
        if total_iter >= max_iter:
            break
        # 到点直接修改优化器学习率
        if total_iter in lr_schedule:
            for param_group in optimizer.param_groups:
                param_group['lr'] = lr_schedule[total_iter]
        
        # 常规训练步骤
        x, y = x.cuda(), y.cuda()
        optimizer.zero_grad()
        loss = torch.nn.functional.cross_entropy(model(x), y)
        loss.backward()
        optimizer.step()

        total_iter += 1

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 10:51:35