接着上一篇blog继续写,今天是使用数据来训练LeNet,此处是用来进行图像的二分类问题,但是因为LeNet本身结构上的一些问题(主要是用来识别手写数字,在Mnist上训练效果可以达到99%),在进行了几轮实验后,发现最终的实验结果并不是非常理想,accuracy最高也才到85%,loss大概是在0.33左右,训练model重在调参,这是今天感受最深的一句话,我能说这大半天都在进行调参吗?
(/ω\)
虽然用的GPU比用CPU但是训练一遍也大概要20min(两块1080ti),但是实际训练中应该只有一块在跑(可能还是数据量小?相比于Mnist的数据集,GPU的色噪音小多了),现在正在一旁训练LeNet。
回到调参的问题,昨天晚上因为是第一次训练没经验,有些参数也没太看懂,导致出了一些问题。先来看一下比较重要的几个文件
再来附上这张图(比昨天的增加和修改了一些)
定义网络结构的lenet_train_text.prototxt文件
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168name: "LeNet"
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
data_param {
source: "/home/deep/caffe/examples/My_Files/Build_lmdb/train_lmdb"
batch_size: 34 //注意调节好此处和下面的batch_size的大小
backend: LMDB
}
}
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
data_param {
source: "/home/deep/caffe/examples/My_Files/Build_lmdb/val_lmdb"
batch_size: 38
backend: LMDB
}
}
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"
}
}
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 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"
}
}
}
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"
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: "relu1"
type: "ReLU"
bottom: "ip1"
top: "ip1"
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 2 //注意根据自己的需要进行改变,这里是二分类问题
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "accuracy"
type: "Accuracy"
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
}注意调节batch_size大小,第一次直接使用训练Mnist的那套参数导致,一直不收敛,且loss一直是87.3365,改变之后loss终于降低
定义训练参数的lenet_solver.prototxt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#网络原型文件的位置
net: "/home/deep/caffe/examples/My_Files/lenet_train_test.prototxt"
#测试迭代的次数,这里需要test_iter和上面TEST下面的batch_size的乘积要>=测试集的数据量
test_iter: 50
#由于是边进行训练边进行测试,这里就是指每训练500次要进行一下测试
test_interval: 500
#基础的学习率,学习率请看下方引用1部分;下面两个一般不用改
base_lr: 0.0001
momentum: 0.9
weight_decay: 0.0005
#这里也没改过
lr_policy: "inv"
gamma: 0.0001
power: 0.75
# Display every 100 iterations
display: 100
#这个就是指最大的迭代次数
max_iter: 10000
#每5000次保存一次快照,方便之后对模型进行后续的训练
snapshot: 5000
snapshot_prefix: "/home/deep/caffe/examples/My_Files/lenet"
#训练模式,这里选择的是GPU模式
solver_mode: GPU引用1:
运用梯度下降算法进行优化时,权重的更新规则中,在梯度项前会乘以一个系数,这个系数就叫学习速率η。下面讨论在训练时选取η的策略。
- 固定的学习速率。如果学习速率太小,则会使收敛过慢,如果学习速率太大,则会导致代价函数振荡,如下图所示
执行训练的脚本文件train.sh
1
2
3
4
5#!/usr/bin/env sh
set -e
/home/deep/caffe/build/tools/caffe train \
--solver=/home/deep/caffe/examples/My_Files/lenet_solver.prototxt $@这个直接执行sudo bash train.sh就开始训练了,打印过程就不写了
| Type | test_iter | test_interval | base_lr | train_size | test_size | accuracy | loss |
| :—: | :——-: | :———–: | :—–: | :——–: | :——-: | :——: | :——: |
| LeNet | 100 | 500 | 0.0001 | 136 | 24 | 0.85875 | 0.338477 |
| LeNet | 50 | 500 | 0.0001 | 136 | 40 | 0.860526 | 0.337723 |
| LeNet | 50 | 500 | 0.0001 | 34 | 38 | 0.861053 | 0.321303 |几次训练的参数和最终的结果见上表↑
这里可以看一篇文章↓
训练完成之后可以看到生成的多个成对出现的 .caffemodel 和 .solverstate文件,一个是模型文件,一个是中间状态文件(生成多少个取决于你自己设定的snapshot)。当训练过程中断,你想继续运行数据学习,此时只需要调用.solverstate文件即可。
使用方式代码,我使用的是.sh直接运行,配置和官方给的文件train_caffenet.sh差不多,稍微添加点内容就可以了,按自己的情况进行对应修改。
1
2
3./build/tools/caffe train \
--solver=examples/test/solver.prototxt \
--snapshot=examples/test/test_100000.solverstate参考下面的文章↓
之后改用AlecNet进行了5W次迭代准确率可以达到95%左右,通过输出结果可以看出1.5W次到5W次迭代之间accuracy大概就是在94%~96%这个范围之间
这个马一些以后用↓