您的位置:首页 > Web前端

自己的数据在caffe上训练识别遇到的问题及解决方案

2017-05-29 16:45 423 查看
网上有很多教程,文中的源码大多都是借用别人的,但在自动动手做的时候出现了很多问题,自己查了很多资料,把相关问题记录下,给新手的你一些启示:

如果你是第一次使用caffemodel,建议你参考

http://www.cnblogs.com/denny402/p/5111018.html这个博客,它使用了caffe里自带的生成模型来识别,在caffe/examples/images的目录下,有一张自带的cat.jpg,可以使用上面博客中的代码跑一下,大概了解下流程。

在此之后,我们来系统的构架下用自己数据训练识别的过程:

1. 建数据两个分别是train 和val两个文件夹在,space是自建的他们两个的上层目录,下同,并在train中按类放好你的训练数据,而val中的则不用分类存放

2. 生成val 和 train路径文档。我找到另一个博客(地址实在找不到了,先谢过这位客主大神)找到一个写的很精悍的编译代码

这里注意下路径问题:很多人说caffe里面的程序是要在主目录下运行,其实哪里运行都没关系,只要你写程序的时候注意就行。比如这个程序要在你train目录中运行才行。后执行sudo python train.py即可生成train.txt,同里生成val.txt

import os
#将其保存为train.py
root = os.getcwd()
data = 'train'
path = os.listdir(root+'/'+ data)
path.sort()
file = open('train.txt','w')

i = 0

for line in path:
str = root+'/'+ data +'/'+line
for child in os.listdir(str):
str1 = data+'/'+line+'/'+child;
d = ' %s' %(i)
t = str1 + d
file.write(t +'\n')
i=i+1

file.close()


3 将train和val生成lmdb格式的数据,因为在caffe网络训练时只认识这种格式的数据。进行转化的脚本文件在caffe中自带有,根据自己需要的进行修下即可

这里的坑就是:最容易出现的问题是No such file or directory,这个问题的出现肯定是路径问题。比如下面的程序必需要在主目下即caffe/目录下执行才不会错,其他目录是找不到的。如果相在其加目录下都能执行,只需要加上全路径或绝对路径,比如EXAMPLE=/home/xxx/caffe/examples/myself即可。

执行sudo python mk_lmdb.py生成space_val_lmdb。

#!/usr/bin/env sh
# Create the imagenet lmdb inputs
# N.B. set the path to the imagenet train + val data dirs
set -e
#将该程序存为mk_lmdb.py
EXAMPLE=examples/myself
DATA=data/space
TOOLS=build/tools

#TRAIN_DATA_ROOT=data/space/
VAL_DATA_ROOT=data/space/

# Set RESIZE=true to resize the images to 256x256. Leave as false if images have
# already been resized using another tool.
RESIZE=false
if $RESIZE; then
RESIZE_HEIGHT=256
RESIZE_WIDTH=256
else
RESIZE_HEIGHT=0
RESI
b81f
ZE_WIDTH=0
fi

if [ ! -d "$VAL_DATA_ROOT" ]; then
echo "Error: VAL_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

echo "Creating train lmdb..."

GLOG_logtostderr=1 $TOOLS/convert_imageset \
--resize_height=$RESIZE_HEIGHT \
--resize_width=$RESIZE_WIDTH \
--shuffle \
$VAL_DATA_ROOT \
$DATA/val.txt \
$EXAMPLE/space_val_lmdb

echo "Done."


4 再将上面生成lmdb转化成二进制文件,代码如下:

这些源代码都在caffe/build/tools下

注意路径,最后生成imagenet_mean.binaryproto文件

#!/usr/bin/env sh
# Compute the mean image from the imagenet training lmdb
# N.B. this is available in data/ilsvrc12

EXAMPLE=examples/myself
DATA=data/space
TOOLS=build/tools

$TOOLS/compute_image_mean $EXAMPLE/space_train_lmdb \
$DATA/imagenet_mean.binaryproto

echo "Done."


5.再python中最后训练网络要中要将其转化为.npy格式的均值文件才行。源代码来自

http://blog.csdn.net/may0324/article/details/52316967

import numpy as np
import caffe
import sys

blob = caffe.proto.caffe_pb2.BlobProto()
data = open( 'mean.binaryproto' , 'rb' ).read()
blob.ParseFromString(data)
arr = np.array( caffe.io.blobproto_to_array(blob) )
out = arr[0]
np.save( 'mean.npy' , out )


