Oneflow-Inc / swin-transformer

0 stars 0 forks source link

Swin-Transformer Eager DDP 完整训练实验 #5

Open Ldpe2G opened 2 years ago

Ldpe2G commented 2 years ago

实验目的

实验1: mixup off + clip-grad off

Framework Init Method Version Epoch Acc@1 Log
pytorch 固定初始化 1.10.1 300 75.75% log
oneflow 固定初始化 master nightly 0.6.0.dev20211228+cu102 300 76.30% log
oneflow 固定初始化 dev_debug_swin_transformer_gr 300 75.89% log
oneflow 随机初始化 master nightly 0.6.0.dev20211228+cu102 300 75.76% log
oneflow 随机初始化 dev_debug_swin_transformer_gr 300 75.94% log

实验2: mixup on + clip-grad on

Framework Init Method Version Epoch Acc@1 Log
pytorch 固定初始化 1.10.1 300 78.5% log
oneflow 固定初始化 master nightly 0.6.0.dev20211228+cu102 300 78.62% log
oneflow 固定初始化 dev_debug_swin_transformer_gr 300 78.49% log
oneflow 随机初始化 master nightly 0.6.0.dev20211228+cu102 300 78.31% log
oneflow 随机初始化 dev_debug_swin_transformer_gr 300 78.77% log

实验3: mixup on + clip-grad on

Framework Init Method Version Epoch Acc@1 Log
pytorch 固定初始化 1.10.1 300 78.53% log
oneflow 固定初始化 master nightly 0.6.0.dev20211230+cu112 300 78.40% log
oneflow 固定初始化 dev_debug_swin_transformer_gr 300 78.22% log
oneflow 随机初始化 master nightly 0.6.0.dev20211230+cu112 300 77.69% log
oneflow 随机初始化 dev_debug_swin_transformer_gr 300 78.19% log

实验4: mixup on + clip-grad on

Framework Init Method Version Epoch Acc@1 Log
pytorch 固定初始化 1.10.1 300 72.42% log
oneflow 固定初始化 master nightly 0.6.0.dev20211230+cu112 300 74.75% log
oneflow 固定初始化 dev_debug_swin_transformer_gr 300 74.29% log
oneflow 随机初始化 master nightly 0.6.0.dev20211230+cu112 300 71.85% log
oneflow 随机初始化 dev_debug_swin_transformer_gr 300 73.79% log

实验结论

通过上面4组实验,可以得到以下结论:

1、从所有 master 分支的实验结果可以看到,采用 pytorch 的初始化比 oneflow 的随机初始化最终收敛精度都要高,且基本都超过或者与torch的精度持平。而初始化这个问题随着模型的增大(tiny < small < base)越明显,目前要实现 timm 的 truncnormal 初始化方法,仍然缺一个 erfinv_ 算子,等修复之后再重新做一次实验。

2、从所有 dev_debug_swin_transformer_gr 分支的实验结果可以看到,修复 layernorm 和 gelu 之后,初始化的问题没那么明显了,但是从4组实验中有3组精度都不如 master 分支 + torch 初始化,所以这个对改动还是得先等上面初始化的修复再重新做实验和master对比精度。

3、oneflow ddp 单卡显存占用比 torch 多1G多,V100 16G 单卡 batch 32 最大只能跑 swin base,swin large 跑不了,而官方设置, tiny 和 small 单卡batch 128,base 是 64,所以显存问题需要解决,不然没法上大batch训练。

yuanms2 commented 2 years ago

总结一下,看我理解的对不对:

1, dev_debug_swin_transformer_gr 分支和master 分支的区别是修复了layer norm和gelu 的问题 2, 发现了oneflow和pytorch初始化方法的不同,而且这个初始化方法对精度产生了影响 3, oneflow ddp 单卡比pytorch 显存占用高,这个是不是后江正在想办法解决?

Ldpe2G commented 2 years ago

总结一下,看我理解的对不对:

1, dev_debug_swin_transformer_gr 分支和master 分支的区别是修复了layer norm和gelu 的问题 2, 发现了oneflow和pytorch初始化方法的不同,而且这个初始化方法对精度产生了影响 3, oneflow ddp 单卡比pytorch 显存占用高,这个是不是后江正在想办法解决?

是的,理解没问题

yuanms2 commented 2 years ago

我大概回顾了一下过程:

1,发现和修复了mixup的问题,https://github.com/Oneflow-Inc/swin-transformer/issues/2#issuecomment-1001159164

2,swin transformer 使用的初始化方法是比较特殊吗,我们之前一直没有使用过? 按说初始化方法这种问题应该早就解决了。从这里得到一个经验,精度对齐时,有一个步骤应该是固定权重,用相同初始化权重,这里要求我们能save和load pytorch权重,并导入oneflow

3,发现layernorm 微妙的区别,除法改乘法 https://github.com/Oneflow-Inc/swin-transformer/issues/2#issuecomment-1002374774 这个问题的确不容易发现

4, gelu 的问题,问了一下,以前使用的公式是和tf 对齐的,现在改成了和pytorch一样 https://github.com/Oneflow-Inc/oneflow/pull/7103/files

Ldpe2G commented 2 years ago

swin transformer 使用的初始化方法是比较特殊吗,我们之前一直没有使用过? 按说初始化方法这种问题应该早就解决了。从这里得到一个经验,精度对齐时,有一个步骤应该是固定权重,用相同初始化权重,这里要求我们能save和load pytorch权重,并导入oneflow

