【caffe】Caffe的Python接口-官方教程-00-classification-详细说明(含代码)
00-classification 主要讲的是如何利用caffenet(与Alex-net稍稍不同的模型)对一张图片进行分类(基于imagenet的1000个类别)
先说说教程到底在哪(反正我是找了半天也没发现。。。)
其实并没有官方教程一说,只是在caffe/example/下有
00-classification.ipynb;
01-learning-lenet.ipynb;
02-fine-tuning.ipynb;
等等一些列 ipython notebook文件,里面就是一些example,这就是所说的官方教程,打开ipynb文件有多种方式,我是直接在github上打开的(附链接:http://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/00-classification.ipynb)
这些example其实是比较全的,例如00-classification不仅告诉怎么用训练好的.caffemodel+ deploy.prototxt对一张新来的图片进行分类,而且还讲到如何使用python对filters可视化,对feature maps 可视化;如何对各层activations进行绘制直方图;以及如何绘制prob层的输出直方图;
这功能未必是我们想要的,所以大家可以自行挑选,最后我会附上我的代码
函数总结
先总结一些最关心的接口函数,即可能用到的python接口函数,也是我们最关心的python里用什么函数对blob,params进行 ”读“,”写“
1. 加载model的函数,net = caffe.Net(model_def, model_weights, caffe.TEST) ,model_def是deploy.prototxt的路径,model_weights是*.caffemodel的路径,caffe.TEST是说明网络是用来test的,不会执行dropout
2. 执行测试out = net.forward() ,
3. 获取 batchsize中第一张图像的输出 put_prob = output[‘prob’][0]
4. 最大值所在的标号 output_prob.argmax()
5. 获取 网络weights 参数net.params[‘conv1’][0].data
6. 获取网络blob里的数据net.blobs[‘conv1’].data[0, :9]
7. top 5的获取 top_inds = output_prob.argsort()[::-1][:5]
开始之前说一下,第一步至第四步都是按照官方教程上来的,并不是很完整的一个code,完整的code在最后面给出,但是和官方教程不一样,但是本质上是一样的。所以说一下注意事项,即需要的文件以及路径的注意事项
需要的文件:
1. 网络模型文件在 caffe/models/bvlc_reference_caffenet下 的 bvlc_reference_caffenet.caffemodel
2. 网络描述文件在caffe/models/bvlc_reference_caffenet下 的deploy.prototxt
3.测试图片 cat.png 在caffe/examples/images下
4. 类别名称文件 synset_words.txt 自行下载
5.均值文件 ilsvrc_2012_mean.npy 自行下载
(百度云盘打包5个文件:链接: https://pan.baidu.com/s/1o8dqifS 密码: rjbb)
第一步、Setup
第一步肯定是要安装好 python,安装好numpy,matplotlib 包。配置好python-caffe的接口(怎么配置请参考别 的优秀blog)。
在import caffe 之前一定要把路径添加进来,要不然会找不到caffe这个模块;这里提供两种方法,一种是文档里的
import sys
caffe_root = '../' # this file should be run from {caffe_root}/examples (otherwise change this line)
sys.path.insert(0, caffe_root + 'python')
一种是我用的(参见底部代码)
第一步的完整代码
import numpy as np
import matplotlib.pyplot as plt
# set display defaults
plt.rcParams['figure.figsize'] = (10, 10) # large images
plt.rcParams['image.interpolation'] = 'nearest' # don't interpolate: show square pixels
plt.rcParams['image.cmap'] = 'gray' # use grayscale output rather than a (potentially misleading) color heatmap
第二步、Load net and set up input preprocessing
第二步,加载网络以及对图片进行预处理
加载网络需要有 deploy.prototxt和 *.caffemodel文件,而加载网络是通过路径名,所以先设置好这两个文件的路径名
model_def = caffe_root + 'models/bvlc_reference_caffenet/deploy.prototxt'
model_weights = caffe_root + 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel'
然后即可加载网络
net = caffe.Net(model_def, model_weights,caffe.TEST)
然后设置cpu or gpu,可自行挑选其中一个
# 用cpu
caffe.set_mode_cpu()
# 用gpu
caffe.set_device(0)
caffe.set_mode_gpu()
由于输入到网络的图片是经过处理的,所以要把读取进来的图片处理成与网络训练时所见过的图片是一致的,这里的一致包括 shape,颜色通道顺序,取值范围([0,1] or [0,255]?),以及是否减均值(channel-wise or pixel-wise ?) , 这些都需要一致。
首先把网络用到的均值文件加载进来(这个文件在caffe/imagenet/ilsvrc_2012_mean.npy),
mu = np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy')
mu = mu.mean(1).mean(1) # 这里即是计算出 channel-wise所用到的均值
print 'mean-subtracted values:', zip('BGR', mu) # print出来BGR三个channel的均值是多少
接下来设置(create)预处理操作
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2,0,1)) [h,w,c] → [c,h,w]
transformer.set_mean('data', mu) # 减均值 channel-wise
transformer.set_raw_scale('data', 255) [0,1] → [0,255]
transformer.set_channel_swap('data', (2,1,0)) RGB--> BGR
第三步,输入图像进行分类
有了网络net,有个对输入图像的预处理操作的设置,接来下就可以把一张图像 put到net中,net给出分类结果
首先读取图像,读取图像这里需要注意几点,采用不同函数读取进来的图像数据,其形式可能不一样,这里给出一些总结
**caffe.io.load_image读取,读取进来的是[0,1],RGB,(h,w,3)
cv.2 读取进来的是 [0,255], BGR, (h,w,3)
matlab 读取进来的是 [0,255],RGB,(h,w,3)**
image = caffe.io.load_image(caffe_root + 'examples/images/cat.jpg')
transformed_image = transformer.preprocess('data', image)
plt.imshow(image)
(ps: 要自己加上 plt.show() 才能显示如下这只可爱的喵星人~~)
接下来把图像喂给net吧
net.blobs['data'].data[...] = transformed_image
output = net.forward()
output_prob = output['prob'][0] # 把网络输出层(prob)第一个值取出来 (注意了!这里shape用的是[50,3,227,227],一次一个batch的,batchsize是50,而我们只喂给网络一张图像,所以要取出对应的prob,即 output['prob'][0])output['prob'][0]是一个 1000维的向量
print 'predicted class is:', output_prob.argmax() # 再把这1000维的向量最大值所在的标号取出来,即分类类别
只知道分类类别标号,并不能满足我们最终想知道这张图片到底是什么物体,所以需要一个索引,索引存在synset_words.txt中,这个文件需要自己下载,(下载方式:caffe/data/ilsvrc12里有个sh文件,通过这个文件即可下载)
labels_file = caffe_root + 'data/ilsvrc12/synset_words.txt'
labels = np.loadtxt(labels_file, str, delimiter='\t')
print 'output label:', labels[output_prob.argmax()]
这样就可以print出这张图像是什么物体了,结果没错的话就是:
output label: n02123045 tabby, tabby cat
对于Imagenet,总所周知的是除了top1 还有 top5, 那么如何获取top5呢,我们来看看:
top_inds = output_prob.argsort()[::-1][:5] # reverse sort and take five largest items
print 'probabilities and labels:'
zip(output_prob[top_inds], labels[top_inds])
至此classification就结束啦!
第四步,看看中间层都是什么
不能让神经网络太”黑“,只知道input,output,所以这里提供了一些函数可以对filters,feature maps进行可视化,还可以对输入的概率值进行绘制直方图
我这里按照功能分1-7个步骤
1.获取各blob的名字以及shape
for layer_name, blob in net.blobs.iteritems():
print layer_name + '\t' + str(blob.data.shape)
2.获取params的名字以及shape
for layer_name, param in net.params.iteritems():
print layer_name + '\t' + str(param[0].data.shape), str(param[1].data.shape)
- 对卷积核进行可视化
首先要定义个函数,要来show出卷积核的,就是把n个卷积核画到一张图片上
def vis_square(data):
"""Take an array of shape (n, height, width) or (n, height, width, 3)
and visualize each (height, width) thing in a grid of size approx. sqrt(n) by sqrt(n)"""
# normalize data for display
data = (data - data.min()) / (data.max() - data.min())
# 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, 1), (0, 1)) # add some space between filters
+ ((0, 0),) * (data.ndim - 3)) # don't pad the last dimension (if there is one)
data = np.pad(data, padding, mode='constant', constant_values=1) # pad with ones (white)
# 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:])
plt.imshow(data); plt.axis('off')
然后来看看conv1 的卷积核长什么样
filters = net.params['conv1'][0].data
vis_square(filters.transpose(0, 2, 3, 1))
transpose的是因为,网络数据流动的shape是[batch,channel,h,w] 而plot函数是绘制[h,w,channel]的,所以要transpose一下
4.看看 经过conv1卷积得到的feature maps 是什么样,这里只看前36个(好plot吧,毕竟36 = 6*6)
feat = net.blobs['conv1'].data[0, :36]
vis_square(feat)
5.看看 pool5后得到的 feature maps 是什么样
feat = net.blobs['pool5'].data[0]
vis_square(feat)
6.看了feature 和 filters还不过瘾,那来看看中间层的activation的分布情况吧
feat = net.blobs['fc6'].data[0]
plt.subplot(2, 1, 1)
plt.plot(feat.flat)
plt.subplot(2, 1, 2)
_ = plt.hist(feat.flat[feat.flat > 0], bins=100)
第一个图可以看到fc6层(4096个神经元)各个神经元输出值是多少,整体分布在(0,60)之间
第二个图可以看出4096个输出值是怎么样的一个分布,可以发现在0-20之间占了绝大部分
7.来看看网络的输出prob的分布
feat = net.blobs['prob'].data[0]
plt.figure(figsize=(15, 3))
plt.plot(feat.flat)
可以看到 281个神经元的输出是最大的,不过也有写干扰项,整体来说这样的输出还是很满意的(即没有太多别的类别的干扰)
以上是根据官方教程来写的,
我自己的demo并不是完全一样,但是思路是一样的,大家可以参考:
注意! 路径需要更改,
# -*- coding: utf-8 -*-
'''
@author: TensorSense
'''
import sys
sys.path.append('/home/***/caffe/python')
sys.path.append('/home/***/caffe/python/caffe')
import caffe
import numpy as np
import argparse
import glob
import matplotlib.pyplot as plt
# import cv2
def obtain_img_path(dir_path, codec='png'):
# dir_path is the directory of image
# imgs_path is a list , element of imgs_path is single image path
imgs_path = [img_path for img_path in glob.glob(dir_path + '*' + codec)]
return imgs_path
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--deploy_folder', default='./', help='path to the deploy FOLDER. [DEFAULT=...]')
parser.add_argument('--deploy_file', default='deploy.prototxt', help='path to the deploy NAME. [DEFAULT=deploy.prototxt]')
parser.add_argument('--model_state_folder', default='./', help='stored model FOLDER. [DEFAULT=../../Result/Section6/]')
parser.add_argument('--caffemodel_file', default='bvlc_reference_caffenet.caffemodel', help='path to the .caffemodel NAME')
args = parser.parse_args()
caffe.set_mode_gpu()
caffe.set_device(0)
DEPLOY_FULL_PATH = args.deploy_folder + args.deploy_file
CAFFEMODEL_FULL_PATH = args.model_state_folder + args.caffemodel_file
# load caffemodel
# requirements: deploy.prototxt and ***.caffemodel
net = caffe.Net(DEPLOY_FULL_PATH,CAFFEMODEL_FULL_PATH,caffe.TEST)
# load test images_path
img_dir = '../../../caffe/examples/images/cat.jpg'
# imgs_dir = '../../Data/tt/' # the last '/' can not be less'
# imgs_path = obtain_img_path(imgs_dir, codec='png')
labels_filename = './synset_words.txt' # 类别名称文件,将数字标签转换回类别名称
# image preprocess
# load ImageNet mean
mu = np.load('./ilsvrc_2012_mean.npy')
mu = mu.mean(1).mean(1) # BGR ,channel-wise not pixel-wise
print '111111111111111111111`~~~~~~~~~~~`mu :',type(mu)
print 'mean-subtracted values:', zip('BGR', mu)
# process image
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) # (10,3,227,227), input one image, it will copy 10 copies
transformer.set_transpose('data', (2,0,1)) # (w,h,c)--> (c,w,h)
transformer.set_mean('data', mu) # channel-wise
transformer.set_raw_scale('data', 255) # [0,1] --> [0,255]
transformer.set_channel_swap('data', (2,1,0)) # RGB --> BGR
# load image
img = img_dir
im=caffe.io.load_image(img) # im is RGB with 0~1 float
# print 'raw im ~~~~ :' , im.shape
net.blobs['data'].data[...]=transformer.preprocess('data',im)
# print 'processed im ~~~: ', net.blobs['data'].data
# 执行测试
out = net.forward()
labels = np.loadtxt(labels_filename, str, delimiter='\t') # 读取类别名称文件
prob= net.blobs['prob'].data[0].flatten() # 取出最后一层(Softmax)属于某个类别的概率值,并打印
# print prob
order=prob.argsort()[-1] # [-2] is second largest
print 'the class is:',labels[order] # find labels name
print 'the class is : ' + str(order)
# sort top five predictions from softmax output
top_inds = prob.argsort()[::-1][:5]
# the shape of net.blobs
for layer_name, blob in net.blobs.iteritems():
print layer_name + '\t' + str(blob.data.shape)
# the shape of net.params
for layer_name, param in net.params.iteritems():
print layer_name + '\t' + str(param[0].data.shape) , str(param[1].data.shape)
# vis function
def vis_square(data):
"""输入一个形如:(n, height, width) or (n, height, width, 3)的数组,并对每一个形如(height,width)的特征进行可视化sqrt(n) by sqrt(n)"""
data = (data - data.min()) / (data.max() - data.min())
#
n = int(np.ceil(np.sqrt(data.shape[0])))
padding = (((0, n ** 2 - data.shape[0]),
(0, 1), (0, 1)) # 在相邻的滤波器之间加入空白
+ ((0, 0),) * (data.ndim - 3)) # 不扩展最后一维
data = np.pad(data, padding, mode='constant', constant_values=1) # 扩展一个像素(白色)
# 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:])
plt.imshow(data)
plt.axis('off')
plt.show()
# show filters
# filters = net.params['conv1'][0].data
# vis_square(filters.transpose(0, 2, 3, 1)) batchsize,c,w,h --> bs,w,h,c
# show fearture maps it require input
# feat = net.blobs['conv1'].data[0, :9]
# vis_square(feat)
# show the distribution
feat = net.blobs['prob'].data[0]
plt.ylim(feat.min(),feat.max()) # 设置坐标轴的最大最小区间
plt.subplot(2, 1, 1)
plt.plot(feat.flat)
plt.subplot(2, 1, 2)
_ = plt.hist(feat.flat[feat.flat > 0], bins=100)
plt.show()
【caffe】Caffe的Python接口-官方教程-00-classification-详细说明(含代码)的更多相关文章
- 【caffe】Caffe的Python接口-官方教程-01-learning-Lenet-详细说明(含代码)
01-learning-Lenet, 主要讲的是 如何用python写一个Lenet,以及用来对手写体数据进行分类(Mnist).从此教程可以知道如何用python写prototxt,知道如何单步训练 ...
- 【python接口自动化测试教程】00---00章节就代表开篇吧
今天突然想写个接口测试教程,由于本人是初级的比小白稍微好那么一丢丢,所以不知道能不能坚持下来 写的不对的地方还请大咖指教 先去忙自己的工作了,忙完了回来开始写第一章吧 或者先写个大纲,要不然写的章节会 ...
- 自定义View(7)官方教程:自定义View(含onMeasure),自定义一个Layout(混合组件),重写一个现有组件
Custom Components In this document The Basic Approach Fully Customized Components Compound Controls ...
- windows环境用python修改环境变量的注意点(含代码)
1.部分环境变量字段需要保留原来的值,只是做添加,不可以替换 2.Path和PATH对于python来说是一样的,也就是说存在名为Path的环境变量时,添加PATH的环境变量,会覆盖原有的Path环境 ...
- 机器学习caffe环境搭建——redhat7.1和caffe的python接口编译
相信看这篇文章的都知道caffe是干嘛的了,无非就是深度学习.神经网络.计算机视觉.人工智能这些,这个我就不多介绍了,下面说说我的安装过程即遇到的问题,当然还有解决方法. 说下我的环境:1>虚拟 ...
- windows10下基于vs2015的 caffe安装教程及python接口实现
啦啦啦:根据网上的教程前一天安装失败,第二天才安装成功.其实caffe的安装并不难,只是网上的教程不是很全面,自己写一个,留作纪念. 准备工作 Windows10 操作系统 vs2015(c++编译器 ...
- ubuntu16.04+caffe+python接口配置
在Windows上用了一个学期的caffe了.深感各种不便,于是乎这几天在ubuntu上配置了caffe和它的python接口,现在记录配置过程,亲测可用: 环境:ubuntu16.04 , caff ...
- caffe的python接口学习(7):绘制loss和accuracy曲线
使用python接口来运行caffe程序,主要的原因是python非常容易可视化.所以不推荐大家在命令行下面运行python程序.如果非要在命令行下面运行,还不如直接用 c++算了. 推荐使用jupy ...
- Windows+Caffe+VS2013+python接口配置过程
前段时间在笔记本上配置了Caffe框架,中间过程曲曲折折,但由于懒没有将详细过程总结下来,这两天又在一台配置较高的台式机上配置了Caffe,配置时便非常后悔当初没有写到博客中去,现已配置好Caffe, ...
随机推荐
- IMAGE_OPTIONAL_HEADER32 结构作用
IMAGE_OPTIONAL_HEADER32 结构作用 接 着我们来谈谈 IMAGE_OPTIONAL_HEADER 结构,正如名字的意思,这是一个可选映像头,是一个可选的结构,但是呢,实际上上节课 ...
- Codeforces Gym100735 I.Yet another A + B-Java大数 (KTU Programming Camp (Day 1) Lithuania, Birˇstonas, August 19, 2015)
I.Yet another A + B You are given three numbers. Is there a way to replace variables A, B and C with ...
- svn安装配置使用小总结
1svn:版本控制系统服务端与客户端协作服务端:subversion客户端:eclipse_svn_site-1.10.5.zip插件1安装问题: 1subversion版本过高 会出现版 ...
- Codeforces 586D Phillip and Trains(DP)
题目链接 Phillip and Trains 考虑相对位移. 每一轮人向右移动一格,再在竖直方向上移动0~1格,列车再向左移动两格. 这个过程相当于每一轮人向右移动一格,再在竖直方向上移动0~1格, ...
- Jmeter脚本两种录制方式
Jmeter 是一个非常流行的性能测试工具,虽然与LoadRunner相比有很多不足,比如:它结果分析能力没有LoadRunner详细:很它的优点也有很多: l 开源,他是一款开源的免 ...
- JMeter特殊情况二:针对某些请求数据每次请求都是变化的情况
概要:某些post请求,例如,登录的请求除了有我们再页面上需要输入的一些值(用户名.密码.是否记住密码等)之外,还有其他的参数,例如token等等,而且这些参数不固定,也就是说每一次post请求这些参 ...
- dhlin-vim-wiki
记录vim中常用的几个操作 入门指南 $ vimtutor vim中是区分大小写 vim中移动光标 h 向左移动 j 向下移动 k 向上移动 l 向右移动 其实使用方向键也是能移动的,但是熟悉后再一些 ...
- unsupported Scan, storing driver.Value type []uint8 into type *time.Time 解决方案
数据库取数据的字段为created_at,数据库中类型是TIMESTAMP,允许NULL,此时在取数据的时候就会出现这种报错. 解决方案:在数据库连接的字符串中添加:&parseTime=Tr ...
- 数据库资源博客---小麦苗BEST
http://blog.csdn.net/lihuarongaini/article/details/60584577 http://blog.csdn.net/lihuarongaini/artic ...
- GDI 编程基础简介
今天准备重新对GDI的知识进行回顾一下,以便加深认识. 一.GDI 在进行Windows编程时,可能经常会用到设备描述表的类型句柄,例如,最厂家的HDC,它就是图像设备描述类型句柄.因为GDI的绘图函 ...