背景:
为了更新代码的mmalb版本,将自己的工程代码移植了一下,改动基本都是pipline方面的改动,模型一点点点儿都没动过(一分钱也没敢花)。结果将旧版本代码训练好的模型.pth文件加载到新版本的代码中得到的测试结果是完全一样的,至此好像问题解决了。但是为了保证万无一失,就用新版本的代码训练了一次,此次训练数据和各种超参数完全和旧版本代码一模一样,结果训练精度差了10%,至此直接崩溃。。。。 但是问题不大,可以追根溯源。
问题提出:
两个版本的代码,测试结果一样但训练结果相差这么大??
基本思路:
问题肯定出现在模型前推过程或者loss反向传播过程中,那么就先前推一步一步对照结果,前推没问题就反向传播查问题,我就不信看不出问题在哪。
具体方法:
给两个版本的代码都load进一个模型参数,这样保证了初始的模型参数完全相同(有的同学说可以加入随机种子保证模型初始化相同,但我的建议是没必要,mmlab懂得都懂)。数据也不折腾了,我就直接整一条数据,batch-size设置成1,我看你怎么给我变动,还好我的数据不需要初始化,所以没有其他要考虑的点,至此可以前推喽!!!
直接进入旧版本代码的第一个层--Conv2d:非常普遍的一个卷积层,也是resnet的第一层,这里我直接是在此处打断点不让模型前推,我留个心眼先把模型的输入打印一下(虽然我知道我的数据就一条不可能不一样,但我做事就是这样(保命狗头)),然后再把Conv2d的weight打印一下(bias=False也就不用打印了,padding_mode=0更不必细说),然后再把输出output打印一下。
再进入新版本代码的第一个层--同样的Conv2d,后续操作一模一样,至此我打印的txt文件存储是这样的,非常清晰明了:
└── new └── new
└── x_input.txt └── x_input.txt
└── x_weight.txt容 └── x_weight.txt容
└── x_output.txt └── x_output.txt
我想此刻我指定是最细心的男人,但是问题来了,input和weight两边对比是完全一模一样的,但是output就是在小数点后3位有差距,太奇怪了,我的意识此刻收到了神的打击,为什么,我想到了浮点的问题,但是都是torch.float32,怎么可能在小数点后3为出现差距,不合理,我想不清楚为什么,还好我又机智了一把。。。
具体方法2:
我又来了,我懂了,我既然把input和weight都打印好了,为什么不自己用F.conv2d函数算一遍,反正我都知道padding,dilation,stride,说到了就直接整,这下结果才是完犊子了,new和old出的output-self竟然完全一模一样,说明什么,说明torch在跟我演戏,他在玩我,我又懂了。。。 一定是torch的版本, 我又看了一下,两边建立的conda虚拟环境中除了mmcv的版本不一样,torch都是0.12.0+cu113,完了完了,说明模型在演我, 我自己算是ok的,但是进到模型就有问题,模型它 不 他活了。
寻求帮助:
现在召集全国勇士跟我一起攻打模型,他向我宣战,我必战之。。 现在不宜出兵,我的想法是广招天下码农建议与模型谈和,希望广大码友给予我最诚恳的建议