在平时某个项目的时候,在完成对模型结构的建模之后,还需要对模型的训练超参数进行一个寻优过程,
当然这个结构建模过程也是可以进行参数寻优的。但这个不是重点,重点在于我们在进行超参数寻优的过程中,如果需要不断的加载模型进内存,则会导致内存不断增加,就算你加载的是同个建立好了的模型,
当内存溢出的时候进程就会被kill,白寻优了~
产生的内存
首先我们要分清楚,加载模型会消耗内存,在对模型进行训练的时候也会消耗内存。这两部分的内存是不一样的。因此针对的处理方法也不一样。
可以看看测试内存的例子
可以看到load_model 消耗了64m
model.fit 消耗了110m
比较好解决的是加载模型消耗的内存。
直接上代码
from memory_profiler import profile
@profile(precision=4, stream=open('memory_profiler.log', 'w+'))
def main_test():
train_x, train_s_x, train_y, steps_per_epoch_size, test_steps, batch_size = get_data_test()
for i in range(10):
model = load_model('model.h5')
if __name__ == '__main__':
main_test()
借助memory_profiler 对内存进行分析,没用的可以看下我的其他文章,有对这个模块进行介绍。
没有优化过的加载模型,我们看看内存消耗的情况如下
加载模块包其他的运行消耗了411m的内存,加载数据消耗了9m,总加载10次内存一共消耗了1.5g内存,其中最大的一次大概是消耗了235m。可以预想到如果我们加载上百次甚至上千次,内存很快就会被我们消耗完。
加上清除图代码
from memory_profiler import profile
@profile(precision=4, stream=open('memory_profiler.log', 'w+'))
def main_test():
train_x, train_s_x, train_y, steps_per_epoch_size, test_steps, batch_size = get_data_test()
for i in range(10):
tf.keras.backend.clear_session()
model = load_model('model.h5')
if __name__ == '__main__':
main_test()
按照文档的理解,clear_session会销毁当前的 TF 图并创建一个新图。在同时会释放旧图所占用的内存,并且还有用于避免旧模型/网络层混乱。相信这部分很多人也体会多,同时循环创建N个模型的时候,除了第一个模型的输入层是从编号1开始,其他模型都是延续了上个模型最后的编号进行叠加的。这会导致模型的混乱,图节点的不断增加,也会导致速度变慢。
我们看一下加了清除图之后的效果
可以看到clear_session确实清除了旧图产生的内存。其中有部分其他的数值占用的内存则还是会被保留在内存里,但是这部分就比较小了。
model.fit 消耗的内存分析
先看一下不清除图产生的内存如下图
可以看到跟之前相比,循环训练10次产生的内存大概300m
清除图之后的内存消耗如下图
清除图后消耗的内存也大概是300m
也就是说clear_session并不能清除fit 产生的内存。
看看在循环20次的时候,内存使用情况
循环20次,里面fit产生的内存大概是700m,这也就是说随着循环次数的增加,fit产生的内存会不断增加,并且随着训练数据量的增加,消耗的内存更加明显。
找了很多资料,对于fit产生的内存这一块还是没有很好的解决方案,因此只能用最简单的方法曲线救国,执行一定的任务数就重启进程。如果需要详细的流程再私信我出个具体的教程吧。
如果有大佬知道怎么解决fit产生的内存,希望能指导一下小蚂蚁~
我是一只前进的蚂蚁,希望能一起前行。
如果对您有一点帮助,一个赞就够了,感谢!
注:如果本篇博客有任何错误和建议,欢迎各位指出,不胜感激!!!