37

我正在尝试使用函数在 tensorflow 中可视化卷积层的输出tf.image_summary。我已经在其他情况下成功地使用了它(例如可视化输入图像),但是在此处正确地重塑输出时遇到了一些困难。我有以下转换层:

img_size = 256
x_image = tf.reshape(x, [-1,img_size, img_size,1], "sketch_image")

W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)

所以 的输出h_conv1将具有形状[-1, img_size, img_size, 32]。只是使用tf.image_summary("first_conv", tf.reshape(h_conv1, [-1, img_size, img_size, 1]))不考虑 32 个不同的内核,所以我基本上在这里切片不同的特征图。

如何正确重塑它们?或者我可以使用另一个辅助函数来将此输出包含在摘要中吗?

4

5 回答 5

36

我不知道辅助函数,但如果您想查看所有过滤器,您可以将它们打包到一张图像中,并使用tf.transpose.

所以如果你有一个张量是imagesx ixx iyxchannels

>>> V = tf.Variable()
>>> print V.get_shape()

TensorShape([Dimension(-1), Dimension(256), Dimension(256), Dimension(32)])

所以在这个例子ix = 256iy=256channels=32

首先切下 1 个图像,然后删除image维度

V = tf.slice(V,(0,0,0,0),(1,-1,-1,-1)) #V[0,...]
V = tf.reshape(V,(iy,ix,channels))

接下来在图像周围添加几个零填充像素

ix += 4
iy += 4
V = tf.image.resize_image_with_crop_or_pad(image, iy, ix)

然后重塑,以便您拥有 4x8 通道而不是 32 个通道,让我们调用它们cy=4cx=8.

V = tf.reshape(V,(iy,ix,cy,cx)) 

现在是棘手的部分。tf似乎以 C 顺序返回结果,numpy 的默认值。

当前顺序,如果展平,将列出第一个像素的所有通道(迭代cxcy),然后列出第二个像素的通道(递增ix)。ix在递增到下一行 ( ) 之前遍历像素行 ( iy)。

我们想要将图像布置在网格中的顺序。因此,在沿着通道行 () 前进之前,您会穿过图像ix的一行 ( cx),当您到达通道行的末尾时,您会进入图像中的下一行 ( iy)在图像中,您递增到下一行通道 ( cy)。所以:

V = tf.transpose(V,(2,0,3,1)) #cy,iy,cx,ix

就我个人np.einsum而言,为了可读性,我更喜欢花哨的转置,但它还没有tf .

newtensor = np.einsum('yxYX->YyXx',oldtensor)

无论如何,现在像素的顺序正确,我们可以安全地将其展平为 2d 张量:

# image_summary needs 4d input
V = tf.reshape(V,(1,cy*iy,cx*ix,1))

试试看tf.image_summary,你应该得到一个小图像网格。

下面是按照此处的所有步骤操作后得到的图像。

在此处输入图像描述

于 2015-11-20T00:33:53.763 回答
2

如果有人想“跳转”到 numpy 并可视化“那里”,这里有一个示例如何同时显示Weightsprocessing result. 所有转换均基于上一个答案mdaoust

# to visualize 1st conv layer Weights
vv1 = sess.run(W_conv1)

# to visualize 1st conv layer output
vv2 = sess.run(h_conv1,feed_dict = {img_ph:x, keep_prob: 1.0})
vv2 = vv2[0,:,:,:]   # in case of bunch out - slice first img


def vis_conv(v,ix,iy,ch,cy,cx, p = 0) :
    v = np.reshape(v,(iy,ix,ch))
    ix += 2
    iy += 2
    npad = ((1,1), (1,1), (0,0))
    v = np.pad(v, pad_width=npad, mode='constant', constant_values=p)
    v = np.reshape(v,(iy,ix,cy,cx)) 
    v = np.transpose(v,(2,0,3,1)) #cy,iy,cx,ix
    v = np.reshape(v,(cy*iy,cx*ix))
    return v

# W_conv1 - weights
ix = 5  # data size
iy = 5
ch = 32   
cy = 4   # grid from channels:  32 = 4x8
cx = 8
v  = vis_conv(vv1,ix,iy,ch,cy,cx)
plt.figure(figsize = (8,8))
plt.imshow(v,cmap="Greys_r",interpolation='nearest')

#  h_conv1 - processed image
ix = 30  # data size
iy = 30
v  = vis_conv(vv2,ix,iy,ch,cy,cx)
plt.figure(figsize = (8,8))
plt.imshow(v,cmap="Greys_r",interpolation='nearest')
于 2016-02-06T23:36:20.960 回答
1

您可以尝试以这种方式获取卷积层激活图像:

    h_conv1_features = tf.unpack(h_conv1, axis=3)
    h_conv1_imgs = tf.expand_dims(tf.concat(1, h_conv1_features_padded), -1)

这得到一个垂直条纹,所有图像垂直连接。

如果你想让它们填充(在我的 relu 激活用白线填充的情况下):

    h_conv1_features = tf.unpack(h_conv1, axis=3)
    h_conv1_max = tf.reduce_max(h_conv1)
    h_conv1_features_padded = map(lambda t: tf.pad(t-h_conv1_max, [[0,0],[0,1],[0,0]])+h_conv1_max, h_conv1_features)
    h_conv1_imgs = tf.expand_dims(tf.concat(1, h_conv1_features_padded), -1)
于 2016-09-17T05:11:09.737 回答
1

我个人尝试将每个 2d 过滤器平铺在单个图像中。

为了做到这一点——如果我没有大错特错,因为我对 DL还很陌生——我发现利用depth_to_space函数可能会有所帮助,因为它需要一个 4d 张量

[batch, height, width, depth]

并产生形状的输出

[batch, height*block_size, width*block_size, depth/(block_size*block_size)]

其中 block_size 是输出图像中“图块”的数量。唯一的限制是深度应该是block_size的平方,它是一个整数,否则它不能正确“填充”结果图像。一种可能的解决方案是将输入张量的深度填充到该方法接受的深度,但我还没有尝试过。

于 2017-09-29T11:34:38.510 回答
0

另一种我认为非常简单的方法是使用该get_operation_by_name功能。我很难用其他方法来可视化图层,但这对我有帮助。

#first, find out the operations, many of those are micro-operations such as add etc.
graph = tf.get_default_graph()
graph.get_operations()

#choose relevant operations
op_name = '...' 
op = graph.get_operation_by_name(op_name)
out = sess.run([op.outputs[0]], feed_dict={x: img_batch, is_training: False}) 
#img_batch is a single image whose dimensions are (1,n,n,1). 

# out is the output of the layer, do whatever you want with the output
#in my case, I wanted to see the output of a convolution layer
out2 = np.array(out)
print(out2.shape)

# determine, row, col, and fig size etc.
for each_depth in range(out2.shape[4]):
    fig.add_subplot(rows, cols, each_depth+1)
    plt.imshow(out2[0,0,:,:,each_depth], cmap='gray')

例如下面是我模型中第二个卷积层的输入(彩色猫)和输出。以下

请注意,我知道这个问题很老,而且 Keras 有更简单的方法,但对于使用其他人(例如我)的旧模型的人来说,这可能很有用。

于 2019-09-07T13:34:49.473 回答