caffe简易上手指南(二)—— 训练我们自己的数据

训练我们自己的数据

本篇继续之前的教程,下面我们尝试使用别人定义好的网络,来训练我们自己的网络。

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......

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."

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."

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

5、开始训练

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

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

6、小技巧

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

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

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

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

时间: 2024-10-22 11:46:44

caffe简易上手指南(二)—— 训练我们自己的数据的相关文章

caffe简易上手指南(一)—— 运行cifar例子

简介 caffe是一个友好.易于上手的开源深度学习平台,主要用于图像的相关处理,可以支持CNN等多种深度学习网络. 基于caffe,开发者可以方便快速地开发简单的学习网络,用于分类.定位等任务,也可以用于科研,在其源码基础上进行修改,实现自己的算法. 本文的主要目的,是介绍caffe的基本使用方法,希望通过本文,能让普通的工程师可以使用caffe训练自己的简单模型. 本文主要包括以下内容:运行caffe的例子训练cifar训练集.使用别人定义好的网络训练自己的数据.使用训练好的模型fine tu

caffe简易上手指南(三)—— 使用模型进行fine tune

之前的教程我们说了如何使用caffe训练自己的模型,下面我们来说一下如何fine tune. 所谓fine tune就是用别人训练好的模型,加上我们自己的数据,来训练新的模型.fine tune相当于使用别人的模型的前几层,来提取浅层特征,然后在最后再落入我们自己的分类中. fine tune的好处在于不用完全重新训练模型,从而提高效率,因为一般新训练模型准确率都会从很低的值开始慢慢上升,但是fine tune能够让我们在比较少的迭代次数之后得到一个比较好的效果.在数据量不是很大的情况下,fin

caffe 进行自己的imageNet训练分类:loss一直是87.3365,accuracy一直是0

caffe 进行自己的imageNet训练分类: loss一直是87.3365,accuracy 一直是0,可能的原因是: 解决方法: http://blog.csdn.net/jkfdqjjy/article/details/52268565?locationNum=14知道了原因,解决时就能对症下药.总体上看,softmax输入的feature由两部分计算得到:一部分是输入数据,另部分是各层权重参数. 1.观察数据中是否有异常样本或异常label导致数据读取异常 2.调小初始化权重,以便使s

C++11线程指南(二)--Lambda线程实现

1. Thread with lambda function 基于前一章中的Lambda程序,我们进行了扩展,当前创建5个线程. #include<iostream> #include<thread> #include<vector> #include<algorithm> int main() { std::vector<std::thread> threadVec; for(int i=0; i<5; ++i){ threadVec.p

Android SDK上手指南 3:用户交互

在这篇教程中,我们将对之前所添加的Button元素进行设置以实现对用户点击的检测与响应.为了达成这一目标,我们需要在应用程序的主Activity类中略微涉及Java编程内容.如果大家在Java开发方面的经验不太丰富也没必要担心,只要按步骤进行即可完成学习.我们将在本系列的下一篇文章中深入探讨Java语法,从而保证大家了解初步Android开发任务中所必需的编程语言知识. 大家可以在Android当中以多种不同方式实现用户交互.我们将学习两种最为典型的处理方案,从而实现应用按钮对用户点击的感应--

Android SDK上手指南 2:用户界面设计

http://mobile.51cto.com/ahot-419184.htm 内容简介 我们将为应用程序项目添加布局方案,在这方面XML与Eclipse ADT接口将成为工作中的得力助手--不过在后面两节中还会用到一部分Java开发知识.XML与Java在Android平台的开发工作当中可谓无处不在,如果大家对二者还缺乏基本的了解,请尽快想办法补补课.对于刚刚入门的读者朋友来说,本文所介绍的要点将成为各位日后开发工作的重要基础. 1. XML基础知识 在我们开始讨论布局之前,先来梳理作为标记语

android快速上手(二)android开发环境搭建及hello world

基本了解了java语法,下一步,我们一起开启hello world的神秘之旅. (一)android开发环境搭建 之前搭建android开发环境是件非常费力的事情,下载Eclipse,安装ADT等,如今android官方给我们提供了全套配置. https://developer.android.com/sdk/index.html 搭建android开发环境之前记得先安装jdk (二)开启Hello World之旅 (1)创建Hello World项目 安装完带ADT的Eclipse,打开Ecl

Swift语言指南(二)--语言基础之注释和分号

注释 通过注释向自己的代码中注入不可执行的文本,作为你自己的笔记或提示.Swift编译器运行时会忽略注释. Swift的注释与C语言极其相似,单行注释以两个反斜线开头: //这是一行注释 多行注释以/*开始,以*/结束: ? 1 2 3 <span style="color: rgb(0, 128, 0);">/* 这也是一条注释, 但跨越多行 */ </span> 与 C 语言的多行注释有所不同的是,Swift 的多行注释可以嵌套在其他多行注释内部.写法是在一

官方文档 恢复备份指南二 Getting Started with RMAN

本章对RMAN进行基本的熟悉和了解 1.Overview of the RMAN Environment RMAN运行时需要的最小环境: target database          :RMAN用target命令连接的数据库,在该数据库上执行备份和恢复操作,并备份信息(RMAN reposity 资源库)记录在target数据库的控制文件中. RMAN client              :rman客户端,即RMAN可执行程序.在$ORACLE_HOME/bin下 RMAN运行时可能需要