开源节流

欢迎交流评论留言,有不到之处请指教。

【深度学习】使用caffeNet训练自己的数据集(caffe框架)

主要参考:官方网址:http://caffe.berkeleyvision.org/gathered/examples/imagenet.html
数据集及第一部分参考网址:http://www.lxway.com/4010652262.htm

主要步骤:

1. 准备数据集
2. 标记数据集
3. 创建lmdb格式的数据
4. 计算均值
5. 设置网络及求解器
6. 运行求解
由于imagenet的数据集太大,博主电脑显卡840m太弱,所以就选择了第二个网址中的数据集 http://pan.baidu.com/s/1o60802I ,其训练集为1000张10类图片,验证集为200张图片,原作者已经整理好其标签放于对应的txt文件中,所以这里就省去上面的1-2步骤。

PS 主要步骤:

备注:具有GPU运算能力

【实验目标】

使用自己的图片集,以及caffe框架,对imagenet进行训练,得到自己的model。

【前期准备】

1.      安装并配置caffe环境

【实验过程】

1.      数据集准备

获取训练图片集与验证图片集,并产生train.txt与val.txt,内容为图片路径与分类标签;将图片进行大小重设,设置为256*256大小;使用create_imagenet.sh脚本将2组图片集转换为lmbp格式。

2.      计算图像均值

使用make_imagenet_mean.sh计算图像均值,产生imagenet_mean.binaryproto文件。

3.      设置网络参数

拷贝caffe-master/model/bvlc_reference_caffenet中的文件,修改train_val.prototxt,solver.prototxt中的运行参数,并进行路径的修改;拷贝caffe_master/examples/imagenet中的train_caffnet.sh文件,对路径进行修改。

4.      运行train_caffnet.sh

【实验过程详细版】

备注一下目录的情况,这样比较调理啦:

Caffe根目录:caffe_root=/home/james/caffe/

图片类数据:caffe_root/data/mydata

命令参数类数据:caffe_root/examples/mytask

注:默认我们手动添加的除图片以及.txt之外的文件都属于命令参数类数据,运行的时候注意路径就好,另外,我门在实验的时候换了别人的电脑,因此存在caffe根路径前后不一致的状况,大家注意一下就好。

利用Caffe创建自己的lmdb数据集

参考https://blog.csdn.net/sinat_34474705/article/details/77101661

有时候我们还需要创建自己的数据集进行训练。本篇博客讲的就是如何利用Caffe中的模块创建自己lmdb数据集。

1数据集准备

我们需要自己准备好带类别标签的图片数据,并将数据统一命名,这里为了方便,我直接从CIFAR10训练集中拿出5000张图片用于制作验证集,图片为.png格式,并采用‘图片编号_类别标签.png’的命名方式(这个实现起来应该不难,这里就不赘述了),保存在一个文件夹下,部分例子如下: 


train_valid

创建图片名列表清单

这里我们需要创建一个txt文本用来存放所有图片的信息,文本中每行存放一个样本,内容包括图片名和类别标签信息,中间用空格分开。这个实现方法很多,这里我给出一个用python实现的方法:

import os
def create_image_list(file_path,txtpath):
    """
    Create a list of all images and save to a '.txt' file, each image is 
    named as'num_label.png'. For example: 1001_2.png
    Inputs:
    file_path: path of image file
    txtpath: '.txt' file used to save all images' names and labels
    Return: none
    """
    # remove the old list file
    if os.path.isfile(txtpath):
        os.remove(txtpath)

    # get the name list of all images 
    image_name_list = os.listdir(file_path)

    # save the names and labels of all images to the '.txt' file named 'txtname'
    with open(txtpath,'a') as f:
        print 'saving to '+txtpath+'...'
        for image_name in image_name_list:
            image_label = image_name.split('_')[1].split('.')[0]
            image_data = image_name+' '+image_label
            f.write(image_data+'\n')
        print 'done.'  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

