在调优超参数以使模型更好地执行时,我注意到,每次运行代码时,我所获得的分数(以及由此创建的模型)都不一样,尽管为随机操作修复了所有种子。如果我在CPU上运行,则不会发生此问题。
我搜索并发现,这是一个常见的问题时,使用GPU训练。下面是一个非常好的/详细的示例,其中包含了一些简短的代码片段来验证该问题的存在。
他们将非决定论定位为"tf.reduce_sum“函数。然而,对我来说,情况并非如此。这可能是因为我使用的是不同的硬件(1080 TI)或不同版本的CUDA库或Tensorflow。看起来,数据自动化系统库中有很多不同的部分是非确定性的,要准确地找出它的哪一部分和如何摆脱它似乎并不容易。而且,这一定是故意的,所以很可能会有足够的效率提高,以换取非确定性。
所以,我的问题是:
由于GPU在NNs中很受欢迎,在这个领域的人必须有一种处理不确定性的方法,因为我看不出你如何能够可靠地调优这些超参数。在使用GPU时,处理不确定性的标准方法是什么?
发布于 2022-05-25 12:06:41
从TF 2.9 (TF >= 2.9)开始,如果您希望TF模型确定地运行,则需要在程序开始时添加以下行。
import tensorflow as tf
tf.keras.utils.set_random_seed(1)
tf.config.experimental.enable_op_determinism()重要注意事项:第一行为以下内容设置随机种子: Python、NumPy和TensorFlow。第二行使每个TensorFlow操作都具有确定性。
发布于 2018-06-07 17:21:05
TL;博士
那个,但是更长的
当你把神经网络操作看作数学运算时,你会期望一切都是确定性的。卷积,激活,交叉熵-这里的一切都是数学方程,应该是确定性的.即使是伪随机操作,如洗牌、退出、噪音等,也完全由种子决定。
另一方面,当您从它们的计算实现中看到这些操作时,您将它们看作是大规模并行计算,除非非常小心,否则它们可能是随机性的来源。
问题的核心是,当您在多个并行线程上运行操作时,通常不知道哪个线程将首先结束。当线程对自己的数据进行操作时,这并不重要,例如,将激活函数应用于张量应该是确定性的。但是,当这些线程需要同步时,比如计算和时,结果可能取决于求和的顺序,进而取决于线程首先结束的顺序。
从这一点出发,你大致上有两个选择:
哪条路走CuDNN?好吧,大部分是决定性的。在最近的发行版中,确定性操作是规范而不是例外。但它过去提供了许多非确定性操作,更重要的是,它过去不提供一些操作,比如减少,人们需要在CUDA中实现自己,并对确定性进行不同程度的考虑。
一些库,如theano,通过在用户可以打开或关闭的deterministic标志的早期公开,比这个主题更领先--但是正如您从它的描述中看到的,它远非提供任何保证。
如果是
more,有时我们会选择一些确定性更强但速度更慢的实现。特别是在GPU上,我们将避免使用AtomicAdd。有时我们仍然会使用非确定性实现,例如,当我们没有确定性的GPU实现时。此外,请参阅dnn.conv.algo*标志以涵盖更多情况。
在TensorFlow中,对确定性需求的认识已经相当晚了,但它正在慢慢地实现--这也得益于CuDNN在这方面的进步。长期以来,削减一直是不确定的,但现在看来是决定性的。当然,CuDNN在Version6.0中引入了确定性的简化可能有所帮助。
现在看来,TensorFlow走向决定论的主要障碍是卷积的向后通过。。它确实是CuDNN提出的一种非确定性算法,标记为CUDNN_CONVOLUTION_BWD_FILTER_ALGO_0的少数几个操作之一。该算法还存在于向后筛选器的可能选择列表。中的TensorFlow中。自从过滤器的选择似乎是基于性能的。以来,如果它更有效率的话,它确实可以被选中。(我对TensorFlow的C++代码不太熟悉,所以请稍加考虑。)
这很重要吗?
如果您正在调试一个问题,决定论不仅是重要的:它是强制性的。您需要重现导致问题的步骤。对于TensorFlow这样的工具包来说,这是一个真正的问题。为了缓解这个问题,您唯一的选择是调试活动,在正确的位置添加检查和断点--不是很好。
部署是事物的另一个方面,它通常希望有一个确定性的行为,部分是为了人类的接受。虽然没有人会合理地期望医疗诊断算法永远不会失败,但如果计算机能够根据运行情况给同一个病人提供不同的诊断,那将是很尴尬的。(尽管医生本身也不能对这种变异免疫。)
这些原因是纠正神经网络中不确定性的正当动机。
对于所有其他方面,我要说的是,我们需要接受神经网络训练的不确定性,如果不是接受的话。就所有目的而言,培训是随机的。我们使用随机梯度下降,洗牌数据,使用随机初始化和退出-更重要的是,训练数据本身只是一个随机样本的数据。从这个角度来看,计算机只能产生带有种子的伪随机数这一事实是一个人造产物。当你训练时,由于这种随机性,你的损失也是一个置信区间的值。比较这些值来优化超参数,同时忽略这些置信区间是没有什么意义的,因此,在我看来,花太多的精力去解决这个问题和许多其他情况下的不确定性是徒劳的。
发布于 2020-07-03 09:22:36
要获得一个MNIST网络(cnn.py),可以在我的GPU (1050 To )上进行确定的训练:
python_random.seed(42)
np.random.seed(42)
tf.set_random_seed(42) import tensorflow as tf
from tfdeterminism import patch
patch()或者:
os.environ['TF_CUDNN_DETERMINISTIC']='1'
import tensorflow as tf请注意,无论哪种方法从TF中选择确定性算法,结果损失都是可重复的,但这两种方法导致不同的损失。而且,上面的解决方案并不能使我使用的模型更复杂。
请查看https://github.com/NVIDIA/framework-determinism,以获得更最新的答案。
附带说明:
对于cuda 8.0.1,存在不确定的算法:
(来自https://docs.nvidia.com/deeplearning/sdk/cudnn-developer-guide/index.html)
https://stackoverflow.com/questions/50744565
复制相似问题