Tensorflow 2.x代码中如何控制随机性
引言
控制实验的随机性非常有必要:(1) 保证结果的可复现/重复性一直都是研究中的一个基本问题; (2)在验证所提方法/系统中往往需要做分离/消融实验来对结果进行拆分,以验证各个模块是否有效以及对总体结果的贡献,控制随机性可以消除因随机性的引入产生的影响。基于此,在此总结tensorflow2.x
实验环境的随机性控制方法。
随机性控制
基本常用包中的随机性
numpy
, random
, os
中的随机性控制:
import numpy as np
import random
seed_value = 0
random.seed(seed_value )
np.random.seed(seed_value)
os.environ['PYTHONHASHSEED'] = str(seed_value)
在重复实验时,往往需要利用随机性来产生数据集的不同划分,例如:
(基于sklearn
通过控制随机性来产生不同的划分)
from sklearn.model_selection import train_test_split, StratifiedKFold
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=seed_value)
cv = StratifiedKFold(n_splits=10, random_state=seed_value) # 10折
Tensorflow中的随机性
tensorflow2.x中的随机性控制
import tensorflow as tf
tf.random.set_seed(0)
tensorflow2.x 中各层的随机性控制
(1)各层初始化过程中的随机性
以1D conv.
为例,其API
格式为:
tf.keras.layers.Conv1D(kernel_initializer=None, ....)
可以看到kernel_initializer
默认为Null
, 如何控制初始化中的随机性?
tn_initializer = tf.initializers.TruncatedNormal(seed=seed_value)
conv_1d_f_pointwise = tf.keras.layers.Conv1D(filters=1, kernel_size=1, activation=None, kernel_initializer=tn_initializer)
注:Conv1D
还有其他参数初始化会引入随机性,此处仅以kernel_initializer
为例.
(2)Dropout
Dropout
层的构造函数如下:
__init__(self, rate=0.5, noise_shape=None, seed=None, name=None, **kwargs)
在使用过程中需要指定随机种子来控制dropout
操作本身带来的随机性:
tf.keras.layers.Dropout(rate=self.drop_rate, seed=self.random_seed_alg_part)
(3) 训练过程中的随机性
如果调用model.fit()
进行训练,API接口如下:
fit(self,x=None, y=None, batch_size=None, epochs=1, verbose=1, shuffle=True, **kwargs)
其中参数shuffle
默认True
会带来随机性,需要将参数shuffle
显式置为False
.
(4) GPU多线程训练中的随机性
tensorflow-determinism
包(https://github.com/NVIDIA/framework-determinism):该包解决了GPU上训练时不确定性的问题。注意:安装时通过命令:pip install tensorflow-determinism
安装, 安装后调用如下:
from tfdeterminism import patch
patch()
可惜的是:tfdeterminism 暂时只适用于小于2.1的tensorflow版本,因为目前没有适用于TensorFlow 2.1版或更高版本的修补程序。
对于Tensorflow2.3
版本(通过命令:pip package tensorflow=2.3.0
安装),因为其本身实现了大多数当前可用的GPU确定性操作解决方案, 因此可以通过如下代码控制GPU中的不确定性:
import tensorflow as tf
import os
os.environ['TF_DETERMINISTIC_OPS'] = '1'
另外, 还看到如下代码: os.environ['TF_CUDNN_DETERMINISTIC'] = str(seed_value)
, 暂时还不清楚其适用场景。
总结
未完待续。
References
1.https://github.com/NVIDIA/framework-determinism
2.https://zhuanlan.zhihu.com/p/95416326
3.https://stackoverflow.com/questions/50744565/how-to-handle-non-determinism-when-training-on-a-gpu