caffe本身没有可视化的工具,一般需要配合python或matlab实现数据的可视化,在实践本文之前要先把caffe python编译好。另外有的服务器只有shell,没有可视化的界面,只好先把每一层的数据先保存成图片格式,再进行显示。
载入数据
import numpy as np
import caffe
from skimage import io
caffe_root='/home/XXX/caffe/'
import os,sys
os.chdir(caffe_root)
sys.path.insert(0,caffe_root+'python')
im = caffe.io.load_image('examples/images/cat.jpg')
io.imsave('cat.jpg',im)
print im.shape
这里用到了skimage 这个库,caffe用于读取图像的函数caffe.io.load_image
也是用的这个,具体可以在python/caffe/io.py
中查看。之后我们也用这个库进行图像的保存。
以上的程序较为简单,读取了示例图片,为了验证是否正确又另存为了副本。最后输出的shape为:(360,480,3)。
载入卷积模型
net = caffe.Net('examples/net_surgery/conv.prototxt', caffe.TEST)
# Simple single-layer network to showcase editing model parameters.
name: "convolution"
layer {
name: "data"
type: "Input"
top: "data"
input_param { shape: { dim: 1 dim: 3 dim: 100 dim: 100 } }
}
layer {
name: "conv"
type: "Convolution"
bottom: "data"
top: "conv"
convolution_param {
num_output: 16
kernel_size: 5
stride: 1
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}
载入的是示例中简单的卷积模型,但在shape上有所修改:第二个dim由1改为3,代表三通道输入;同时num_output改为了16,增加了滤波器的个数。
数据格式处理
im_input=im[np.newaxis,:,:,:].transpose(0,3,1,2)
print "data-blobs:",im_input.shape
#print "datashape:",net.blobs['data'].data.shape
net.blobs['data'].reshape(*im_input.shape)
net.blobs['data'].data[...] = im_input
图片的输入规格和caffe的blob规格并不相同。图片的维度为(360,480,3),而blob的4维数组要求通道数在前,因此需要改变顺序,并且由于仅有一张图片,需要增加一维代表图片序号,该维值为0即可。因此im_input=im[np.newaxis,:,:,:].transpose(0,3,1,2)
先增加了一个维度,后改变了维的顺序,使其与输入要求相同。之后改变blobs数据层的维度,使之与图像大小相同(这一步感觉会让网络配置文件中input_param:shape的维度改变,可能是为了方便程序的扩展,没有直接改配置文件)。最后把图像数据输入到blob。
保存图像
为了方便调用,可以写一个保存图片的函数:
def save_data(data,name,padsize=1, padval=0):
data -= data.min()
data /= data.max()
# force the number of filters to be square
n = int(np.ceil(np.sqrt(data.shape[0])))
padding = ((0, n ** 2 - data.shape[0]), (0, padsize), (0, padsize)) + ((0, 0),) * (data.ndim - 3)
data = np.pad(data, padding, mode='constant', constant_values=(padval, padval))
# 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 = data.reshape((n * data.shape[1], n * data.shape[3]) + data.shape[4:])
io.imsave(name,data)
保存图片首先进行了归一化操作,之后为了美观生成一个方形模板,再把图片依次放上去。
测试这一段可以看一下原图多通道的每一通道分量:
save_data(net.blobs['data'].data[0],'origin images.jpg')
卷积层输出
net.forward()
print "data-blobs:",net.blobs['data'].data.shape
print "conv-blobs:",net.blobs['conv'].data.shape
print "weight-blobs:",net.params['conv'][0].data.shape
save_data(net.params['conv'][0].data[:,0],'conv weights(filter).jpg')
save_data(net.blobs['conv'].data[0],'post-conv images.jpg')
经过一次向前计算,得到了卷积后的结果和初始的卷积核值,打印他们的大小分别为:
data-blobs: (1, 3, 360, 480)
conv-blobs: (1, 16, 356, 476)
weight-blobs: (16, 3, 5, 5)
最后保存成了两个图片文件: