在TensorFlow中实现im2col

12
我希望在TensorFlow中实现类似于2D卷积的操作。根据我的理解,实现卷积的最常见方法是首先对图像应用im2col操作(请参阅此处 - 子节“作为矩阵乘法的实施”)- 这是一种将图像转换为二维矩阵的操作,其中内核应用于图像的各个“块”作为扁平列。
换句话说,上面链接资源中的摘录很好地解释了im2col的作用:
[...]例如,如果输入是[227x227x3] (以高度x宽度x n_channels格式),并且要以11x11x3过滤器进行卷积,步长为4,则会在输入中取[11x11x3]像素块,并将每个块拉伸成大小为11 * 11 * 3 = 363的列向量。在步幅为4的输入中迭代此过程可得(227-11)/ 4 +1 = 55个沿宽度和高度的位置,导致输出矩阵X_colim2col 的大小为[363 x 3025],其中每列都是拉伸的感受野,总共有55 * 55 = 3025个。请注意,由于接收场重叠,因此输入卷积核中的每个数字可能会复制到多个不同的列中。
据我从TensorFlow文档中了解到,这也是tf.nn.conv2d内部执行的操作。
现在,我想在TensorFlow中单独实现im2col操作(因为我希望能够访问这个中间结果)。由于这涉及以非平凡方式复制值,因此如何为该操作构建相对有效的计算图?同样,如何实现反向操作?
1个回答

5
你可以使用extract_image_patches轻松完成此操作。
该函数将图像的每个filter_size x filter_size补丁放入深度中,生成一个[batch_size, height, width, 9]张量。
为了与tf.nn.conv2d进行比较,您可以实现用于图像的Sobel算子。
import tensorflow as tf
import numpy as np

image = np.arange(10 * 10 * 1).reshape(1, 10, 10, 1)

images = tf.convert_to_tensor(image.astype(np.float32))

filter_size = 3
sobel_x = tf.constant([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], tf.float32)
sobel_x_filter = tf.reshape(sobel_x, [3, 3, 1, 1])

image_patches = tf.extract_image_patches(images,
                                         [1, filter_size, filter_size, 1],
                                         [1, 1, 1, 1], [1, 1, 1, 1],
                                         padding='SAME')


actual = tf.reduce_sum(tf.multiply(image_patches, tf.reshape(sobel_x_filter, [9])), 3, keep_dims=True)
expected = tf.nn.conv2d(images, sobel_x_filter, strides=[1, 1, 1, 1], padding='SAME')

with tf.Session() as sess:
    print sess.run(tf.reduce_sum(expected - actual))

这将给你0.0,因为它们是等价的。这不需要反向函数。 编辑: 根据TensorFlow文档的理解,这也是在tf.nn.conv2d内部执行的操作。

不完全是这样。例如,GPU 上的 TF 依赖于 CuDNN,这是一个更加复杂的兽头(winograd,ptx,...)。只有在某些情况下才会使用im2col方法,如此处在 CPU 上以及量化版本此处


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接