caffe学习入门:pycaffe的使用
转自 http://blog.csdn.net/liyaohhh/article/details/50932430
caffe的官方完美的支持python语言的兼容,提供了pycaffe的接口。用起来很方便,首先来看一下最常用到的:caffe的一个程序跑完之后会在snapshot所指定的目录下产生一个后缀名为caffemodel的文件,这里存放的就是我们在训练网络的时候得到的每层的参数信息,具体访问由net.params['layerName'][0].data访问权重参数(num_filter,channel,weight,high),net.params['layerName'][1].data访问biase,格式是(biase,)。如下图所示:这里的net.params使用的是字典格式
当然还有保存网络结构的字典类型net.blobs['layerName'].data。这里最常用的也就是net.blobs['data']相关的使用,例如得到输入图片的大小net.blobs['data'].data.shape。改变输入图片的大小net.blobs['data'].reshape(0,3,227,227),把图片fed into网络。net.blob['data'].data[...]=inputImage,注意,这里最后一个data是一个数组,要是只有一张图片就这样net.blob['data'].data[0]=inputImage。如下图所示:
下面用python实现一个使用自己的图片的例子:
- import numpy as np
- import sys,os
- # 设置当前的工作环境在caffe下
- caffe_root = '/home/xxx/caffe/'
- # 我们也把caffe/python也添加到当前环境
- sys.path.insert(0, caffe_root + 'python')
- import caffe
- os.chdir(caffe_root)#更换工作目录
- # 设置网络结构
- net_file=caffe_root + 'models/bvlc_reference_caffenet/deploy.prototxt'
- # 添加训练之后的参数
- caffe_model=caffe_root + 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel'
- # 均值文件
- mean_file=caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy'
- # 这里对任何一个程序都是通用的,就是处理图片
- # 把上面添加的两个变量都作为参数构造一个Net
- net = caffe.Net(net_file,caffe_model,caffe.TEST)
- # 得到data的形状,这里的图片是默认matplotlib底层加载的
- transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
- # matplotlib加载的image是像素[0-1],图片的数据格式[weight,high,channels],RGB
- # caffe加载的图片需要的是[0-255]像素,数据格式[channels,weight,high],BGR,那么就需要转换
- # channel 放到前面
- transformer.set_transpose('data', (2,0,1))
- transformer.set_mean('data', np.load(mean_file).mean(1).mean(1))
- # 图片像素放大到[0-255]
- transformer.set_raw_scale('data', 255)
- # RGB-->BGR 转换
- transformer.set_channel_swap('data', (2,1,0))
- # 这里才是加载图片
- im=caffe.io.load_image(caffe_root+'examples/images/cat.jpg')
- # 用上面的transformer.preprocess来处理刚刚加载图片
- net.blobs['data'].data[...] = transformer.preprocess('data',im)
- #注意,网络开始向前传播啦
- output = net.forward()
- # 最终的结果: 当前这个图片的属于哪个物体的概率(列表表示)
- output_prob = output['prob'][0]
- # 找出最大的那个概率
- print 'predicted class is:', output_prob.argmax()
- # 也可以找出前五名的概率
- top_inds = output_prob.argsort()[::-1][:5]
- print 'probabilities and labels:'
- zip(output_prob[top_inds], labels[top_inds])
- # 最后加载数据集进行验证
- imagenet_labels_filename = caffe_root + 'data/ilsvrc12/synset_words.txt'
- labels = np.loadtxt(imagenet_labels_filename, str, delimiter='\t')
- top_k = net.blobs['prob'].data[0].flatten().argsort()[-1:-6:-1]
- for i in np.arange(top_k.size):
- print top_k[i], labels[top_k[i]]
- import os
- import numpy as np
- import os
- import matplotlib.pyplot as plt
- import matplotlib.patches as mpatches
- %matplotlib inline
- # 设置默认的属性:用于在ipython中显示图片
- plt.rcParams['figure.figsize'] = (10, 10)
- plt.rcParams['image.interpolation'] = 'nearest'
- plt.rcParams['image.cmap'] = 'gray'
- from math import pow
- from skimage import transform as tf
- caffe_root='/opt/modules/caffe-master/'
- sys.insert.path(0,caffe_root+'python')
- caffe_modelcaffe=caffe_root+''
- caffe_deploy=caffe_root+''
- caffe.set_mode_cpu()
- net=caffe.Net(caffe_deploy,caffe_modelcaffe,caffe.TEST)
- transform=caffe.io.Transformer({'data':net.blobs['data'].data.shape})
- transform.set_transpose('data',(2,0,1))
- transform.set_raw_scale('data',255)
- transform.set_channel_swap('data',(2,1,0))
- #把加载到的图片缩放到固定的大小
- net.blobs['data'].reshape(1,2,227,227)
- image=caffe.io.load_image('/opt/data/person/1.jpg')
- transformed_image=transform.preprocess('data',image)
- plt.inshow(image)
- # 把警告过transform.preprocess处理过的图片加载到内存
- net.blobs['data'].data[...]=transformed_image
- output=net.forward()
- #因为这里仅仅测试了一张图片
- #output_pro的shape中有对于1000个object相似的概率
- output_pro=output['prob'][0]
- #从候选的区域中找出最有可能的那个object的索引
- output_pro_max_index=output_pro.argmax()
- labels_file = caffe_root + '.../synset_words.txt'
- if not os.path.exists(labels_file):
- print "in the direct without this synset_words.txt "
- return
- labels=np.loadtxt(labels_file,str,delimiter='\t')
- # 从对应的索引文件中找到最终的预测结果
- outpur_label=labels[output_pro_max_index]
- # 也可以找到排名前五的预测结果
- top_five_index=output_pro.argsort()[::-1][:5]
- print 'probabilities and labels:'
- zip(output_pro[top_five_index],labels[top_five_index])
http://blog.csdn.net/godissleeping/article/details/50475952
到的python的包:
图像处理:opencv(需要自己编译) 或者 scipy(scipy中的image子类)
矩阵相关:numpy
获取已经训练好的模型的结果和中间特征:
- import caffe #导入caffe的python接口
- caffe.set_mode_gpu() #设置成gpu模式或者设置成cpu模式 caffe.set_mode_cpu()
- net = caffe.Classifier(
- model_file='deploy prototxt文件路径',
- pretrained_file='生成的二进制caffemodel模型的路径',
- mean=np.load('均值文件的路径'),
- raw_scale=255 #若使用的原始图像值在0-255,则保留该参数
- ) #至此,初始化caffe的分类器模型,保存到变量
- nettransformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) # caffe.io.Transformer 是用于预处理的类。事先填写进行预处理的要求。
- transformer.set_transpose('data', (2,0,1)) #将 高x宽x通道,转化为,通道x高x宽的格式
- img=caffe.io.load_image('图片路径') #读取图像
- newImg=transformer.preprocess('data',img ) #设置data层的数据,这里以单张图像为例。将读取的图像传入,获得按之前设置的预处理方式处理好的新图像(通道x高x宽)。
- net.blobs['data'].reshape(图像数,原来训练时定义的通道数,训练时图像的高,训练时图像的宽) #
- net.blobs['data'].data[...] = newImg #让网络模型的数据层获取预处理好的图像,要传入多张图像,参考numpy的教程,将图像堆叠成多维矩阵(图像数x通道x高x宽)。
- out = net.forward() #让数据通过整个训练好的模型,前向传播
- filters = net.params['层的名称,如文件中定义好的conv1'][0].data #获取指定层的filters
- feat = net.blobs['conv1'].data #获取conv1层的特征图谱
- prediction=out['loss'].argmax() #直接得到模型输出的最终结果
标签:
当训练好一个model之后,我们通常会根据这个model最终的loss和在验证集上的accuracy来判断它的好坏。但是,对于分类问题,我们如果只是知道整体的分类正确率
显然还不够,所以只有知道模型对于每一类的分类结果以及正确率这样才能更好的理解这个模型。
下面就是一个用训练好的模型,来对测试集进行测试,并输出每个样本的分类结果的实现。
代码如下:
#coding=utf-8 import os import caffe import numpy as np root=‘/home/liuyun/caffe/‘ #根目录 deploy=root + ‘models/bvlc_googlenet/deploy.prototxt‘ #模型对应的deploy文件 caffe_model=root + ‘models/CCC/C2/bvlc_googlenet_iter_10000.caffemodel‘ #训练好的 caffemodel ########################################## import os dir = root+‘examples/CCC/test/‘ #测试数据路径 filelist=[] #用于存放完整路径以及文件名 filenames = os.listdir(dir) #读入在某个目录下的所有文件 for fn in filenames: fullfilename = os.path.join(dir,fn) filelist.append(fullfilename) #连接成完整路径 # img=root+‘data/DRIVE/test/60337.jpg‘ #随机找的一张待测图片 ############################################### def Test(img): #定义测试函数 net = caffe.Net(deploy,caffe_model,caffe.TEST) #加载model和network #图片预处理设置 transformer = caffe.io.Transformer({‘data‘: net.blobs[‘data‘].data.shape}) #设定图片的shape格式(1,3,28,28) transformer.set_transpose(‘data‘, (2,0,1)) #改变维度的顺序,由原始图片(28,28,3)变为(3,28,28) #transformer.set_mean(‘data‘, np.load(mean_file).mean(1).mean(1)) #减去均值,前面训练模型时没有减均值,这儿就不用 transformer.set_raw_scale(‘data‘, 255) # 缩放到【0,255】之间 transformer.set_channel_swap(‘data‘, (2,1,0)) #交换通道,将图片由RGB变为BGR im=caffe.io.load_image(img) #加载图片 net.blobs[‘data‘].data[...] = transformer.preprocess(‘data‘,im) #执行上面设置的图片预处理操作,并将图片载入到blob中 #执行测试 out = net.forward() labels = np.loadtxt(labels_filename, str, delimiter=‘\t‘) #读取类别名称文件 prob= net.blobs[‘prob‘].data[0].flatten() #取出最后一层(prob)属于某个类别的概率值,并打印,‘prob‘为最后一层的名称 print prob order=prob.argsort()[999] #将概率值排序,取出最大值所在的序号 ,9指的是分为0-9十类 指的是在deploy文件中的类别数; #argsort()函数是从小到大排列 print ‘the class is:‘,labels[order] #将该序号转换成对应的类别名称,并打印 f=file("/home/liuyun/caffe/examples/CCC/label.txt","a+") f.writelines(labels[order]+‘\n‘) #将输出结果写入label.txt文件中 ################################################################## labels_filename = root +‘examples/CCC/DR.txt‘ #类别名称文件,将数字标签转换回类别名称 for i in range(0, len(filelist)): img= filelist[i] Test(img)
http://blog.csdn.net/jinxueliu31/article/details/52066709
【Caffe】Blobs数据结构的Python表示
Caffe主要处理两种形式的数据流:
1. 图像和标签在网络上的传输,随着网络的传输,它们转化更高层次的表示,最终以得分或者概率值的形式输出。
2. 第二种数据流,主要保存各个网络层的参数,比如卷积层的weights和bias. 这些值是随着的网络的训练过程不断变化的。
这两种数据流虽然说角色不一样,但是都是以blob的形式进行保存和处理的。
下面以手写体LeNet为例:
import os import numpy as np import caffe caffe_root = '/path/your/caffe' os.chdir(caffe_root) solver_prototxt = 'examples/mnist/lenet_solver.prototxt' solver = caffe.SGDSolver(solver_prototxt) net = solver.net
第一种形式的数据流保存在net.blobs中
net.blobs
它是有序字典,保存了每一层对应的数据。每个blob保存了data和gradient:
net.blobs['data'].data.shape # >> (64, 1, 28, 28) net.blobs['data'].diff.shape # >> (64, 1, 28, 28) net.blobs['conv1'].data.shape # >> (64, 20, 24, 24) net.blobs['conv1'].diff.shape # >> (64, 20, 24, 24) net.blobs['ip1'].data.shape # >> (64, 500) net.blobs['ip1'].diff.shape # >> (64, 500)
第二种形式的数据流可以通过net.layers来获得
net.layers
这是一个caffe形式的向量,保存了各层的参数。它的第一层是data layer:
len(net.layers[0].blobs) # >> 0
因为输入层没有权重参数,因此blob的个数是0
它的第二层是卷积层:
len(net.layers[1].blobs) # >> 2 net.layers[1].blobs[0].data.shape # >> (20, 1, 5, 5) conv1 weights net.layers[1].blobs[1].data.shape # >> (20,) bias
表示有20个卷积核,每个卷积核的大小是5*5,处理1-channel的输入图像。
另一种获得各层参数的方式就是net.params
print net.params['conv1'][0].data.shape # (20, 1, 5, 5) conv1 weights print net.params['conv1'][1].data.shape # (20,) bias
这种方式更直观。