🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎
📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】 深度学习【DL】
🖍foreword
✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。
如果你对这个系列感兴趣的话,可以关注订阅哟👋
文章目录
本章介绍了用于训练图像分类模型和获得最先进结果的更高级技术。如果您想了解有关深度学习的其他应用的更多信息,您可以跳过它,稍后再回来阅读——后面的章节不会假设您已经掌握了这些材料。
我们将了解什么是标准化、一种称为 Mixup 的强大数据增强技术、渐进式调整大小方法和测试时间增强。为了展示所有这些,我们将从头开始训练一个模型(不使用迁移学习),方法是使用 ImageNet 的子集称为 Imagenette。它包含与原始 ImageNet 数据集非常不同的 10 个类别的子集,可以在我们想要进行实验时更快地进行训练。
这将比我们以前的数据集更难做好,因为我们使用的是全尺寸、全彩色的图像,这些图像是不同大小、不同方向、不同照明等对象的照片。因此,在本章中,我们将介绍充分利用数据集的重要技术,尤其是当您从头开始训练或使用迁移学习在与预训练模型完全不同的数据集上训练模型时用过的。
当 fast.ai 刚开始时,人们使用三个主要数据集来构建和测试计算机视觉模型:
ImageNet
130 万张各种尺寸的图像,大约 500 像素,1000 个类别,需要几天的时间来训练
MNIST
CIFAR10
问题是较小的数据集没有有效地泛化到大型 ImageNet 数据集。在 ImageNet 上运行良好的方法通常必须在 ImageNet 上开发和训练。这导致许多人认为,只有拥有庞大计算资源的研究人员才能有效地为开发图像分类算法做出贡献。
我们认为这似乎不太可能是真的。我们从未见过一项研究表明 ImageNet 恰好大小合适,并且无法开发其他数据集来提供有用的见解。因此,我们希望创建一个新的数据集,研究人员可以快速、廉价地测试他们的算法,但这也将提供可能适用于完整 ImageNet 数据集的见解。
大约三个小时后,我们创建了 Imagenette。我们从整个 ImageNet 中选择了 10 个看起来彼此非常不同的类。正如我们所希望的那样,我们能够快速、廉价地创建一个能够识别这些类的分类器。然后,我们尝试了一些算法调整,看看它们如何影响 Imagenette。我们发现一些效果很好,并在 ImageNet 上进行了测试——我们很高兴地发现我们的调整在 ImageNet 上也很有效!
这里有一个重要信息:给你的数据集不一定是你想要的数据集。它不太可能是您想要进行开发和原型设计的数据集。您的目标应该是迭代速度不超过几个 几分钟——也就是说,当你想出一个想要尝试的新想法时,你应该能够在几分钟内训练一个模型并看看它是如何进行的。如果进行实验需要更长的时间,请考虑如何减少数据集或简化模型,以提高实验速度。你可以做的实验越多越好!
让我们开始使用这个数据集:
- from fastai.vision.all import *
- path = untar_data(URLs.IMAGENETTE)
首先,我们将使用第 5 章中介绍的调整大小技巧将数据集放入一个DataLoaders
对象中:
- dblock = DataBlock(blocks=(ImageBlock(), CategoryBlock()),
- get_items=get_image_files,
- get_y=parent_label,
- item_tfms=Resize(460),
- batch_tfms=aug_transforms(size=224, min_scale=0.75))
- dls = dblock.dataloaders(path, bs=64)
- model = xresnet50(n_out=dls.c)
- learn = Learner(dls, model, loss_func=CrossEntropyLossFlat(), metrics=accuracy)
- learn.fit_one_cycle(5, 3e-3)
epoch | train_loss | valid_loss | accuracy | time |
---|---|---|---|---|
0 | 1.583403 | 2.064317 | 0.401792 | 01:03 |
1 | 1.208877 | 1.260106 | 0.601568 | 01:02 |
2 | 0.925265 | 1.036154 | 0.664302 | 01:03 |
3 | 0.730190 | 0.700906 | 0.777819 | 01:03 |
4 | 0.585707 | 0.541810 | 0.825243 | 01:03 |
这是一个很好的基准,因为我们没有使用预训练模型,但我们可以做得更好。当使用从头开始训练的模型,或微调到与用于预训练的数据集非常不同的数据集时,一些额外的技术非常重要。在本章的其余部分,我们将考虑一些您希望熟悉的关键方法。第一个是规范化您的数据。
在训练模型时,如果您的输入数据经过归一化(即均值为 0,标准差为 1)会有所帮助。但大多数图像和 计算机视觉库使用 0 到 255 之间的像素值,或 0 到 1 之间的值;在任何一种情况下,您的数据都不会具有 0 的平均值和 1 的标准差。
让我们获取一批数据并查看这些值,方法是对除通道轴(即轴 1)以外的所有轴进行平均:
- x,y = dls.one_batch()
- x.mean(dim=[0,2,3]),x.std(dim=[0,2,3])
(TensorImage([0.4842, 0.4711, 0.4511], device='cuda:5'),
TensorImage([0.2873, 0.2893, 0.3110], device='cuda:5'))
正如我们预期的那样,均值和标准差与期望值不是很接近。幸运的是,通过添加转换,在 fastai 中很容易对数据进行规范化 Normalize
。这一次作用于整个小批量,因此您可以将其添加到batch_tfms
数据块的部分。您需要将要使用的均值和标准差传递给此变换;fastai 带有已经定义的标准 ImageNet 均值和标准差。(如果您没有将任何统计信息传递给 Normalize
转换,fastai 将自动从您的一批数据中计算它们。)
让我们添加这个变换(使用imagenet_stats
,因为 Imagenette 是 ImageNet 的一个子集),现在看一个批次:
- def get_dls(bs, size):
- dblock = DataBlock(blocks=(ImageBlock, CategoryBlock),
- get_items=get_image_files,
- get_y=parent_label,
- item_tfms=Resize(460),
- batch_tfms=[*aug_transforms(size=size, min_scale=0.75),
- Normalize.from_stats(*imagenet_stats)])
- return dblock.dataloaders(path, bs=bs)
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], device='cuda:0'),
TensorImage([1.2330, 1.2112, 1.3031], device='cuda:0'))
让我们检查一下这对训练我们的模型有什么影响:
- model = xresnet50()
- learn = Learner(dls, model, loss_func=CrossEntropyLossFlat(), metrics=accuracy)
- learn.fit_one_cycle(5, 3e-3)
epoch | train_loss | valid_loss | accuracy | time |
---|---|---|---|---|
0 | 1.632865 | 2.250024 | 0.391337 | 01:02 |
1 | 1.294041 | 1.579932 | 0.517177 | 01:02 |
2 | 0.960535 | 1.069164 | 0.657207 | 01:04 |
3 | 0.730220 | 0.767433 | 0.771845 | 01:05 |
4 | 0.577889 | 0.550673 | 0.824496 | 01:06 |
尽管它在这里只起到了一点作用,但在使用预训练模型时,归一化变得尤为重要。预训练模型知道 如何只使用它以前见过的类型的数据。如果训练数据中的平均像素值为 0,但您的数据中像素的最小可能值为 0,那么模型将看到与预期完全不同的东西!
这意味着当您分发模型时,您还需要分发 用于标准化的统计数据,因为任何使用它进行推理或迁移学习的人都需要使用相同的统计数据。同样,如果您使用的是其他人训练过的模型,请确保找出他们使用的归一化统计数据,并进行匹配。
在前面的章节中,我们不必处理规范化,因为在使用预训练模型时cnn_learner
,fastai 库自动添加适当的Normalize
变换;该模型已经使用某些统计数据进行Normalize
了预训练(通常来自 ImageNet 数据集),因此库可以为您填写这些数据。请注意,这仅适用于预训练模型,这就是为什么我们需要在从头开始训练时在此处手动添加此信息。
到目前为止,我们所有的训练都是在 224 码上完成的。我们本可以在开始之前以较小的码数进行训练。这称为 渐进式调整大小。
当 fast.ai 及其学生团队 赢得了2018 年的 DAWNBench 比赛,最重要的创新之一是非常简单的:使用小图像开始训练,并使用大图像结束训练。用小图像进行大部分时期的训练有助于更快地完成训练。使用大图像完成训练使最终的准确度更高。我们称这种方法为渐进式调整大小。
在训练时逐渐使用越来越大的图像。
正如我们所看到的,卷积神经网络学习的特征种类与图像的大小没有任何关系——早期的层会发现边缘和梯度等东西,而后面的层可能会发现鼻子和日落之类的东西。因此,当我们在训练过程中改变图像大小时,并不意味着我们必须为模型找到完全不同的参数。
但很明显,小图像和大图像之间存在一些差异,所以我们不应该期望我们的模型能够继续工作,完全没有任何变化。这是否让你想起了什么?当我们提出这个想法时,它让我们想起了迁移学习!我们正试图让我们的模型学习做一些与以前学习做的事情有点不同的事情。因此,我们应该能够fine_tune
在调整图像大小后使用该方法。
渐进式调整大小还有一个好处:它是另一个 数据增强的形式。因此,您应该期望看到通过渐进式调整大小训练的模型得到更好的泛化。
要实现渐进式调整大小,最方便的是首先创建一个get_dls
函数,该函数采用图像大小和批量大小,就像我们在上一节中所做的那样,并返回您的DataLoaders
.
现在你可以创建你DataLoaders
的小尺寸并 fit_one_cycle
以通常的方式使用,训练比你可能做的更少的时期:
- dls = get_dls(128, 128)
- learn = Learner(dls, xresnet50(n_out=dls.c), loss_func=CrossEntropyLossFlat(),
- metrics=accuracy)
- learn.fit_one_cycle(4, 3e-3)
epoch | train_loss | valid_loss | accuracy | time |
---|---|---|---|---|
0 | 1.902943 | 2.447006 | 0.401419 | 00:30 |
1 | 1.315203 | 1.572992 | 0.525765 | 00:30 |
2 | 1.001199 | 0.767886 | 0.759149 | 00:30 |
3 | 0.765864 | 0.665562 | 0.797984 | 00:30 |
然后你可以替换DataLoaders
里面的Learner
, 并微调:
- learn.dls = get_dls(64, 224)
- learn.fine_tune(5, 1e-3)
epoch | train_loss | valid_loss | accuracy | time |
---|---|---|---|---|
0 | 0.985213 | 1.654063 | 0.565721 | 01:06 |
epoch | train_loss | valid_loss | accuracy | time |
---|---|---|---|---|
0 | 0.706869 | 0.689622 | 0.784541 | 01:07 |
1 | 0.739217 | 0.928541 | 0.712472 | 01:07 |
2 | 0.629462 | 0.788906 | 0.764003 | 01:07 |
3 | 0.491912 | 0.502622 | 0.836445 | 01:06 |
4 | 0.414880 | 0.431332 | 0.863331 | 01:06 |
如您所见,我们的性能要好得多,并且在每个 epoch 上对小图像的初始训练要快得多。
您可以根据需要多次重复增加尺寸和训练更多时期的过程,以获得尽可能大的图像 - 但当然,使用大于图像尺寸的图像尺寸不会获得任何好处在磁盘上。
请注意,对于迁移学习,渐进式调整大小实际上可能会造成伤害 表现。如果您的预训练模型与您的迁移学习任务和数据集非常相似,并且在相似大小的图像上进行了训练,那么这种情况很可能发生,因此不需要对权重进行太大更改。在这种情况下,对较小图像的训练可能会损坏预训练的权重。
另一方面,如果迁移学习任务将使用与预训练任务中使用的图像大小、形状或样式不同的图像,则渐进式调整大小可能会有所帮助。与往常一样,回答“有帮助吗?” 是“试试看!”
我们可以尝试的另一件事是将数据增强应用于验证集。到目前为止,我们只在训练集上应用了它;验证集总是得到相同的图像。但也许我们可以尝试对验证集的一些增强版本进行预测,并对它们进行平均。接下来我们将考虑这种方法。
我们一直在使用随机裁剪来获取一些有用的数据 增强,这会导致更好的泛化,并导致需要更少的训练数据。当我们使用随机裁剪时,fastai 将自动对验证集使用中心裁剪——也就是说,它将在图像中心选择最大的正方形区域,而不会越过图像的边缘。
这通常是有问题的。例如,在多标签数据集中,有时会出现靠近图像边缘的小物体;这些可以通过中心裁剪完全裁剪掉。即使对于像我们的宠物品种分类示例这样的问题,也可能会裁剪出识别正确品种所必需的关键特征,例如鼻子的颜色。
这个问题的一种解决方案是完全避免随机裁剪。相反,我们可以简单地挤压或拉伸矩形图像以适应方形空间。但是我们错过了一个非常有用的数据增强,而且我们也让我们的模型更难以识别图像,因为它必须学习如何识别挤压和挤压的图像,而不仅仅是正确比例的图像。
另一种解决方案是不居中裁剪以进行验证,而是从原始矩形图像中选择一些要裁剪的区域,将它们中的每一个都传递给我们的模型,然后取预测值的最大值或平均值。事实上,我们不仅可以针对不同的作物这样做,还可以针对我们所有测试时间增强参数的不同值执行此操作。这称为测试时间增强(TTA)。
在推理或验证期间,使用数据增强创建每个图像的多个版本,然后对图像的每个增强版本进行预测的平均值或最大值。
根据数据集,测试时间增加可以显着提高准确性。它根本不会改变训练所需的时间,但会根据请求的测试时间增强图像的数量增加验证或推理所需的时间。默认情况下,fastai 将使用未增强的中心裁剪图像加上四个随机增强的图像。
您可以将 any 传递DataLoader
给 fastai 的tta
方法;默认情况下,它将使用您的验证集:
- preds,targs = learn.tta()
- accuracy(preds, targs).item()
0.8737863898277283
正如我们所看到的,使用 TTA 可以很好地提高性能,而无需额外的培训。但是,它确实会使推理速度变慢——如果你为 TTA 平均五张图像,推理速度会慢五倍。
我们已经看到了一些数据增强如何帮助训练更好模型的示例。现在让我们关注一种名为Mixup的新数据增强技术。
Mixup,在 2017 年的论文中介绍 Hongyi Zhang 等人的“ mixup : Beyond Empirical Risk Minimization”是一种强大的数据增强技术,可以 提供显着更高的准确性,尤其是当您没有太多数据并且没有经过与您的数据集相似的数据训练的预训练模型时。该论文解释说:“虽然数据增强始终可以提高泛化能力,但该过程依赖于数据集,因此需要使用专家知识。” 例如,翻转图像作为数据增强的一部分是很常见的,但你应该只水平翻转还是垂直翻转?答案是它取决于您的数据集。此外,如果翻转(例如)不能为您提供足够的数据增强,您就不能“翻转更多”。使用能够“向上”或“向下”调整变化量的数据增强技术会很有帮助,以查看最适合您的方法。
对于每个图像,Mixup 的工作方式如下:
从您的数据集中随机选择另一个图像。
随机选择一个重量。
对所选图像与您的图像进行加权平均(使用步骤 2 中的权重);这将是您的自变量。
将此图像的标签与您的图像标签进行加权平均(具有相同的权重);这将是您的因变量。
在伪代码中,我们正在这样做(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
为此,我们的目标需要进行一次热编码。本文使用图 7-1中的等式对此进行了描述(其中l与我们的伪代码相同t
)。
图 7-1。Mixup 论文的摘录
论文和数学
我们将看到越来越多的研究论文 从这里开始。现在您已经掌握了基本的行话,您可能会惊讶地发现,只要稍加练习,您就能理解其中的多少!您会注意到的一个问题是希腊语 字母,例如l, 出现在大多数论文中。学习所有希腊字母的名称是个好主意,否则很难自己阅读论文并记住它们(或基于它们阅读代码,因为代码通常使用拼写出来的希腊字母的名称,例如作为lambda
)。
论文更大的问题是他们使用数学而不是代码来解释正在发生的事情。如果您没有太多的数学背景,那么一开始这可能会令人生畏和困惑。但请记住:数学中显示的内容将在代码中实现。这只是谈论同一件事的另一种方式!阅读几篇论文后,您会掌握越来越多的符号。如果您不知道符号是什么,请尝试查找 维基百科的数学符号列表或在Detexify中绘制它 ,它(使用机器学习!)将找到您手绘符号的名称。然后,您可以在线搜索该名称以了解其用途。
图 7-2显示了当我们对图像进行线性组合时的样子,就像在 Mixup 中所做的那样。
图 7-2。混合教堂和加油站
第三个图像是通过添加第一个图像的 0.3 倍和第二个图像的 0.7 倍来构建的。在这个例子中,模型应该预测“教堂”还是“加油站”?正确答案是 30% 的教堂和 70% 的加油站,因为如果我们采用 one-hot-encoded 目标的线性组合,这就是我们将得到的结果。例如,假设我们有 10 个类,“church”由索引 2 表示,“gas station”由索引 7 表示。 one-hot-encoded 表示如下:
[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 中为我们完成的,方法是向我们的 Learner
. Callback
s 是 fastai 内部用于在训练循环中注入自定义行为的内容(如学习率计划或混合精度训练)。您将在第 16 章中学习所有关于回调的知识,包括如何制作自己的回调 。现在,您只需要知道使用cbs
参数 toLearner
来传递回调。
以下是我们使用 Mixup 训练模型的方法:
- model = xresnet50(n_out=dls.c)
- learn = Learner(dls, model, loss_func=CrossEntropyLossFlat(),
- metrics=accuracy, cbs=MixUp()
- learn.fit_one_cycle(5, 3e-3)
当我们用这种方式“混合”的数据训练模型时会发生什么?显然,它会更难训练,因为更难看到每张图像中的内容。并且该模型必须预测每张图像的两个标签,而不仅仅是一个,以及计算每个标签的权重。然而,过度拟合似乎不太可能成为问题,因为我们不是在每个 epoch 中显示相同的图像,而是显示两个图像的随机组合。
与我们见过的其他增强方法相比,Mixup 需要更多的 epoch 来训练以获得更好的准确性。您可以尝试使用或不使用 Mixup 来训练 Imagenette fastai repo中的示例/train_imagenette.py脚本。在撰写本文时, Imagenette 存储库中的排行榜显示,Mixup 用于所有超过 80 个 epoch 训练的领先结果,而对于更少的 epoch,Mixup 没有被使用。这也符合我们使用 Mixup 的经验。
Mixup 如此令人兴奋的原因之一是它可以应用于照片以外的数据类型。事实上,有些人甚至通过在模型内部的激活上使用 Mixup 显示出很好的结果,而不仅仅是在输入上——这使得 Mixup 可以用于 NLP 和其他数据 类型也。
Mixup 为我们处理了另一个微妙的问题,那就是模型实际上不可能 我们以前见过我们的损失永远是完美的。问题是我们的标签是 1 和 0,但是 softmax 和 sigmoid 的输出永远不会等于 1 或 0。这意味着训练我们的模型会使我们的激活值越来越接近这些值,这样我们做的 epoch 越多,越极端我们的激活变成了。
使用 Mixup,我们不再有这个问题,因为只有当我们碰巧与同一类的另一个图像“混合”时,我们的标签才会恰好是 1 或 0。其余时间,我们的标签将是线性组合,例如我们之前在教堂和加油站示例中得到的 0.7 和 0.3。
然而,与此有关的一个问题是,Mixup “意外地”使标签大于 0 或小于 1。也就是说,我们没有明确告诉我们的模型我们想以这种方式更改标签。所以,如果我们想让标签更接近或远离 0 和 1,我们必须改变 Mixup 的数量——这也会改变数据增强的数量,这可能不是我们想要的。然而,有一种方法可以更直接地处理这个问题,即使用标签平滑。
在损失的理论表达中,在分类问题中, 我们的目标是 one-hot 编码(实际上,我们倾向于避免这样做以节省内存,但我们计算的损失与使用 one-hot 编码时相同)。这意味着模型被训练为所有类别都返回 0,除了一个,它被训练返回 1。即使 0.999 也不是“足够好”;该模型将获得梯度并学会以更高的置信度预测激活。这会鼓励过度拟合,并在推理时为您提供一个不会给出有意义概率的模型:即使不太确定,它也会总是对预测类别说 1,只是因为它是这样训练的。
如果您的数据没有完美标记,这可能会变得非常有害。在我们在第 2 章研究的熊分类器中,我们看到一些图像被错误标记,或者包含两种不同种类的熊。一般来说,您的数据永远不会完美。即使标签是由人类手动制作的,他们也可能会出错,或者对更难标注的图像有不同的看法。
相反,我们可以将所有的 1 替换为略小于 1 的数字,并将我们的 0 替换为略大于 0 的数字,然后进行训练。这称为标签平滑。通过鼓励您的模型不那么自信,标签平滑将使您的训练更加稳健,即使存在错误标记的数据。结果将是一个更好地概括推理的模型。
这就是标签平滑在实践中的工作方式:我们从 one-hot-encoded 标签开始,然后将所有 0 替换为 εñ(那是希腊字母 epsilon,这是在 介绍标签平滑的论文中使用的并且在 fastai 代码中使用的),其中ñ是类的数量和ε是一个参数(通常为 0.1,这意味着我们 10% 不确定我们的标签)。由于我们希望标签加起来为 1,因此我们还将 1 替换为 1-ε+εñ. 这样,我们不鼓励模型过度自信地预测某些事情。在我们的具有 10 个类的 Imagenette 示例中,目标变成这样(这里是对应于索引 3 的目标):
[0.01, 0.01, 0.01, 0.91, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01]
在实践中,我们不想对标签进行 one-hot 编码,幸运的是我们不需要(one-hot 编码很好地解释了标签平滑并将其可视化)。
标签平滑,纸张
以下是 Christian Szegedy 等人在论文中解释标签平滑背后的原因:
对于有限的,这个最大值是无法实现的和ķ但如果接近和是≫和ķ对所有人ķ≠是——也就是说,如果对应于真实标签的 logit 比所有其他 logit 大得多。然而,这会导致两个问题。首先,它可能会导致过度拟合:如果模型学会为每个训练样本的真实标签分配全部概率,则不能保证泛化。其次,它鼓励最大 logit 与所有其他 logit 之间的差异变大,这与有界梯度相结合 ∂ℓ∂和ķ,降低了模型的适应能力。直观地说,这是因为模型对其预测过于自信。
让我们练习我们的论文阅读技巧来尝试解释这一点。“这个最大值”是指该段的前一部分,其中谈到了 1 是正类标签的值。因此,任何值(无穷大除外)都不可能在 sigmoid 或 softmax 之后产生 1。在一篇论文中,你通常不会看到“任何值”的写法;相反,它会得到一个符号,在这种情况下是和ķ. 这种速记在论文中很有帮助,因为以后可以再次引用它,读者会知道正在讨论哪个值。
然后它说:“如果和是≫和ķ对所有人ķ≠是。” 在这种情况下,论文会立即在数学后面加上英文描述,这很方便,因为你可以直接阅读。在数学中,是指的是目标(是在本文前面定义;有时很难找到定义符号的位置,但几乎所有论文都会在某个地方定义所有符号),并且和是是对应于目标的激活。因此,要接近 1,该激活值需要远高于该 预测的所有其他值。
接下来,考虑“如果模型学会为每个训练样本的真实标签分配完整概率,则不能保证泛化”这样的陈述。这就是说,使和是非常大意味着我们需要在整个模型中使用大权重和大激活。大权重会导致“颠簸”函数,其中输入的微小变化会导致预测发生巨大变化。这对于 泛化来说真的很糟糕,因为这意味着只要一个像素改变一点就可以完全改变我们的预测!
最后,我们有“它鼓励最大 logit 和所有其他 logit 之间的差异变大,并且结合有界梯度∂ℓ∂和ķ,降低了模型的适应能力。” 记住,交叉熵的梯度基本上是output - target
。output
和 都target
在 0 和 1 之间,所以区别在-1
和 之间1
,这就是为什么论文说梯度是“有界的”(它不可能是无限的)。因此,我们的 SGD 步骤也是有界的。“降低模型的适应能力”意味着它很难在迁移学习环境中更新。这是因为错误预测导致的损失差异是无限的,但我们每次只能采取有限的步骤。
要在实践中使用它,我们只需将调用中的损失函数更改为Learner
:
- model = xresnet50(n_out=dls.c)
- learn = Learner(dls, model, loss_func=LabelSmoothingCrossEntropy(),
- metrics=accuracy)
- learn.fit_one_cycle(5, 3e-3)
与 Mixup 一样,在训练更多 epoch 之前,您通常不会看到标签平滑的显着改进。自己尝试一下,看看:在标签平滑显示改进之前,您必须训练多少个 epoch?