在TensorFlow中实现im2col

时间:2017-08-07 18:56:43

标签: python machine-learning tensorflow neural-network conv-neural-network

我希望在TensorFlow中实现类似于2D卷积的操作。根据我的理解,实现卷积的最常用方法是首先对图像应用im2col操作(参见here - 子部分“实现为矩阵乘法”) - 将图像转换为2D矩阵的操作,其中内核作为扁平列应用于图像的各个“块”。

换句话说,上述链接资源的摘录解释了im2col做得很好:

  

[...]例如,如果输入是[227x227x3] (格式为高x宽x n_channels)并且要在步幅4处与11x11x3滤波器进行卷积,那么我们将输入中的[11x11x3]像素块取出并将每个块拉伸为大小为11 * 11 * 3 = 363的列向量。在输入处以4的步长迭代此过程给出(227-11)/ 4 + 1 =沿宽度和高度的55个位置,导致X_col的输出矩阵im2col大小为[363 x 3025],其中每列都是伸出的感受野,并且有55 * 55 = 3025的他们总共。请注意,由于感知字段重叠,因此输入卷中的每个数字都可能在多个不同的列中重复。

据我所知TensorFlow docs,这也是tf.nn.conv2d内部所做的事情。

现在,我想在TensorFlow中单独实现所述im2col操作(因为我希望能够访问此中间结果)。由于这涉及以非平凡的方式复制值,我将如何为此操作自己构建相对有效的计算图?同样,如何实现反向操作?

1 个答案:

答案 0 :(得分:4)

您可以使用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,这是complex beast(winograd,ptx,...)。只有在某些情况下,它才会在CPU上使用im2col方法here和量化版本here