如何在TensorFlow中可视化卷积神经网络中的权重(变量)?

46

在训练完cnn模型后,我想可视化权重或打印出权重,我该怎么做呢? 甚至在训练后我也无法打印变量。 谢谢!

在训练完CNN模型后,您可以通过可视化来观察权重,或者通过打印输出来查看权重。但是,在训练后您可能无法直接打印变量。

另外,请查看tensorboard示例:https://github.com/tensorflow/tensorflow/issues/225 - Blaze
4个回答

37

为了可视化权重,你可以使用tf.image_summary()操作将卷积滤波器(或滤波器的一个切片)转换为摘要proto,使用tf.train.SummaryWriter将它们写入日志,并使用TensorBoard可视化日志。

假设您有以下(简化版)程序:

filter = tf.Variable(tf.truncated_normal([8, 8, 3]))
images = tf.placeholder(tf.float32, shape=[None, 28, 28])

conv = tf.nn.conv2d(images, filter, strides=[1, 1, 1, 1], padding="SAME")

# More ops...
loss = ...
optimizer = tf.GradientDescentOptimizer(0.01)
train_op = optimizer.minimize(loss)

filter_summary = tf.image_summary(filter)

sess = tf.Session()
summary_writer = tf.train.SummaryWriter('/tmp/logs', sess.graph_def)
for i in range(10000):
  sess.run(train_op)
  if i % 10 == 0:
    # Log a summary every 10 steps.
    summary_writer.add_summary(filter_summary, i)

完成此操作后,您可以启动TensorBoard来可视化/tmp/logs中的日志,并可以看到过滤器的可视化。

请注意,此技巧将深度为3的过滤器可视化为RGB图像(以匹配输入图像的通道)。如果您有更深的过滤器,或者它们没有意义解释为颜色通道,则可以使用tf.split()操作在深度维上拆分过滤器,并为每个深度生成一个图像摘要。


如果我只想将它打印出来怎么办?如何访问名称范围为“conv1”的变量,其名称为“weight”? - Wuchen
1
如果您只想打印变量,可以将 tf.Variable 对象传递给 sess.run(),它将返回一个包含权重的 numpy 数组。 - mrry
1
@Wuchen 这里是如何在作用域“conv1”下获取变量“weight”的代码 -- 使用tf.variable_scope('conv1') as scope_conv: weights = tf.get_variable('weights') - etoropov
4
请注意,后续版本中的语法已更改为tf.image_summary(tag, tensor, ...) - Dima Lituiev
18
自2016年11月30日起,tf.image_summary已经被弃用,取而代之的是tf.summary.image。详情请参见https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/ops/logging_ops.py。 - P-Gn

22

像@mrry所说,你可以使用tf.image_summary。例如,在cifar10_train.py中,你可以在def train()下的某个地方放置这段代码。注意如何在scope 'conv1'下访问变量。

# Visualize conv1 features
with tf.variable_scope('conv1') as scope_conv:
  weights = tf.get_variable('weights')

  # scale weights to [0 255] and convert to uint8 (maybe change scaling?)
  x_min = tf.reduce_min(weights)
  x_max = tf.reduce_max(weights)
  weights_0_to_1 = (weights - x_min) / (x_max - x_min)
  weights_0_to_255_uint8 = tf.image.convert_image_dtype (weights_0_to_1, dtype=tf.uint8)

  # to tf.image_summary format [batch_size, height, width, channels]
  weights_transposed = tf.transpose (weights_0_to_255_uint8, [3, 0, 1, 2])

  # this will display random 3 filters from the 64 in conv1
  tf.image_summary('conv1/filters', weights_transposed, max_images=3)

如果您想将所有conv1滤波器可视化为一个漂亮的网格,您需要自己将它们组织成一个网格。今天我做到了,所以现在我想分享一个用于将conv1可视化为网格的gist


没问题!谢谢。 - Tanvir
1
如果通道数为16,如何进行可视化呢? - raptoravis
@raptoravis 没有默认的方法,也没有太多意义。我猜这不是针对第一层的。如果我想这样做,我会修改答案中的要点以显示16个网格,每个网格为1个通道(灰度)。 - etoropov
@etoropov 是的,你说得对,这是为第二层设计的。感谢你的建议! - raptoravis

7
您可以按以下方式将值提取为 numpy 数组:
with tf.variable_scope('conv1', reuse=True) as scope_conv:
    W_conv1 = tf.get_variable('weights', shape=[5, 5, 1, 32])
    weights = W_conv1.eval()
    with open("conv1.weights.npz", "w") as outfile:
        np.save(outfile, weights)

请注意,您需要调整作用域(在我的情况下为'conv1')和变量名(在我的情况下为'weights')。接下来就是对numpy数组进行可视化。一个展示numpy数组的例子如下:
#!/usr/bin/env python

"""Visualize numpy arrays."""

import numpy as np
import scipy.misc

arr = np.load('conv1.weights.npb')

# Get each 5x5 filter from the 5x5x1x32 array
for filter_ in range(arr.shape[3]):
    # Get the 5x5x1 filter:
    extracted_filter = arr[:, :, :, filter_]

    # Get rid of the last dimension (hence get 5x5):
    extracted_filter = np.squeeze(extracted_filter)

    # display the filter (might be very small - you can resize the window)
    scipy.misc.imshow(extracted_filter)

1
我必须使用 with open("conv1.weights.npz", "wb") as outfile:(注意b)与Python 3一起使用。 - mimoralea

0

使用 tensorflow 2 API,有几个选项:

使用 get_weights() 函数提取权重。

weights_n = model.layers[n].get_weights()[0]

使用 numpy() 转换函数提取偏差。

bias_n = model.layers[n].bias.numpy()


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