4. 设计自己的网络结构
通过前文的例子,我们都知道了Caffe的网络都是一个prototxt的网络结构配置文件定义的,该文件可以用文本工具打开,打开后,我们可以看到如下结构:
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
transform_param {
scale: 0.00390625
}
data_param {
source: "../../data/mnist/mnist_train_lmdb"
batch_size: 64
backend: LMDB
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 20
pad: 0
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0
}
}
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
...
在prototxt文件中,层都是用layer{}的结构表示,而里面包含的层的参数可以在caffe.proto文件中找到,比如说Data类型的结构由message DataParameter所定义,Convolution类型的结构由message ConvolutionParameter所定义。
具体说明下:
name表示该层的名称type表示该层的类型,如Data或者Convolution类型top表示该层后接的Blob结构的名称bottom表示该层前接的Blob数据结构的名称*_param表示该层的参数,比如对于某卷积层conv1来说,convolution_param中
num_output表示输出通道数pad表示卷积padkernel_size表示卷积核的大小- 关于卷积操作的具体解释可以参考
Theano的对卷积的介绍。
对于如何使用层结构,一方面我们可以从model_libs.py及caffenet.py等文件找到如何使用层结构的例子。另外可能参考这个教程,里面给出caffe的所有层的Python函数使用例子。
另一方面我们可以参照caffe的C++类定义。在我们知道各层的描述后,可以将这些层结构拼接成我们自己的网络,手动在文本工具中直接编写prototxt文件。
但对于一些非常复杂的网络,很多情况下可能有成百上千的层。这样的情况下,我们能难人工一层接一层的编写prototxt文件,而且还很容易出错,因此可以通过python来直接自动生成结构文件。
在caffe目录下的example/pycaffe文件夹的caffenet.py给出了如何直接生成一个多层线性分类器的网络配置文件prototxt文件,而本节还将介绍一个直接生成mnist LeNet5网络的训练、测试及实施的三个网络配置文件prototxt。而我们将以后章节中介绍通过三个文件完成LeNet5网络的训练及测试任务。
Tips:可以将一些常用的网络结构打包成基础体,比如在model_lib.py文件中将VGG网络、AlexNet等常用网络打包成基础网络。另外训练、测试及实施的三个网络的中间结构是一致的,只是输入层和最终输出层是不一样的,因此将可以中间相同层都用一个固定函数生成。
生成网络配置主要分为如下几个部分:
4.1 配置基础网络结构
这里生成训练、测试及实施的三个网络中都相同的网络中间部件
# 此函数生成LeNet5的主体结构
def lenet5_body(net, from_layer):
# 网络参数
kwargs = {
# param定义学习率,这里是指基础学习率step的情况,lt_mult乘以基础学习率为实际学习率,为0表示权重不更新,decay_mult同权重衰减相关
'param': [dict(lr_mult=1, decay_mult=1), dict(lr_mult=2, decay_mult=0)],
'weight_filler': dict(type='xavier'), # 权重初始化模式
'bias_filler': dict(type='constant', value=0)} # 权重偏差初始化模式
# 判断是否存在from_layer层
assert from_layer in net.keys()
# conv1
net.conv1 = L.Convolution(net[from_layer], kernel_size=5, stride=1, num_output=20, pad=0, **kwargs)
net.pool1 = L.Pooling(net.conv1, pool=P.Pooling.MAX, kernel_size=2, stride=2)
net.conv2 = L.Convolution(net.pool1, kernel_size=5, stride=1, num_output=50, pad=0, **kwargs)
net.pool2 = L.Pooling(net.conv2, pool=P.Pooling.MAX, kernel_size=2, stride=2)
net.ip1 = L.InnerProduct(net.pool2, num_output=500, **kwargs)
net.relu1 = L.ReLU(net.ip1, in_place=True)
net.ip2 = L.InnerProduct(net.relu1, name='ip2', num_output=10, **kwargs)
4.2 构建整体网络
训练、测试及实施的三个网络的结构有些许不同,主要集中在输入层和输出层。
# 训练网络
train_net = caffe.NetSpec() # 基础网络
# 带标签的数据输入层
train_net.data, train_net.label = L.Data(source=train_data,backend=P.Data.LMDB, batch_size=64,ntop=2,transform_param=dict(scale=0.00390625))
# 生成LeNet5的主体结构
lenet5_body(train_net, 'data')
# 生成误差损失层
train_net.loss = L.SoftmaxWithLoss(train_net.ip2, train_net.label)
# 测试网络
test_net = caffe.NetSpec() # 基础网络
# 带标签的数据输入层
test_net.data, test_net.label = L.Data(source=test_data, batch_size=100, backend=P.Data.LMDB, ntop=2,transform_param=dict(scale=0.00390625))
# 生成LeNet5的主体结构
lenet5_body(test_net, 'data')
# 生成误差损失层
test_net.loss = L.SoftmaxWithLoss(test_net.ip2, test_net.label)
# 添加一个精确层
test_net.accuracy = L.Accuracy(test_net.ip2, test_net.label)
# 实施网络
deploy_net = caffe.NetSpec() # 基础网络
# 带标签的数据输入层
deploy_net.data = L.Input(input_param=dict(shape=dict(dim=[64,1,28,28])))
# 生成LeNet5的主体结构
lenet5_body(deploy_net, 'data')
deploy_net.prob = L.Softmax(deploy_net.ip2)
4.3 prototxt文件的保存
通过to_proto将网络保存成prototxt文件
# 保存训练文件
with open(model_root+'train.prototxt', 'w') as f:
print('name: "LenNet5_train"', file=f)
print(train_net.to_proto(), file=f)
with open(model_root+'test.prototxt', 'w') as f:
print('name: "LenNet5_test"', file=f)
print(test_net.to_proto(), file=f)
with open(model_root+'deploy.prototxt', 'w') as f:
print('name: "LenNet5_test"', file=f)
print(deploy_net.to_proto(), file=f)
4.4 具体代码下载
GitHub仓库Caffe-Python-Tutorial中的prototxt.py

本文介绍如何使用Caffe自定义网络结构,包括通过Python生成LeNet5的训练、测试和部署配置文件的过程。文中详细解释了prototxt文件的组成,并提供了具体的代码示例。
565

被折叠的 条评论
为什么被折叠?



