您的位置:首页 > 理论基础 > 计算机网络

caffe学习笔记2:lenet网络结构分析

2017-11-23 10:13 459 查看
最近一直在研究linux下的caffe,记录下自己在学习过程的一些步骤。

1、Solver文件分析

在caffe中,整个训练和加载开始是从solver.prototxt文件开始的,程序解析网络的solver文件开始,在solver.prototxt文件定义了网络的一些超参数,以及net网络模型的路径。lenet网络结构的solver文件(即./examples/mnist目录下的lenet_solver.prototxt文件)如下:

# The train/test net protocol buffer definition

#定义模型的文件
#定义网络结构的txt文件 -- 这里必须加载对
net: "examples/mnist/lenet_train_test.prototxt"

# test_iter specifies how many forward passes the test should carry out.
# In the case of MNIST, we have test batch size 100 and 100 test iterations,
# covering the full 10,000 testing images.
test_iter: 100          #指定测试应该执行多少次前传算法

# Carry out testing every 500 training iterations.
test_interval: 500   #多少次训练的迭代执行一次测试

# The base learning rate, momentum and the weight decay of the network.
base_lr: 0.01           # 基础的学习率
momentum: 0.9           # 动量值,使参数更新更稳健

weight_decay: 0.0005        #权重衰减率
# The learning rate policy
lr_policy: "inv"                # 学习策略

gamma: 0.0001                   #学习率变化的参数
power: 0.75

# Display every 100 iterations
display: 100            # 多少次迭代显示一次结果

#最大迭代次数
# The maximum number of iterations
max_iter:  10000

#输出中间结果snapshot的迭代次数,snapshot快照的思想
# snapshot intermediate results
snapshot: 5000
#保存中间结果存的路径
snapshot_prefix: "examples/mnist/lenet"

# 使用CPU还是GPU训练
solver mode:GPU


在解析solver文件的时候,最开始的是解析网络的模型,网络的模型也是由prototxt文件定义的,在这里是lenet_train_test.prototxt”文件。

2、Net 文件分析

Net文件主要是定义网络的模型结构,网络的结构,几个层每个层的结构等,以下是lenet的net文件,即examples/mnist/lenet_train_test.prototxt文件,这个文件路径要在solver.prototxt文件的第一行给出。

#定义模型prototxt文件
#训练和测试的时候也会用到
#这里layer的type类型时Data,所以读取的数据必须是转换后的lmdb或者leveb文件

name: "LeNet"           #整个网络的名字

# 数据层--训练
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
# 只在训练过程中有效
include
{
phase: TRAIN
}
# 预处理的操作
transform_param {
mean_file:"../mnist_mean/mean.binaryproto"              # 均值文件地址
scale: 0.00390625               # 归一化的参数
}
# 指定训练用的lmdb文件的路径
data_param {
source: "../mnist_train_lmdb"
batch_size: 64          #指定batch_size批量的大小
backend: LMDB
}
}

# 数据层--测试
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
# 只在测试过程中有效
include {
phase: TEST
}
transform_param {
mean_file:"../mnist_mean/mean.binaryproto"
scale: 0.00390625
}
# 指定测试用的lmdb文件的路径,注意这里和train使用的文件不同
data_param {
source: "../mnist_test_lmdb"
batch_size: 100     #指定batch_size批量的大小,和train的不同
backend: LMDB
}
}

# 卷积层1
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
# 学习率
param {
lr_mult: 1      # 卷积层参数的学习率
}
param {
lr_mult: 2      # 偏置参数的学习率
}
# 卷积层的参数
convolution_param {
num_output: 20
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"        #卷积层参数的初始化的方式
}
bias_filler {
type: "constant"      #偏置参数出初始化为常数
}
}
}

# 池化层1
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
# 层的参数
pooling_param {
pool: MAX       # 池化的方式
kernel_size: 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
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}

# 池化层2
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}

# 全连接层1
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"
}
}
}

# ReLU层
# 注意:一般激活层的bottom和top的名字一样(后面解释)
layer {
name: "relu1"
type: "ReLU"
bottom: "ip1"
top: "ip1"
}

# 全连接层2
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"
}
}
}

# 精度层,只在test时有效
layer {
name: "accuracy"
type: "Accuracy"
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}

# softmaxloss层
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
}


*说明以下几点:

1、可以将全连接层看成是一种特殊的卷积层,所以一般全连接层的卷积层的参数形式是一样的。

2、除了数据输入层其他层都有top和bottom,输入数据层有top但是没有bottom层。

3、注意: 层的名字和top和bottom名字是没有关系的,一般默认的情况是top的名字和层的名字相同,但是也可以不同,只要下一层的bottom和上一层的top名字一致就可以了,层取什么名字不影响,这里需要注意的是下层的bottom其实对应的上层的top的名字而不是上层的层的名字。

4、注意:在激活层中,一般top和bottom层的名字一样,是因为在caffe中内存是与top和bottom的名字对应起来的,比如只要几个top或者bottom的名字相同,则其是相同的内存,因此在RELU层,经过RELU后相当于把上一层的Conv层的输出的数据改变了,这样可以节省空间。

以上路径都是自己为了测试改过的,实际都应该对应自己的对应文件的路径

3、网络结构

在caffe中根据定义的net文件如何显式显示网络的结构,这里推荐网站

http://ethereon.github.io/netscope/#/editor),lenet文件可视化后的网络结构如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: