caffe-在新样本上使用训练好的模型

用训练好的模型给测试样本打分

经过训练有了模型:my_lr_iter_10000.caffemodel,将新的样本数据的LMDB文件 mnist_newTEST_lmdb 的路径在TEST网络的DataLayer层中指明,将含有标签的新样本文件dataLayer的source:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
layer{
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST # 该层应用与TEST
}
transform_param{
scale: 0.0039063
}
data_param{
source: "/media/junhui/DATA/caffe_workspace/my_linearReggresion/mnist_newTEST_lmdb"
batch_size: 100 # 每一批 100个样本
backend: LMDB
}
}

使用一下命令执行:

1
2
3
4
~/caffe-master/build/tools/caffe test \
-model /media/junhui/DATA/caffe_workspace/my_linearReggresion/mylr.prototxt \
-weights /media/junhui/DATA/caffe_workspace/my_linearReggresion/my_lr_iter_10000.caffemodel \
-iterations 2

test 表示使用TEST网络【只进行前行传播】打分,-model 指明模型结构参数,-weights 指明训练好的模型权值,-iterations 指明对多少样本进行inference,2*100 个样本。

其中caffe实际是可执行文件caffe.bin

这里是日志文件:

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
I0617 13:28:09.083691  4697 caffe.cpp:275] Use CPU.
I0617 13:28:09.308647 4697 net.cpp:296] The NetState phase (1) differed from the phase (0) specified by a rule in layer mnist
I0617 13:28:09.308768 4697 net.cpp:53] Initializing net from parameters:
name: "lrNet"
state {
phase: TEST
level: 0
stage: ""
}
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.0039063
}
data_param {
source: "/media/junhui/DATA/caffe_workspace/my_linearReggresion/mnist_newtest_lmdb"
batch_size: 100
backend: LMDB
}
}
layer {
name: "ip"
type: "InnerProduct"
bottom: "data"
top: "ip"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "accuracy"
type: "Accuracy"
bottom: "ip"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip"
bottom: "label"
top: "loss"
}
I0617 13:28:09.308953 4697 layer_factory.hpp:77] Creating layer mnist
I0617 13:28:09.309533 4697 db_lmdb.cpp:35] Opened lmdb /media/junhui/DATA/caffe_workspace/my_linearReggresion/mnist_newtest_lmdb
# 略
I0617 13:14:44.887392 3080 net.cpp:200] loss needs backward computation.
I0617 13:14:44.887401 3080 net.cpp:202] accuracy does not need backward computation.
I0617 13:14:44.887406 3080 net.cpp:200] ip_ip_0_split needs backward computation.
I0617 13:14:44.887411 3080 net.cpp:200] ip needs backward computation.
I0617 13:14:44.887415 3080 net.cpp:202] label_mnist_1_split does not need backward computation.
I0617 13:14:44.887420 3080 net.cpp:202] mnist does not need backward computation.
I0617 13:14:44.887424 3080 net.cpp:244] This network produces output accuracy
I0617 13:14:44.887430 3080 net.cpp:244] This network produces output loss
I0617 13:14:44.887439 3080 net.cpp:257] Network initialization done.
I0617 13:14:44.888084 3080 caffe.cpp:281] Running for 2 iterations.
# 结果:
I0617 13:14:44.888623 3080 caffe.cpp:304] Batch 0, accuracy = 0.94
I0617 13:14:44.888634 3080 caffe.cpp:304] Batch 0, loss = 0.21204
I0617 13:14:44.889169 3080 caffe.cpp:304] Batch 1, accuracy = 0.96
I0617 13:14:44.889178 3080 caffe.cpp:304] Batch 1, loss = 0.199202
I0617 13:14:44.889200 3080 caffe.cpp:309] Loss: 0.205621
I0617 13:14:44.889210 3080 caffe.cpp:321] accuracy = 0.95
I0617 13:14:44.889219 3080 caffe.cpp:321] loss = 0.205621 (* 1 = 0.205621 loss)

由Log发现,在新样本上使用TEST网络,依然进行了反向传播?因为在TEST网络中要求loss,与accuracy一样是衡量模型在样本上的性能的指标,accuracy越大,loss越小,新能相对越好。而这层需要反向传播计算获得。从尾反向传播到头,所以Log就理所当然了

使用不带标签的新样本

