caffe建立一个分类网络

一、将自己的图片数据生成lmdb格式的数据(caffe可以接收的数据格式)
1、在caffe/data中建立文件夹 myself,在myself中建立子文件夹 train 和 val
2、在train文件夹中建立dog和bird文件夹,分别从网上下载50(数量不固定)张猫和50(数量不固定)张鸟存放在相应的文件夹下
3、命名图片为1.jpeg ……2.jpeg和 19.jpeg……50.jpeg。
jpg格式也是可以的,但是命名要按照顺序用数字命名,否则之后可能会报错。
命名好以后是这样子的:
狗的图片
4、重新下载10张猫和10张鸟存放在val文件夹下为测试用,并按照上面的方式命名 ,注意命名不要与上面的重复。
5、在myself文件夹下,创建train.txt,test.txt以及val.txt文件,最后的结构是这个样子的:
在这里插入图片描述
train.txt内容:
前面为路径,后面为标签

cat/cat1.jpeg 0
cat/cat2.jpeg 0
cat/cat50.jpeg 0
bird/bird1.jpeg 1
bird/bird2.jpeg 1
bird/bird50.jpeg 1

val.txt和test.txt的格式和train.txt一样,只是变换了路径。
6、在caffe/examples下创建myself文件夹存放一些网络搭建程序,将此目录下的imagenet的create_imagenet.sh复制到该文件夹下进行修改,主要修改添加注释的几个路径,运行该sh文件(目的是将之前设置好的猫和鸟数据生成相应的lmbd格式的数据)
create_imagenet.sh文件修改后为:

#!/usr/bin/env sh
# Create the imagenet lmdb inputs
# N.B. set the path to the imagenet train + val data dirs
set -e

EXAMPLE=/home/coco/caffe/examples/myself  #生成的lmdb数据的存放地址,注意后面无'/'
DATA=/home/coco/caffe/data/myself         #上面建立的myself文件夹的存放地址,注意后面无'/'
TOOLS=/home/coco/caffe/build/tools        #caffe路径下build.tools所在位置,注意后面无'/'

TRAIN_DATA_ROOT=/home/coco/caffe/data/myself/train/   #训练数据的存放地址,注意后面有'/'
VAL_DATA_ROOT=/home/coco/caffe/data/myself/val/       #校验数据的存放地址,注意后面有'/'

# Set RESIZE=true to resize the images to 256x256. Leave as false if images have
# already been resized using another tool.
#此处resize要改为true,让其自动缩放图片
RESIZE=true
if $RESIZE; then
  RESIZE_HEIGHT=256
  RESIZE_WIDTH=256
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/imagenet_train_lmdb1

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/imagenet_val_lmdb1

echo "Done."

运行

sh create_imagenet.sh

此时在caffe/examples/myself文件夹下会得到 imagenet_train_lmdb和imagenet_val_lmdb文件夹。
二、归一化
模型需要我们从每张图片减去均值,所以我们必须获得训练的均值,用tools/compute_image_mean.cpp实现,这个cpp是一个很好的例子去熟悉如何操作多个组件。直接复制imagenet的./make_imagenet_mean到caffe/examples/myself下进行修改即可。仍然是修改几个路径

#!/usr/bin/env sh
# Compute the mean image from the imagenet training lmdb
# N.B. this is available in data/ilsvrc12
#此三个路径与上面文件里的前三个路径一直,可以拷过来
EXAMPLE=/home/coco/caffe/examples/myself
DATA=/home/coco/caffe/data/myself
TOOLS=/home/coco/caffe/build/tools 

$TOOLS/compute_image_mean.bin $EXAMPLE/imagenet_train_lmdb \
  $DATA/imagenet_mean.binaryproto

echo "Done."

三、定义网络
这一部分比较简单,主要是修改一些路径即可
从/home/coco/caffe/models/bvlc_reference_caffenet文件夹下复制train_val.prototxt,solver.prototxt文件到examples/myself文件夹下,并进行路径的修改。
train_val.prototxt进行相关路径修改:

name: "CaffeNet"
layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mirror: true
    crop_size: 227
    #上面生成的均值文件所在位置
    mean_file: "/home/coco/caffe/data/myself/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
#  }
  data_param {
  #上面生成的训练mdb文件所在文件夹
    source: "/home/coco/caffe/examples/myself/imagenet_train_lmdb"
    batch_size: 256
    backend: LMDB
  }
}
layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    mirror: false
    crop_size: 227
    #均值文件所在位置
    mean_file: "/home/coco/caffe/data/myself/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: false
#  }
  data_param {
  #生成的测试mdb文件所在文件夹
    source: "/home/coco/caffe/examples/myself/imagenet_val_lmdb"
    batch_size: 50
    backend: LMDB
  }

Solver.prototxt的内容如下:

