caffe中如何可视化cnn各层的输出

正如caffe的examples所提,CNN model并不是一个黑盒,caffe提供了工具来查看cnn各层的所有输出

1.查看CNN各层的activations值的结构(即每一层的输出)

代码如下:

# 显示每一层
for layer_name, blob in net.blobs.iteritems():
    print layer_name + '\t' + str(blob.data.shape)

第i次循环体内部

  • layer_name提取的是net的第i层的名称
  • blob提取的是net的第i层的输出数据(4d)

结果为:

data (50, 3, 227, 227) 网络的输入,batch_number = 50,图像为227*227*3的RGB图像

conv1 (50, 96, 55, 55) 第一个conv层的输出图像大小为55*55,feature maps个数为96

pool1 (50, 96, 27, 27) 第一个pool层的图像尺寸为27*27,feature map个数为96

norm1 (50, 96, 27, 27) 第一个norm层的图像尺寸为27*27,feature map个数为96

conv2 (50, 256, 27, 27) 第二个conv层的图像尺寸为27*27,feature map个数为256

pool2 (50, 256, 13, 13) 第二个pool层的图像尺寸为13*13,feature map个数为256

norm2 (50, 256, 13, 13) 第二个norm层的图像尺寸为13*13,feature map个数为256

conv3 (50, 384, 13, 13) 第三个conv层的图像尺寸为13*13,feature map个数为384

conv4 (50, 384, 13, 13) 第四个conv层的图像尺寸为13*13,feature map个数为384

conv5 (50, 256, 13, 13) 第五个conv层的图像尺寸为13*13,feature map个数为256

pool5 (50, 256, 6, 6) 第五个pool层的图像尺寸为13*13,feature map个数为256

fc6 (50, 4096)
第六个fc层的图像尺寸为4096

fc7 (50, 4096)
第七个fc层的图像尺寸为4096

fc8 (50, 1000)
第八个fc层的图像尺寸为1000

prob (50, 1000)
probablies层的尺寸为1000

下面画出该数据,从图中观察更为形象

caffe中如何可视化cnn各层的输出_第1张图片

2.查看每一层的参数结构

代码如下:

for layer_name, param in net.params.iteritems():
        print layer_name + '\t' + str(param[0].data.shape), str(param[1].data.shape)

第i次循环体内部

  • layer_name提取的是net的第i层的名称
  • param提取的是net的第i层的参数

结果如下:

conv1 (96, 3, 11, 11) (96,) 第一个conv层的filters的尺寸,这里的3是因为输入层的data为rgb,可以看做三个feature maps

conv2 (256, 48, 5, 5) (256,) 第二个conv层的filters尺寸

conv3 (384, 256, 3, 3) (384,)第三个conv层的filters尺寸

conv4 (384, 192, 3, 3) (384,)第四个conv层的filters尺寸

conv5 (256, 192, 3, 3) (256,)第五个conv层的filters尺寸

fc6 (4096, 9216) (4096,)第一个fc层的权值尺寸

fc7 (4096, 4096) (4096,)第二个fc层的权值尺寸

fc8 (1000, 4096) (1000,)第三个fc层的权值尺寸

应该注意到,由于pool层和norm层并没有需要优化的参数,所以参数中并没有关于pool层和norm层的信息

下面给出filters如何对输入数据进行filter的一幅形象化的图
caffe中如何可视化cnn各层的输出_第2张图片

3.可视化4D数据的函数

def vis_square(data):

    # 输入的数据为一个ndarray,尺寸可以为(n, height, width)或者是 (n, height, width, 3)
    # 前者即为n个灰度图像的数据,后者为n个rgb图像的数据
    # 在一个sqrt(n) by sqrt(n)的格子中,显示每一幅图像

    # 对输入的图像进行normlization
    data = (data - data.min()) / (data.max() - data.min())

    # 强制性地使输入的图像个数为平方数,不足平方数时,手动添加几幅
    n = int(np.ceil(np.sqrt(data.shape[0])))
    # 每幅小图像之间加入小空隙
    padding = (((0, n ** 2 - data.shape[0]),
               (0, 1), (0, 1))                 # add some space between filters
                           + ((0, 0),) * (data.ndim - 3)) # don't pad the last dimension (if there is one)
       data = np.pad(data, padding, mode='constant', constant_values=1) # pad with ones (white) 

        # 将所有输入的data图像平复在一个ndarray-data中(tile the filters into an image)
        data = data.reshape((n, n) + data.shape[1:]).transpose((0, 2, 1, 3) + tuple(range(4, data.ndim + 1)))
        # data的一个小例子,e.g., (3,120,120)
        # 即,这里的data是一个2d 或者 3d 的ndarray
        data = data.reshape((n * data.shape[1], n * data.shape[3]) + data.shape[4:])

        # 显示data所对应的图像
        plt.imshow(data); plt.axis('off')

4.查看第一个convolution layers的filters的图像

代码如下:

    # the parameters are a list of [weights, biases]
    filters = net.params['conv1'][0].data
    vis_square(filters.transpose(0, 2, 3, 1))
  • filters存储的是第一个conv层的filters的数据
  • 例子:形状为:(96, 3, 11, 11)

结果如下:共96幅图像(96个filters,每个filters为11*11*3)

caffe中如何可视化cnn各层的输出_第3张图片

5.查看第一个convolution layers的输出(activations)的图像

代码如下:

    feat = net.blobs['conv1'].data[0, :36]
    vis_square(feat)
  • feat存储的是第一个卷基层的后36幅图像
    feat的尺寸为(36, 55, 55)

结果如下:
caffe中如何可视化cnn各层的输出_第4张图片

6. 查看pool5的输出图像

代码如下:

    feat = net.blobs['pool5'].data[0]
    vis_square(feat)
  • feat存储的是pool5的输出图像
    feat的尺寸为(256, 6, 6)

结果如下:
caffe中如何可视化cnn各层的输出_第5张图片

7. 第一个全连接层的输出

代码如下:

    feat = net.blobs['fc6'].data[0]
    plt.subplot(2, 1, 1)
    plt.plot(feat.flat)
    plt.subplot(2, 1, 2)
    _ = plt.hist(feat.flat[feat.flat > 0], bins=100)

结果如下:
caffe中如何可视化cnn各层的输出_第6张图片

8. probability层的输出

代码如下:

    feat = net.blobs['prob'].data[0]
    plt.figure(figsize=(15, 3))
    plt.plot(feat.flat)

结果如下:
caffe中如何可视化cnn各层的输出_第7张图片

9.小结

在获取了net后:
如何获取网络各层的数据:net.blobs[‘layer name’].data[0]
如何获取网络各层的参数数据:net.params[‘layer name’][0].data

你可能感兴趣的:(cnn,caffe)