caffe入门:安装、测试、参数介绍

    以前一直用TensorFlow,但是发现好多大牛写的文章都是用caffe实现的,因此不得不入门caffe。caffe的安装参考这里,包括Ubuntu和window下的安装。在我们安装好caffe以后,我们可以在caffe内置的目录下进行mnist的测试,测试步骤如下:

1、下载mnist数据库

    cd ~/caffe
    sduo ./data/mnist/get_mnist.sh

    执行之后,在./data/mnist文件夹下生成4个文件,分别是测试、训练数据库和测试、训练标签: 

2、二进制数据库文件转换成lmdb数据库格式 

    sudo ./examples/mnist/create_mnist.sh

    执行之后,在 ./examples/mnist文件夹下生成两个文件夹,一个是 mnist_train_lmdb 和 mnist_test_lmdb,分别存放了训练和测试数据:

3、训练lenet网络:

   如果只是用CPU训练的话,需要先在 lenet_solver.prototxt 文件中修改训练模式为CPU,修改文件最后一行的 solver_mode的配置为 CPU。以下指令执行训练:

sudo ./examples/mnist/train_lenet.sh

训练结果的分类文件 lenet_iter_10000.caffemodel 文件保存在 ./examples/mnist路径下。

------------------------------------------------------------------------------------------------------    

    接下来我们介绍caffe训练模型需要三个文件,分别是solver.prototxt、train_val.prototxt、train.sh,下面我们依次介绍。

4、solver.prototxt

 solver.prototxt这个文件主要存放模型训练所用到的一些超参数:
    net := 指定待训练模型结构文件,即train_val.prototxt
    test_interval := 测试间隔,即每隔多少次迭代进行一次测试。
    test_initialization := 指定是否进行初始测试,即模型未进行训练时的测试
    test_iteration := 指定测试时进行的迭代次数,即test_iter* batchsize(测试集的)=测试集的大小,测试集的 batchsize可以在prototx文件里设置。
    base_lr := 指定基本学习率
    lr_policy := 学习率变更策略,这个参数代表的是learning rate应该遵守什么样的变化规则,这个参数对应的是字符串,选项及说明如下:
        “step” - 需要设置一个stepsize参数,返回base_lr * gamma ^ ( floor ( iter / stepsize ) ),iter为当前迭代次数
        “multistep” - 和step相近,但是需要stepvalue参数,step是均匀等间隔变化,而multistep是根据stepvalue的值进行变化
        “fixed” - 保持base_lr不变
        “exp” - 返回base_lr * gamma ^ iter, iter为当前迭代次数
        “poly” - 学习率进行多项式误差衰减,返回 base_lr ( 1 - iter / max_iter ) ^ ( power )
        “sigmoid” - 学习率进行sigmod函数衰减,返回 base_lr ( 1/ 1+exp ( -gamma * ( iter - stepsize ) ) )
    gamma := 学习率变更策略需要用到的参数
    power := 同上
    stepsize := 学习率变更策略Step的变更步长(固定步长),每stepsize次迭代减少学习率,这一项和lr_policy有关
    stepvalue := 学习率变更策略Multistep的变更步长(可变步长)

   iter_size: iter_size,iter_size:iter_size*batch size=实际使用的batch size。 相当于读取batchsize*itersize个图像才做一下gradient decent。 这个参数可以规避由于gpu不足而导致的batchsize的限制 因为你可以用多个iteration做到很大的batch 即使单次batch有限
    max_iter := 模型训练的最大迭代次数
    momentum := 动量,这是优化策略(Adam, SGD, … )用到的参数,灵感来自于牛顿第一定律,基本思路是为寻优加入了“惯性”的影响,这样一来,当误差曲面中存在平坦区的时候,SGD可以更快的速度学习。
    momentum2 := 优化策略Adam用到的参数
    weight_decay := 权重衰减率,用于防止过拟合。使用方式:样本越多,该值越小,模型参数越多,该值越大。一般建议值:weight_decay: 0.0005。
    clip_gradients := 固定梯度范围
    display := 每隔几次迭代显示一次结果
    snapshot := 快照,每隔几次保存一次模型参数
    snapshot_prefix := 保存模型文件的前缀,可以是路径
    type := solver优化策略,即SGD、Adam、AdaGRAD、RMSProp、NESTROVE、ADADELTA等,在solver配置文件中,通过设置type类型来选择:
        Stochastic Gradient Descent (type: "SGD"),
        AdaDelta (type: "AdaDelta"),
        Adaptive Gradient (type: "AdaGrad"),
        Adam (type: "Adam"),
        Nesterov’s Accelerated Gradient (type: "Nesterov") and
        RMSprop (type: "RMSProp")
    solver_mode := 指定训练模式,即GPU/CPU
    debug_info := 指定是否打印调试信息,这里有对启用该功能的输出作介绍
    device_id := 指定设备号(使用GPU模式),选择几块GPU,默认为0

