【个人思考】深度学习模型稳定可复现,设定随机种子大全

深度学习模型稳定可复现

深度学习这一块奥,稳定性奥,必须拿捏的死死的奥。

深度学习的一个项目,其中的随机性会非常的大

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)

这一块主要是设置了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)

大家可能会觉得为什么没有keras的?其实本质原因是keras内核的random number generator用的就是numpy的。也就是说keras内部调用了numpy的随机数生成器,只要将numpy确定随机种子,那么keras的生成数就是确定的。

random

import random
seed = 42
random.seed(seed)

randompython自带的一个包,存在的操作会有random.choice等等,从一个list中随机取一个或多个元素。

hashseed

seed = 42
os.environ['PYTHONHASHSEED'] = str(seed)

HASHSEEDHASH映射函数时,保证每一次新的运行进程,对于一个相同的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

额外介绍一下:最后三行使用了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

Tensorflow

def seed_tensorflow(seed=42):
    random.seed(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)
    np.random.seed(seed)
    tf.set_random_seed(seed)
发布了1158 篇原创文章 · 获赞 1854 · 访问量 1460万+

猜你喜欢

转载自blog.csdn.net/weixin_40400177/article/details/105625873