solver各参数的用途
#往往loss function是非凸的,没有解析解,我们需要通过优化方法来求解。
#caffe提供了六种优化算法来求解最优参数,在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")
net: "examples/mnist/lenet_train_test.prototxt"
test_iter: 100
test_interval: 500
base_lr: 0.01
momentum: 0.9
type: SGD
weight_decay: 0.0005
lr_policy: "inv"
gamma: 0.0001
power: 0.75
display: 100
max_iter: 3000
snapshot: 500
snapshot_prefix: "examples/mnist/lenet"
solver_mode: CPU
net: "examples/mnist/lenet_train_test.prototxt" #网络位置
train_net: "examples/hdf5_classification/logreg_auto_train.prototxt" #也可以分别设定train和test
test_net: "examples/hdf5_classification/logreg_auto_test.prototxt"
test_iter: 100 #迭代了多少个测试样本呢? batch*test_iter 假设有5000个测试样本,一次测试想跑遍这5000个则需要设置test_iter×batch=5000,如果你的gpu显存是3g的,那batchsize可以设置为64,8g的可以设置为128。
test_interval: 500 #测试间隔。也就是每训练500次,才进行一次测试。
base_lr: 0.01 #base_lr用于设置基础学习率
lr_policy: "inv" #学习率调整的策略
- fixed: 保持base_lr不变.
- step: 如果设置为step,则还需要设置一个stepsize, 返回 base_lr * gamma ^ (floor(iter / stepsize)),其中iter表示当前的迭代次数
- exp: 返回base_lr * gamma ^ iter, iter为当前迭代次数
- inv: 如果设置为inv,还需要设置一个power, 返回base_lr * (1 + gamma * iter) ^ (- power)
- multistep: 如果设置为multistep,则还需要设置一个stepvalue。这个参数和step很相似,step是均匀等间隔变化,而multistep则是根据 stepvalue值变化
- poly: 学习率进行多项式误差, 返回 base_lr (1 - iter/max_iter) ^ (power)
- sigmoid: 学习率进行sigmod衰减,返回 base_lr ( 1/(1 + exp(-gamma * (iter - stepsize))))
momentum :0.9 #动量
display: 100 #每训练100次,在屏幕上显示一次。如果设置为0,则不显示。
max_iter: 3000 #最大迭代次数,2W次就停止了
snapshot: 500 #快照。将训练出来的model和solver状态进行保存,snapshot用于设置训练多少次后进行保存,我一般设置为max_iter/10,多保存几个model
snapshot_prefix: "examples/mnist/lenet"
solver_mode: CPU #设置运行模式。默认为GPU,如果你没有GPU,则需要改成CPU,否则会出错。
python接口生成solver
#!/usr/bin/python # -*- coding: utf-8 -*- from caffe.proto import caffe_pb2 s = caffe_pb2.SolverParameter() #typelist = ['SGD','AdaDelta','AdaGrad','Adam','Nesterov','RMSProp'] #lrlist = ['inv','fixed','step','exp','multistep','poly','sigmoid'] path='/home/xxx/data/' solver_file=path+'solver1.prototxt' s.train_net = path+'train.prototxt' s.test_net.append(path+'val.prototxt') s.test_interval = 500 s.test_iter.append(100) s.max_iter = 100000 s.base_lr = 0.001 s.momentum = 0.9 s.weight_decay = 5e-4 s.lr_policy = 'step' s.stepsize=26067 s.gamma = 0.1 s.display = 1000 s.snapshot = 10000 s.snapshot_prefix = 'shapshot' s.type = “SGD” s.solver_mode = caffe_pb2.SolverParameter.GPU with open(solver_file, 'w') as f: f.write(str(s))
1.数据层
layer {
name: "cifar"
type: "Data"
top: "data" #一般用bottom表示输入,top表示输出,多个top代表有多个输出
top: "label"
include {
phase: TRAIN #训练网络分为训练阶段和自测试阶段,如果没写include则表示该层即在测试中,又在训练中
}
transform_param {
mean_file: "examples/cifar10/mean.binaryproto" #用一个配置文件来进行均值的操作
transform_param {
scale: 0.00390625
mirror: 1 # 1表示开启镜像,0表示关闭,也可用ture和false来表示
# 剪裁一个 227*227的图块,在训练阶段随机剪裁,在测试阶段从中间裁剪
crop_size: 227
}
}
data_param {
source: "examples/cifar10/cifar10_train_lmdb" #数据库来源
batch_size: 64 #每次批处理的个数
backend: LMDB #选用数据的名称
}
}
### 使用LMDB源
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/mnist/mnist_train_lmdb"
batch_size: 64
backend: LMDB
}
}
###使用HDF5数据源
layer {
name: "data"
type: "HDF5Data"
top: "data"
top: "label"
hdf5_data_param {
source: "examples/hdf5_classification/data/train.txt"
batch_size: 10
}
}
###数据直接来源与图片
#/path/to/images/img3423.jpg 2
#/path/to/images/img3424.jpg 13
#/path/to/images/img3425.jpg 8
layer {
name: "data"
type: "ImageData" #类型
top: "data"
top: "label"
transform_param {
mirror: false
crop_size: 227
mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"
}
image_data_param {
source: "examples/_temp/file_list.txt"
batch_size: 50
new_height: 256 #如果设置就对图片进行resize操作
new_width: 256
}
}
2.卷积层
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1 #lr_mult: 学习率的系数,最终的学习率是这个数乘以solver.prototxt配置文件中的base_lr。如果有两个lr_mult, 则第一个表示权值的学习率,第二个表示偏置项的学习率。一般偏置项的学习率是权值学习率的两倍。
}
param {
lr_mult: 2
}
convolution_param {
num_output: 20 #卷积核(filter)的个数
kernel_size: 5 #卷积核的大小
stride: 1 #卷积核的步长,默认为1
pad: 0 #扩充边缘,默认为0,不扩充
weight_filler {
type: "xavier" #权值初始化。 默认为“constant",值全为0,很多时候我们用"xavier"算法来进行初始化,也可以设置为”gaussian"
}
bias_filler {
type: "constant" #偏置项的初始化。一般设置为"constant",值全为0
}
}
}
输入:n*c0*w0*h0
输出:n*c1*w1*h1
其中,c1就是参数中的num_output,生成的特征图个数
w1=(w0+2*pad-kernel_size)/stride+1;
h1=(h0+2*pad-kernel_size)/stride+1;
3.池化层
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX #池化方法,默认为MAX。目前可用的方法有MAX, AVE
kernel_size: 3 #池化的核大小
stride: 2 #池化的步长,默认为1。一般我们设置为2,即不重叠。
}
}
#pooling层的运算方法基本是和卷积层是一样的。
4.激活函数
#在激活层中,对输入数据进行激活操作,是逐元素进行运算的,在运算过程中,没有改变数据的大小,即输入和输出的数据大小是相等的。
#ReLU是目前使用最多的激活函数,主要因为其收敛更快,并且能保持同样效果。标准的ReLU函数为max(x, 0),当x>0时,输出x; 当x<=0时,输出0
f(x)=max(x,0)
layer {
name: "relu1"
type: "ReLU"
bottom: "pool1"
top: "pool1"
}
5.全连接层
#全连接层,输出的是一个简单向量 参数跟卷积层一样
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: "accuracy"
type: "Accuracy"
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
import sys
caffe_root='/home/tyd/caffe/'
sys.path.insert(0, caffe_root+'python')
from caffe import layers as L
from caffe import params as P
import caffe
def lenet(lmdb, batch_size):
# our version of LeNet: a series of linear and simple nonlinear transformations
n = caffe.NetSpec()
n.data, n.label = L.Data(batch_size=batch_size, backend=P.Data.LMDB, source=lmdb,
transform_param=dict(scale=1./255), ntop=2)
n.conv1 = L.Convolution(n.data, kernel_size=5, num_output=20, weight_filler=dict(type='xavier'))
n.pool1 = L.Pooling(n.conv1, kernel_size=2, stride=2, pool=P.Pooling.MAX)
n.conv2 = L.Convolution(n.pool1, kernel_size=5, num_output=50, weight_filler=dict(type='xavier'))
n.pool2 = L.Pooling(n.conv2, kernel_size=2, stride=2, pool=P.Pooling.MAX)
n.ip1 = L.InnerProduct(n.pool2, num_output=500, weight_filler=dict(type='xavier'))
n.relu1 = L.ReLU(n.ip1, in_place=True)
n.ip2 = L.InnerProduct(n.relu1, num_output=10, weight_filler=dict(type='xavier'))
n.loss = L.SoftmaxWithLoss(n.ip2, n.label)
return n.to_proto()
with open('lenet_auto_train.prototxt', 'w') as f:
f.write(str(lenet('examples/mnist/mnist_train_lmdb', 64)))
with open('lenet_auto_test.prototxt', 'w') as f:
f.write(str(lenet('examples/mnist/mnist_test_lmdb', 100)))