caffe:利用python分类,并可视化模型参数、数据

来源:互联网 发布:java 获取版本号 编辑:程序博客网 时间:2024/05/16 18:45

caffe官方文档:http://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/00-classification.ipynb

1准备工作

1.1 安装python,numpy,matplotlib

[cpp] view plain copy
  1. #安装python、numpy、matplotlib  
  2. import numpy as np  
  3. import matplotlib.pyplot as plt  
  4. %matplotlib inline  
  5.   
  6. #设置默认显示参数  
  7. plt.rcParams['figure.figsize'] = (10, 10)        # 图像显示大小  
  8. plt.rcParams['image.interpolation'] = 'nearest'  # 最近邻差值: 像素为正方形  
  9. plt.rcParams['image.cmap'] = 'gray'              # 使用灰度输出而不是彩色输出  


1.2 加载 caffe

[cpp] view plain copy
  1. import sys  
  2. caffe_root = '/home/shine/caffe/'   
  3. sys.path.insert(0, caffe_root + 'python')  
  4. import caffe  
  5. # 如果你看到"No module named _caffe",那么要么就是你没有正确编译pycaffe;要么就是你的路径有错误。  


1.3 下载CaffeNet模型,该模型是AlexNet的变形

[cpp] view plain copy
  1. import os  
  2. if os.path.isfile(caffe_root + 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel'):  
  3.      print 'CaffeNet found.'  
  4. else:  
  5.      print 'Downloading pre-trained CaffeNet model...'  
  6.      !../scripts/download_model_binary.py ../models/bvlc_reference_caffenet  


2 加载网络并设置输入预处理

2.1 将Caffe设置为CPU模式,并从硬盘加载网络

[cpp] view plain copy
  1. caffe.set_mode_cpu()  
  2. model_def = caffe_root + 'models/bvlc_reference_caffenet/deploy.prototxt'    #注意这里使用deploy.prototxt  
  3. model_weights = caffe_root + 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel'  
  4. net = caffe.Net(model_def,      # 定义模型结构  
  5.                 model_weights,  # 包含了模型的训练权值  
  6.                 caffe.TEST)     # 使用测试模式(不执行dropout)  


2.2 设置输入预处理

       利用caffe.io.Transformer来进行预处理。CaffeNet模型默认的输入图像格式是BGR,像素值的取值范围为[0,255],同时每个像素值都减去了ImageNet图像的平均值。matplotlib加载的图像的像素值位于[0,1]之间,并且格式是RGB格式,所以我们需要做一些变换。

[cpp] view plain copy
  1. # 加载ilsvrc12数据集的图像均值 (随着Caffe一起发布的)  
  2. mu = np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy')  
  3. mu = mu.mean(1).mean(1)                      #对所有像素值取平均以此获取BGR的均值像素值  
  4. print 'mean-subtracted values:', zip('BGR', mu)  
  5.   
  6. # 对输入数据进行变换  
  7. transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})  
  8. transformer.set_transpose('data', (2,0,1))    #还没弄清楚?  
  9. transformer.set_mean('data', mu)              #对于每个通道,都减去BGR的均值像素值  
  10. transformer.set_raw_scale('data', 255)        #将像素值从[0,255]变换到[0,1]之间  
  11. transformer.set_channel_swap('data', (2,1,0)) #交换通道,从RGB变换到BGR  

3 用CPU分类

3.1 开始分类,尽管我们只对一张图像进行分类,不过我们将batch的大小设置为50,以此来演示batching

[cpp] view plain copy
  1. # 设置输入图像大小  
  2. net.blobs['data'].reshape(50,        # batch 大小  
  3.                           3,         # 3-channel (BGR) images  
  4.                           227, 227)  # 图像大小为:227x227  


3.2 加载图像,并进行预处理

[cpp] view plain copy
  1. image = caffe.io.load_image(caffe_root + 'examples/images/cat.jpg')  
  2. transformed_image = transformer.preprocess('data', image)  
  3. plt.imshow(image)  

3.3 进行识别分类


3.3.1 分类
[cpp] view plain copy
  1. # 将图像数据拷贝到为net分配的内存中  
  2. net.blobs['data'].data[...] = transformed_image  
  3.   
  4. # 执行分类  
  5. output = net.forward()    
  6. output_prob = output['prob'][0]  #batch中第一张图像的概率值     
  7. print 'predicted class is:', output_prob.argmax()  
输出:predictd class is: 281