用到了 trunc_normal 这个初始化方法,之前训的模型应该都没用过这个,我们内置的实现和timm中的的有差异

Ldpe2G commented 2 years ago

从这里得到一个经验,精度对齐时,有一个步骤应该是固定权重,用相同初始化权重,这里要求我们能save和load pytorch权重,并导入oneflow

是的,这个步骤很重要,而且现在我们接口和torch对齐之后,加载torch的权重就几行代码的事情

rentainhe commented 2 years ago

我大概回顾了一下过程:

1,发现和修复了mixup的问题,#2 (comment)

2,swin transformer 使用的初始化方法是比较特殊吗,我们之前一直没有使用过? 按说初始化方法这种问题应该早就解决了。从这里得到一个经验,精度对齐时,有一个步骤应该是固定权重,用相同初始化权重,这里要求我们能save和load pytorch权重,并导入oneflow

3,发现layernorm 微妙的区别,除法改乘法 #2 (comment) 这个问题的确不容易发现

4, gelu 的问题,问了一下,以前使用的公式是和tf 对齐的,现在改成了和pytorch一样 https://github.com/Oneflow-Inc/oneflow/pull/7103/files

目前看来是这几个问题,只是影响的程度不一样大,因为我们实验发现其实初始化问题对于tiny model的影响并不会很大,但是随着模型容量增大之后,初始化的影响还是很明显的,Swin-T的初始化方法中有个比较特殊的点是,我们用了内置的truncnornal,但是swin-t是用timm里的truncnormal,timm是用pytorch的一些接口拼出来的,这个问题我和开杰之前debug过一次,在使用内置的一个相同的接口替换之后就没有接着考虑这个,确实是疏忽了

Ldpe2G commented 2 years ago

精度验证实验

实验目的:验证初始化方法对齐torch之后的精度

实验1: mixup on + clip-grad on

Framework Init Method Version Epoch Acc@1 Log
pytorch(历史数据) 固定初始化 1.10.1 300 78.53% log
oneflow(历史数据) 随机初始化 master nightly 0.6.0.dev20211230+cu112 300 77.69% log
oneflow(历史数据) 固定初始化 master nightly 0.6.0.dev20211230+cu112 300 78.40% log
oneflow 随机初始化 master nightly 0.7.0.dev20220113+cu112 300 78.35% log

实验2: mixup on + clip-grad on

Framework Init Method Version Epoch Acc@1 Log
pytorch(历史数据) 固定初始化 1.10.1 300 72.42% log
oneflow(历史数据) 随机初始化 master nightly 0.6.0.dev20211230+cu112 300 71.85% log
oneflow(历史数据) 固定初始化 master nightly 0.6.0.dev20211230+cu112 300 74.75% log
oneflow 随机初始化 master nightly 0.7.0.dev20220113+cu112 300 74.26% log

实验结论

  1. 从 swin small 和 base 着两组的实验结果可以看出,初始化方法对齐 torch 之后,在最新的 master 分支上,模型随机初始化的最终收敛精度都超过了之前未对齐的随机初始化精度。并且都超过或与torch的结果持平。初始化的问题已经认为已解决。
yuanms2 commented 2 years ago

上面各行的实验配置需要进一步解释一下,仍不懂每行的结果意味着什么

第一行和第三行表示pytorch 和 oneflow 使用了相同的初始化方法,在swin small上 oneflow比pytorch低一点,在swin base上 oneflow 比 pytorch 高一些。

第三行和第四行表示,oneflow 的随机初始化的效果和使用pytorch初始化方法相比效果差不多,在swin small上 oneflow随机初始化比pytorch固定初始化稍微弱一点,在swin base上 oneflow 随机初始化也比pytorch固定初始化稍微弱一点。

Ldpe2G commented 2 years ago

上面各行的实验配置需要进一步解释一下,仍不懂每行的结果意味着什么

第一行和第三行表示pytorch 和 oneflow 使用了相同的初始化方法,在swin small上 oneflow比pytorch低一点,在swin base上 oneflow 比 pytorch 高一些。

第三行和第四行表示,oneflow 的随机初始化的效果和使用pytorch初始化方法相比效果差不多,在swin small上 oneflow随机初始化比pytorch固定初始化稍微弱一点,在swin base上 oneflow 随机初始化也比pytorch固定初始化稍微弱一点。

这个实验主要是第二和第四行对比,在修复了初始化方法之后,0.7.0 的 master 随机初始化收敛精度就和之前 0.6.0 的 master 加载 torch 初始化是差不多了,即使弱一些至少差距也不会像之前 0.6.0 随机初始化那样差那么多。

而 0.7.0 master 随机初始化比 0.6.0 master 加载 torch 初始化要弱一些,这个可能是波动,也可能是 0.6.0 的master linspace 这个算子的行为没有和 torch 对齐, 算出来的 drop path rate 要比 torch 的要低一些,这个可能是导致在 cifar100 比之前的精度要弱一些,需要在 Imagenet 上完整训练一把看看。

rentainhe commented 2 years ago

ImageNet完整实验

Model Framework Acc@1 log
Swin-Tiny OneFlow 81.24 oneflow log
Swin-Tiny Pytorch 81.29 pytorch log