注意:代码中输入参数的路径都是绝对路径,当然如果感觉用绝对路径麻烦也该以稍微改动一下变成相对路径。 
自己写代码调用上面这个函数,就可以生成下面的txt文本: 


train_valid_txt 


1、准备数据

首先很重要的一点,我们需要准备若干种不同类型的图片进行分类。这里我选择从ImageNet上下载了3个分类的图片(Cat,Dog,Fish)。

图片需要分两批:训练集(train)、测试集(test),一般训练集与测试集的比例大概是5:1以上,此外每个分类的图片也不能太少,我这里每个分类大概选了5000张训练图+1000张测试图。

找好图片以后,需要准备以下文件:

words.txt:分类序号与分类对应关系(注意:要从0开始标注

0 cat
1 dog
2 fish

 

train.txt:标明训练图片路径及其对应分类,路径和分类序号直接用空格分隔,最好随机打乱一下图片

复制代码
/opt/caffe/examples/my_simple_image/data/cat_train/n02123045_4416.JPEG 0
/opt/caffe/examples/my_simple_image/data/cat_train/n02123045_3568.JPEG 0
/opt/caffe/examples/my_simple_image/data/fish_train/n02512053_4451.JPEG 2
/opt/caffe/examples/my_simple_image/data/cat_train/n02123045_3179.JPEG 0
/opt/caffe/examples/my_simple_image/data/cat_train/n02123045_6956.JPEG 0
/opt/caffe/examples/my_simple_image/data/cat_train/n02123045_10143.JPEG 0
......
复制代码

 

val.txt:标明测试图片路径及其对应分类

/opt/caffe/examples/my_simple_image/data/dog_val/n02084071_12307.JPEG 1
/opt/caffe/examples/my_simple_image/data/dog_val/n02084071_10619.JPEG 1
/opt/caffe/examples/my_simple_image/data/cat_val/n02123045_13360.JPEG 0
/opt/caffe/examples/my_simple_image/data/cat_val/n02123045_13060.JPEG 0
/opt/caffe/examples/my_simple_image/data/cat_val/n02123045_11859.JPEG 0
......

 

1.      数据集准备

a.      准备训练图片集以及验证图片集

新建caffe_root/data/mydata,分别将图片集放置于caffe_root/data/mydata/train与caffe_root/data/mydata/val下面

b.      准备图片清单

在caffe_root/data/mydata下面新建两个文件train.txt与val.txt,train.txt中的内容为:

       1.jpg 7

       2.jpg7

       3.jpg 7

       …

以上格式为图片名称+空格+类标(数字)的格式,val.txt的格式也是一样的(同样需要类标)。

此步可以使用create_filelist.sh进行批量添加图片路径至train.txt。create_filelist.sh内容需要按照自身图片的名称与类标情况进行修改,并持续运行(因为是在文件后面追加)内容如下:

 

#!/usr/bin/env sh

#!/bin/bash

DATA=/home/james/caffe/data/mydata/val

MY=/home/james/caffe/data/mydata

 

for i in {3122..3221}

do

echo $i.jpg 3 >> $MY/val.txt

done

 

echo "All done"

 

以上命令意思是,在val文件夹下面的图片中,名称为3122.jpg至3221.jpg的图片都是第3类,因此就会在val.txt写入:

        3122.jpg 3

        3123.jpg 3

        …

注意:此时可能会报出bad loop variable的错误,这是由于Ubuntu bash的版本的原因,可以自行查看如何解决。

c.      调整图片大小至256*256

因为之前没有仔细看caffe的相关文件,后来才知道可以使用之自动调整大小,因此此步采用的是自己调用命令进行调整大小。如果不调整图片大小的话,在运行后面命令的时候是会报错的。

   可以使用convert256.sh进行转换。注意,该命令中用到了imagemagick工具,因此如果自己没有安装的话,还需要安装该工具(命令为:sudo apt-get install imagemagick)。convert256.sh内容如下:

 

for name in/home/james/caffe/data/mydata/train/*.jpg; do

convert -resize 256x256\! $name $name

done


生成lmdb文件

这里我们用到的是Caffe下自带的convert_imageset可执行文件,如果你已经成功编译Caffe,这个文件应该在caffe-master/build/tools/下。要用这个可执行文件,我们需要提供三个路径,分别是原始图片数据存放路径、图片列表清单路径(就是之前生成的txt文本路径)和生成的lmdb文件存放路径,这里给出我之前转化数据集时用的脚本:

#!/bin/bash
# convert images to lmdb

DATA=/home/meringue/DataBase/cifar-10-batches-py
IMGDIRNAME=train_valid
IMGLIST=img_name_list/train_valid.txt
LMDBNAME=train_valid_lmdb

rm -rf $DATA/$LMDBNAME
echo 'converting images...'
/home/meringue/Softwares/caffe-master/build/tools/convert_imageset --shuffle=true \
$DATA/$IMGDIRNAME/ $DATA/$IMGLIST $DATA/$LMDBNAME
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

上面代码中的参数shuffle=true表示打乱数据,还有很多其他参数设置可以在caffe-master/tools/convert_imageset.cpp中查看。 
转化速度很快,运行结束后,我们可以在程序中指定的lmdb路径下看到类似下面的文件: 


train_train_valid_lmdb 

为了保险起见,最好看一下data.mdb这个文件的大小,当你的数据比较大的时候,这个文件也因该很大。如果发现data.mdb很小,说明转化的时候出现了问题,回去检查一下。一般我们最后需要给lmdb数据添加可读权限,可以通过linux下sudo chmod 777 -R ./PATH 获取所有权限。否则有时候程序调用会出现类似没有权限的错误。

1.1 创建lmdb

使用对应的数据集创建lmdb:
这里使用 examples/imagenet/create_imagenet.sh,需要更改其路径和尺寸设置的选项,为了减小更改的数目,这里并没有自己新创建一个文件夹,而是直接使用了原来的imagenet的文件夹,而且将train.txt,val.txt都放置于/data/ilsvrc12中,

TRAIN_DATA_ROOT=/home/beatree/caffe-rc3/examples/imagenet/train/
VAL_DATA_ROOT=/home/beatree/caffe-rc3/examples/imagenet/val/

RESIZE=true

注意下面的地址的含义:

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

主要用了tools里的convert_imageset


2、生成lmdb文件

lmdb是caffe使用的一种输入数据格式,相当于我们把图片及其分类重新整合一下,变成一个数据库输给caffe训练。

这里我们使用caffenet的create_imagenet.sh文件修改,主要是重新指定一下路径:

复制代码
EXAMPLE=examples/my_simple_image/
DATA=examples/my_simple_image/data/
TOOLS=build/tools

TRAIN_DATA_ROOT=/
VAL_DATA_ROOT=/

# 这里我们打开resize,需要把所有图片尺寸统一
RESIZE=true
if $RESIZE; then
  RESIZE_HEIGHT=256
  RESIZE_WIDTH=256
else
  RESIZE_HEIGHT=0
  RESIZE_WIDTH=0
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/ilsvrc12_train_lmdb  #生成的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/ilsvrc12_val_lmdb    #生成的lmdb路径
echo "Done."
复制代码

 

d.      构建图片数据库

要让Caffe进行图片的训练,必须有图片数据库,并且也是使用其作为输入,而非直接使用图片作为输入。使用create_imagenet.sh脚本将train与val的2组图片集转换为lmbp格式。create_imagenet.sh内容如下:

 

#!/usr/bin/env sh

# Create the imagenet lmdb inputs

# N.B. set the path to the imagenet train +val data dirs

 

EXAMPLE=/home/james/caffe/examples/mytask

DATA=/home/james/caffe/data/mydata

TOOLS=/home/james/caffe/build/tools

 

TRAIN_DATA_ROOT=/home/james/caffe/data/mydata/train/

VAL_DATA_ROOT=/home/james/caffe/data/mydata/val/

 

# Set RESIZE=true to resize the images to256x256. 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

 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 thepath" \

      "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 thepath" \

      "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/ilsvrc12_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/ilsvrc12_val_lmdb

 

echo "Done."

 

注:将其中的地址均修改为自己的对应地址,不是地址的就不要强行修改啦。


1.2 计算均值

模型需要我们从每张图片减去均值,所以我们需要获得训练的均值,直接利用./examples/imagenet/make_imagenet_mean.sh创建均值文件binaryproto,如果之前创建了新的路径,这里同样需要修改sh文件里的路径。
这里的主要语句是

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

如果显示Check failed: size_in_datum == data_size () Incorrect data field size说明上一步的图片没有统一尺寸


3、生成mean_file

下面我们用lmdb生成mean_file,用于训练(具体做啥用的我还没研究。。。)

这里也是用imagenet例子的脚本:

复制代码
EXAMPLE=examples/my_simple_image
DATA=examples/my_simple_image
TOOLS=build/tools

$TOOLS/compute_image_mean $EXAMPLE/ilsvrc12_train_lmdb $DATA/imagenet_mean.binaryproto

echo "Done."
复制代码

 

2.      计算图像均值

据说计算图像均值之后的训练效果会更好,使用make_imagenet_mean.sh计算图像均值,产生imagenet_mean.binaryproto文件。make_imagenet_mean.sh文件内容如下:

 

#!/usr/bin/env sh

# Compute the mean image from the imagenettraining lmdb

# N.B. this is available in data/ilsvrc12

 

EXAMPLE=/home/james/caffe/examples/mytask

DATA=/home/james/caffe/data/mydata/

TOOLS=/home/james/caffe/build/tools

 

TOOLS/computeimagemeanTOOLS/computeimagemeanEXAMPLE/ilsvrc12_train_lmdb \

  $DATA/imagenet_mean.binaryproto

 

echo "Done." 

注:将其中的地址修改为自己的地址,并且产生的imagenet_mean.binaryproto文件在data/mydata文件夹下,稍后设置的时候注意该路径。

1.3 设置网络及求解器

这里是利用原文的网络设置tain_val.prototxt和slover.prototext,在models/bvlc_reference_caffenet/solver.prototxt路径中,这里的训练和验证的网络基本一样用 include { phase: TRAIN } or include { phase: TEST }和来区分,其两点不同之处具体为:

transform_param {
mirror: true#不同1:训练集会randomly mirrors the input image
crop_size: 227
mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"
}
data_param {
source: "examples/imagenet/ilsvrc12_train_lmdb"#不同2:来源不同
batch_size: 32#原文很大,显卡比较弱的会内存不足,这里改为了32,这里根据需要更改,验证集和训练集的设置也不一样
backend: LMDB
}

另外在输出层也有不同,训练时的loss需要用来进行反向传递,而val就不需要了。
solver.protxt的改动:
根据

net: "/home/beatree/caffe-rc3/examples/imagenet/train_val.prototxt"#网络配置存放地址
test_iter: 4, 每个批次是50,一共200个
test_interval: 300 #每300次测试一次
base_lr: 0.01 #是基础学习率,因为数据量小,0.01 就会下降太快了,因此可以改成 0.001,这里博主没有改
lr_policy: "step" #lr可以变化
gamma: 0.1 #学习率变化的比率
stepsize: 300
display: 20 #20层显示一次
max_iter: 1200 一共迭代1200次
momentum: 0.9
weight_decay: 0.0005
snapshot: 600 #每600存一个状态
snapshot_prefix: "/home/beatree/caffe-rc3/examples/imagenet/"#状态存放地址

4、修改solver、train_val配置文件

这里我们可以选用cifar的网络,也可以用imagenet的网络,不过后者的网络结构更复杂一些,为了学习,我们就用cifar的网络来改。

把cifar的两个配置文件拷过来:

cifar10_quick_solver.prototxt
cifar10_quick_train_test.prototxt

首先修改cifar10_quick_train_test.prototxt的路径以及输出层数量(标注出黑体的部分):

复制代码
name: "CIFAR10_quick"
layer {
  name: "cifar"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mean_file: "examples/my_simple_image/imagenet_mean.binaryproto"
  }
  data_param {
source: "examples/my_simple_image/ilsvrc12_train_lmdb" batch_size: 50 #一次训练的图片数量,一般指定50也够了 backend: LMDB } } layer { name: "cifar" type: "Data" top: "data" top: "label" include { phase: TEST } transform_param { mean_file: "examples/my_simple_image/imagenet_mean.binaryproto" } data_param { source: "examples/my_simple_image/ilsvrc12_val_lmdb" batch_size: 50 #一次训练的图片数量 backend: LMDB } }
..........
layer { name: "ip2" type: "InnerProduct" bottom: "ip1" top: "ip2" .......... inner_product_param { num_output: 3 #输出层数量,就是你要分类的个数 weight_filler { type: "gaussian" std: 0.1 } bias_filler { type: "constant" } } } ......
复制代码

 

cifar10_quick_solver.prototxt的修改根据自己的实际需要:

复制代码
net: "examples/my_simple_image/cifar/cifar10_quick_train_test.prototxt"   #网络文件路径
test_iter: 20 #测试执行的迭代次数
test_interval: 10 #迭代多少次进行测试 base_lr: 0.001 #迭代速率,这里我们改小了一个数量级,因为数据比较少
momentum: 0.9 weight_decay: 0.004 lr_policy: "fixed" #采用固定学习速率的模式display: 1 #迭代几次就显示一下信息,这里我为了及时跟踪效果,改成1 max_iter: 4000 #最大迭代次数 snapshot: 1000 #迭代多少次生成一次快照 snapshot_prefix: "examples/my_simple_image/cifar/cifar10_quick" #快照路径和前缀 solver_mode: CPU #CPU或者GPU
复制代码

 

3.      设置训练参数

拷贝caffe-master/model/bvlc_reference_caffenet中的文件,修改train_val.prototxt,solver.prototxt中的运行参数,并进行路径的修改;拷贝caffe_master/examples/imagenet中的train_caffnet.sh文件,对路径进行修改。

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/dina/caffe/examples/mytask/imagenet_mean.binaryproto"

  }

# mean pixel / channel-wise mean instead ofmean image

# transform_param {

#   crop_size: 227

#   mean_value: 104

#   mean_value: 117

#   mean_value: 123

#   mirror: true

#  }

 data_param {

   source: "/home/dina/caffe/examples/mytask/ilsvrc12_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/dina/caffe/examples/mytask/imagenet_mean.binaryproto"

  }

# mean pixel / channel-wise mean instead ofmean image

# transform_param {

#   crop_size: 227

#   mean_value: 104

#   mean_value: 117

#   mean_value: 123

#   mirror: false

#  }

 data_param {

   source: "/home/dina/caffe/examples/mytask/ilsvrc12_val_lmdb"

   batch_size: 50

   backend: LMDB

  }

}

layer {

 name: "conv1"

 type: "Convolution"

 bottom: "data"

 top: "conv1"

 param {

    lr_mult: 1

   decay_mult: 1

  }

 param {

   lr_mult: 2

   decay_mult: 0

  }

 convolution_param {

   num_output: 96

   kernel_size: 11

   stride: 4

   weight_filler {

     type: "gaussian"

     std: 0.01

    }

   bias_filler {

     type: "constant"

     value: 0

    }

  }

}

layer {

 name: "relu1"

 type: "ReLU"

 bottom: "conv1"

 top: "conv1"

}

layer {

 name: "pool1"

 type: "Pooling"

 bottom: "conv1"

 top: "pool1"

 pooling_param {

   pool: MAX

   kernel_size: 3

   stride: 2

  }

}

layer {

 name: "norm1"

 type: "LRN"

 bottom: "pool1"

 top: "norm1"

 lrn_param {

   local_size: 5

   alpha: 0.0001

   beta: 0.75

  }

}

layer {

 name: "conv2"

 type: "Convolution"

 bottom: "norm1"

 top: "conv2"

 param {

    lr_mult:1

   decay_mult: 1

  }

 param {

   lr_mult: 2

   decay_mult: 0

  }

 convolution_param {

   num_output: 256

   pad: 2

   kernel_size: 5

   group: 2

   weight_filler {

     type: "gaussian"

     std: 0.01

    }

   bias_filler {

     type: "constant"

     value: 1

    }

  }

}

layer {

 name: "relu2"

 type: "ReLU"

 bottom: "conv2"

 top: "conv2"

}

layer {

 name: "pool2"

 type: "Pooling"

 bottom: "conv2"

 top: "pool2"

 pooling_param {

   pool: MAX

   kernel_size: 3

   stride: 2

  }

}

layer {

 name: "norm2"

 type: "LRN"

 bottom: "pool2"

 top: "norm2"

 lrn_param {

   local_size: 5

   alpha: 0.0001

   beta: 0.75

  }

}

layer {

 name: "conv3"

 type: "Convolution"

 bottom: "norm2"

 top: "conv3"

 param {

    lr_mult:1

   decay_mult: 1

  }

 param {

   lr_mult: 2

   decay_mult: 0

  }

 convolution_param {

   num_output: 384

   pad: 1

   kernel_size: 3

   weight_filler {

     type: "gaussian"

     std: 0.01

    }

   bias_filler {

     type: "constant"

     value: 0

    }

  }

}

layer {

 name: "relu3"

 type: "ReLU"

 bottom: "conv3"

 top: "conv3"

}

layer {

 name: "conv4"

 type: "Convolution"

 bottom: "conv3"

 top: "conv4"

 param {

   lr_mult: 1

   decay_mult: 1

  }

 param {

   lr_mult: 2

   decay_mult: 0

  }

 convolution_param {

   num_output: 384

   pad: 1

   kernel_size: 3

   group: 2

   weight_filler {

     type: "gaussian"

     std: 0.01

    }

   bias_filler {

     type: "constant"

     value: 1

    }

  }

}

layer {

 name: "relu4"

 type: "ReLU"

 bottom: "conv4"

 top: "conv4"

}

layer {

 name: "conv5"

 type: "Convolution"

 bottom: "conv4"

 top: "conv5"

 param {

   lr_mult: 1

   decay_mult: 1

  }

 param {

   lr_mult: 2

   decay_mult: 0

  }

 convolution_param {

   num_output: 256

   pad: 1

   kernel_size: 3

   group: 2

   weight_filler {

     type: "gaussian"

     std: 0.01

    }

   bias_filler {

     type: "constant"

     value: 1

    }

  }

}

layer {

 name: "relu5"

 type: "ReLU"

 bottom: "conv5"

 top: "conv5"

}

layer {

 name: "pool5"

 type: "Pooling"

 bottom: "conv5"

 top: "pool5"

 pooling_param {

   pool: MAX

   kernel_size: 3

   stride: 2

  }

}

layer {

 name: "fc6"

 type: "InnerProduct"

 bottom: "pool5"

 top: "fc6"

 param {

   lr_mult: 1

   decay_mult: 1

  }

 param {

   lr_mult: 2

   decay_mult: 0

  }

 inner_product_param {

   num_output: 4096

   weight_filler {

     type: "gaussian"

     std: 0.005

    }

   bias_filler {

     type: "constant"

     value: 1

    }

  }

}

layer {

 name: "relu6"

 type: "ReLU"

 bottom: "fc6"

 top: "fc6"

}

layer {

 name: "drop6"

 type: "Dropout"

 bottom: "fc6"

 top: "fc6"

 dropout_param {

   dropout_ratio: 0.5

  }

}

layer {

 name: "fc7"

 type: "InnerProduct"

 bottom: "fc6"

 top: "fc7"

 param {

   lr_mult: 1

   decay_mult: 1

  }

 param {

   lr_mult: 2

   decay_mult: 0

  }

 inner_product_param {

   num_output: 4096

   weight_filler {

     type: "gaussian"

     std: 0.005

    }

   bias_filler {

     type: "constant"

     value: 1

    }

  }

}

layer {

 name: "relu7"

 type: "ReLU"

 bottom: "fc7"

 top: "fc7"

}

layer {

 name: "drop7"

 type: "Dropout"

 bottom: "fc7"

 top: "fc7"

 dropout_param {

   dropout_ratio: 0.5

  }

}

layer {

 name: "fc8"

 type: "InnerProduct"

 bottom: "fc7"

 top: "fc8"

 param {

   lr_mult: 1

   decay_mult: 1

  }

 param {

   lr_mult: 2

   decay_mult: 0

  }

 inner_product_param {

   num_output: 1000

   weight_filler {

     type: "gaussian"

     std: 0.01

    }

   bias_filler {

     type: "constant"

     value: 0

    }

  }

}

layer {

 name: "accuracy"

 type: "Accuracy"

 bottom: "fc8"

 bottom: "label"

 top: "accuracy"

 include {

   phase: TEST

  }

}

layer {

 name: "loss"

 type: "SoftmaxWithLoss"

 bottom: "fc8"

 bottom: "label"

 top: "loss"

}

 

solver.prototxt是网络参数的设置,内容如下:

net:"/home/dina/caffe/examples/mytask/train_val.prototxt"

test_iter: 2

test_interval: 50

base_lr: 0.001

lr_policy: "step"

gamma: 0.1

stepsize: 100

display: 20

max_iter: 1000

momentum: 0.9

weight_decay: 0.0005

snapshot: 500

snapshot_prefix:"models/bvlc_reference_caffenet/caffenet_train"

solver_mode: GPU



1.4 训练

使用上面的配置训练,得到的结果准确率仅仅是0.2+,数据集的制作者迭代了12000次得到0.5的准确率

train_caffnet.sh是运行网络的命令,内容如下:

 

#!/usr/bin/env sh

 

./build/tools/caffe train \

--solver=./examples/mytask/solver.prototxt

 

好了,可以等待训练过程了,我们的训练图片是2000个训练图片,1000个验证图片,大约过了3-4个小时,就训练好了。

5、开始训练

运行下面的命令,开始训练(为了方便可以做成脚本)

./build/tools/caffe train 
--solver=examples/my_simple_image/cifar/cifar10_quick_solver.prototxt

 

6、小技巧

网络的配置和训练其实有一些小技巧。

- 训练过程中,正确率时高时低是很正常的现象,但是总体上是要下降的

- 观察loss值的趋势,如果迭代几次以后一直在增大,最后变成nan,那就是发散了,需要考虑减小训练速率,或者是调整其他参数

- 数据不能太少,如果太少的话很容易发散

1.5 其他

1.5.1杀掉正在运行的caffe进程:

ps -A#查看所有进程,及caffe的代码
kill -9 代码#杀掉caffe

1.5.2 查看gpu的使用情况

nvidia-sim -l
(NVIDIA System Management Interface)

1.5.3 查看时间使用情况

./build/tools/caffe time --model=models/bvlc_reference_caffenet/train_val.prototxt

我的时间使用情况

Average Forward pass: 3490.86 ms.
Average Backward pass: 5666.73 ms.
Average Forward-Backward: 9157.66 ms.
Total Time: 457883 ms.

1.5.4 恢复数据

如果我们在训练途中就停电或者有了其他的情况,我们可以通过之前保存的状态恢复数据,使用的时候直接添加–snapshot参数即可,如:

./build/tools/caffe train --solver=models/bvlc_reference_caffenet/solver.prototxt --snapshot=models/bvlc_reference_caffenet/caffenet_train_iter_10000.solverstate

这时候运行会从snapshot开始继续运行,如从第600迭代时运行:


阅读更多
上一篇【视觉=立体视觉】立体匹配算法 StereoBM/StereoSGBM/StereoVar(OpenCV中源码分析)+SAD块匹配算法+GC算法+HH算法
下一篇【学习OpenCV】opencv 2.4 版本共100个自带例子
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