//网络结构文件位置
net: "/home/coco/caffe/examples/myself/train_val.prototxt" 
//测试次数,test_iter*测试阶段的batchsize=总的测试图片数,batchsize在train_val里
test_iter: 1000 
//为网络训练多少代,进行一次测试
test_interval: 1000 
//基础学习率
base_lr: 0.01 
//学习率随训练变化
lr_policy: "step" 
gamma: 0.1 
stepsize: 100000 
display: 20 
//最大迭代次数
max_iter: 450000 
//表示上一次梯度更新的权重
momentum: 0.9 
//表示权重衰减,防止过拟合
weight_decay: 0.0005 
snapshot: 10000 
//中间结果,以及停止训练时的结果存放位置
snapshot_prefix: "/home/coco/caffe/examples/myself/snapshot"  //快照的存放地址
solver_mode: GPU

四、训练
在myself文件夹下编写train_mynet.sh文件,或者把imagenet下的train_caffe.sh拷过来更改,内容如下:

#!/usr/bin/env sh
set -e

/home/coco/caffe/build/tools/caffe train \
    --solver=/home/coco/caffe/examples/myself/solver.prototxt $@

运行此sh文件。由于样本量很小,理论上很短的时间内就可以收敛。可能是caffe没有收敛的功能,最终会迭代到最大的迭代次数才可以结束整个训练过程。观察test过程中accuarucy很早就已经为1了,所以最大的迭代次数可以不必设置成很大的值。
四 、测试
在caffe/examples/myself/testtxt文件夹下已经写好了所有的需要测试的文件,文件目录如下:
在这里插入图片描述
1.deploy.prototxt文件编写
直接从models文件夹里面考过来,更改一些小细节

layer { 
  name: "fc8" 
  type: "InnerProduct" 
  bottom: "fc7" 
  top: "fc8" 
  inner_product_param { 
    num_output: 2 //需要更改的地方,输出的分类数量是2,因为此时我们只有两类鸟和狗
  } 

2、Mynet.caffemodel
caffe模型,存放的是一些模型的参数,直接用之前训练过程结果即可。复制粘贴过来并改名称。
3、mynetmean.npy均值文件,用来对测试数据去均值的,可以加快测试的速度。
该文件是从caffe/data/myself/imagenet_mean.binary文件转化过来的,转化的方法是:
终端输入:

python pychang.py

pychang.py是写好的python格式的转化工具 。
其实,这个文件不用也没有太大影响
4、word.txt文件,是分类文件,里面保存了分的类别数,内容如下:

0 cat
1 bird

5、py-classify.py是python版本的最终用来执行的分类文件
文件里面的一些内容主要是依托前面写的文件内容如下:
主要更改路径,以及分类数目

#coding=utf-8
#加载必要的库
import numpy as np

import sys,os

#设置当前目录
caffe_root = '/home/coco/caffe/' 
sys.path.insert(0, caffe_root + 'python')
import caffe
os.chdir(caffe_root)

net_file=caffe_root + 'examples/myself/testtxt/deploy.prototxt'
caffe_model=caffe_root + 'examples/myself/testtxt/Mynet.caffemodel'
mean_file=caffe_root + 'examples/myself/testtxt/mynetmean.npy'

#创建神经网络,加载模型文件
net = caffe.Net(net_file,caffe_model,caffe.TEST)
#指定caffe数据转换器data的shape等于神经网络data层shape
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
#指定交换维度,caffe读取的图片是H*W*C,交换后变成C*H*W
transformer.set_transpose('data', (2,0,1))
#指定减去均值,np.load(mean_file)返回数据格式channel0数据:channel1数据:channel2数据
#mean(1).mean(1)返回每个通道的均值
#此句可以注释掉,不用也没有太大影响
transformer.set_mean('data', np.load(mean_file).mean(1).mean(1))
#这里是将图像数据变成(0,255),注释掉该行代码表示使用(0,1)的数据
transformer.set_raw_scale('data', 255) 
#caffe.io.load_image()读进来是RGB格式和(0,1)(float)
#cv2.imread()读进来直接是BGR格式和(0,255)
#这里是将RGB变换到BGR
transformer.set_channel_swap('data', (2,1,0))
#这里表示你要测试的图片的地址
im=caffe.io.load_image(caffe_root+'data/myself/train/bird/bird19.jpeg')
#转换器转换数据,并赋值给net的data层
net.blobs['data'].data[...] = transformer.preprocess('data',im)
out = net.forward()


imagenet_labels_filename = caffe_root + 'examples/myself/testtxt/word.txt'
labels = np.loadtxt(imagenet_labels_filename, str, delimiter='\t')
#[-1:-3:-1],中间的数字就是分类数加一取反
top_k = net.blobs['prob'].data[0].flatten().argsort()[-1:-3:-1]
for i in np.arange(top_k.size):
    print top_k[i], labels[top_k[i]]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值