深度学习模型稳定可复现
深度学习这一块奥,稳定性奥,必须拿捏的死死的奥。
深度学习的一个项目,其中的随机性会非常的大
1 随机生成的模型参数,
2 可能是随机选取的训练样本顺序
3 随机dropout
以上等等,会使得模型具有一定的随机性,其实也并非完全算作坏事
因为模型性能的抖动能够让模型性能更高一些,可以报告跑出来的最高性能,是吧。
但是在某些阶段时,我们必须使得性能稳定,这样才可以明显的对比。
比如:
1 调整一些超参数
2 改进模型结构
3 优化算法
等等上述情况时候,会需要稳定模型。因为改进模型结构,可能就提升了0.5%-1%的性能,但是模型本身会有2%的性能抖动(更有甚者会有5%-10% FaceNet这种训练embedding的方式抖动会更大,triplet semihard loss详解,懂得都懂)。
本身具有抖动,在实验的时候,就不一定能验证出改进的有效性了。
大家不必笑,模型的改进往往就是这0.5%, 0.5%的累积
举个例子现在做目标检测任务的,每次在sota上提升个2%,就已经非常了不得了。
所以建议大家每次将模型固定好,进行优化的调整,确定最终模型之后,再进行随机化或者设定新的随机种子,这样可以再把模型性能抖动的更高。
当然其实现在的这么大的深度模型,很少存在性能抖动这么厉害的情况,但是相对小的模型上,情况还是很普遍的
下面关于tensorflow, pytorch, keras, random, numpy等库,给大家一些代码,方便确定随机数,以固定模型结果。
Tensorflow
import tensorflow as tf
seed = 42 # 可以自己设置
tf.set_random_seed(seed)
1
2
3
这一块主要是设置了graph级别的随机种子,大家也可以设置成为单个点确定的随机种子(但我觉得对一个模型来说,这样完全是没有任何必要的)
(tensorflow生成的是静态图,所以为graph级别的)
Keras & numpy
import tensorflow as tf
from tensorflow import keras as K
import numpy as np
seed = 42
np.random.seed(seed)
1
2
3
4
5
大家可能会觉得为什么没有keras的?其实本质原因是keras内核的random number generator用的就是numpy的。也就是说keras内部调用了numpy的随机数生成器,只要将numpy确定随机种子,那么keras的生成数就是确定的。
random
import random
seed = 42
random.seed(seed)
1
2
3
random是python自带的一个包,存在的操作会有random.choice等等,从一个list中随机取一个或多个元素。
hashseed
seed = 42
os.environ[‘PYTHONHASHSEED’] = str(seed)
1
2
HASHSEED是 HASH映射函数时,保证每一次新的运行进程,对于一个相同的object生成的hash是相同的。
PyTorch
seed = 42
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed) # multi gpu
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
torch.backends.cudnn.enabled = False
1
2
3
4
5
6
7
额外介绍一下:最后三行使用了cudnn:
cuDNN 是英伟达专门为深度神经网络所开发出来的 GPU 加速库,针对卷积、池化等等常见操作做了非常多的底层优化,比一般的 GPU 程序要快很多。大多数深度学习框架都支持 cuDNN,PyTorch 也不例外。在使用 GPU 的时候,PyTorch 会默认使用 cuDNN 加速。
其中:
1 torch.manual_seed(seed)是cpu情况下的seed
2 torch.cuda.manual_seed(seed)是单GPU情况下的seed
3 torch.cuda.manual_seed_all(seed)是多GPU情况下的seed
4 torch.backends.cudnn.deterministic = True和下述的benchmark搭配使用,确定卷积算法的类型。
5 torch.backends.cudnn.benchmark = False是cudnn使用确定性卷积,而不是使用优化提速型的卷积
(这个的意思是cudnn在开始时会对模型的每个卷积层使用合适的卷积算法加速,由于卷积网络的kernel大小,数量,计算方式等等,选用合适的卷积算法会使得后续计算加快) 速度会慢,但是可复现
6 torch.backends.cudnn.enabled = False 直接不使用cudnn底层加速。
这边给大家两份代码吧,分别是pytorch和tensorflow的所有相关随机数整理的函数,于主程序运行之前一次即可。
PyTorch
def seed_torch(seed=42):
seed = int(seed)
random.seed(seed)
os.environ[‘PYTHONHASHSEED’] = str(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
torch.backends.cudnn.enabled = False
1
2
3
4
5
6
7
8
9
10
11
Tensorflow
def seed_tensorflow(seed=42):
random.seed(seed)
os.environ[‘PYTHONHASHSEED’] = str(seed)
np.random.seed(seed)
tf.set_random_seed(seed)
————————————————
版权声明:本文为CSDN博主「DrogoZhang」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_40400177/article/details/105625873