测试猜想

猜测这种情况下的TEST网络结构只有数据层和全连接层(因为上述网络只有这两个层与label数据无关),最终结果是全连接层的输出。只有两层,进行前向计算(对一批测试,每一批只有一个元素):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
I0617 13:48:08.206188 5203 caffe.cpp:304] Batch 0, ip = 0.483029
I0617 13:48:08.206202 5203 caffe.cpp:304] Batch 0, ip = -4.20101
I0617 13:48:08.206208 5203 caffe.cpp:304] Batch 0, ip = 0.95857
I0617 13:48:08.206213 5203 caffe.cpp:304] Batch 0, ip = 4.77686
I0617 13:48:08.206219 5203 caffe.cpp:304] Batch 0, ip = -5.86976
I0617 13:48:08.206223 5203 caffe.cpp:304] Batch 0, ip = 5.99296
I0617 13:48:08.206228 5203 caffe.cpp:304] Batch 0, ip = -1.1105
I0617 13:48:08.206233 5203 caffe.cpp:304] Batch 0, ip = 0.394778
I0617 13:48:08.206238 5203 caffe.cpp:304] Batch 0, ip = -0.198426
I0617 13:48:08.206243 5203 caffe.cpp:304] Batch 0, ip = -0.884502
I0617 13:48:08.206248 5203 caffe.cpp:309] Loss: 0
I0617 13:48:08.206256 5203 caffe.cpp:321] ip = 0.483029
I0617 13:48:08.206264 5203 caffe.cpp:321] ip = -4.20101
I0617 13:48:08.206269 5203 caffe.cpp:321] ip = 0.95857
I0617 13:48:08.206272 5203 caffe.cpp:321] ip = 4.77686
I0617 13:48:08.206277 5203 caffe.cpp:321] ip = -5.86976
I0617 13:48:08.206282 5203 caffe.cpp:321] ip = 5.99296
I0617 13:48:08.206287 5203 caffe.cpp:321] ip = -1.1105
I0617 13:48:08.206292 5203 caffe.cpp:321] ip = 0.394778
I0617 13:48:08.206297 5203 caffe.cpp:321] ip = -0.198426
I0617 13:48:08.206301 5203 caffe.cpp:321] ip = -0.884502

发现比没有反向计算,因为不需要求loss,且输出是10个值,与网络结构对应 num_output: 10

转化自己的raw数据为LMDB数据

对于自己的MNIST数据,使用 /home/junhui/caffe-master/build/examples/mnist/convert_mnist_data.bin 命令,用法如下:

1
2
# 命令 图片文件 对应标签文件 保存位置
convert_mnist_data.bin input_image_file input_label_file output_db_file

那么caffe是如何将所下载的mnist数据集转化为LMDB的,见examples/mnist/create_mnist.sh,分析一下:

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
# 只要这个bash脚本中任何一条命令的返回值不是0,
# 就退出整个脚本,因为默认是有错继续执行。
set -e

# 4个变量,
EXAMPLE=examples/mnist
DATA=data/mnist
BUILD=build/examples/mnist

BACKEND="lmdb"

# 打印内容:
echo "Creating ${BACKEND}..."

# 将之前的DB文件删除
rm -rf $EXAMPLE/mnist_train_${BACKEND}
rm -rf $EXAMPLE/mnist_test_${BACKEND}

# 调用 convert_mnist_data.bin 命令,
$BUILD/convert_mnist_data.bin $DATA/train-images-idx3-ubyte \
$DATA/train-labels-idx1-ubyte $EXAMPLE/mnist_train_${BACKEND} --backend=${BACKEND}
$BUILD/convert_mnist_data.bin $DATA/t10k-images-idx3-ubyte \
$DATA/t10k-labels-idx1-ubyte $EXAMPLE/mnist_test_${BACKEND} --backend=${BACKEND}
# 最终在制定的路径中生成 mnist_train_ 和 mnist_test_ 。

echo "Done."

convert_mnist_data.bin 命令对应的源文件在 examples/mnist/convert_mnist_data.cpp,阅读发现其解析过程是根据 train-images-idx3-ubyte 文件的格式的。

下一步:

  1. 如何从LMDB中读取每一条数据?
  2. 将不含标签的数据保存为LMDB?
  3. 写自己的 convert_XXX_data.bin 工具,和bash脚本。