我正在运行一个遗传超参数搜索算法,它可以快速地饱和所有可用的内存。
经过几次测试,看起来在不同的时期之间和在训练不同的模型时,keras所需的内存都会增加。随着小批处理规模的增加,问题变得更加严重,1~5的小批处理至少给了我足够的时间来看到内存使用量在最初的几次调整中快速上升,然后缓慢而稳定地随着时间的推移而增加。
我已经检查了keras预测内存交换无限期增加、Keras:执行超参数网格搜索时内存不足和Keras (TensorFlow,CPU):循环中的顺序模型训练,所以每次迭代之后,我已经在清除keras会话并重置tensorflow的图形。
我还尝试显式删除模型和历史对象,并运行gc.collect(),但没有结果。
我在CPU上运行Keras2.2.4、tensorflow 1.12.0、Python3.7.0。我为每个基因运行的代码以及用于度量内存使用情况的回调:
import tensorflow as tf
import keras as K
class MemoryCallback(K.callbacks.Callback):
def on_epoch_end(self, epoch, log={}):
print(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss)
def Rateme(self,loss,classnum,patience,epochs,DWIshape,Mapshape,lr,TRAINDATA,TESTDATA,TrueTrain, TrueTest,ModelBuilder,maxthreads):
K.backend.set_session(K.backend.tf.Session(config=K.backend.tf.ConfigProto(intra_op_parallelism_threads=maxthreads, inter_op_parallelism_threads=maxthreads)))
#Early Stopping
STOP=K.callbacks.EarlyStopping(monitor='val_acc', min_delta=0.001,
patience=patience, verbose=0, mode='max')
#Build model
Model=ModelBuilder(DWIshape, Mapshape, dropout=self.Dropout,
regularization=self.Regularization,
activ='relu', DWIconv=self.nDWI, DWIsize=self.sDWI,
classes=classnum, layers=self.nCNN,
filtersize=self.sCNN,
FClayers=self.FCL, last=self.Last)
#Compile
Model.compile(optimizer=K.optimizers.Adam(lr,decay=self.Decay), loss=loss, metrics=['accuracy'])
#Fit
his=Model.fit(x=TRAINDATA,y=TrueTrain,epochs=epochs,batch_size=5, shuffle=True, validation_data=(TESTDATA,TrueTest), verbose=0, callbacks=[STOP, MemoryCallback()]) #check verbose and callbacks
#Extract
S=Model.evaluate(x=TESTDATA, y=TrueTest,verbose=1)[1]
del his
del Model
del rateme
K.backend.clear_session()
tf.reset_default_graph()
gc.collect()
return S发布于 2021-04-17 12:17:10
由于内存泄漏似乎仍然存在于TensorFlow 2.4.1中,所以在使用内置函数(如model.fit() )时,这里是我的看法。
发行
解决方案
run_eagerly=True参数添加到model.compile()函数中。然而,这样做可能会导致TensorFlow的图形优化不再工作,从而导致性能下降(参考文献)。activation内部使用tf.keras.layers参数。将激活函数作为分离层(参考文献)。LeakyReLU而不是ReLU作为激活函数(参考文献)。注意:因为所有的要点都可以单独实现,所以您可以混合和匹配它们,直到得到对您有用的结果。无论如何,下面是一个代码片段,显示了所有解决方案:
import gc
from tensorflow.keras import backend as k
from tensorflow.keras.layers import Conv2D, BatchNormalization, ReLU
from tensorflow.keras.callbacks import Callback
class CovNet:
...
x = Conv2d(
...,
activation=None
)(x)
x = BatchNormalization()(x)
x = ReLU()(x) # or LeakyReLU
...
#--------------------------------------------------------------------------------
class ClearMemory(Callback):
def on_epoch_end(self, epoch, logs=None):
gc.collect()
k.clear_session()
#--------------------------------------------------------------------------------
model.compile(
...,
run_eagerly=True
)
#--------------------------------------------------------------------------------
model.fit(
...,
callbacks=ClearMemory()
)有了这些解决方案,我现在能够训练占用较少的RAM,保持不变,如果仍然存在内存泄漏,这是可以忽略不计的。
感谢@洪涛杨致远提供了一个相关的GitHub问题链接,并为他的评论在GitHub提供了新的链接。
Notes
tcmalloc代替默认的malloc分配程序在一定程度上减轻了内存泄漏。有关参考资料,请参阅这里或这里。我希望这也能帮助到其他人,并为你节省一些在互联网上进行研究的时间。
发布于 2018-12-08 17:13:12
消耗整个可用内存是TF的默认行为。
可以使用以下代码限制TF中的内存量:
import tensorflow as tf
from keras.backend.tensorflow_backend import set_session
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.9 # fraction of memory
config.gpu_options.visible_device_list = "0"
set_session(tf.Session(config=config))发布于 2019-01-22 13:37:19
最后,我只是用bash脚本重新启动了每个培训班之间的python会话,找不到更好的方法来避免爆炸性的内存占用。
https://stackoverflow.com/questions/53683164
复制相似问题