使用caffe框架进行深度学习训练的流程如下:
1、数据预处理(建立数据库)
2、网络结构与模型训练的配置
3、训练与再训练
4、训练日志分析
5、预测检验与分析
6、性能测试
下面分别来分析各个流程的处理过程:

1、数据预处理(建立数据库)

  训练数据与测试数据的预处理阶段,一般是 把待分析识别的图像进行简单的预处理,然后保存到数据库中。为什么要进行这一步而不是直接从图片读入呢?因为实际任务中的训练数据的数量非常大,从图像文件中读取数据并进行初始化效率非常低,所以很有必要把数据预先保存在数据库中来加快训练的节奏。
  将图片下载到本地,通过脚本文件将图片转换成leveldb或lmdb格式,这两种数据库在存储数据和操纵上有所不同。
  (1)数据组织方式不同,leveldb生成的文件比较多;lmdb的文件更紧凑,只有两个
  (2)读取数据的接口不同

2、网络结构与模型训练的配置

  caffe采用读入配置文件的方式进行训练,其配置文件一般由两部分组成:solver.prototxt和net.prototxt(有时有多个net.prototxt),分别对应caffe系统架构中两个十分关键的实体——求解器(Solver)和网络结构(Net)。
下面讲解一下相对简单的solver.prototxt文件:

#网络配置的位置
net: "examples/mnist/net.prototxt"
#要使用GPU进行训练
solver_mode: GPU
#本次训练共迭代5000次
max_iter: 5000
#测试每500轮跑一遍,一遍跑100个迭代
test_iter: 100
test_interval: 500
#每50次输出一些信息
display: 50
#基础的学习速率为0.01
base_lr: 0.01
lr_policy: "step"
gamma: 0.1
stepsize: 50000
#动量衰减率是0.9,正则项的权重是0.0005
momentum: 0.85
weight_decay: 0.0005
#每1000轮保存一下进度
snapshot: 1000
snapshot_prefix: "examples/mnist/net_train"

基本回答了以下几个问题:
(1)网络文件在哪
(2)用什么计算资源训练?CPU还是GPU?
(3)训练多久?训练和测试比例是如何安排的?什么时候输出一些东西?
(4)优化的学习速率怎么设定?动量和正则的设置
(5)要时刻记得存档,不然得从头来过。
net.prototxt文件说明

name: "LeNet"           网络名
layer {
  name: "mnist"         本层名称
  type: "Data"              层类型
  top: "data"               下一层接口
  top: "label"              下一层接口
  include {
    phase: TRAIN
  }
  transform_param {
    scale: 0.00390625           #1/256,预处理如减均值,尺寸变换,随机剪,镜像等
  }
  data_param {
    source: "examples/mnist/mnist_train_lmdb"   训练数据位置
    batch_size: 64                  一次训练的样本数
    backend: LMDB                   读入的训练数据格式,默认leveldb
  }
}


layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    scale: 0.00390625
  }
  data_param {
    source: "examples/mnist/mnist_test_lmdb"
    batch_size: 100                 一次测试使用100个数据
    backend: LMDB
  }
}


layer {
  name: "conv1"
  type: "Convolution"               卷积层
  bottom: "data"                上一层名“data”
  top: "conv1"                  下一层接口“conv1”
  param {
    lr_mult: 1                  (weights的学习率与全局相同)
  }
  param {
    lr_mult: 2                  (biases的学习率是全局的2倍)
  }
  convolution_param {
    num_output: 20              卷积核20个
    kernel_size: 5              卷积核尺寸5×5
    stride: 1                   步长1
    weight_filler {
      type: "xavier"                (随机的初始化权重和偏差)
    }
    bias_filler {
      type: "constant"              bias用0初始化
    }
  }
}


layer {
  name: "pool1"
  type: "Pooling"               池化层
  bottom: "conv1"               上层“conv1”
  top: "pool1"                  下层接口“pool1”
  pooling_param {
    pool: MAX                   池化函数用MAX
    kernel_size: 2              池化核函数大小2×2
    stride: 2                   步长2
  }
}


layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 50              卷积核50个
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}


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"               上层连接“pool2”
  top: "ip1"                    “下层输出接口ip1”
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 500             输出数量500
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}


layer {
  name: "relu1"
  type: "ReLU"              激活函数
  bottom: "ip1"
  top: "ip1"    (这个地方还是ip1,底层与顶层相同减少开支,下一层全连接层的输入也还是ip1)
}


layer {
  name: "ip2"
  type: "InnerProduct"
  bottom: "ip1"
  top: "ip2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 10              输出结果10个
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}


layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "ip2"         上层连接ip2全连接层
  bottom: "label"           上层连接label层
  top: "accuracy"           输出接口为accuracy
  include {
    phase: TEST         
  }
}


layer {
  name: "loss"
  type: "SoftmaxWithLoss"       损失函数
  bottom: "ip2"
  bottom: "label"
  top: "loss"
}

caffe提供了一套接口,net.prototxt文件可通过写代码生成。

3、训练与再训练

  准备好了数据,确定了训练相关的配置,就可以正式训练了。启动训练脚本train_lenent.sh,经过一段时间的训练,命令行产生了大量的日志训练过程也宣告结束,这时目录中多了如下目录:
net_train_iter_1000.caffemodel
net_train_iter_1000.solverstate
……
  caffemodel文件中保存了caffe模型中的参数,solverstate文件中保存了训练过程中的一些中间结果。
  再训练包含两种模式:
  (1)断点训练,solverstate中存储了训练的历史信息,这些信息能够帮助模型继续训练;
  (2)迁移学习,这个模式会在之前训练的基础上,对模型结构做一定的修改,然后应用到其他模型中,这种模式称为迁移学习。

4、训练日志分析

  训练过程caffe产生了大量的日志,这些日志包含很多训练过程的信息,很值得分析。其中之一就是分析目标函数Loss的变化曲线,和测试环节的精确度。
  正常的训练过程中,日志中只会显示每一组迭代后模型训练的整体信息,如果想了解更多信息就要将solver.prototxt中的调试信息打开。

5、预测检验与分析

  模型完成训练后,要对它的训练表现做验证,看它在其他测试数据上的正确性。除此之外,还可以将每一层的中间结果可视化出来,进行分析。

6、性能测试

  除了测试数据上的准确率,模型的运行时间也非常值得关心。
以上就是在caffe上训练数据的整个过程。
参考《深度学习轻松学》