回归咖啡的测试标签,不允许浮动?
Test labels for regression caffe, float not allowed?
我正在使用 caffe 进行回归,我的 test.txt
和 train.txt
文件是这样的:
/home/foo/caffe/data/finetune/flickr/3860781056.jpg 2.0
/home/foo/caffe/data/finetune/flickr/4559004485.jpg 3.6
/home/foo/caffe/data/finetune/flickr/3208038920.jpg 3.2
/home/foo/caffe/data/finetune/flickr/6170430622.jpg 4.0
/home/foo/caffe/data/finetune/flickr/7508671542.jpg 2.7272
我的问题是当我在阅读时使用浮动标签时,caffe 似乎不允许像 2.0 这样的浮动标签,例如 'test.txt'
文件 caffe
认识
a total of 1 images
这是错误的。
但是当我将文件中的 2.0 更改为 2 并且以下行相同时,caffe 现在给出
a total of 2 images
暗示浮动标签是造成问题的原因。
任何人都可以帮我解决这个问题,我肯定需要使用浮动标签进行回归,所以有人知道解决这个问题的方法或解决方案吗?提前致谢。
编辑
对于面临类似问题的任何人 可能会有帮助。感谢@Shai。
当使用图像数据集输入层时(使用 lmdb
或 leveldb
后端)caffe 仅支持每个输入图像一个 integer 标签。
如果你想做回归,并使用浮点标签,你应该尝试使用 HDF5 数据层。例如参见 [=19=].
在 python 中,您可以使用 h5py
包来创建 hdf5 文件。
import h5py, os
import caffe
import numpy as np
SIZE = 224 # fixed size to all images
with open( 'train.txt', 'r' ) as T :
lines = T.readlines()
# If you do not have enough memory split data into
# multiple batches and generate multiple separate h5 files
X = np.zeros( (len(lines), 3, SIZE, SIZE), dtype='f4' )
y = np.zeros( (len(lines),1), dtype='f4' )
for i,l in enumerate(lines):
sp = l.split(' ')
img = caffe.io.load_image( sp[0] )
img = caffe.io.resize( img, (SIZE, SIZE, 3) ) # resize to fixed size
# you may apply other input transformations here...
# Note that the transformation should take img from size-by-size-by-3 and transpose it to 3-by-size-by-size
# for example
# transposed_img = img.transpose((2,0,1))[::-1,:,:] # RGB->BGR
X[i] = transposed_img
y[i] = float(sp[1])
with h5py.File('train.h5','w') as H:
H.create_dataset( 'X', data=X ) # note the name X given to the dataset!
H.create_dataset( 'y', data=y ) # note the name y given to the dataset!
with open('train_h5_list.txt','w') as L:
L.write( 'train.h5' ) # list all h5 files you are going to use
获得所有 h5
文件和列出它们的相应测试文件后,您可以将 HDF5 输入层添加到 train_val.prototxt
:
layer {
type: "HDF5Data"
top: "X" # same name as given in create_dataset!
top: "y"
hdf5_data_param {
source: "train_h5_list.txt" # do not give the h5 files directly, but the list.
batch_size: 32
}
include { phase:TRAIN }
}
澄清:
当我说 "caffe only supports one integer label per input image" 我并不是说 leveldb/lmdb 容器是有限的,我的意思是 caffe 的工具,特别是 工具。
仔细观察,caffe 似乎将 Datum
类型的数据存储在 leveldb/lmdb 中,并且该类型的 "label" 属性 被定义为整数(参见 caffe.proto)因此,当使用 caffe 接口 leveldb/lmdb 时,每个图像只能使用一个 int32 标签。
already covers saving float labels to HDF5 format. In case LMDB is required/preferred, here's a snippet on how to create an LMDB from float data (adapted from this github 评论):
import lmdb
import caffe
def scalars_to_lmdb(scalars, path_dst):
db = lmdb.open(path_dst, map_size=int(1e12))
with db.begin(write=True) as in_txn:
for idx, x in enumerate(scalars):
content_field = np.array([x])
# get shape (1,1,1)
content_field = np.expand_dims(content_field, axis=0)
content_field = np.expand_dims(content_field, axis=0)
content_field = content_field.astype(float)
dat = caffe.io.array_to_datum(content_field)
in_txn.put('{:0>10d}'.format(idx) dat.SerializeToString())
db.close()
我最终转置,切换通道顺序,并使用无符号整数而不是浮点数来获得结果。我建议从您的 HDF5 文件中读回图像以确保它正确显示。
首先将图像读取为无符号整数:
img = np.array(Image.open('images/' + image_name))
然后将通道顺序从 RGB 更改为 BGR:
img = img[:, :, ::-1]
最后,从高 x 宽 x 通道切换到通道 x 高 x 宽:
img = img.transpose((2, 0, 1))
仅仅改变形状会扰乱您的图像并破坏您的数据!
回读图像:
with h5py.File(h5_filename, 'r') as hf:
images_test = hf.get('images')
targets_test = hf.get('targets')
for i, img in enumerate(images_test):
print(targets_test[i])
from skimage.viewer import ImageViewer
viewer = ImageViewer(img.reshape(SIZE, SIZE, 3))
viewer.show()
这是我编写的脚本,它处理自动驾驶汽车任务的两个标签(转向和速度):https://gist.github.com/crizCraig/aa46105d34349543582b177ae79f32f0
除了 above, I wrote a MultiTaskData 层支持 float
类型的标签。
其主要思想是将标签存储在Datum
的float_data
字段中,MultiTaskDataLayer
会根据[的值将其解析为任意数量任务的标签。 =15=] 和 label_dimension
在 net.prototxt
中设置。相关文件包括:caffe.proto
、multitask_data_layer.hpp/cpp
、io.hpp/cpp
.
你可以轻松地将这一层添加到你自己的caffe中并像这样使用它(这是面部表情标签分布学习任务的示例,其中"exp_label"可以是浮点类型的向量,例如[0.1, 0.1, 0.5, 0.2, 0.1]代表面部表情(5class)的概率分布。):
name: "xxxNet"
layer {
name: "xxx"
type: "MultiTaskData"
top: "data"
top: "exp_label"
data_param {
source: "expression_ld_train_leveldb"
batch_size: 60
task_num: 1
label_dimension: 8
}
transform_param {
scale: 0.00390625
crop_size: 60
mirror: true
}
include:{ phase: TRAIN }
}
layer {
name: "exp_prob"
type: "InnerProduct"
bottom: "data"
top: "exp_prob"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
inner_product_param {
num_output: 8
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "exp_loss"
type: "EuclideanLoss"
bottom: "exp_prob"
bottom: "exp_label"
top: "exp_loss"
include:{ phase: TRAIN }
}
我正在使用 caffe 进行回归,我的 test.txt
和 train.txt
文件是这样的:
/home/foo/caffe/data/finetune/flickr/3860781056.jpg 2.0
/home/foo/caffe/data/finetune/flickr/4559004485.jpg 3.6
/home/foo/caffe/data/finetune/flickr/3208038920.jpg 3.2
/home/foo/caffe/data/finetune/flickr/6170430622.jpg 4.0
/home/foo/caffe/data/finetune/flickr/7508671542.jpg 2.7272
我的问题是当我在阅读时使用浮动标签时,caffe 似乎不允许像 2.0 这样的浮动标签,例如 'test.txt'
文件 caffe
认识
a total of 1 images
这是错误的。
但是当我将文件中的 2.0 更改为 2 并且以下行相同时,caffe 现在给出
a total of 2 images
暗示浮动标签是造成问题的原因。
任何人都可以帮我解决这个问题,我肯定需要使用浮动标签进行回归,所以有人知道解决这个问题的方法或解决方案吗?提前致谢。
编辑
对于面临类似问题的任何人
当使用图像数据集输入层时(使用 lmdb
或 leveldb
后端)caffe 仅支持每个输入图像一个 integer 标签。
如果你想做回归,并使用浮点标签,你应该尝试使用 HDF5 数据层。例如参见 [=19=].
在 python 中,您可以使用 h5py
包来创建 hdf5 文件。
import h5py, os
import caffe
import numpy as np
SIZE = 224 # fixed size to all images
with open( 'train.txt', 'r' ) as T :
lines = T.readlines()
# If you do not have enough memory split data into
# multiple batches and generate multiple separate h5 files
X = np.zeros( (len(lines), 3, SIZE, SIZE), dtype='f4' )
y = np.zeros( (len(lines),1), dtype='f4' )
for i,l in enumerate(lines):
sp = l.split(' ')
img = caffe.io.load_image( sp[0] )
img = caffe.io.resize( img, (SIZE, SIZE, 3) ) # resize to fixed size
# you may apply other input transformations here...
# Note that the transformation should take img from size-by-size-by-3 and transpose it to 3-by-size-by-size
# for example
# transposed_img = img.transpose((2,0,1))[::-1,:,:] # RGB->BGR
X[i] = transposed_img
y[i] = float(sp[1])
with h5py.File('train.h5','w') as H:
H.create_dataset( 'X', data=X ) # note the name X given to the dataset!
H.create_dataset( 'y', data=y ) # note the name y given to the dataset!
with open('train_h5_list.txt','w') as L:
L.write( 'train.h5' ) # list all h5 files you are going to use
获得所有 h5
文件和列出它们的相应测试文件后,您可以将 HDF5 输入层添加到 train_val.prototxt
:
layer {
type: "HDF5Data"
top: "X" # same name as given in create_dataset!
top: "y"
hdf5_data_param {
source: "train_h5_list.txt" # do not give the h5 files directly, but the list.
batch_size: 32
}
include { phase:TRAIN }
}
澄清:
当我说 "caffe only supports one integer label per input image" 我并不是说 leveldb/lmdb 容器是有限的,我的意思是 caffe 的工具,特别是
仔细观察,caffe 似乎将 Datum
类型的数据存储在 leveldb/lmdb 中,并且该类型的 "label" 属性 被定义为整数(参见 caffe.proto)因此,当使用 caffe 接口 leveldb/lmdb 时,每个图像只能使用一个 int32 标签。
import lmdb
import caffe
def scalars_to_lmdb(scalars, path_dst):
db = lmdb.open(path_dst, map_size=int(1e12))
with db.begin(write=True) as in_txn:
for idx, x in enumerate(scalars):
content_field = np.array([x])
# get shape (1,1,1)
content_field = np.expand_dims(content_field, axis=0)
content_field = np.expand_dims(content_field, axis=0)
content_field = content_field.astype(float)
dat = caffe.io.array_to_datum(content_field)
in_txn.put('{:0>10d}'.format(idx) dat.SerializeToString())
db.close()
我最终转置,切换通道顺序,并使用无符号整数而不是浮点数来获得结果。我建议从您的 HDF5 文件中读回图像以确保它正确显示。
首先将图像读取为无符号整数:
img = np.array(Image.open('images/' + image_name))
然后将通道顺序从 RGB 更改为 BGR:
img = img[:, :, ::-1]
最后,从高 x 宽 x 通道切换到通道 x 高 x 宽:
img = img.transpose((2, 0, 1))
仅仅改变形状会扰乱您的图像并破坏您的数据!
回读图像:
with h5py.File(h5_filename, 'r') as hf:
images_test = hf.get('images')
targets_test = hf.get('targets')
for i, img in enumerate(images_test):
print(targets_test[i])
from skimage.viewer import ImageViewer
viewer = ImageViewer(img.reshape(SIZE, SIZE, 3))
viewer.show()
这是我编写的脚本,它处理自动驾驶汽车任务的两个标签(转向和速度):https://gist.github.com/crizCraig/aa46105d34349543582b177ae79f32f0
除了 float
类型的标签。
其主要思想是将标签存储在Datum
的float_data
字段中,MultiTaskDataLayer
会根据[的值将其解析为任意数量任务的标签。 =15=] 和 label_dimension
在 net.prototxt
中设置。相关文件包括:caffe.proto
、multitask_data_layer.hpp/cpp
、io.hpp/cpp
.
你可以轻松地将这一层添加到你自己的caffe中并像这样使用它(这是面部表情标签分布学习任务的示例,其中"exp_label"可以是浮点类型的向量,例如[0.1, 0.1, 0.5, 0.2, 0.1]代表面部表情(5class)的概率分布。):
name: "xxxNet"
layer {
name: "xxx"
type: "MultiTaskData"
top: "data"
top: "exp_label"
data_param {
source: "expression_ld_train_leveldb"
batch_size: 60
task_num: 1
label_dimension: 8
}
transform_param {
scale: 0.00390625
crop_size: 60
mirror: true
}
include:{ phase: TRAIN }
}
layer {
name: "exp_prob"
type: "InnerProduct"
bottom: "data"
top: "exp_prob"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
inner_product_param {
num_output: 8
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "exp_loss"
type: "EuclideanLoss"
bottom: "exp_prob"
bottom: "exp_label"
top: "exp_loss"
include:{ phase: TRAIN }
}