caffe的python与matlab接口(网络训练与卷积核、特征图可视化)

一、Python接口

楼燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/(卷积网络feature map可视化)
caffe学习笔记1-7-完整版-薛开宇(包括网络训练与多层的可视化)
以下部分代码是根据caffe的python接口,从一次forword中取出param和blob里面的卷积核 和响应的卷积图。

import numpy as np
import matplotlib.pyplot as plt
import os
import caffe
import sys
import pickle
import cv2

caffe_root = '../'  

deployPrototxt =  '/home/chenjie/louyihang/caffe/models/bvlc_reference_caffenet/deploy_louyihang.prototxt'
modelFile = '/home/chenjie/louyihang/caffe/models/bvlc_reference_caffenet/caffenet_carmodel_louyihang_iter_50000.caffemodel'
# meanFile = 'python/caffe/imagenet/ilsvrc_2012_mean.npy'
#imageListFile = '/home/chenjie/DataSet/CompCars/data/train_test_split/classification/test_model431_label_start0.txt'
# imageBasePath = '/home/chenjie/DataSet/CompCars/data/cropped_image'
# resultFile = 'PredictResult.txt'

#网络初始化
def initilize():
    print 'initilize ... '
    sys.path.insert(0, caffe_root + 'python')
    caffe.set_mode_gpu()
    caffe.set_device(0)
    net = caffe.Net(deployPrototxt, modelFile,caffe.TEST)
    return net

#取出网络中的params和net.blobs的中的数据
def getNetDetails(image, net):
    # input preprocessing: 'data' is the name of the input blob == net.inputs[0]
    transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
    transformer.set_transpose('data', (2,0,1))
    # transformer.set_mean('data', np.load(caffe_root + meanFile ).mean(1).mean(1)) # mean pixel
    transformer.set_raw_scale('data', 255)  
    # the reference model operates on images in [0,255] range instead of [0,1]
    transformer.set_channel_swap('data', (2,1,0))  
    # the reference model has channels in BGR order instead of RGB
    # set net to batch size of 50
    net.blobs['data'].reshape(1,3,227,227)

    net.blobs['data'].data[...] = transformer.preprocess('data', caffe.io.load_image(image))
    out = net.forward()

    #网络提取conv1的卷积核
    filters = net.params['conv1'][0].data
    with open('FirstLayerFilter.pickle','wb') as f:
       pickle.dump(filters,f)
    vis_square(filters.transpose(0, 2, 3, 1))
    #conv1的特征图
    feat = net.blobs['conv1'].data[0, :36]
    with open('FirstLayerOutput.pickle','wb') as f:
       pickle.dump(feat,f)
    vis_square(feat,padval=1)
    pool = net.blobs['pool1'].data[0,:36]
    with open('pool1.pickle','wb') as f:
       pickle.dump(pool,f)
    vis_square(pool,padval=1)


# 此处将卷积图和进行显示,
def vis_square(data, padsize=1, padval=0 ):
    data -= data.min()
    data /= data.max()

    #让合成图为方
    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))
    #合并卷积图到一个图像中

    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:])
    print data.shape
    plt.imshow(data)
    plt.show()

if __name__ == "__main__":
    net = initilize()
    testimage = '../data/MyTest/visualize_test.jpg'
    getNetDetails(testimage, net)

二、caffe的Matlab接口的使用方法(用matlab训练cnn)

原作者:及时澍雨Timely
https://blog.csdn.net/ws_20100/article/details/50525879
matlab列优先与高维矩阵重构 及 CNN 逐层可视化 on Matlab
http://www.cnblogs.com/jeffwilson/p/4750938.html

(1)编译MatCaffe

使用如下命令编译MatCaffe

make all matcaffe

之后,你可以用以下命令测试MatCaffe:

make mattest

如果你在运行上面命令时,遇到如下错误:libstdc++.so.6 version ‘GLIBCXX_3.4.15’ not found,说明你的Matlab库不匹配。你需要在启动Matlab之前运行如下命令:

export LD_LIBRARY_PATH=/opt/intel/mkl/lib/intel64:/usr/local/cuda/lib64
export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6

在Caffe根目录启动Matlab之后需要增加路径:

addpath ./matlab

你可以使用savepath来保存Matlab搜索路径,这样下次就不用再添加路径了。

(2)使用MatCaffe

MatCaffe 和 PyCaffe 的使用方法很相似。
下面将用一个例子来解释MatCaffe的具体使用细节,假设你已经下载了BVLC CaffeNet,并且在caffe根目录启动matlab。

model = './models/bvlc_reference_caffenet/deploy.prototxt';
weights = './models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel';

1.设置模式和设备

模式和设备的设置必须在创建一个net或solver之前。
使用CPU:

caffe.set_mode_cpu();

使用GPU并指定gpu_id:

affe.set_mode_gpu();
caffe.set_device(gpu_id);

2.创建一个网络并访问它的layers和blobs

2.1 创建网络

创建一个网络:

net = caffe.Net(model, weights, 'test'); % create net and load weights

or

net = caffe.Net(model, 'test'); % create net but not load weights
net.copy_from(weights); % load weights

它可以创建一个如下的net对象:

Net with properties:
           layer_vec: [1x23 caffe.Layer]
            blob_vec: [1x15 caffe.Blob]
              inputs: {'data'}
             outputs: {'prob'}
    name2layer_index: [23x1 containers.Map]
     name2blob_index: [15x1 containers.Map]
         layer_names: {23x1 cell}
          blob_names: {15x1 cell}

两个containers.Map对象可以通过layer或者blob的名称找到对应的索引。

2.2 访问blob

你可以访问网络中的每一个blob,将data的blob填充为全一:

net.blobs('data').set_data(ones(net.blobs('data').shape));

将data的blob中数值全部乘以10:

net.blobs('data').set_data(net.blobs('data').get_data() * 10);

注意:因为Matlab是以1作为起始单元,且以列为主,在Matlab中使用四维blob为[width, height, channels, num],且width是最快的维度,而且要在BGR通道。而且Caffe使用单精度浮点型数据。如果你的数据不是浮点型的,set_data将会自动转换为single。

2.3 访问layer

你也可以访问网络的每一层,以便你作一些网络调整。例如把conv1参数乘以10:

net.params('conv1', 1).set_data(net.params('conv1', 1).get_data() * 10); % set weights
net.params('conv1', 2).set_data(net.params('conv1', 2).get_data() * 10); % set bias

你也可以如下代码:

net.layers('conv1').params(1).set_data(net.layers('conv1').params(1).get_data() * 10);
net.layers('conv1').params(2).set_data(net.layers('conv1').params(2).get_data() * 10);

2.4 保存网络

你仅仅需要如下代码保存网络:

net.save('my_net.caffemodel');

2.5 获得一层的类型(string)

layer_type = net.layers('conv1').type;

3.前向和后向计算

前向和后向计算可以使用net.forward或者net.forward_prefilled实现。函数net.forward将一个包含输入blob(s)的cell数组作为输入,并输出一个包含输出blob(s)的cell数组。函数net.forward_prefilled将使用输入blob(s)中的已有数据进行计算,没有输入数据,没有输出数据。

在通过一些方法(如:data = rand(net.blobs(‘data’).shape);)产生输入数据后,你可以运行:

res = net.forward({data});
prob = res{1};

或者

net.blobs('data').set_data(data);
net.forward_prefilled();
prob = net.blobs('prob').get_data();

后向计算使用net.backward或者net.backward_prefilled,并且把get_data和set_data替换为get_diff和set_diff。在通过一些方法(例如prob_diff = rand(net.blobs(‘prob’).shape);)产生输出blobs的梯度后,你可以运行:

res = net.backward({prob_diff});
data_diff = res{1};

或者

net.blobs('prob').set_diff(prob_diff);
net.backward_prefilled();
data_diff = net.blobs('data').get_diff();

然而,如上的后向计算并不能得到正确的结果,因为Caffe默认网络不需要后向计算。为了获取正确的后向计算结果,你需要在你的网络prototxt文件中设置force_backward: true
在完成前向和后向计算之后,你可以获得中间blobs的data和diff。例如,你可以在前向计算后获取pool5的特征。

4.Reshape

假设你想要运行1幅图像,而不是10幅时:

net.blobs('data').reshape([227 227 3 1]); % reshape blob 'data'
net.reshape();

然后,整个网络就reshape了,此时net.blobs(‘prob’).shape应该是[1000 1];

5.训练网络

假设你按照ImageNET Tutorial的方法创建了训练lmdb和验证lmdb,产生一个solver并且在ILSVRC 2012 分类数据集上训练:

solver = caffe.Solver('./models/bvlc_reference_caffenet/solver.prototxt');

这样可以创建一个solver对象:

 Solver with properties:

          net: [1x1 caffe.Net]
    test_nets: [1x1 caffe.Net]

训练代码:

solver.solve();

如果只想训练迭代1000次:

solver.step(1000);

来获取迭代数量:

iter = solver.iter();

来获取这个网络:

train_net = solver.net;
test_net = solver.test_nets(1);

假设从一个snapshot中恢复网络训练:

solver.restore('your_snapshot.solverstate');

6.输入和输出

caffe.io类提供了基本的输入函数load_image和read_mean。例如,读取ILSVRC 2012 mean文件(假设你已经通过运行./data/ilsvrc12/get_ilsvrc_aux.sh下载imagenet例程辅助文件)

mean_data = caffe.io.read_mean('./data/ilsvrc12/imagenet_mean.binaryproto');

为了读取Caffe例程图片,并且resize到[width, height],且假设width = 256; height = 256;

im_data = caffe.io.load_image('./examples/images/cat.jpg');
im_data = imresize(im_data, [width, height]); % resize using Matlab's imresize

注意:width是最快的维度,通道为BGR,与Matlab存取图片的一般方式不一样。如果你不想要使用caffe.io.load_image,且想自己导入一幅图片:

im_data = imread('./examples/images/cat.jpg'); % read image
im_data = im_data(:, :, [3, 2, 1]); % convert from RGB to BGR
im_data = permute(im_data, [2, 1, 3]); % permute width and height
im_data = single(im_data); % convert to single precision

你也可以看一下caffe/matlab/demo/classification_demo.m文件,了解如何将输入图片crop成多个输入块。
你可以查看caffe/matlab/hdf5creation,了解如何通过Matlab读和写HDF5数据。但不提供额外的数据输出函数,因为在Matlab本身已经具有了强大的功能。

7.清除nets和solvers

调用caffe.reset_all()来清理你所创建的所有的solvers,和stand-alone nets。

(3)利用matlab卷积核可视化

【caffe-matlab】权重以及特征图的可视化
https://blog.csdn.net/zb1165048017/article/details/52643188
非常详细,包括网络的训练、卷积核与特征图的可视化!
【注】卷积核可视化中,采用的像素放大方法与特征图的不一样。特征图中采用归一化mapminmax到(0,1)范围,然后乘以255,;在下面卷积核的可视化中采用(x-最小值)/最大值*255的方法去放大像素。读者可根据自己喜好决定。

前言

  • 一模型读取
  • 二输入数据整理
  • 三前向计算
  • 四特征图可视化
    - 特征图提取方法
    - 部分可视化方法
    - 全部可视化
  • 五卷积核可视化
    - 权重提取方法
    - 部分可视化方法
    - 全部可视化
  • 六全连接探讨

猜你喜欢

转载自blog.csdn.net/yifen4234/article/details/80644026
今日推荐