5、train_val.prototxt

train_val文件是用来存放模型结构的地方,模型的结构主要以layer为单位来构建。下面我们以LeNet为例介绍网络层的基本组成:

name: "LeNet"
layer {                                      # 这里为训练的数据层
  name: "mnist"                                # 网络层名称
  type: "Data"                                 # 网络层类型,数据层
  top: "data"                                  # 这一层的输出,数据
  top: "label"                                 # 这一层的输出,标签
  include {    phase: TRAIN  }                 # TRAIN:=用于训练,TEST:=用于测试,表明这是在训练阶段才包括进去
  transform_param {
    scale: 0.00390625                           # 对数据进行scale
    mirror: true                                # 是否做镜像
    crop_size: 227                              # 对图像做裁剪
    mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"   # 减去均值文件
  }   
  data_param {                                 # 数据层配置 
    source: "examples/mnist/mnist_train_lmdb"  # 数据存放路径
    batch_size: 64                             # 指定batch大小
    backend: LMDB                              # 指定数据库格式,LMDB/LevelDB
  }
}
layer {                                      # 这里为测试的数据层
  name: "mnist"                                # 网络层名称
  type: "Data"                                 # 网络层类型,数据层
  top: "data"                                  # 这一层的输出,数据
  top: "label"                                 # 这一层的输出,标签
  include {    phase: TEST  }                  #TRAIN:=用于训练,TEST:=用于测试,表明这是在测试阶段才包括进去
  transform_param {
    scale: 0.00390625                           # 对数据进行scale
    mirror: true                                # 是否做镜像
    crop_size: 227                              # 对图像做裁剪
    mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"   # 减去均值文件
  } 
  data_param {                                 # 数据层配置 
    source: "examples/mnist/mnist_test_lmdb"   # 数据存放路径
    batch_size: 100                            # 指定batch大小
    backend: LMDB                              # 指定数据库格式,LMDB/LevelDB
  }
}
layer{                                      # 这里为第一个卷积层
    name:"conv1"                               # 卷积层名
    type:"Convolution"                         # 卷积层类型:卷积层
    bottom:"data"                              # 上一层的输出作为输入
    top:"conv1"                                # 这一层的输出,conv1
    param{
     name:"conv1_w"                            # 卷积层参数w(权重)的名称、
     lr_mult:1                                 # 卷积层参数w学习率,最终的学习率需要乘以 solver.prototxt 配置文件中的base_lr
     decay_mult:1                              # 卷积层参数w的衰减率,最终的衰减率需要乘以 solver.prototxt 配置文件中的weight_decay
   }                            
    param{
     name:"conv1_b"                            # 卷积层参数b(偏置)的名称,学习率和衰减率
     lr_mult:2                                 # 偏置设为2倍学习率,能够加速收敛
     decay_mult:0} 
    convolution_param{
        num_output:20                            #  卷积层输出的feature map数量 
        kernel_size:5                            #  卷积层的大小
        pad:0                                    #  卷积层的填充大小
        stride:1                                 #  进行卷积的步长
        weight_filler{type:"xavier" }            #  参数w的初始话策略
        weight_filler{type:"constant" value:0.1} #  参数b的初始化策略
    }
}
layer {                              # BatchNorm层,对feature map进行批规范化处理
    name:"bn1"
    type:"BatchNorm"
    bottom:"conv1"
    top:"conv1"
    batch_norm_param{ use_global_stats:false} #训练时为false,测试时为true
}
layer {                                    # 池化层,即下采样层
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX                                # 最大值池化,还有AVE均值池化
    kernel_size: 2
    stride: 2
  }
}                                          # 第二个卷积层配置
layer {                                    
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {    lr_mult: 1  }
  param {    lr_mult: 2  }
  convolution_param {
    num_output: 50
    kernel_size: 5
    stride: 1
    weight_filler {      type: "xavier"    }
    bias_filler {      type: "constant"    }
  }
}
layer {                                   # 第二个batchnorm层
    name:"bn2"
    type:"BatchNorm"
    bottom:"conv2"
    top:"conv2"
    batch_norm_param{ use_global_stats:false}
}
layer {                                   # 第二个池化层
  name: "pool2"
  type: "Pooling"
  bottom: "conv2"
  top: "pool2"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {                                #全连接层
  name: "ip1"
  type: "InnerProduct"
  bottom: "pool2"
  top: "ip1"
  param {    lr_mult: 1  }  
  param {    lr_mult: 2  }
  inner_product_param {
    num_output: 500
    weight_filler {      type: "xavier"    }
    bias_filler {      type: "constant"    }
  }
}
layer {                                 # 激活函数层,提供非线性能力
  name: "relu1"
  type: "ReLU"
  bottom: "ip1"
  top: "ip1"
}
layer {                                 # 第二个全连接层
  name: "ip2"
  type: "InnerProduct"
  bottom: "ip1"
  top: "ip2"
  param {    lr_mult: 1  }
  param {    lr_mult: 2  }
  inner_product_param {
    num_output: 10
    weight_filler {      type: "xavier"    }
    bias_filler {      type: "constant"    }
  }
}
layer {                                  # 损失函数层
  name: "prob"
  type: "SoftmaxWithLoss"
  bottom: "ip2"
  bottom: "label"
  top: "prob"
}

 6、train.sh

    这个脚本文件可写,可不写。每次运行需要写一样的命令,所以建议写一下。以下是最简单训练脚本:

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

caffe/build/tools/caffe train --solver=xxxxx/solver.prototxt --weights=xxxxx/xxxxx.caffemode

    其中, caffe程序的命令行执行格式如下:

      caffe <command> <args>

其中的<command>有这样四种:
  train : 训练或finetune模型(model),
  test :测试模型
  device_query :显示gpu信息
  time  : 显示程序执行时间
其中的<args>参数有:
  -solver : 指定sovler.prototxt文件,在train的时候需要这个参数
  -gpu    :可选;给定时运行GPU模式,用’ , ’分隔开不同的gpu,‘-gpu all’表示运行在所有可用的gpu设备上,此时有效训练批量大小就是gpu设备数乘以batch_size.如使用第二块gpu运行:-gpu 2
  -snapshot :可选,恢复训练时指定上次中止的快照,就是比如训练到一般按Ctrl+C终止训练(Linux中这个Ctrl+C不是copy,而是终止当前操作),就会得到一个solverstate文件,下次恢复训练时就可以指定这个.
  -weights  : 指定用于微调的预训练权值,也即 训练后得到的**.caffemodel文件,不可与snapshot同时出现.
  -iteration :循环迭代次数,默认为50.
  -model  :指定模型定义文本文件名,xxx.prototxt,也可以在solver配置文件中指定。
  -sighup_effect :用来设定当程序发生挂起事件时,执行的操作,可以设置为snapshot, stop或none, 默认为snapshot.
  -sigint_effect :可选参数。用来设定当程序发生键盘中止事件时(ctrl+c), 执行的操作,可以设置为snapshot, stop或none, 默认为stop

    折腾了很久,发现caffe和TensorFlow区别还是好大的,首先是安装问题,TensorFlow安装简单快捷,只需要一条命令pip install TensorFlow,而caffe安装非常复杂,需要安装各种依赖包,然后还需要自己编译,如果是第一次安装,通常会折腾很久才能装上。其次,TensorFlow训练神经网络时整个训练过程需要自己动手实现,包括如何进行数据预处理(如何生成TFrecord文件高效利用内存)、一层一层的调用TensorFlow的函数搭建网络结构、然后定义损失函数和优化器、最后进行训练和保存模型。而caffe在进行网络训练的过程中,前面安装很复杂,但是成功安装以后训练过程就非常简单了。首先是用原始图像制作caffe所支持的数据集文件(通常是lmdb或leveldb,使用一个脚本文件生成),然后是定义好网络结构的文件train.prototxt,然后定义训练过程中的各种参数的文件solver.prototxt,最后就是写一个训练脚本train.sh,在这个脚本中调用编译生成caffe.exe传入各种参数就开始训练了。相对于TensorFlow而言,caffe进行神经网络的训练相对更加抽象,只需要在prototxt文件定义网络层各种参数,caffe从这个文件读取参数然后调用底层的函数帮你创建模型训练,而TensorFlow整个网络结构需要你自己调用TF的函数来创建。 

参考:https://blog.csdn.net/cham_3/article/details/72141753

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值