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

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

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的一幅形象化的图

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)

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

代码如下:

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

    feat的尺寸为(36, 55, 55)

结果如下:

6. 查看pool5的输出图像

代码如下:

feat = net.blobs[‘pool5‘].data[0]
vis_square(feat)
  • feat存储的是pool5的输出图像

    feat的尺寸为(256, 6, 6)

结果如下:

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)

结果如下:

8. probability层的输出

代码如下:

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

结果如下:

9.小结

在获取了net后:

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

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

时间: 2024-08-19 09:51:58

caffe中如何可视化cnn各层的输出的相关文章

caffe添加自己编写的Python层

由于Python的灵活性,我们在caffe中添加自己定义的层时使用python层会更加方便,开发速速也会比C++更快,现在我就在这儿简单说一下如何在caffe中添加自定义的python层(使用的原网络结构时Lenet结构): 首先在caffe->python文件夹中添加自己定义的层函数.py文件,比如我这里命名为MyPythonLayer.py,该层实现的功能是对输入数据加上一个数字,如下: 然后在/home/zf/caffe/examples/mnist/lenet_train_test.pr

caffe 中 python 数据层

caffe中大多数层用C++写成. 但是对于自己数据的输入要写对应的输入层,比如你要去图像中的一部分,不能用LMDB,或者你的label 需要特殊的标记. 这时候就需要用python 写一个输入层. 如在fcn 的voc_layers.py 中 有两个类: VOCSegDataLayer SBDDSegDataLayer 分别包含:setup,reshape,forward, backward, load_image, load_label. 不需要backward 没有参数更新. import

TensorFlow与caffe中卷积层feature map大小计算

刚刚接触Tensorflow,由于是做图像处理,因此接触比较多的还是卷及神经网络,其中会涉及到在经过卷积层或者pooling层之后,图像Feature map的大小计算,之前一直以为是与caffe相同的,后来查阅了资料发现并不相同,将计算公式贴在这里,以便查阅: caffe中: TF中: 参考: http://blog.csdn.net/lujiandong1/article/details/53728053 http://www.cnblogs.com/denny402/p/5071126.h

caffe中HingeLossLayer层原理以及源码分析

输入: bottom[0]: NxKx1x1维,N为样本个数,K为类别数.是预测值. bottom[1]: Nx1x1x1维, N为样本个数,类别为K时,每个元素的取值范围为[0,1,2,-,K-1].是groundTruth. 输出: top[0]: 1x1x1x1维, 求得是hingeLoss. 关于HingeLoss: p: 范数,默认是L1范数,可以在配置中设置为L1或者L2范数. :指示函数,如果第n个样本的真实label为k,则为,否则为-1. tnk: bottom[0]中第n个样

如何向caffe中添加层

修改caffe\src\caffe\proto\caffe.proto 在最后添加centerloss层的参数信息 message CenterLossParameter { optional uint32 num_output = 1; // The number of outputs for the layer optional FillerParameter center_filler = 2; // The filler for the centers // The first axis

caffe中关于(ReLU层,Dropout层,BatchNorm层,Scale层)输入输出层一致的问题

在卷积神经网络中.常见到的激活函数有Relu层 layer { name: "relu1" type: "ReLU" bottom: "pool1" top: "pool1" }其中可选参数为:negative_slope:默认为0. 对标准的ReLU函数进行变化,如果设置了这个值,那么数据为负数时,就不再设置为0,而是用原始数据乘以negative_slope relu层有个很大的特点:bottom(输入)和top(输出)一

转 Caffe学习系列(3):视觉层(Vision Layers)及参数

所有的层都具有的参数,如name, type, bottom, top和transform_param请参看我的前一篇文章:Caffe学习系列(2):数据层及参数 本文只讲解视觉层(Vision Layers)的参数,视觉层包括Convolution, Pooling, Local Response Normalization (LRN), im2col等层. 1.Convolution层: 就是卷积层,是卷积神经网络(CNN)的核心层. 层类型:Convolution lr_mult: 学习率

Caffe中对MNIST执行train操作执行流程解析

之前在 http://blog.csdn.net/fengbingchun/article/details/49849225 中简单介绍过使用Caffe train MNIST的文章,当时只是仿照caffe中的example实现了下,下面说一下执行流程,并精简代码到仅有10余行: 1.        先注册所有层,执行layer_factory.hpp中类LayerRegisterer的构造函数,类LayerRegistry的AddCreator和Registry静态函数:关于Caffe中Lay

Caffe 中添加自己的网络层

写在前面: Caffe 中有众多的网络层,最新版本的代码已经涵盖了很多种类型的网络层,然而,有时候由于各种原因,其给定的网络层不能满足我们的要求,这时候就要对其更改,以使其满足自己的需求,感谢作者开源代码以及众多的代码维护者. 由于Caffe 中的网络层都是直接或者间接地给予Layer 基类,所以,在我们需要添加新的类型时,就需要选择好自己的基类,以使我们能够更好的利用基类已有的一些方法.我们新建的类可以基于 1. 直接继承于Layer 2. 继承于DataLayer 3. 继承于NeuronL