ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

fastbook 第七章实战:用 fastai 从零训练 SOTA 图像分类模型——归一化、渐进式调整大小、TTA、Mixup 与标签平滑

fastbook 第七章实战:用 fastai 从零训练 SOTA 图像分类模型——归一化、渐进式调整大小、TTA、Mixup 与标签平滑 教程深度学习机器学习【免费下载链接】fastbookThe fastai book, published as Jupyter Notebooks项目地址https://gitcode.com/gh_mirrors/fa/fastbook点击查看免费下载本篇技术指南以 fastbook 仓库第七章 07_sizing_and_tta.ipynb中文译稿见 translations/cn/07_sizing_and_tta.md为骨架系统讲解在不使用迁移学习的前提下借助 Imagenette 数据集将图像分类模型从 82% 提升至 87% 准确率的五项关键技术数据归一化Normalization、渐进式调整大小Progressive Resizing、测试时间增强TTA、Mixup 数据混合与标签平滑Label Smoothing。读完本文你将掌握这些技巧在 fastai 中的完整可运行代码、各方法的适用场景与调参要点并理解其背后的训练动力学原理。为什么需要一个小 ImageNetImagenette在 fast.ai 起步阶段社区主要用三大数据集构建与测试视觉模型ImageNet约 130 万张、约 500 像素宽、1000 类、需数天训练、MNIST5 万张 28×28 灰度手写数字、CIFAR106 万张 32×32 彩色图像、10 类。问题在于小数据集无法有效泛化到大 ImageNet 场景——在 ImageNet 上有效的方法往往必须在 ImageNet 上开发和训练这曾让许多人误以为只有拥有巨型算力的研究者才能参与图像分类算法的研发。fast.ai 团队的做法是自建一个能在几分钟内完成训练、又能提供对完整 ImageNet 有价值的见解的数据集。于是他们从完整 ImageNet 中挑选了 10 个差异很大的类别用了大约三个小时构建出Imagenette——训练快、成本低且在此数据集上验证有效的算法调整在 ImageNet 上同样有效。核心方法论你拿到的数据集未必是你想要的。开发与原型设计时应追求几分钟内跑完一个实验的迭代速度若实验过慢应设法缩小数据集或简化模型。实验做得越多效果越好。获取 Imagenette 并构建基线模型from fastai.vision.all import * path untar_data(URLs.IMAGENETTE) dblock DataBlock(blocks(ImageBlock(), CategoryBlock()), get_itemsget_image_files, get_yparent_label, item_tfmsResize(460), batch_tfmsaug_transforms(size224, min_scale0.75)) dls dblock.dataloaders(path, bs64)这里沿用了第五章的预调整presizing技巧先用Resize(460)做 item 级处理再在 batch 级用aug_transforms完成随机裁剪与缩放min_scale0.75表示最小缩放比例为 75%。随后做一次不加载预训练权重的基线训练model xresnet50(n_outdls.c) learn Learner(dls, model, loss_funcCrossEntropyLossFlat(), metricsaccuracy) learn.fit_one_cycle(5, 3e-3)epochtrain_lossvalid_lossaccuracytime01.5834032.0643170.40179201:0311.2088771.2601060.60156801:0220.9252651.0361540.66430201:0330.7301900.7009060.77781901:0340.5857070.5418100.82524301:035 个 epoch 后验证准确率约82.5%。这是一个不错的起点——没有使用任何预训练模型。接下来要做的就是让这个数字继续上涨。归一化让输入分布匹配模型的预期模型训练时若输入数据是归一化的均值为 0、标准差为 1会有帮助。但大多数图像与视觉库使用 0~255 或 0~1 的像素值都不满足该条件。先看看实际批次数据长什么样对除通道轴外的所有轴求均值通道轴是轴 1x,y dls.one_batch() x.mean(dim[0,2,3]),x.std(dim[0,2,3])输出(TensorImage([0.4842, 0.4711, 0.4511], devicecuda:5), TensorImage([0.2873, 0.2893, 0.3110], devicecuda:5))均值明显偏离 0、标准差也远非 1。在 fastai 中只需添加Normalize转换即可它一次性作用于整个小批量因此应放入数据块的batch_tfms。你需要传入目标均值与标准差fastai 已内置 ImageNet 标准统计量imagenet_stats若不给Normalize传任何统计量fastai 会自动从数据的一个批次中计算出来。把get_dls封装成接受bs与size的函数便于后续渐进式调整大小复用def get_dls(bs, size): dblock DataBlock(blocks(ImageBlock, CategoryBlock), get_itemsget_image_files, get_yparent_label, item_tfmsResize(460), batch_tfms[*aug_transforms(sizesize, min_scale0.75), Normalize.from_stats(*imagenet_stats)]) return dblock.dataloaders(path, bsbs) dls get_dls(64, 224) x,y dls.one_batch() x.mean(dim[0,2,3]),x.std(dim[0,2,3])输出(TensorImage([-0.0787, 0.0525, 0.2136], devicecuda:5), TensorImage([1.2330, 1.2112, 1.3031], devicecuda:5))均值已接近 0。重新训练同一模型model xresnet50(n_outdls.c) learn Learner(dls, model, loss_funcCrossEntropyLossFlat(), metricsaccuracy) learn.fit_one_cycle(5, 3e-3)epochtrain_lossvalid_lossaccuracytime01.6328652.2500240.39133701:0211.2940411.5799320.51717701:0220.9605351.0691640.65720701:0430.7302200.7674330.77184501:0540.5778890.5506730.82449601:06归一化在从头训练时收益有限准确率仍约 82.4%但在使用预训练模型时至关重要预训练模型只认识它见过的数据类型——若预训练数据平均像素值为 0而你的数据像素最小值为 0模型看到的将完全不是它预期的输入。由此引出一条工程准则分发模型时必须同时分发归一化统计量任何用它做推断或迁移学习的人都要使用相同统计量同理使用他人训练的模型时务必弄清并匹配其归一化统计量。此前章节之所以无需手动处理是因为通过vision_learner原书cnn_learner使用预训练模型时fastai 会自动加入合适的Normalize转换——模型已用特定统计量通常来自 ImageNet预训练库可以自动填充。这一机制仅适用于预训练模型这正是从头训练时需要手动添加的原因。渐进式调整大小小图起步大图收尾2018 年 fast.ai 团队赢得 DAWNBench 比赛时最重要的创新之一非常朴素用较小的图像开始训练用较大的图像结束训练。大部分 epoch 用小数图像训练能让训练显著加快最后用大图收尾则能显著提升最终准确率——这就是渐进式调整大小Progressive Resizing。术语渐进式调整大小—— 在训练过程中逐渐使用越来越大的图像。其可行性来自卷积网络的一个特性CNN 学到的特征类型与图像尺寸无关——浅层找边缘、梯度深层找鼻子、日落等。因此训练中途改图像大小不必为模型寻找完全不同的参数。但小图与大图之间终究存在差异不应指望模型毫无变化地继续完美工作——这听起来很像迁移学习是的调整图像大小后应使用fine_tune方法。渐进式调整大小还有一个额外收益它本身是另一种数据增强形式因此可以期待更好的泛化能力。利用上文的get_dls函数先用小尺寸训练较少的 epochdls get_dls(128, 128) learn Learner(dls, xresnet50(n_outdls.c), loss_funcCrossEntropyLossFlat(), metricsaccuracy) learn.fit_one_cycle(4, 3e-3)epochtrain_lossvalid_lossaccuracytime01.9029432.4470060.40141900:3011.3152031.5729920.52576500:3021.0011990.7678860.75914900:3030.7658640.6655620.79798400:30注意每个 epoch 只耗时 30 秒。然后直接在Learner内部替换DataLoaders并微调learn.dls get_dls(64, 224) learn.fine_tune(5, 1e-3)epochtrain_lossvalid_lossaccuracytime00.9852131.6540630.56572101:06epochtrain_lossvalid_lossaccuracytime00.7068690.6896220.78454101:0710.7392170.9285410.71247201:0720.6294620.7889060.76400301:0730.4919120.5026220.83644501:0640.4148800.4313320.86333101:06最终验证准确率达到86.3%明显超过直接 224 尺寸训练的基线且小图阶段每 epoch 更快。这一增大尺寸→继续训练的过程可按需重复直到期望的图像大小——当然使用比磁盘上原图更大的尺寸不会带来任何额外收益。需要警惕的适用边界对于迁移学习渐进式调整大小可能反而损害性能。如果预训练模型与你的任务、数据集高度相似且训练图像尺寸相近那么权重几乎无需改动此时用较小图像训练可能损伤预训练权重反之若迁移任务使用的图像在尺寸、形状或风格上与预训练差异较大渐进式调整大小大概率有帮助。结论依然是那句试试看。测试时间增强TTA验证阶段也做增强此前我们只用随机裁剪做训练增强验证集始终看到同一张图。fastai 在训练用随机裁剪时验证集自动使用中心裁剪选择图像中心、不超过边缘的最大正方形区域。这在多标签场景中常出问题图像边缘的小物体可能被整体裁掉即使在宠物品种分类中鼻子的颜色等关键特征也可能被裁掉。两个候选方案完全放弃随机裁剪直接压缩或拉伸矩形图像填充正方形——但这会丢掉一项非常有效的数据增强且迫使模型学会识别被压扁/拉长的图像识别更难验证时不做单一中心裁剪而是从原始矩形图像中选取多个区域分别过模型再对预测取最大值或平均值。事实上不仅可以对不同裁剪做还可以对所有测试时增强参数的不同取值做。这就是测试时间增强TTA。术语测试时间增强TTA—— 在推断或验证期间使用数据增强创建每个图像的多个版本然后取每个增强版本预测的平均值或最大值。TTA 视数据集不同可显著提升准确率它不改变训练时间但验证/推断时间会按请求的增强图像数量成倍增加。fastai 默认使用未增强的中心裁剪图 四张随机增强图像。任何DataLoader都可以传给tta方法默认使用验证集preds,targs learn.tta() accuracy(preds, targs).item()0.8737863898277283在渐进式调整大小得到的 86.3% 基础上TTA 把准确率推到87.4%无需额外训练。代价是推断变慢若平均五张图像推断约慢 5 倍。Mixup对图像与标签同时做线性组合Mixup 由张宏毅等人在 2017 年论文《mixup: Beyond Empirical Risk Minimization》中提出是一种非常强大的数据增强技术能带来显著更高的准确率尤其适合数据不多、又没有在相似数据上预训练过的模型的场景。论文指出虽然数据增强总能带来泛化改进但该过程依赖数据集因此需要专业知识的运用。例如翻转图像很常见但该水平翻转还是垂直翻转答案取决于数据集而且翻转这种增强无法多翻。Mixup 的价值在于它可以像旋钮一样调节变化程度。对每张图像Mixup 的工作流程随机从数据集中选择另一张图像随机选择一个权重用该权重对所选图像与当前图像做加权平均——这是自变量用同一权重对两幅图像的标签做加权平均——这是因变量。伪代码如下t是加权平均的权重image2,target2 dataset[randint(0,len(dataset)] t random_float(0.5,1.0) new_image t * image1 (1-t) * image2 new_target t * target1 (1-t) * target2要让这种加权标签成立目标需要独热编码。下图是论文中的公式摘录论文中的 λ 即伪代码中的t图 7-1. Mixup 论文摘录下图展示了 Mixup 中图像线性组合的样子图 7-2. 混合教堂与加油站第三张图由 0.3×第一张 0.7×第二张构成。模型该预测教堂还是加油站正确答案是30% 教堂、70% 加油站。例如 10 个类别中教堂用索引 2、加油站用索引 7 表示独热编码分别为[0, 0, 1, 0, 0, 0, 0, 0, 0, 0] and [0, 0, 0, 0, 0, 0, 0, 1, 0, 0]最终目标[0, 0, 0.3, 0, 0, 0, 0, 0.7, 0, 0]在 fastai 中这一切由一个callback完成。Callback 是 fastai 在训练循环中注入自定义行为的机制如学习率调度、混合精度训练第十六章会详细讲解如何自建 callback眼下只需知道用Learner的cbs参数传入model xresnet50(n_outdls.c) learn Learner(dls, model, loss_funcCrossEntropyLossFlat(), metricsaccuracy, cbsMixUp()) learn.fit_one_cycle(5, 3e-3)用混合数据训练会发生什么显然训练更难——图像内容难以辨认模型必须同时预测两个标签并推断各自的权重。但过拟合似乎不再是个问题每个 epoch 看到的不是同一张图像而是两张图像的随机组合。要点与权衡Mixup 需要更多 epoch才能达到更好的准确率。原书提示可参考 fastai 仓库的examples/train_imagenette.py脚本做对照实验截至撰写时Imagenette 排行榜上超过 80 epoch 的领先结果均使用 Mixup更少 epoch 时则不用——与本章经验一致。Mixup 不止适用于照片有人通过在模型内部激活上使用 Mixup 也取得了良好结果这让 Mixup 可用于 NLP 等其他数据类型。Mixup 顺带解决了损失永远无法为 0的问题此前模型标签是 1 和 0但 softmax/sigmoid 输出永远无法等于 1 或 0导致训练把激活值越推越极端、epoch 越多越极端使用 Mixup 后标签只有恰好与同类图像混合时才为 1 或 0其余时间都是线性组合如 0.7 与 0.3模型不再被推向极端。一个潜在局限Mixup 是意外地把标签改到大于 0、小于 1——我们并未显式声明要这样修改标签。若想把标签调得离 0/1 更近或更远只能改变 Mixup 的量而这会同时改变数据增强的量可能并非所愿。更直接的处理方式是标签平滑。标签平滑让模型别那么自信在分类问题损失的理论表达中目标target是独热编码的实践中为省内存通常不真的做独热编码但计算出的损失等价。这意味着模型被训练成除一个类别返回 1 外其余全部返回 0。即使是 0.999 也不够好——模型仍会获得梯度、学到更高置信度的激活。这会鼓励过拟合并在推理时给出没有意义概率的模型即便不太确定它也会对预测类别输出 1只因它被如此训练。如果数据标注不完全干净这会非常有害。本书第二章的熊分类器中就存在错误标注、或一张图含两种熊的情况人工标注同样可能出错或在难以标注的图像上意见不一。标签平滑的做法是把所有 1 换成略小于 1 的数、所有 0 换成略大于 0 的数再训练。通过鼓励模型降低自信度标签平滑让训练对错误标注更健壮最终得到泛化更好的模型。具体实现从独热编码标签出发用 ε/N 替换所有 0ε 是希腊字母epsilon源自提出标签平滑的论文及 fastai 代码其中 N 是类别数ε 通常取 0.1意味着对标签有 10% 的不确定。由于希望标签总和为 1把原来的 1 替换为 1−εε/N。于是 Imagenette10 类中对应于索引 3 的目标变为[0.01, 0.01, 0.01, 0.91, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01]实践中无需真的独热编码标签独热编码只是用于解释与可视化。使用它只需在调用Learner时更换损失函数model xresnet50(n_outdls.c) learn Learner(dls, model, loss_funcLabelSmoothingCrossEntropy(), metricsaccuracy) learn.fit_one_cycle(5, 3e-3)与 Mixup 类似通常训练更多 epoch 后才能看到标签平滑带来的显著改进——不妨自己实验需要训练多少个 epoch 才能观察到标签平滑的改善标签平滑的原理论文视角提出标签平滑的论文Szegedy 等人这样解释其动机让与真实标签对应的 logit 远大于其余 logit 可逼近最大值 1但会引发两个问题其一模型对每个训练样本都学到把全部分配给真实标签泛化没有保证其二它鼓励最大 logit 与其余 logit 的差距拉大叠加有界的梯度 ∂ℓ/∂z_k会削弱模型的适应能力——直觉上这是因为模型对自身预测变得过于自信。交叉熵的梯度本质是output - target两者都在 0~1 之间差值有界不超过 ±1因此 SGD 每步更新也受限在迁移学习场景中更难被更新。结论与实战路线图至此你已经掌握从头训练或迁移学习场景下训练 SOTA 计算机视觉模型所需的全部要素。本章给出的完整方案在 Imagenette 上的提升路径清晰可见基线224 尺寸、无归一化82.5%加入归一化82.4%从头训练收益有限但迁移学习必备渐进式调整大小128 → 22486.3%且小图阶段每 epoch 更快测试时间增强中心裁剪 4 张增强87.4%若希望进一步冲榜Mixup 与标签平滑配合更长的训练周期可有效避免过拟合并给出更好的结果。在自己问题上动手时请记住用cbsMixUp()与loss_funcLabelSmoothingCrossEntropy()尝试更长训练试试渐进式调整大小与测试时间增强如果数据集很大不要在全集上做原型——找出一个代表整体的小子集就像 Imagenette 之于 ImageNet先做实验。本文对应的可运行代码、完整实验输出与课后练习位于 07_sizing_and_tta.ipynb清理版见 clean/07_sizing_and_tta.ipynb中文译稿见 translations/cn/07_sizing_and_tta.md。仓库运行环境可参考根目录的 environment.yml 与 requirements.txt。延伸思考原书问卷精选ImageNet 与 Imagenette 有何区别何时该在哪个上做实验为什么用预训练模型时无需操心归一化在自己的项目中实现渐进式调整大小它是否有帮助推理阶段用 TTA 比常规推理更慢还是更快为什么为什么 Mixup 能防止模型过于自信为什么 5 个 epoch 的 Mixup 训练反而更差标签平滑能解决数据中的哪些问题用 5 个类别做标签平滑时与索引 1 关联的目标是什么想在新数据集上快速原型实验第一步应该做什么赞分享教程深度学习机器学习【免费下载链接】fastbookThe fastai book, published as Jupyter Notebooks项目地址https://gitcode.com/gh_mirrors/fa/fastbook点击查看免费下载相关推荐fastai 深度学习入门实战在 fastbook 中用 Jupyter 训练你的第一个图像分类模型fastai 深度学习入门实战在 fastbook 中用 Jupyter 训练你的第一个图像分类模型 本文是 fastai 官方书籍 fastbook 第一章教程深度学习机器学习如何用fastai MixUp数据增强提升模型性能简单实用的深度学习正则化指南如何用fastai MixUp数据增强提升模型性能简单实用的深度学习正则化指南 fastai是一个强大的深度学习库提供了丰富的数据增强工具其中MixUp数人工智能深度学习DIGITS图像分类实战从零开始训练你的第一个AI模型DIGITS图像分类实战从零开始训练你的第一个AI模型 想要快速入门深度学习却苦于复杂的编程和配置DIGITSDeep Learning GPU Tra上一篇基于 Prisma 的 GraphQL 服务器托管指南Now、Apex Up 与 Serverless 部署方案解析下一篇Antmicro Jetson Nano Baseboard开源硬件如何重塑边缘AI开发边界创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表