我正在尝试检测两个图像在同一个地方拍摄不同时间的变化像素,因此我使用切片窗口为两个图像中的每个像素获取5x5色块。
之后,我为每张图片获得了45000个补丁,我随机选择了35000个补丁用于训练,其他补丁用于测试(两个图像使用相同的选择)。
然后我存储在train/train1
和train/train2
,val/val1
和val/val2
中。
train1.txt
看起来像path/to/train/train1/1_00001.png 0
,train2.txt looks like path/to/train/train2/2_00001.png 0
,
1_00001
和2_00001
是两张图片中的对应像素,label=0
表示未更改,label=1
表示已更改,val1.txt
和val2.txt
相似。
我没有转换成lmdb或leveldb,而是直接使用ImageData Layer,在DataLayer
之后,我的目标是在通道中连接两个blob(两个图像是单通道),所以我的train_val.prototxt
是:
name: "ChangeDetec"
layer {
name: "data"
type: "ImageData"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
image_data_param {
source: "data/changedetec/train1.txt"
batch_size: 500
}
}
layer {
name: "pair_data"
type: "ImageData"
top: "pair_data"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
image_data_param {
source: "data/changedetec/train2.txt"
batch_size: 500
}
}
layer {
name: "data"
type: "ImageData"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
image_data_param {
source: "data/changedetec/val1.txt"
batch_size: 1000
}
}
layer {
name: "pair_data"
type: "ImageData"
top: "pair_data"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
image_data_param {
source: "data/changedetec/val2.txt"
batch_size: 1000
}
}
layer {
name: "channelconcat"
type: "Concat"
bottom: "data"
bottom: "para_data"
top: "concatdata"
}
layer {
name: "conv1/5x5"
type: "Convolution"
bottom: "concatdata"
top: "conv1/5x5"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 64
pad: 0
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv1/relu_5x5"
type: "ReLU"
bottom: "conv1/5x5"
top: "conv1/5x5"
}
layer {
name: "conv2/1x1"
type: "Convolution"
bottom: "conv1/5x5"
top: "conv2/1x1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 64
kernel_size: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv2/relu_1x1"
type: "ReLU"
bottom: "conv2/1x1"
top: "conv2/1x1"
}
layer {
name: "conv3/1x1"
type: "Convolution"
bottom: "conv2/1x1"
top: "conv3/1x1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 32
pad: 0
kernel_size: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv3/relu"
type: "ReLU"
bottom: "conv3/1x1"
top: "conv3/1x1"
}
layer {
name: "conv4/1x1"
type: "Convolution"
bottom: "conv3/1x1"
top: "conv4/1x1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 16
pad: 0
kernel_size: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv4/relu"
type: "ReLU"
bottom: "conv4/1x1"
top: "conv4/1x1"
}
layer {
name: "conv5/1x1"
type: "Convolution"
bottom: "conv4/1x1"
top: "conv5/1x1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 8
pad: 0
kernel_size: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv5/relu"
type: "ReLU"
bottom: "conv5/1x1"
top: "conv5/1x1"
}
layer {
name: "conv6/1x1"
type: "Convolution"
bottom: "conv5/1x1"
top: "conv6/1x1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 4
pad: 0
kernel_size: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv6/relu"
type: "ReLU"
bottom: "conv6/1x1"
top: "conv6/1x1"
}
layer {
name: "conv7/1x1"
type: "Convolution"
bottom: "conv6/1x1"
top: "conv7/1x1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 2
pad: 0
kernel_size: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "conv7/relu"
type: "ReLU"
bottom: "conv7/1x1"
top: "conv7/1x1"
}
layers {
name: "pool"
bottom: "conv7/1x1"
top: "pool"
type: "Pooling"
pooling_param {
pool: AVE
kernel_size: 1
stride: 1
}
}
layer {
name: "accuracy"
type: "Accuracy"
bottom: "pool"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
layers {
name: "loss"
type: SoftmaxWithLoss
bottom: "pool"
bottom: "label"
top: "loss"
include: { phase: TRAIN }
}
和solver.prototxt是:
net: "examples/changedetec/train_val.prototxt"
test_iter: 500
test_interval: 500
base_lr: 0.001
lr_policy: "step"
gamma: 0.1
stepsize: 100000
display: 20
max_iter: 450000
momentum: 0.9
weight_decay: 0.0005
snapshot: 5000
snapshot_prefix: "examples/changedetec/changedetec_train"
solver_mode: GPU
但是我得到了错误:
I0812 10:33:31.980985 3846 solver.cpp:91] Creating training net from net file: examples/changedetec/train_val.prototxt
[libprotobuf ERROR google/protobuf/text_format.cc:245] Error parsing text-format caffe.NetParameter: 11:11: Expected double.
F0812 10:33:31.981097 3846 upgrade_proto.cpp:79] Check failed: ReadProtoFromTextFile(param_file, param) Failed to parse NetParameter file: examples/changedetec/train_val.prototxt
*** Check failure stack trace: ***
@ 0x7f148e770daa (unknown)
@ 0x7f148e770ce4 (unknown)
@ 0x7f148e7706e6 (unknown)
@ 0x7f148e773687 (unknown)
@ 0x7f148eecae3e caffe::ReadNetParamsFromTextFileOrDie()
@ 0x7f148eedf17b caffe::Solver<>::InitTrainNet()
@ 0x7f148eee024c caffe::Solver<>::Init()
@ 0x7f148eee057a caffe::Solver<>::Solver()
@ 0x7f148eea2043 caffe::Creator_SGDSolver<>()
@ 0x40ed1e caffe::SolverRegistry<>::CreateSolver()
@ 0x407ec2 train()
@ 0x405cbc main
@ 0x7f148d2cdf45 (unknown)
@ 0x40648d (unknown)
@ (nil) (unknown)
Aborted (core dumped)
我的prototxts有什么问题,或者我做错了什么?有没有更好的方法来解决这个问题?这困扰了我这么多天,请帮助我。
8月23日更新
我修复了一些低级错误,但仍然遇到其他一些错误:
我评论了scale:0.00390625
,因为错误显示Error parsing text-format caffe.NetParameter: 11:11: Expected double.
。
然后原始错误已修复,但错误已跳至Pooling layer
,说Expected integer or identifier
,因此我评论Pooling layer
并更改了最后Convolution layer
和我使用ReLU layer
时SoftmaxWithLoss layer
的num_output为2,但错误与Pooling layer
相同,但SoftmaxWithLoss layer
除外。
我尝试了SigmoidCrossEntropyLoss
,最后Convolution layer
和ReLU layer
的num_output为1,但对此事没有任何影响。
我还将图像转换为LMDB,但错误与上面的1-3一样。