Caffe训练自己的数据集并用Python接口预测
本教程作者是清华大学在读硕士金天童鞋,在当地较为英俊的男子,大家对教程有任何疑问欢迎联系我:WeChat
jintianiloveu
,同时也欢迎大家转载评论,不过请保留这段版权信息,桑口~
之前写了一个博客讲Caffe训练自己的数据集,但是是英文版的,为了防止大家说我有装逼的嫌疑我还是写个中文版吧,而且这次是分五类,简洁明了,caffe入门必备,大家有任何疑问直接在下面评论吧,最后马上过年了大家给我的github repo挨个赞一个呗,地址在此我拯救世界的梦想就靠你们了!
Caffe安装
首先还是简要的说一下Caffe在Ubuntu下的安装过程,具体安装过程如下:
-
安装前置依赖
前置依赖项较多,好在Ubuntu下都可以通过apt下载安装,这个命令一阵复制粘帖吧:
sudo apt-get upgrade
sudo apt-get install -y build-essential cmake git pkg-config
sudo apt-get install -y libprotobuf-dev libleveldb-dev libsnappy-dev libhdf5-serial-dev protobuf-compiler
sudo apt-get install -y libatlas-base-dev
sudo apt-get install -y --no-install-recommends libboost-all-dev
sudo apt-get install -y libgflags-dev libgoogle-glog-dev liblmdb-dev
然后安装OpenCV3.1,这个安装已经轻车熟路了。大家对此有和疑问的查看我这个博客,找到Ubuntu下安装OpenCV的教程进行安装。
接下来就简单了,不过为了防止后面导入caffe出问题,建议软链接一下这个东西:
sudo ln -s /usr/lib/x86_64-linux-gnu/libboost_python-py35.so /usr/lib/x86_64-linux-gnu/libboost_python3.so
接着clone项目:
git clone https://github.com/BVLC/caffe.git
然后在我的Repo里面下载Makefile
和Makefile.config
来替换原有的。接着就是安装python依赖,这里不要按照其他教程里面的安装官方的caffe/python下的requirement.txt,instead,下载我的,然后运行:
sudo pip3 install --upgrade -r python/requirements_python3.txt
后面的requirements_python3.txt
也可以从上面的Repo下载。
接着直接安装就行了:
make all -j
make pycaffe
测试一下是否安装成功:
./data/mnist/get_mnist.sh
./examples/mnist/create_mnist.sh
./examples/mnist/train_lenet.sh
如果成功你就会看到caffe在训练mnist了,大概几千次之后准确度就可以达到99%,非常好。
Caffe生成并训练自己的数据集
本教程所有的代码,文件目录结构可以在我的github上下载,点这里,下载之后你会看到一个完整的caffe训练架构,但是数据还得另外下载,我在这里只是上传了5类图片的样张图片,真正的数据集大概有600张的样子。下载地址为这里。
接下来要生成caffe需要的数据了,步骤如下,大家先不要方,生成数据是整个过程最复杂的部分,不过这个部分也不是很麻烦,我精简一下步骤:
Step 1 Generate the image name file
Run caffe_path_gen.py in your terminal, just type:
python3 caffe_path_gen.py -train=/home/jfg/caffe_tiny5/tiny5/train -shuffle=True
-shuffle is optional, because caffe can do this too.
In this tutorial we only have train data in image_data folder, we don't have test image, so we just generate the train image path, and manully divide them into train and test. But if you have test data folder, you also can type:
python3 caffe_path_gen.py -train=/home/jfg/Documents/PythonSpace/caffe_tiny5/tiny5/train -test=/home/jfg/Documents/PythonSpace/caffe_tiny5/tiny5/test -valid=/home/jfg/Documents/PythonSpace/caffe_tiny5/tiny5/valid
the valid data only generate image path without labels.
After this, you gonna have train.txt, words.txt.
Step 2 Split train.txt into to train.txt and test.txt
Before split please remove the path just make it like this:
/flower/683.jpg 3
/bus/334.jpg 0
/bus/336.jpg 0
/dinosaur/481.jpg 2
/dinosaur/436.jpg 2
/bus/327.jpg 0
/elephant/595.jpg 4
/bus/357.jpg 0
/bus/393.jpg 0
/bus/375.jpg 0
/dinosaur/453.jpg 2
/flower/654.jpg 3
/dinosaur/491.jpg 2
/bus/365.jpg 0
/flower/636.jpg 3
/flower/629.jpg 3
/bus/347.jpg 0
/bus/398.jpg 0
/horse/761.jpg 1
/elephant/560.jpg 4
/dinosaur/449.jpg 2
/elephant/531.jpg 4
/horse/794.jpg 1
/horse/743.jpg 1
/elephant/586.jpg 4
But stay with the class prefix
Step 3 Generate Caffe LMDB data file
First mkdir a data
folder just inside the project directory, and place train.txt and test.txt into it.
And then open caffe_create_lmdb.sh and just edit the following two lines:
TRAIN_DATA_ROOT=/home/jfg/Documents/PythonSpace/caffe_tiny5/tiny5/train
VAL_DATA_ROOT=/home/jfg/Documents/PythonSpace/caffe_tiny5/tiny5/valid
在这一步中,确保TRAIN_DATA_ROOT和上面的train.txt中的文件名能够组成完整的路径即可。
Simply edit two lines, leave other along.
Then type:
bash caffe_create_lmdb.sh
Tip: Anything wrong, check you mkdir a data folder, and have train.txt and test.txt in it.
OK, after this, you gonna have two new folder in your data folder, that is:
caffe_train_lmdb
caffe_val_lmdb
this is what we need to feed into caffe net and it is nothing with your original image anymore! It's complete and clean! Do not warry about path wrong anymore! Very nice!
Step 4 Generate Mean Binary File
This step is very easy, don't change anything ,just type this in your terminal:
bash caffe_make_mean.sh
And you gonna have caffe_mean.binaryproto
file in your data folder.
开始Caffe训练
you already have your data, just finish 80% work. 20% to go. Next, we gonna using solver folder. In this folder we have a solver.prototxt and a train_test.prototxt.
solver.prototxt is the net pramas setting file.
train_test.prototxt is the net structure setting file and your lmdb data feed into net in here.
layer {
name: "cifar"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
mean_file: "/home/jfg/caffe_tiny5/data/caffe_mean.binaryproto"
}
data_param {
source: "/home/jfg/caffe_tiny5/data/caffe_train_lmdb"
batch_size: 100
backend: LMDB
}
}
layer {
name: "cifar"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
mean_file: "/home/jfg/caffe_tiny5/data/caffe_mean.binaryproto"
}
data_param {
source: "/home/jfg/caffe_tiny5/data/caffe_val_lmdb"
batch_size: 100
backend: LMDB
}
}
This 2 layer is data feed layer, so you have to change your data path in here.Make sure it correct.
Open solver.prototxt, find this 2 and edit it:
net: "/home/jfg/caffe_tiny5/solver/caffenet_train_valid.prototxt"
snapshot_prefix: "/home/jfg/caffe_tiny5/model/caffenet"
net: it is your train_test.prototxt file postion, snapshot_prefix is your save model path and prefix name, we place all saved models into a model_snapshot folder with prefix cifar10.
训练
只需要一行命令:
bash train_caffe.sh
重点来了,得到模型之后怎么预测
这里我们使用python接口,直接上代码吧,实际上该的地方也不多:
# !/usr/bin/env python
# -*- coding: utf-8 -*-
"""
caffe_test.py
http://www.lewisjin.coding.me
~~~~~~~~~~~~~~~
This script implement by Jin Fagang.
: copyright: (c) 2017 Didi-Chuxing.
: license: Apache2.0, see LICENSE for more details.
"""
import numpy as np
import sys
import os
import cv2
caffe_root = '/home/jfg/caffe/'
sys.path.insert(0, caffe_root + 'python')
import caffe
net_file = '/home/jfg/Documents/PythonSpace/caffe_tiny5/solver/caffenet_deploy.prototxt'
caffe_model = '/home/jfg/Documents/PythonSpace/caffe_tiny5/solver/model/caffenet_iter_4500.caffemodel'
mean_file = '/home/jfg/Documents/PythonSpace/caffe_tiny5/data/caffe_mean.binaryproto'
print('Params loaded!')
caffe.set_mode_gpu()
net = caffe.Net(net_file,
caffe_model,
caffe.TEST)
mean_blob = caffe.proto.caffe_pb2.BlobProto()
mean_blob.ParseFromString(open(mean_file, 'rb').read())
mean_npy = caffe.io.blobproto_to_array(mean_blob)
a = mean_npy[0, :, 0, 0]
print(net.blobs['data'].data.shape)
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2, 0, 1))
transformer.set_mean('data', a)
transformer.set_raw_scale('data', 255.0)
transformer.set_channel_swap('data', (2, 1, 0))
test_img = 'elephant.jpeg'
im = caffe.io.load_image(test_img)
net.blobs['data'].data[...] = transformer.preprocess('data', im)
predict = net.forward()
names = []
with open('words.txt', 'r+') as f:
for l in f.readlines():
names.append(l.split(' ')[1].strip())
print(names)
prob = net.blobs['prob'].data[0].flatten()
print('prob: ', prob)
print('class: ', names[np.argmax(prob)])
img = cv2.imread(test_img)
cv2.imshow('Image', img)
cv2.waitKey(0)
OK,本教程到此结束,欢迎乘坐本次老司机列车。这几天一直没有更新博客不是没有写,而且写了没有上传,还是得发时间整理整理,笔耕不啜才是一代文豪应该做的事情啊。
近期计划
这是一个花絮,最近我还是决定干点事情了,接下来我会研究一下如何用目标检测算法来识别交通信号灯,这个在无人驾驶领域是肯定会遇到的一个问题,具体来说它有几个难点:
- 检测信号灯的位置
要检测信号灯就需要训练图片,标注信号灯的方框,这个好办,现有的网络可以做到很好,接下来有个问题就是第二个点。
- 检测信号等每个路口转向的信号等情况
比如我检测到了信号灯,但是这个信号灯是左转通行还是右转通行呢?是左转通行直行禁止右转禁止还是其他情况呢?而且我检测算法可能在一个视角中检测多个红绿灯,但是我真正感兴趣的只是我前方的红绿灯,那么如何来却分识别出来的红绿灯也是个问题。
这两个问题如何解决还得看数据标注的情况。
训练接口
网友评论