我有一个张量流模型,带有一些相对较大的135 x 135 x 1 x 3
卷积滤镜。我发现tf.nn.conv2d
对于如此大的过滤器变得无法使用 - 它试图使用超过60GB的内存,此时我需要杀死它。以下是重现我的错误的最小脚本:
import tensorflow as tf
import numpy as np
frames, height, width, channels = 200, 321, 481, 1
filter_h, filter_w, filter_out = 5, 5, 3 # With this, output has shape (200, 317, 477, 3)
# filter_h, filter_w, filter_out = 7, 7, 3 # With this, output has shape (200, 315, 475, 3)
# filter_h, filter_w, filter_out = 135, 135, 3 # With this, output will be smaller than the above with shape (200, 187, 347, 3), but memory usage explodes
images = np.random.randn(frames, height, width, channels).astype(np.float32)
filters = tf.Variable(np.random.randn(filter_h, filter_w, channels, filter_out).astype(np.float32))
images_input = tf.placeholder(tf.float32)
conv = tf.nn.conv2d(images_input, filters, strides=[1, 1, 1, 1], padding="VALID")
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
result = sess.run(conv, feed_dict={images_input: images})
print result.shape
首先,任何人都可以解释这种行为吗?为什么内存使用会因过滤器大小而爆炸? (注意:我也尝试更改我的尺寸以使用单个conv3d
而不是一批conv2d
s,但这有同样的问题)
第二,任何人都可以提出一个解决方案,比如将操作分解为200个独立的单图像卷积吗?
修改:重新阅读tf.nn.conv2d()
上的docs后,我在解释它如何运作时注意到了这一点:
- 将滤镜展平为形状为
[filter_height * filter_width * in_channels, output_channels]
的二维矩阵。- 从输入张量中提取图像色块以形成形状为
[batch, out_height, out_width, filter_height * filter_width * in_channels]
的虚拟张量。- 对于每个补丁,右对乘滤波器矩阵和图像补丁矢量。
醇>
我最初只把它当作过程的描述,但是如果tensorflow实际上是提取和存储单独的过滤器大小的补丁'从引擎盖下的图像开始,然后一个背后的计算结果显示,在我的情况下涉及的中间计算需要大约130GB,远远超过我可以测试的限制..这个可能回答我的第一个问题,但是如果有的话,任何人都可以解释为什么当我仍然只在CPU上调试时TF会这样做?
答案 0 :(得分:3)
我最初只是将此作为对过程的描述, 但是如果tensorflow实际上是提取和存储分开的 从引擎盖下的图像过滤大小的'补丁',然后a 背面计算显示中间 在我的情况下涉及的计算需要大约130GB,远远超过极限 我可以测试一下。
正如你自己想的那样,这就是大量内存消耗的原因。 Tensorflow这样做是因为滤波器通常很小,计算矩阵乘法比计算卷积要快很多。
任何人都可以解释为什么当我还在调试时TF会这样做 在CPU上?
您也可以在没有GPU的情况下使用tensorflow,因此CPU实现不仅仅用于调试。它们还针对速度进行了优化,矩阵乘法在CPU和GPU上都更快。
要使用大型过滤器进行卷积,您必须在C ++中实现大型过滤器的卷积,并将其添加为张量流的新操作。