1. 数据准备
(1)样本
(2) train
(3) val
(4) test
(5)生成样本list
在train/0目录下,命令行执行:
在train/1目录下,命令行执行:
然后,将train.txt在Notepad++中用替换的方式,在前面补上上层路径“0/”和“1/”:
改成如下样式:
val.txt也用这种方式生成。
最终,准备好以下内容:
2.数据格式转换
create_imagenet.sh
特别注意路径,该脚本还实现了resize的功能,将每张图片resize为256×256大小的图片。
我的原图是行人,宽高比比较大,感觉Resize256x256形变太大,我就Resize成256x512,注意resize之后的宽高要大于227。
#!/usr/bin/env sh
# Create the imagenet lmdb inputs
# N.B. set the path to the imagenet train + val data dirs
set -e
EXAMPLE=examples/myAxlenetUniform
DATA=data/myAxlenetUniform
TOOLS=build/tools
TRAIN_DATA_ROOT=data/myAxlenetUniform/train/
VAL_DATA_ROOT=data/myAxlenetUniform/val/
# Set RESIZE=true to resize the images to 256x256. Leave as false if images have
# already been resized using another tool.
RESIZE=true
if $RESIZE; then
RESIZE_HEIGHT=256
#RESIZE_WIDTH=256
RESIZE_WIDTH=64
else
RESIZE_HEIGHT=0
RESIZE_WIDTH=0
fi
if [ ! -d "$TRAIN_DATA_ROOT" ]; then
echo "Error: TRAIN_DATA_ROOT is not a path to a directory: $TRAIN_DATA_ROOT"
echo "Set the TRAIN_DATA_ROOT variable in create_imagenet.sh to the path" \
"where the ImageNet training data is stored."
exit 1
fi
if [ ! -d "$VAL_DATA_ROOT" ]; then
echo "Error: VAL_DATA_ROOT is not a path to a directory: $VAL_DATA_ROOT"
echo "Set the VAL_DATA_ROOT variable in create_imagenet.sh to the path" \
"where the ImageNet validation data is stored."
exit 1
fi
echo "Creating train lmdb..."
GLOG_logtostderr=1 $TOOLS/convert_imageset \
--resize_height=$RESIZE_HEIGHT \
--resize_width=$RESIZE_WIDTH \
--shuffle \
$TRAIN_DATA_ROOT \
$DATA/train.txt \
$EXAMPLE/myAxlenetUniform_train_lmdb
echo "Creating val lmdb..."
GLOG_logtostderr=1 $TOOLS/convert_imageset \
--resize_height=$RESIZE_HEIGHT \
--resize_width=$RESIZE_WIDTH \
--shuffle \
$VAL_DATA_ROOT \
$DATA/val.txt \
$EXAMPLE/myAxlenetUniform_val_lmdb
echo "Done."
执行后得到myAxlenetUniform_train_lmdb 和 myAxlenetUniform_val_lmdb:
3.计算图像均值,生成均值文件。
make_imagenet_mean.sh
#!/usr/bin/env sh
# Compute the mean image from the imagenet training lmdb
# N.B. this is available in data/ilsvrc12
EXAMPLE=examples/myAxlenetUniform
DATA=data/myAxlenetUniform
TOOLS=build/tools
$TOOLS/compute_image_mean $EXAMPLE/myAxlenetUniform_train_lmdb \
$DATA/myAxlenetUniform_mean.binaryproto
echo "Done."
执行完得到均值文件:myAxlenetUniform_mean.binaryproto
4. 训练
(1)设置网络和solver
从caffe\models\bvlc_alexnet路径下copy过来的,然后再修改一下路径
train_val.prototxt中前面的路径修改一下,另外最后的num_output修改一下,修改成类别个数。
(2) 开始训练
exbot@exbot:~/caffe$ sudo build/tools/caffe train --solver=models/myAxlenetUniform/solver.prototxt
(3)训练过程的一些log
(4)训练结束
我都是晚上睡觉时候让它跑着训练,所以也没认真看它倒地训练了多久,看log打印的时间应该大约是19:00~~01:00,可以作为参考。
得到训练模型:
不知道为什么我之前训练时候正常,这次训练时候,生成的模型名称不完整,如下,不过只是个名称而已,没太大影响,就没有深究,手动补充完整了。
5.测试
(1)使用caffe.bin test评估训练好的模型。
exbot@exbot:~/caffe$ ./build/tools/caffe.bin
执行caffe.bin可以看到一下信息,train用来训练,test用来评估训练好的模型,time评估模型执行时间,等等,具体使用自己百度一下caffe.bin即可明了。
这里我只使用了caffe.bin test命令来评估模型:
exbot@exbot:~/caffe$ ./build/tools/caffe.bin test --model=models/myAxlenetUniform/train_val.prototxt --weights=models/myAxlenetUniform/myAxlenetUniform_iter_60000.caffemodel
–iterations参数我这里缺省了,默认是50?
执行完可以看着如下log,可以看到最后的结果和训练结束的loss、accuracy值是一样的,我认为这一步的作用之一,就是能让我们更直观的看到这么模型的评估结果(loss、accuracy),并非必须的步骤。
(2)用图片进行测试
首先:将均值文件bin转换成npy格式
bin2npy.py
#encoding=utf8
import caffe
import numpy as np
MEAN_PROTO_PATH = 'myAxlenetUniform_mean.binaryproto'
MEAN_NPY_PATH = 'myAxlenetUniform_mean.npy'
blob = caffe.proto.caffe_pb2.BlobProto()
data = open(MEAN_PROTO_PATH, 'rb' ).read()
blob.ParseFromString(data)
array = np.array(caffe.io.blobproto_to_array(blob))
mean_npy = array[0]
np.save(MEAN_NPY_PATH ,mean_npy)
均值文件所在目录下执行,得到npy格式的均值文件:
测试代码:
test.py 注意确认几个路径是否正确。
#encoding=utf8
import sys
sys.path.append('./python')
sys.path.append('./python/caffe')
import caffe
import numpy as np
import cv2
import argparse
import matplotlib.pyplot as plt
color = {'common':'0', 'uniform':'1'}
#root = '×××/caffe/'
caffe_model = '/home/exbot/caffe/models/myAxlenetUniform/myAxlenetUniform_iter_60000.caffemodel'
deploy = '/home/exbot/caffe/models/myAxlenetUniform/deploy.prototxt'
mean_file= '/home/exbot/caffe/data/myAxlenetUniform/myAxlenetUniform_mean.npy' #mean.npy
def classifier(img, net):
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2,0,1))
transformer.set_mean('data', np.load(mean_file).mean(1).mean(1))
# transformer.set_raw_scale('data', 255)
# transformer.set_channel_swap('data', (2,1,0))
net.blobs['data'].data[...]= transformer.preprocess('data',img)
out = net.forward()
prob = out['prob']
print prob
return np.argmax(prob)
if __name__ == '__main__':
testList = open('/home/exbot/caffe/data/myAxlenetUniform/test_all.txt', 'r')
caffe.set_mode_gpu()
caffe.set_device(0)
net = caffe.Net(deploy, caffe_model, caffe.TEST)
count = 0
for line in testList:
imagePath = line.split()[0]
label = line.split()[1]
path = '/home/exbot/caffe/data/myAxlenetUniform/test/'+imagePath
img = cv2.imread(path)
print 'path:'+path
#plt.imshow(img)
#plt.axis('on')
#plt.show()
result = classifier(img, net)
print '-------------------------------'
#plt.imshow(img)
#plt.axis('off')
#plt.show()
print 'result:{}'.format(str(result))
print 'label:{}'.format(str(label))
print '-------------------------------'
if result == int(label):
count = count+1
Precession = count*1.0/139 #test pic num.test_0=68,test_1=71,test_all=139
print 'Precession is {}'.format(str(Precession))
其中test_all.txt这个文件是我自己创建的,用来一次性测多个图片,每张图片的测试结果和label比较,用于统计准确率的。
test_all.txt里面放了139张测试图片的list。
执行测试程序:
exbot@exbot:~/caffe$ python examples/myAxlenetUniform/alexnetTest.py
一些log,测试了139张图片,统计出来准确率0.877。
你也可以修改test_all.txt图片list,只测试label 0的图片,或者只测试label 1 的图片,或者只测试一张图片,记得test.py中相应的修改图片个数。