600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > pytorch用同一个随机种子 使每次训练结果相同

pytorch用同一个随机种子 使每次训练结果相同

时间:2022-12-07 06:57:39

相关推荐

pytorch用同一个随机种子 使每次训练结果相同

设置随机种子:

在使用PyTorch时,如果希望通过设置随机数种子,在gpu或cpu上固定每一次的训练结果,则需要在程序执行的开始处添加以下代码:

def setup_seed(seed):torch.manual_seed(seed)torch.cuda.manual_seed_all(seed)np.random.seed(seed)random.seed(seed)torch.backends.cudnn.deterministic = True# 设置随机数种子setup_seed(3407)# 预处理数据以及训练模型# ...# ...

随机数种子seed确定时,模型的训练结果将始终保持一致。

torch.backends.cudnn.benchmark =False,torch.backends.cudnn.deterministic = True是否要这样设置?

首先种子是不是都设置了?可以参考这里pytorch reproducibility把种子都给设置了。

种子没问题后,假如结果还是不一样可能是torch.backends.cudnn.benchmark的问题。这是python调用cudnn来加速卷积的一个机制。假如你设置这个为True的话。然后你的code出现一些地方使得这个机制被不停触发的话,可能就会导致结果不一样。我试过一个batch的loss会有小数点后第5位的差距。它被触发后,会重新判断如何卷积最快,这个时候会使用不同的卷积方式,这样计算出来的卷积结果会有很细微的不同。但是经过很多batch,epoch的累积,最后结果就会相去甚远,1,2%不是问题

这个时候解决方法是将torch.backends.cudnn.benchmark =False,

然后直接加一句torch.backends.cudnn.deterministic = True。虽然在pytorch源码torch.backends.cudnn.benchmark ?!里面,假如deterministic设置为True即使benchmark也为True还是会返回默认的卷积算法。(但是亲测,两个都设置为True的情况下,无法固定训练结果,所以必须benchmark设置为False,deterministic设置为True)。在一般情况下,这样设置后,就失去了加速的效果,可能导致程序运行变慢。但是在某些情况下,上面这种设置可能训练速度会更快,

原因是torch.backends.cudnn.benchmark = True后(在torch.backends.cudnn.deterministic没有设置,或者为False)的情况下,出现了某些因素使得这个机制不停被触发,而每次触发都会导致有一个耗时的优化搜索时间。

想要最终解决这个问题是找一下代码中哪些因素导致了这个机制被不停地触发。因为一般情况下,即网络卷积架构不会在运行的时候改变,输入的B,C,H,W不会不停改变,这个机制只会在最开始的时候触发一次。所以训练过程是确定的,训练结果不会改变。所以问题可能出现在代码输入上面,

比如batch_size改变(边训练边验证,batchsize大小不一样; dataloader加载最后一个batch的时候数量不足batch_size个<可使用drop_last=True来避免>)等等都会触发重新优化。还有一种可能性,假如你在不同平台上,或者不同GPU,CPU上跑模型的话,那么就算前面的benchmark、deterministic、种子全部都设置对了的话都会导致训练结果不同。因为pytorch是基于CUDA API的,CUDA在不同设备上的伪随机数生成器不会是完全一样的,这是由设备决定的。最后一种可能性是使用了一些CUDA本来就不会产生确定性结果的操作,如AtomicAdd、上采样(torch.nn.Upsample,Unet中常用到)等。较新版本的pytorch现在支持对这种操作的检查,只需要在代码中加入一行torch.use_deterministic_algorithms(True)。这句话相当于自检,只要使用了不可复现的运算操作,代码就会自动报错。

链接:/question/345043149/answer/1160114523

其实我觉得如果你的网络卷积架构不总是改变的话,输入的B,C,H,W不会不停改变,这个机制只会在最开始的时候触发一次,损失的精度几乎为0,我们为了加速训练,只设置一个torch.backends.cudnn.benchmark = True就可以了,而不需要torch.backends.cudnn.benchmark =False+torch.backends.cudnn.deterministic = True

所以随机种子的代码为:

# ######### Set Seeds ###########random.seed(3407)np.random.seed(3407)torch.manual_seed(3407)torch.cuda.manual_seed_all(3407)

为什么要将随机种子设置为3407?看以下链接

https://mp./s/bxspzdoHQlAtKeKJqcP_FA

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。