3.3.1 输出类别标签
[cpp] view plain copy
  1. # 加载标签  
  2. labels_file = caffe_root + 'data/ilsvrc12/det_synset_words.txt'  
  3. if not os.path.exists(labels_file):  
  4.      !../data/ilsvrc12/get_ilsvrc_aux.sh  
  5. labels = np.loadtxt(labels_file, str, delimiter='\t')  
  6. # 输出对应的类别标签  
  7. print 'output label:', labels[output_prob.argmax()]  
输出:output label: n02123043 tabby, tabby cat

3.3.2 输出置信度较高的前几个类别
[cpp] view plain copy
  1. # 查看置性度较高的几个结果  
  2. # sort top five predictions from softmax output  
  3. top_inds = output_prob.argsort()[::-1][:5]  # reverse sort and take five largest items  
  4. print 'probabilities and labels:'  
  5. zip(output_prob[top_inds], labels[top_inds])  

4 测试网络的中间层输出

4.1 读取网络的结构 

对于每一层参数为(batch_size, channel_dim, height, width)
[cpp] view plain copy
  1. # 对于每一层,显示输出类型。  
  2. for layer_name, blob in net.blobs.iteritems():  
  3.       print layer_name + '\t' + str(blob.data.shape)  
输出:
data        (50, 3, 227, 227)conv1(50, 96, 55, 55)pool1(50, 96, 27, 27)norm1(50, 96, 27, 27)conv2(50, 256, 27, 27)pool2(50, 256, 13, 13)norm2(50, 256, 13, 13)conv3(50, 384, 13, 13)conv4(50, 384, 13, 13)conv5(50, 256, 13, 13)pool5(50, 256, 6, 6)fc6        (50, 4096)fc7        (50, 4096)fc8        (50, 1000)prob(50, 1000)

4.2 读取网络的参数

net.params[0]表示weights, net.params[0]表示biases, weights:(output_channels, input_channels, filter_height, filter_width),biases:
(output_channels)
[cpp] view plain copy
  1. for layer_name, param in net.params.iteritems():  
  2.        print layer_name + '\t' + str(param[0].data.shape), str(param[1].data.shape)  
输出:
conv1(96, 3, 11, 11) (96,)conv2(256, 48, 5, 5) (256,)conv3(384, 256, 3, 3) (384,)conv4(384, 192, 3, 3) (384,)conv5(256, 192, 3, 3) (256,)fc6        (4096, 9216) (4096,)fc7        (4096, 4096) (4096,)fc8        (1000, 4096) (1000,)

4.3 可视化特征

[cpp] view plain copy
  1. def vis_square(data):  
  2.         # 输入一个形如:(n, height, width) or (n, height, width, 3)的数组,并对每一个形如(height,width)的特征进行可视化  
  3.   
  4.         # 正则化数据  
  5.         data = (data - data.min()) / (data.max() - data.min())  
  6.   
  7.         # 将滤波器的核转变为正方形  
  8.         n = int(np.ceil(np.sqrt(data.shape[0])))  
  9.         padding = (((0, n ** 2 - data.shape[0]),  
  10.                    (0, 1), (0, 1))                 # 在相邻的滤波器之间加入空白   
  11.                    + ((0, 0),) * (data.ndim - 3))  # 不扩展最后一维  
  12.         data = np.pad(data, padding, mode='constant', constant_values=1)  # 扩展一个像素(白色)  
  13.   
  14.         # tile the filters into an image  
  15.         data = data.reshape((n, n) + data.shape[1:]).transpose((0, 2, 1, 3) + tuple(range(4, data.ndim + 1)))  
  16.         data = data.reshape((n * data.shape[1], n * data.shape[3]) + data.shape[4:])  
  17.   
  18.         plt.imshow(data)  
  19.         plt.axis('off')  
  20.         plt.show()  
4.3.1 可视化第一个卷积层(
conv1)的参数
[cpp] view plain copy
  1. # 参数为一个[weights, biases]的列表  
  2. filters = net.params['conv1'][0].data  
  3. vis_square(filters.transpose(0, 2, 3, 1))  
4.3.2 可视化第一个卷积层(conv1)的输出特征
[cpp] view plain copy
  1. feat = net.blobs['conv1'].data[0, :36]  
  2. vis_square(feat)  
4.3.3 可视化第五个池化层(pooling5)的输出特征
[cpp] view plain copy
  1. feat = net.blobs['pool5'].data[0]  
  2. vis_square(feat)  
4.3.4 可视化第一个全连接层(f6)的输出特征
[cpp] view plain copy
  1. feat = net.blobs['fc6'].data[0]  
  2. plt.subplot(2, 1, 1)  
  3. plt.plot(feat.flat)  
  4. plt.subplot(2, 1, 2)  
  5. _ = plt.hist(feat.flat[feat.flat > 0], bins=100)  
  6. plt.show()  
输出:
原创粉丝点击