如果用公式 y=f(wx+b)
来表示整个运算过程的话,那么w和b就是我们需要训练的东西,w称为权值,在cnn中也可以叫做卷积核(filter),b是偏置项。f是激活函数,有sigmoid、relu等。x就是输入的数据。
数据训练完成后,保存的caffemodel里面,实际上就是各层的w和b值。
我们运行代码:
deploy=root + 'mnist/deploy.prototxt' #deploy文件
caffe_model=root + 'mnist/lenet_iter_9380.caffemodel' #训练好的 caffemodel
net = caffe.Net(net_file,caffe_model,caffe.TEST) #加载model和network
就把所有的参数和数据都加载到一个net变量里面了,但是net是一个很复杂的object, 想直接显示出来看是不行的。
caffe中数据的保存说明:
在caffe中,我们的网络可以分为训练网络与测试网络哦,训练网络用solver.net.blobs、solver.net.params;
测试网络,用solver.test_nets[i].blobs、solver.test_nets[i].params(其中 i 表示 第几个测试网络,从0开始。例如,我们就一个测试网络的话,我们就写为:solver.test_nets[0].blobs。)
solver.net.blobs 里面放的为每一层layer输出的data、对输出结点求的导数 diff,另外还有几个如count等参数,不过我们基本用不到的,不要关注一下data数据就可以了。
#solver.net.blobs为一个字典的数据类型,里面的key值为各个layer 的名字,value为caffe的blob块;
solver.net.blobs
#输出:
rderedDict([('data', <caffe._caffe.Blob at 0x7f7bde968398>),
('label', <caffe._caffe.Blob at 0x7f7bde968488>),
('conv1', <caffe._caffe.Blob at 0x7f7bde968578>),
('pool1', <caffe._caffe.Blob at 0x7f7bde968e60>),
('conv2', <caffe._caffe.Blob at 0x7f7bde9686e0>),
('pool2', <caffe._caffe.Blob at 0x7f7bde968cf8>),
('ip1', <caffe._caffe.Blob at 0x7f7bde968c80>),
('ip2', <caffe._caffe.Blob at 0x7f7bde968c08>),
('loss', <caffe._caffe.Blob at 0x7f7bde968b90>)])
#我们可以访问Blob块里的内容了,通过看Blob块的源码你会发现里面有data, diff,count等内容的。
#我们以conv1层为例子,我们访问 conv1的输出的数据,可以通过下面的语句:
solver.net.blobs['data'].data
solver.net.blobs['data'].diff
#如果想看它们的数据结构,可以通过下面的语句得到:
solver.net.blobs['data'].data.shape
solver.net.blobs['data'].diff.shape
#另外,还可以通过reshape()transpose()等操作对它们变形,应该是对数组的操作之类的吧。
可用命令:
[(k,v[0].data) for k,v in net.params.items()]
查看各层的参数值,其中k表示层的名称,v[0].data就是各层的W值,而v[1].data是各层的b值。注意:并不是所有的层都有参数,只有卷积层和全连接层才有。
也可以不查看具体值,只想看一下shape,可用命令
[(k,v[0].data.shape) for k,v in net.params.items()]
假设我们知道其中第一个卷积层的名字叫'Convolution1', 则我们可以提取这个层的参数:
w1=net.params['Convolution1'][0].data
b1=net.params['Convolution1'][1].data
输入这些代码,实际查看一下,对你理解network非常有帮助。
同理,除了查看参数,我们还可以查看数据,但是要注意的是,net里面刚开始是没有数据的,需要运行:
net.forward()
之后才会有数据。我们可以用代码:
[(k,v.data.shape) for k,v in net.blobs.items()]
或
[(k,v.data) for k,v in net.blobs.items()]
来查看各层的数据。注意和上面查看参数的区别,一个是net.params, 一个是net.blobs.
实际上数据刚输入的时候,我们叫图片数据,卷积之后我们就叫特征了。
如果要抽取第一个全连接层的特征,则可用命令:
fea=net.blobs['InnerProduct1'].data
只要知道某个层的名称,就可以抽取这个层的特征。
推荐大家运行一下上面的所有代码,深入理解模型各层。
最后,总结一个代码:
#!/usr/bin/env python
# encoding: utf-8
'''
@author: lele Ye
@contact: 1750112338@qq.com
@software: pycharm 2018.2
@file: draw.py
@time: 2018/10/22 20:01
@desc:
'''
import os,sys
caffe_root = '/home/yeler082/caffe/'
sys.path.insert(0,caffe_root+'python')
import caffe
deploy=root + 'mnist/deploy.prototxt' #deploy文件
caffe_model=root + 'mnist/lenet_iter_9380.caffemodel' #训练好的 caffemodel
net = caffe.Net(deploy,caffe_model,caffe.TEST) #加载model和network
[(k,v[0].data.shape) for k,v in net.params.items()] #查看各层参数规模
w1=net.params['Convolution1'][0].data #提取参数w
b1=net.params['Convolution1'][1].data #提取参数b
net.forward() #运行测试
[(k,v.data.shape) for k,v in net.blobs.items()] #查看各层数据规模
fea=net.blobs['InnerProduct1'].data #提取某层数据(特征)