深度学习框架与实例
深度学习框架
深度学习是机器学习的一个分支,它利用多层神经网络对数据进行非线性变换,从而学习到数据的内在规律,并应用到其他任务中。目前,深度学习框架有很多,如 TensorFlow、PyTorch、Caffe、Theano、Keras 等。
可以参考以下文档了解详情:
资料包中提供的代码由 pytorch 实现,可以作为深度学习入门的实践框架。
提示
“框架”一词可以泛指深度学习的各种工具、库、框架,包括 TensorFlow、PyTorch、Caffe、Theano、Keras 等,也可以指成套的、通过修改关键部分即可适用不同项目的代码。
框架结构概述
本深度学习框架是基于 PyTorch 实现的,主要用于训练和评估图像识别模型,特别是针对数据高效(Data-efficient)的图像变换器(Transformer)模型,如 DeiT(Data-Efficient Image Transformers)和 CaiT(Class-Attention Image Transformers)。以下是对这个框架的整体概述:
- 核心组件
- 模型定义:在 cait_models.py 和 models.py 中定义了模型架构,包括 DeiT 和 CaiT 模型的不同变体。这些模型基于 Vision Transformer(ViT)架构,通过修改和扩展来适应不同的任务和数据集。
- 数据集处理:datasets.py 提供了数据集加载和预处理的工具,支持 ImageNet、CIFAR 等数据集,并允许自定义数据集的处理。
- 训练与评估:engine.py 包含了训练和评估模型的函数,如 train_one_epoch 和 evaluate,这些函数处理模型的一个训练周期和测试过程。
- 损失函数:losses.py 定义了用于训练模型的损失函数,包括知识蒸馏损失(DistillationLoss)。
- 主程序:main.py 是程序的入口点,它解析命令行参数,设置训练环境,并启动训练或评估过程。
- 训练支持
- 分布式训练:通过 run_with_submitit.py 和 samplers.py 支持多节点训练,使用 Submitit 库来管理作业提交和分布式训练过程。
- 混合精度训练:使用 NativeScaler(在 engine.py 中)来实现混合精度训练,以提高训练速度和减少内存使用。
- 预处理和增强
- 数据增强:框架使用了 timm 库中的增强策略,如 RandAugment 和 RandErasing,这些策略在训练过程中自动应用。
- 模型保存与加载
- 模型保存:使用 torch.save 在训练过程中保存模型的状态字典。
- 模型加载:支持从预训练模型加载权重,也可以从断点续训。
- 日志和输出
- 日志记录:utils.py 和 loggers.py 提供了日志记录功能,允许将训练过程中的输出保存到文件中。
- 依赖管理
- 依赖文件:requirements.txt 列出了项目运行所需的 Python 依赖。
- 模型库
- 模型注册:通过 register_model 装饰器(在 models.py 和 cait_models.py 中使用),可以将不同的模型变体注册到框架中,方便通过名称加载特定的模型。
- 可扩展性
- 自定义模型和层:框架允许用户通过修改或添加新的模型定义来扩展现有的模型架构。
这个框架提供了一个完整的从数据处理、模型训练、评估到日志记录的流程,特别适合于图像识别任务,尤其是那些需要高效率和高性能的场景。
代码架构解读(选读)
关键的代码模块如下:
cait_models.py
:这个文件定义了 CaiT(Class-Attention Image Transformers)模型的架构。CaiT 是一种基于 Vision Transformer(ViT)的图像识别模型,它通过引入类注意力机制来增强模型的性能。其中:Class_Attention
:定义了类注意力(Class Attention)模块,这是 CaiT 的核心组件之一。LayerScale_Block_CA
:定义了带有类注意力和层缩放(LayerScale)的块,这是 CaiT 模型的基本构建块。Attention_talking_head
:定义了 Talking Heads Attention(THA)模块,这是另一种注意力机制。LayerScale_Block
:定义了带有层缩放的块,用于非类注意力部分。cait_models
:定义了 CaiT 模型的总体架构,包括 patch embedding、位置编码、多个 LayerScale 块等。register_model
:注册了多个 CaiT 模型变体,如 cait_XXS24_224、cait_XXS36 等,这些模型在不同的设置下进行了预训练。
datasets.py
:这个文件提供了数据集加载和预处理的工具。INatDataset
:定义了一个用于处理 iNaturalist 数据集的类,它继承自 ImageFolder。build_dataset
:根据给定的参数(如数据集类型、路径等),构建并返回相应的数据集对象。build_transform
:构建数据增强和预处理的转换链。
engine.py
:这个文件包含了训练和评估模型的函数。train_one_epoch
:执行一个训练周期,包括前向传播、损失计算、反向传播和参数更新。evaluate
:评估模型在测试集上的性能,计算准确率等指标。
hubconf.py
:这个文件定义了 PyTorch Hub 的配置,允许用户通过 PyTorch Hub 加载预训练模型。dependencies
:列出了依赖项,如 torch、torchvision 和 timm。
losses.py
:这个文件定义了用于训练模型的损失函数。DistillationLoss
:定义了知识蒸馏损失函数,它结合了基础损失和蒸馏损失。
main.py
:这是程序的入口点,它解析命令行参数,设置训练环境,并启动训练或评估过程。get_args_parser
:定义了命令行参数。main
:主函数,负责初始化训练环境、构建数据加载器、模型、优化器等,并调用训练和评估函数。
models.py
:这个文件定义了 DeiT(Data-Efficient Image Transformers)模型的架构。DistilledVisionTransformer
:定义了蒸馏版本的 Vision Transformer 模型。register_model
:注册了多个 DeiT 模型变体,如 deit_tiny_patch16_224、deit_small_patch16_224 等。
run_with_submitit.py
:这个文件提供了使用 Submitit 库进行多节点训练的脚本。parse_args
:解析命令行参数。get_shared_folder
:获取共享文件夹的路径。Trainer
:定义了训练器类,用于执行训练任务。main
:主函数,负责设置 Submitit 的执行器并提交训练作业。
samplers.py
:这个文件定义了用于分布式训练的采样器。RASampler
:定义了具有重复增强的分布式采样器,确保每个进程加载不同的数据子集。
utils.py
:这个文件提供了一些辅助函数,包括日志记录、分布式训练支持等。SmoothedValue
:用于平滑值的跟踪和计算。MetricLogger
:用于记录和日志记录度量指标。init_distributed_mode
:初始化分布式训练环境。
loggers.py
:这个文件提供了日志记录工具。Logger
:将控制台输出重定向到外部文本文件。RankLogger
:记录和显示不同测试数据集的排名匹配精度。
tools.py
:这个文件提供了一些工具函数,如文件操作、JSON 处理、图像读取等。mkdir_if_missing
:如果目录不存在,则创建目录。read_json
、write_json
:读取和写入 JSON 文件。read_image
:使用 PIL 读取图像。
主函数解析
导入模块和依赖
代码首先导入了一系列必要的模块,包括 argparse 用于解析命令行参数,datetime 和 time 用于时间处理,numpy 和 torch 用于数学运算和深度学习模型构建,以及 timm 库中的一些工具类和函数,用于模型创建、数据加载、优化器和学习率调度器的配置等。
函数定义
load_checkpoint
:加载模型检查点。它处理了文件不存在的情况和可能的编码问题(如 Python2 和 Python3 的兼容性问题)。load_pretrained_weights
:将预训练的权重加载到模型中。它处理了权重和模型不匹配的情况,并提供了详细的加载信息。get_args_parser
:定义命令行参数解析器,包括输出目录、批量大小、训练周期、模型参数、优化器参数、学习率调度参数、数据增强参数等。main
:主函数,用于初始化分布式训练模式、设置日志、配置随机种子、构建数据集、创建模型、配置优化器和学习率调度器、训练模型并保存检查点。
主要逻辑
- 初始化和配置:设置日志记录、随机种子、CUDA 环境等。
- 数据加载:根据是否使用重复数据增强(repeated_aug)来配置数据加载器。
- 模型创建:根据指定的模型参数创建模型,并将其移动到 GPU 上。
- EMA(指数移动平均):如果启用,创建模型的 EMA 版本。
- 分布式训练:如果启用分布式训练,将模型包装在 DistributedDataParallel 中。
- 优化器和学习率调度器:根据配置创建优化器和学习率调度器。
- 损失函数:根据是否使用混合训练(mixup)或标签平滑来选择合适的损失函数。
- 训练和评估:进行模型训练,并在每个周期结束时评估模型性能。如果达到最大准确率,更新最大准确率并记录。
训练流程
- 训练周期:在每个训练周期中,使用 train_one_epoch 函数进行训练,并在每个周期结束时更新学习率调度器。
- 检查点保存:在每个周期结束时,如果指定了输出目录,保存模型检查点。
- 性能评估:定期评估模型在验证集上的性能,并打印准确率。
调参方式
以下是代码中关键参数的相关解释:
基本参数
--output_dir
: 保存模型和日志的目录。建议设置一个专门的目录以便于管理和备份。--batch-size
: 每个 GPU 上的批量大小。根据 GPU 内存调整,较大的批量大小可能提高训练效率,但也可能影响模型收敛。--epochs
: 训练周期数。通常需要多次实验来确定最佳的训练周期数,以避免过拟合或欠拟合。--print_epoch
: 打印训练状态的周期间隔。根据需要调整,以便监控训练进度。
模型参数
--model
: 模型名称。根据任务需求选择合适的模型,例如 seresnext50_32x4d。--input-size
: 输入图像的大小。根据模型和数据集的要求调整。--drop
,--drop-path
,--drop-block
: 控制模型中的 dropout 比例。dropout 有助于防止过拟合,但过高的比例可能导致模型欠拟合。
优化器参数
--opt
: 优化器类型。常用的有 SGD 和 Adam,根据任务和模型特性选择。--opt-eps
,--opt-betas
: 优化器参数,根据具体优化器的文档调整。--momentum
: SGD 动量参数。通常在 0.9 左右,有助于加速收敛。--weight-decay
: 控制权重衰减,防止过拟合。
学习率调度参数
--sched
: 学习率调度器类型。常用的有 cosine 和 step,根据训练动态选择。--lr
: 学习率。根据模型和任务调整,通常需要多次实验来找到最佳值。--warmup-lr
,--min-lr
: 学习率预热和最小值,用于精细控制学习率变化。
数据增强参数
--color-jitter
,--aa
: 数据增强策略,增加模型泛化能力。根据数据集特性调整。--smoothing:
标签平滑参数。有助于模型训练更加平滑,避免极端预测。--repeated_aug
: 是否使用重复数据增强。对于某些任务可能提高性能,但会增加训练时间。
混合训练参数
--mixup
,--cutmix
: 混合训练参数,可以提高模型鲁棒性。根据任务需求调整混合比例。--mixup-prob
,--switch-prob
: 混合训练的概率参数。根据需要调整,以控制混合训练的频率。
分布式训练参数
--world_size
,--dist_url
: 分布式训练配置。在多 GPU 训练时设置。
其他参数
--seed
: 随机种子。确保实验可复现。--resume
: 从检查点恢复训练。用于继续之前的训练。--pin-mem
: 是否固定 CPU 内存。在某些情况下可以提高数据加载效率。
调参是一个迭代和实验的过程,建议从默认值开始,根据模型在验证集上的表现逐步调整。
如有需要,可以使用如下调参函数,或参照其中的注释来自定义参数:
python
def get_params():
params = {
# 基本参数
'output_dir': '../deit-main/checkpoint/', # 保存模型和日志的目录,建议设置一个专门的目录
'batch_size': 64, # 每个GPU上的批量大小,根据GPU内存调整,推荐范围32-256
'epochs': 240, # 训练周期数,推荐至少100周期,根据验证集性能调整
'print_epoch': 2, # 打印训练状态的周期间隔,根据需要调整,推荐1-10
# 模型参数
'model': 'seresnext50_32x4d', # 模型名称,根据任务需求选择合适的模型
'input_size': 224, # 输入图像的大小,根据模型和数据集的要求调整
'drop': 0.01, # Dropout比例,推荐范围0-0.2,防止过拟合
'drop_path': 0.1, # Stochastic Depth比例,推荐范围0-0.5
'drop_block': None, # DropBlock比例,推荐范围0-0.5
# 优化器参数
'opt': 'sgd', # 优化器类型,推荐SGD或Adam
'opt_eps': 1e-8, # 优化器Epsilon值,根据优化器类型调整
'opt_betas': None, # 优化器Betas值,根据优化器类型调整
'momentum': 0.9, # SGD动量参数,推荐范围0.9-0.99
'weight_decay': 0.0001, # 权重衰减,用于防止过拟合,推荐范围0.0001-0.01
# 学习率调度参数
'sched': 'cosine', # 学习率调度器类型,推荐cosine或step
'lr': 0.06, # 学习率,根据模型和任务调整,推荐范围1e-4-1e-2
'lr_noise': None, # 学习率噪声参数,用于周期性调整学习率
'lr_noise_pct': 0.67, # 学习率噪声百分比,用于周期性调整学习率
'lr_noise_std': 1.0, # 学习率噪声标准差,用于周期性调整学习率
'warmup_lr': 1e-6, # 预热学习率,推荐范围1e-6-1e-4
'min_lr': 1e-5, # 最小学习率,推荐范围1e-6-1e-4
'decay_epochs': 30, # 学习率衰减周期,根据训练周期调整
'warmup_epochs': 5, # 学习率预热周期,推荐范围1-10
'cooldown_epochs': 10, # 学习率冷却周期,推荐范围5-20
'patience_epochs': 10, # 学习率调度器的耐心周期,推荐范围5-20
'decay_rate': 0.1, # 学习率衰减率,推荐范围0.1-0.5
# 数据增强参数
'color_jitter': 0.4, # 颜色抖动因子,推荐范围0-0.5
'aa': 'rand-m9-mstd0.5-inc0,1,2,3,7,8,9,10,11,12,13,14,6', # AutoAugment策略,根据数据集特性调整
'smoothing': 0.1, # 标签平滑参数,推荐范围0-0.2
'train_interpolation': 'bicubic', # 训练时的插值方法,推荐bicubic
'repeated_aug': False, # 是否使用重复数据增强,根据任务需求调整
'no_aug': False, # 是否禁用数据增强,根据任务需求调整
'use_prefetcher': False, # 是否使用数据预取,根据系统性能调整
'load_pretrain': False, # 是否加载预训练权重,根据任务需求调整
'pretrain_address': '', # 预训练权重的地址,根据需要设置
# 混合训练参数
'reprob': 0.25, # 随机擦除概率,推荐范围0-0.5
'remode': 'pixel', # 随机擦除模式,根据数据特性调整
'recount': 1, # 随机擦除次数,推荐范围1-3
'resplit': False, # 是否在第一次增强时不使用随机擦除,根据数据特性调整
'mixup_switch': True, # 是否启用Mixup,根据任务需求调整
'mixup': 0.8, # Mixup比例,推荐范围0-1
'cutmix': 1.0, # Cutmix比例,推荐范围0-1
'cutmix_minmax': None, # Cutmix最小/最大比例,根据任务需求调整
'mixup_prob': 1.0, # 执行Mixup或Cutmix的概率,推荐范围0-1
'mixup_switch_prob': 0.5, # 在Mixup和Cutmix都启用时切换到Cutmix的概率,推荐范围0-1
'mixup_mode': 'batch', # 应用Mixup/Cutmix的方式,推荐batch
# 数据集参数
'data_path': '../OPTIMAL-31-37', # 数据集路径,根据实际路径设置
'data_set': 'IMNET', # 数据集类型,根据任务需求选择
'inat_category': 'name', # INAT数据集的语义粒度,根据任务需求选择
'device': 'cuda', # 训练/测试使用的设备,推荐使用cuda
'seed': 0, # 随机种子,确保实验可复现
'resume': '', # 恢复训练的检查点路径,根据需要设置
'start_epoch': 0, # 开始训练的周期,根据需要调整
'eval': False, # 是否仅进行评估,根据需要设置
'num_workers': 10, # DataLoader的工作线程数,根据系统性能调整
'pin_mem': True, # 是否固定CPU内存,根据系统性能调整
# 分布式训练参数
'world_size': 1, # 分布式训练进程数,根据GPU数量调整
'dist_url': 'env://', # 分布式训练的URL,根据实际环境设置
}
return params