使用 Pytorch API 和 Fast-ai 进行分类的训练结果不同

bat*_*man 3 python pytorch fast-ai

我有两个训练 python 脚本。一种使用 Pytorch 的 API 进行分类训练,另一种使用 Fast-ai。使用 Fast-ai 效果要好得多。

训练成果如下。

Fastai
epoch     train_loss  valid_loss  accuracy  time    
0         0.205338    2.318084    0.466482  23:02                         
1         0.182328    0.041315    0.993334  22:51                         
2         0.112462    0.064061    0.988932  22:47                         
3         0.052034    0.044727    0.986920  22:45                         
4         0.178388    0.081247    0.980883  22:45                         
5         0.009298    0.011817    0.996730  22:44                         
6         0.004008    0.003211    0.999748  22:43 

Using Pytorch
Epoch [1/10], train_loss : 31.0000 , val_loss : 1.6594, accuracy: 0.3568
Epoch [2/10], train_loss : 7.0000 , val_loss : 1.7065, accuracy: 0.3723
Epoch [3/10], train_loss : 4.0000 , val_loss : 1.6878, accuracy: 0.3889
Epoch [4/10], train_loss : 3.0000 , val_loss : 1.7054, accuracy: 0.4066
Epoch [5/10], train_loss : 2.0000 , val_loss : 1.7154, accuracy: 0.4106
Epoch [6/10], train_loss : 2.0000 , val_loss : 1.7232, accuracy: 0.4144
Epoch [7/10], train_loss : 2.0000 , val_loss : 1.7125, accuracy: 0.4295
Epoch [8/10], train_loss : 1.0000 , val_loss : 1.7372, accuracy: 0.4343
Epoch [9/10], train_loss : 1.0000 , val_loss : 1.6871, accuracy: 0.4441
Epoch [10/10], train_loss : 1.0000 , val_loss : 1.7384, accuracy: 0.4552
Run Code Online (Sandbox Code Playgroud)

使用 Pytorch 并不收敛。我使用相同的网络(Wideresnet22),并且两者都是从头开始训练的,没有预先训练的模型。

网络就在这里

使用 Pytorch 进行训练就在这里

使用Fastai的方法如下。

from fastai.basic_data import DataBunch
from fastai.train import Learner
from fastai.metrics import accuracy

#DataBunch takes data and internall create data loader
data = DataBunch.create(train_ds, valid_ds, bs=batch_size, path='./data')
#Learner uses Adam as default for learning
learner = Learner(data, model, loss_func=F.cross_entropy, metrics=[accuracy])
#Gradient is clipped
learner.clip = 0.1

#learner finds its learning rate
learner.lr_find()

learner.recorder.plot()

#Weight decay helps to lower down weight. Learn in https://towardsdatascience.com/
learner.fit_one_cycle(5, 5e-3, wd=1e-4)
Run Code Online (Sandbox Code Playgroud)

我使用 Pytorch 的训练算法可能存在什么问题?

Szy*_*zke 5

fastai在幕后使用了很多技巧。快速了解他们在做什么而你没有做什么。

这些是按我认为最重要的顺序排列的,尤其是前两个应该可以提高你的分数。

总长DR

使用一些调度程序(最好是torch.optim.lr_scheduler.CyclicLR)并AdamW代替SGD.

加长版

fit_one_cycle

Leslie Smith 的 1 周期策略用于fastai. 在 PyTorch 中,可以使用torch.optim.lr_scheduler.CyclicLR创建类似的例程,但这需要一些手动设置。

基本上,它从较低的学习率开始,逐渐增加到5e-3您的情况,然后再次回到较低的学习率(形成一个循环)。您可以调整应如何lr升高和降低(在fastai使用余弦退火 IIRC 来实现)。

一开始你的学习率太高了,一些调度程序应该有帮助,首先测试一下。

优化器

在提供的代码片段中,您使用torch.optim.SGD(按optim_fn原样None并设置默认值),这很难正确设置(通常)。

另一方面,如果您设法正确地手动设置它,您可能会更好地概括。

默认情况下fastai 也不使用Adam它使用AdamWiftrue_wd已设置(我认为,无论如何,它在您的情况下都是默认的,请参阅源代码)。AdamW将权重衰减与自适应学习率解耦,这应该可以提高收敛性(请阅读此处原始论文

纪元数

如果您想比较两种方法,请设置相同的纪元数,目前这是苹果与橘子之间的区别。

渐变裁剪

您不剪辑渐变(已注释掉),可能有帮助或没有帮助,具体取决于任务。说实话,暂时不会关注这一点。

其他技巧

阅读Learnerfit_one_cycle并尝试在 PyTorch 中设置类似的东西(如上所述的粗略指南)

此外,您还可以使用某种形式的数据增强来进一步提高分数,但这超出了我认为问题的范围。