本篇文章是我利用 caffe进行深度学习的知识点总结,包含别人学习笔记链接
caffe简介
caffe的作者为UC Berkeley大学的贾扬清。caffe是一个c++/CUDA架构,支持命令行、Python、Matlab接口,可以在CPU/GPU上运行。
Caffe项目的文件结构
- caffe(要编译的文件,里面包含用c++写的数据输入、网络层、计算等核心文件)
- data (要处理或者转换的数据)
- models:
train.prototxt (网络模型) solve.prototxt(设置训练的一系列参数) xxx.caffemodel(finetune 时用的初始化参数,训练新模型则不需要)
- scripts(训练网络的代码,可以是python文件,shell文件等)
caffe 安装参考:https://www.jianshu.com/p/9e0a18608527
caffe 网络结构
caffe 使用Blob数组结构来存储、交换、处理网络(就像numpy的存储结构为narray),用caffe Layer来定义神经网络结构,它包含数据层、视觉层等类型
下面以代码为例,讲解常用层
train.prototxt( 以下为VGG16模型部分代码)
- 数据层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
name: "VGG16" layer { name: "data" type: "Data" #输入的数据类型 top: "data" top: "label" include { phase: TRAIN } #数据预处理,来增强数据 transform_param { mirror: true crop_size: 224 mean_value: 103.939 mean_value: 116.779 mean_value: 123.68 } data_param { source: "data/ilsvrc12_shrt_256/ilsvrc12_train_leveldb" #数据库文件路径 batch_size: 64 #网络单次输入数据数量 backend: LEVELDB #选择使用LevelDB还是LMDB } }
caffe支持输入的数据类型:
type | data |
---|---|
Data | LMDB/levelDB |
MemoryData | 内存数据 |
HDF5Data | HDF5数据 |
ImagesData | 图像数据Images |
WindowsData | 窗口Windows |
top:表示输出的方向,bottom:表示输入的数据来源(层的名称),可以有多个top和bottom
注意:在数据层中,至少有一个命名为data的top。如果有第二个top,一般命名为label
LMDB参考资料:https://zhuanlan.zhihu.com/p/23485774
- 卷积层
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 26 27
layer { bottom: "data" top: "conv1_1" name: "conv1_1" type: "Convolution" param { lr_mult: 1 decay_mult: 1 } param { lr_mult: 2 decay_mult: 0 } convolution_param { num_output: 64 pad: 1 kernel_size: 3 weight_filler { type: "gaussian" std: 0.01 } bias_filler { type: "constant" value: 0 } } }
参数 | |
---|---|
num_output | 卷积核数量 |
kernel_size | 卷积核高度/宽度(可分别设置宽高) |
weight_filler | 参数初始化方案 |
bias_term | 是否给卷积输出添加偏置项 |
pad | 图像周围补0的像素个数 |
stride | 滑动步长 |
group | 指定分组卷积操作的组数 |
lr_mult | 学习率(最终的学习率要乘以 solver.prototxt 配置文件中的 base_lr) |
decay_mult | 权值衰减 |
dropout_ratio | 丢弃数据的概率 |
- | - |
dropout_ratio和decay_mult设置为了防止数据过拟合
- 池化层
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 26 27
layer { bottom: "pool1" top: "conv2_1" name: "conv2_1" type: "Convolution" param { lr_mult: 1 decay_mult: 1 } param { lr_mult: 2 decay_mult: 0 } convolution_param { num_output: 128 pad: 1 kernel_size: 3 weight_filler { type: "gaussian" std: 0.01 } bias_filler { type: "constant" value: 0 } } }
参数 | |
---|---|
pool | 池化方式,Max:最大池化,AVE:均值池化,STOCHASTIC:随机池化 |
-
激活层
1 2 3 4 5 6
layer { bottom: "conv2_2" top: "conv2_2" name: "relu2_2" type: "ReLU" #常用激活函数,除此之外还有Sigmoid }
-
损失函数层
1 2 3 4 5 6 7
layer { bottom: "fc8" bottom: "label" top: "loss" name: "loss" type: "SoftmaxWithLoss" }
type | |
---|---|
SoftmaxWithLoss | 交叉信息熵损失函数 |
Softmax | 多分类损失函数 |
caffe网络模型各层信息(详细):https://wenku.baidu.com/view/f77c73d02f60ddccdb38a025.html
Caffe模型训练
- 网络可视化
当你写好自己的prototxt文件后,想要检查自己的网络框架是否搭建正确,可以借助 Netscope (在线caffe net可视化工具)http://ethereon.github.io/netscope/#/editor
- 训练参数设置
caffe模型的训练参数在solve.prototxt文件中,该文件是caffe的核心,它交替调用前向算法和反向传播算法来更新参数,使loss的值达到最小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
net: "train_val.prototxt" test_iter: 833 # make test net, but don't invoke it from the solver itself test_interval: 1000 display: 200 average_loss: 100 base_lr: 1e-5 lr_policy: "step" gamma: 0.1 stepsize: 5000 # lr for unnormalized softmax -- see train_val definition # high momentum momentum: 0.9 # no gradient accumulation clip_gradients: 10000 iter_size: 1 max_iter: 80000 weight_decay: 0.02 snapshot: 4000 snapshot_prefix: "weight/VGG_item" test_initialization: false |
参数 | |
---|---|
train_net | 训练所需网络模型(最好写绝对路径) |
test_net | 测试所需网络模型 |
test_iter | 测试次数 (test_iter * batchsize = 训练的数据量) |
base_lr | 基本学习率 |
lr_policy | 学习率改变的方法 |
weight_decay | 权重衰减 |
momentum | 表示上一次梯度更新的权重 |
max_iter | 最大迭代次数 |
snapshot | 保存模型间隔 |
snapshot_prefix | 保存模型路径+前缀 |
solver_mode | 是否使用GPU |
average_loss | 取多次foward的loss作平均,进行显示输出 |
type | 优化算法 |
- 训练网络
1、命令行
我们可以在命令行输入代码训练网络
1 2 > ./build/tools/caffe train -solver solver.prototxt >
(详细请参考:《caffe命令行解析》https://www.cnblogs.com/denny402/p/5076285.html)
2、python
我们也可以利用caffe的python接口来编写训练网络的程序
其他问题
- 输入输出大小
在用自己的数据训练或者微调网络的过程中,可能会出现img 与label_img大小不同的情况,这个时候就仔细分析训练过程所显示的每一层输入输出的大小,更改相应的参数使最后训练的img与label_img大小相同
卷积核与池化层输出图像尺寸计算公式:
(W-F+2P)/S+1
参数 | 说明 |
---|---|
w | 输入图像大小 |
F | 卷积核尺寸(kernel_size) |
S | 步幅大小(stride) |
P | padding大小(pad) |