我需要啥 K.clear_session() 和 del 模型(Keras with Tensorflow-gpu)?
Posted
技术标签:
【中文标题】我需要啥 K.clear_session() 和 del 模型(Keras with Tensorflow-gpu)?【英文标题】:What do I need K.clear_session() and del model for (Keras with Tensorflow-gpu)?我需要什么 K.clear_session() 和 del 模型(Keras with Tensorflow-gpu)? 【发布时间】:2018-11-26 10:51:09 【问题描述】:我在做什么 我正在训练并使用卷积神经元网络 (CNN) 进行图像分类,使用 Keras 和 Tensorflow-gpu 作为后端。
我正在使用什么 - PyCharm 社区 2018.1.2 - Python 2.7 和 3.5(但不能同时使用) - Ubuntu 16.04 - Keras 2.2.0 - Tensorflow-GPU 1.8.0 作为后端
我想知道的 在许多代码中,我看到人们使用
from keras import backend as K
# Do some code, e.g. train and save model
K.clear_session()
或使用后删除模型:
del model
关于 clear_session
的 keras 文档说:“销毁当前的 TF 图并创建一个新的。有助于避免旧模型/层造成混乱。” - https://keras.io/backend/
这样做有什么意义,我也应该这样做吗?在加载或创建新模型时,我的模型无论如何都会被覆盖,那何必呢?
【问题讨论】:
您是否发现了与您的问题相关的任何内容?我试图找到相同的答案。提供的 1 个答案并没有完全理清我的想法。 据我所知,模型不会被覆盖,如果您不清除它,TF 图只会将新模型添加到旧模型 TF 图中。 Del 模型只是节省内存,因此 cpu/gpu 不必在其中保存额外的东西。 如果您在 Keras 中使用 Sequential 方法,并通过 model=Sequential() 开始创建新模型,那么我同意您之前的模型应该被覆盖。但是,我在文档中找不到确认。 其实你的问题本身对我很有帮助,非常感谢我在过去的 6 个小时里一直在寻找这个,再次感谢祝你好运 【参考方案1】:K.clear_session()
在您连续创建多个模型时很有用,例如在超参数搜索或交叉验证期间。您训练的每个模型都会向图中添加节点(可能有数千个)。 TensorFlow 会在您(或 Keras)调用 tf.Session.run()
或 tf.Tensor.eval()
时执行整个图形,因此您的模型训练速度会越来越慢,并且您也可能会耗尽内存。清除会话会删除以前模型中遗留的所有节点,释放内存并防止速度变慢。
21/06/19 编辑:
TensorFlow 默认是惰性求值的。 TensorFlow 操作不会立即评估:创建张量或对其执行一些操作会在数据流图中创建节点。当您调用tf.Session.run()
或tf.Tensor.eval()
时,通过一次性评估图表的相关部分来计算结果。这样 TensorFlow 就可以构建一个执行计划,将可以并行执行的操作分配给不同的设备。它还可以将相邻节点折叠在一起或删除冗余节点(例如,如果您连接两个张量,然后再次将它们分开而不改变)。更多详情请见https://www.tensorflow.org/guide/graphs
您的所有 TensorFlow 模型都以一系列张量和张量运算的形式存储在图中。机器学习的基本操作是张量点积——神经网络的输出是输入矩阵和网络权重的点积。如果你有一个单层感知器和 1000 个训练样本,那么每个 epoch 至少会创建 1000 个张量操作。如果您有 1,000 个 epoch,那么在考虑预处理、后处理和更复杂的模型(例如循环网络、编码器-解码器、注意力模型等)之前,您的图最后至少包含 1,000,000 个节点。
问题是最终图表会太大而无法放入视频内存(在我的情况下为 6 GB),因此 TF 会将图表的部分内容从视频传输到主内存并返回。最终它甚至会变得对于主内存(12 GB)来说太大,并开始在主内存和硬盘之间移动。不用说,这让事情变得难以置信,而且随着训练的进行越来越慢。在开发此保存模型/清除会话/重新加载模型流程之前,我计算过,按照我经历的每个时期的减速率,我的模型完成训练所需的时间将超过宇宙的年龄。
免责声明:我已经将近一年没有使用 TensorFlow,所以这可能已经改变了。我记得有很多关于这个的 GitHub 问题,所以希望它已经被修复了。
【讨论】:
在运行 K.clear_session() 时是否需要创建新模型。另外,您能解释一下向图形部分添加节点以及模型变慢和内存不足的原因吗? 这个答案可能不适用于当前版本的 TensorFlow,因为我自去年以来就没有使用过它。假设情况没有改变;是的,您需要创建一个新模型或保存并重新加载旧模型以继续训练。我已编辑我的答案以回答您问题的第二部分。 通过执行 K.clear_session() 我假设当前图被删除并且依赖于该图存在的每个未来操作(例如添加新层或运行 model.fit())没有图表链接到了。 @mathlover Marcus 是正确的,如果您删除图表并创建一个新图表,那么您现有的张量会有一个悬空参考。这就是为什么您应该在删除图形之前保存模型然后重新加载它的原因。这样,您将获得一个包含所有必要数据的新图表。 @Chris Swinchatt 和所有人:今天因 OOM 崩溃后,我可以确认这仍然适用!我通过检查我的 Tensorboard 日志发现了这一点:日志文件按照创建的顺序变大,并且随着不同模型的图表链接在一起,Tensorboard 中的图表越来越复杂。它似乎并没有影响模型结果(正如人们所希望的那样),但任何人都可以确定它不会损害以后的模型吗? (除了明显的速度/内存问题)。【参考方案2】:del 将删除 python 中的变量,由于 model 是一个变量,del model 将删除它,但 TF 图不会有任何变化(TF 是您的 Keras 后端)。这就是说,K.clear_session() 将破坏当前的 TF 图并创建一个新的。创建一个新模型似乎是一个独立的步骤,但不要忘记后端:)
【讨论】:
【参考方案3】:在交叉验证期间,我想运行 number_of_replicates
folds(也称为复制)以获得平均验证损失,作为与其他算法比较的基础。所以我需要对两个独立的算法进行交叉验证,而且我有多个 GPU 可用,所以我认为这不是问题。
不幸的是,我开始在我的丢失日志中看到像_2
、_3
等附加到它们的层名称。我还注意到,如果我通过在单个脚本中使用循环按顺序运行复制(也称为折叠),我会耗尽 GPU 上的内存。
这个策略对我有用;我已经在 Ubuntu lambda 机器上的 tmux
会话中连续运行了几个小时,有时会看到内存泄漏,但它们被超时功能杀死。它需要估计完成每个交叉验证折叠/复制所需的时间长度;在下面的代码中,该数字是timeEstimateRequiredPerReplicate
(最好将循环的次数加倍,以防其中一半被杀死):
from multiprocessing import Process
# establish target for process workers
def machine():
import tensorflow as tf
from tensorflow.keras.backend import clear_session
from tensorflow.python.framework.ops import disable_eager_execution
import gc
clear_session()
disable_eager_execution()
nEpochs = 999 # set lower if not using tf.keras.callbacks.EarlyStopping in callbacks
callbacks = ... # establish early stopping, logging, etc. if desired
algorithm_model = ... # define layers, output(s), etc.
opt_algorithm = ... # choose your optimizer
loss_metric = ... # choose your loss function(s) (in a list for multiple outputs)
algorithm_model.compile(optimizer=opt_algorithm, loss=loss_metric)
trainData = ... # establish which data to train on (for this fold/replicate only)
validateData = ... # establish which data to validate on (same caveat as above)
algorithm_model.fit(
x=trainData,
steps_per_epoch=len(trainData),
validation_data=validateData,
validation_steps=len(validateData),
epochs=nEpochs,
callbacks=callbacks
)
gc.collect()
del algorithm_model
return
# establish main loop to start each process
def main_loop():
for replicate in range(replicatesDesired - replicatesCompleted):
print(
'\nStarting cross-validation replicate '.format(
replicate +
replicatesCompleted + 1
) +
'of desired:\n'.format(
replicatesDesired
)
)
p = Process(target=process_machine)
p.start()
flag = p.join(timeEstimateRequiredPerReplicate)
print('\n\nSubprocess exited with code .\n\n'.format(flag))
return
# enable running of this script from command line
if __name__ == "__main__":
main_loop()
【讨论】:
main_loop
指令状态通过它所需的交叉验证复制(折叠)数量的两倍;这是因为如果发生内存泄漏,当相应的进程被杀死(max_duration_in_seconds
通过之后)时,折叠/复制就会丢失。
奇怪的是,将gc.collect()
放在 del algorithm_model
之后会导致出现内存问题...再次编辑答案。
我在 Github 上将此作为 keras 问题提交,并带有 MVE 代码示例:github.com/keras-team/keras/issues/13975
看起来问题可能在 TF 2.1 中得到解决。我不想冒险再次堵塞我的 GPU 以确保。如果有人听到消息,请让大家知道!
为什么这个答案是负分?它也解决了我的问题。这很有用。我赞成它。实际上,有帮助的是禁用急切执行。以上是关于我需要啥 K.clear_session() 和 del 模型(Keras with Tensorflow-gpu)?的主要内容,如果未能解决你的问题,请参考以下文章