使用Tensorflow时将大型矩阵计算拟合到内存中

使用Tensorflow时将大型矩阵计算拟合到内存中,tensorflow,Tensorflow,我试图建立一个分为两个阶段的模型。 第一个获取输入图像并将其通过conv deconv网络。结果张量具有与所需输出图像(与输入图像大小相同)中的像素对应的条目 为了计算最终的输出图像,我想从第一个阶段开始,获取每个像素位置生成的值,并将其作为应用于整个输入图像的缩减函数的附加输入。第二步没有可训练的变量,但它的计算/内存开销确实随着输入的大小呈指数增长(每个输出像素是所有输入像素的函数) 我目前正在使用tf.map\u fn来计算输出图像。我将输出像素计算函数映射到第一阶段的结果。我的愿望是te

我试图建立一个分为两个阶段的模型。 第一个获取输入图像并将其通过conv deconv网络。结果张量具有与所需输出图像(与输入图像大小相同)中的像素对应的条目

为了计算最终的输出图像,我想从第一个阶段开始,获取每个像素位置生成的值,并将其作为应用于整个输入图像的缩减函数的附加输入。第二步没有可训练的变量,但它的计算/内存开销确实随着输入的大小呈指数增长(每个输出像素是所有输入像素的函数)

我目前正在使用tf.map\u fn来计算输出图像。我将输出像素计算函数映射到第一阶段的结果。我的愿望是tensorflow将分配内存来存储每个像素计算所需的中间张量,然后在继续下一个像素计算之前释放内存。但是,它似乎永远不会释放导致OOM错误的中间计算


有没有办法告诉tensorflow(无论是显式的还是隐式的)它应该释放分配用于保存计算中不再需要的张量数据的内存?

tensorflow会在将来的任何计算中不再需要张量时立即释放该张量的内存。您可以通过查看内存释放消息来验证这一点,如下图所示

可能是因为TensorFlow以内存效率低下的顺序执行节点,所以内存不足

作为一个例子,考虑以下计算:

k = 2000
a = tf.random_uniform(shape=(k,k))
for i in range(n):
    a = tf.matmul(a, tf.random_uniform(shape=(k,k)))
评估的顺序如下所示

首先计算所有圆(
tf.random_uniform
)节点,然后计算正方形(
tf.matmul
)。与优化顺序的
O(1)
相比,这具有
O(n)
内存需求

您可以使用控件依赖项强制执行特定的执行顺序,即使用助手函数,如下所示:

import tensorflow.contrib.graph_editor as ge
def run_after(a_tensor, b_tensor):
    """Force a to run after b"""
    ge.reroute.add_control_inputs(a_tensor.op, [b_tensor.op])

一旦将来的计算不再需要张量,TensorFlow就会释放该张量的内存。您可以通过查看内存释放消息来验证这一点,如下图所示

可能是因为TensorFlow以内存效率低下的顺序执行节点,所以内存不足

作为一个例子,考虑以下计算:

k = 2000
a = tf.random_uniform(shape=(k,k))
for i in range(n):
    a = tf.matmul(a, tf.random_uniform(shape=(k,k)))
评估的顺序如下所示

首先计算所有圆(
tf.random_uniform
)节点,然后计算正方形(
tf.matmul
)。与优化顺序的
O(1)
相比,这具有
O(n)
内存需求

您可以使用控件依赖项强制执行特定的执行顺序,即使用助手函数,如下所示:

import tensorflow.contrib.graph_editor as ge
def run_after(a_tensor, b_tensor):
    """Force a to run after b"""
    ge.reroute.add_control_inputs(a_tensor.op, [b_tensor.op])

您是否将计算划分为多个张量?(即TensorFlow不会释放tensor对象的一部分)是的。我最初确实试着做巨大的矩阵运算,但这对我来说更有意义,为什么它不起作用。这就是为什么我使用tf.map_fn()为每个像素计算创建张量的原因。您是否将计算划分为多个张量?(即TensorFlow不会释放tensor对象的一部分)是的。我最初确实试着做巨大的矩阵运算,但这对我来说更有意义,为什么它不起作用。这就是为什么我使用tf.map_fn()为每个像素计算创建张量的原因。谢谢,很高兴听到这样的消息:如果我能正确地获得依赖项,这应该会自动处理。在我的例子中,我使用的是map_fn,因此我似乎没有立即意识到如何强制按顺序完成操作(顺便说一句,设置parallel_iterations=1似乎并没有像我想象的那样解决我的问题)。构建一个由映射函数创建的输出张量集合,然后按照您的建议将它们与依赖项串在一起,这似乎是正确的方法吗?嗯,map_fn在张量切片上工作,似乎不可能为不需要的切片释放内存,为什么不使用常规Python映射?这是有意义的。我想我只是本能地倾向于使用tensorflow ops,但我想这可能有点过头了。不过,我并不担心tf.map_fn的输入/输出的大小,只担心映射函数中生成的中间张量(如果有意义的话)。在python映射的情况下,我仍然需要构建依赖链,对吗?当我传递一个python函数,该函数构建一部分图(并返回一个张量)作为map_fn fn参数时,我假设tensorflow所做的一切都是压下连接到张量切片的该图结构的大量实例,对吗?不,它比那更有效谢谢,很高兴听到这样的消息,如果我能得到正确的依赖关系,这应该会自动处理。在我的例子中,我使用的是map_fn,因此我似乎没有立即意识到如何强制按顺序完成操作(顺便说一句,设置parallel_iterations=1似乎并没有像我想象的那样解决我的问题)。构建一个由映射函数创建的输出张量集合,然后按照您的建议将它们与依赖项串在一起,这似乎是正确的方法吗?嗯,map_fn在张量切片上工作,似乎不可能为不需要的切片释放内存,为什么不使用常规Python映射?这是有意义的。我想我只是本能地倾向于使用tensorflow ops,但我想这可能有点过头了。不过,我并不担心tf.map_fn的输入/输出的大小,只担心映射函数中生成的中间张量(如果有意义的话)。在pythonmap的情况下,我仍然需要构建依赖链,对吗?当我传递一个python函数作为map_fn参数来构建一个图的一部分(并返回一个张量)时,我假设