caffe中如何可视化cnn各层的输出
Posted tina_ttl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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个数为96conv2 (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个数为256conv3 (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个数为256fc6 (50, 4096)
第六个fc层的图像尺寸为4096fc7 (50, 4096)
第七个fc层的图像尺寸为4096fc8 (50, 1000)
第八个fc层的图像尺寸为1000prob (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
以上是关于caffe中如何可视化cnn各层的输出的主要内容,如果未能解决你的问题,请参考以下文章