6 最后要进行训练,生成我要所需要的caffemodel文件,要完成这一件事需要三个文件。Alenet.prototxt(自己定义的网络模型,这个模型都是参考)caffe/model/train_val.protxt而来的,可以对其进行简单的修改即可变成自己想用的。

solver.prototxt学习率,秩代次数等相关参数的定义。

make_imagenet_mean.sh一个简单的脚本用来生成caffemodel,代码如下:

#!/usr/bin/env sh
# Compute the mean image from the imagenet training lmdb
# N.B. this is available in data/ilsvrc12

EXAMPLE=examples/myself
DATA=data/space
TOOLS=build/tools

$TOOLS/compute_image_mean $EXAMPLE/space_train_lmdb \
$DATA/imagenet_mean.binaryproto

echo "Done."


最后就可生成caffemodel.

7 进行预测

这里你很可能用网上的代码做预测是碰到一个问题,对于简单的分类,输出的结果是错的,预测的结果总是第一类,其他类很少能预测到,而且很可能会报如下的错。

File “./python/caffe/classifier.py”, line 29, in init

in_ = self.inputs[0]

IndexError: list index out of range

有个大神提及了下,一下了懂了害我一整天的问题www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&tn=ubuntuu_cb&wd=csdn博客&oq=%25E5%258D%259A%25E5%25AE%25A2&rsv_pq=a24cc55e0001693e&rsv_t=a9e5xsLxj6lMEgEo%2Fed86gN9RGGWkKFBLBLrOdmw0lbCbS1Py92Y0GJ9qhSvAYAEmQ&rqlang=cn&rsv_enter=1&rsv_sug3=5&rsv_sug1=5&rsv_sug7=100&rsv_sug2=1&prefixsug=cs%25E5%258D%259A%25E5%25AE%25A2&rsp=0&inputT=2598&rsv_sug4=5597

如果你也碰到这个问题的话,那你幸运啦。其实很简单,你训练的时候用的Alenet.prototxt和预测时要用的my.protxt(自己新建的)是不一样的。

前一个的输入是

ame: "CaffeNet"
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
mirror: true
crop_size: 227
mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"
}
# mean pixel / channel-wise mean instead of mean image
#  transform_param {
#    crop_size: 227
#    mean_value: 104
#    mean_value: 117
#    mean_value: 123
#    mirror: true
#  }
......


而后一个预测用的my.prototxt是输入数据是这样的

name: "mAlexNet"
input: "data"
input_shape {
dim: 1000
dim: 3
dim: 224
dim: 224
}


这里参数根据自己需要修改下。总之也们的data层是不样的,其他都一样,这样就不会报上述的错误。

由于我做的是二分类,网上找了很多程序,但最后输入的结果是两种样本输入只输出第一类。这个问题提到的很少,http://blog.csdn.net/wadqse123/article/details/44750561中提到了,对于少分类分类不准的问题终于解决了。

在解决前我们先看个网络定义的两种方式:

这两Classifier的源码定义,其中做预测的时候会用到,目前网上最多的 是后一种,相对简单,我在这里之所以提出来是因为,只是第一种才能有效解决分类不种的问题。

def __init__(self, model_file, pretrained_file, image_dims=None,
mean=None, input_scale=None, raw_scale=None,
channel_swap=None):
caffe.Net.__init__(self, model_file, pretrained_file, caffe.TEST)


最后做预测的完整代码如下:

#!/usr/bin/python
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
root ='/home/lab/caffe1/caffe/'
import sys
#sys.path.insert(0,caffe_root+'python')
import caffe

deploy=root + 'examples/myself/mCNN.prototxt'
caffe_model=root + 'examples/myself_iter_400.caffemodel'
img=root+'examples/images/8.jpg'

import os
net = caffe.Classifier(deploy, caffe_model,mean=np.load(root + 'data/space/mean.npy'),channel_swap=(2,1,0),raw_scale=255,image_dims=(224, 224))
img=filelist[i]   #获取当前图片的路径
print filenames[i]    #打印当前图片的名称
input_image=caffe.io.load_image(img)
prediction = net.predict([input_image])
print 'prediction shape:', prediction[0].shape
print 'predicted class:', prediction[0].argmax()


至于整个过程就完成了,我所遇到其本上问题就这些了。祝好运!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: