如何以HDF5格式提供caffe多标签数据?
我想用一个向量标签的咖啡,而不是整数。 我查了一些答案,看来HDF5是一个更好的方法。 但是,然后我陷入了像这样的错误:
outer_num_ * inner_num_ == bottom[1]->count():34]检查失败:outer_num_ * inner_num_ == bottom[1]->count()(50与200)标签数量必须匹配预测数量; 例如,如果标签轴== 1且预测形状是(N,C,H,W),则标签计数(标签数量)必须是N*H*W,其中整数值在{0,1,…, C-1}。
与HDF5创build为:
f = h5py.File('train.h5', 'w') f.create_dataset('data', (1200, 128), dtype='f8') f.create_dataset('label', (1200, 4), dtype='f4')
我的networking是由以下产生的:
def net(hdf5, batch_size): n = caffe.NetSpec() n.data, n.label = L.HDF5Data(batch_size=batch_size, source=hdf5, ntop=2) n.ip1 = L.InnerProduct(n.data, num_output=50, weight_filler=dict(type='xavier')) n.relu1 = L.ReLU(n.ip1, in_place=True) n.ip2 = L.InnerProduct(n.relu1, num_output=50, weight_filler=dict(type='xavier')) n.relu2 = L.ReLU(n.ip2, in_place=True) n.ip3 = L.InnerProduct(n.relu1, num_output=4, weight_filler=dict(type='xavier')) n.accuracy = L.Accuracy(n.ip3, n.label) n.loss = L.SoftmaxWithLoss(n.ip3, n.label) return n.to_proto() with open(PROJECT_HOME + 'auto_train.prototxt', 'w') as f: f.write(str(net('/home/romulus/code/project/train.h5list', 50))) with open(PROJECT_HOME + 'auto_test.prototxt', 'w') as f: f.write(str(net('/home/romulus/code/project/test.h5list', 20)))
看起来我应该增加标签号码,把整数而不是数组中的东西,但如果我这样做,咖啡抱怨数据的数量和标签是不相等的,然后存在。
那么,提供多标签数据的正确格式是什么?
此外,我很想知道为什么没有人只是写数据格式如何HDF5映射到咖啡斑点?
回答这个问题的标题:
HDF5文件应该有两个根数据集,分别命名为“data”和“label”。 形状是( data amount , dimension )。 我只使用一维数据,所以我不确定channel , width和height的顺序是什么。 也许没关系。 dtype应该是float或者double。
用h5py创build的示例代码创buildh5py是:
导入h5py,os
将numpy导入np
f = h5py.File('train.h5','w')
#1200数据,每个数据是一个128-dimvector
f.create_dataset('data',(1200,128),dtype ='f8')
#数据标签,每个标签都是一个4-dim向量
f.create_dataset('label',(1200,4),dtype ='f4')
#填写固定模式的东西
#将值调整到0到1之间,否则SigmoidCrossEntropyLoss将不起作用
我在范围内(1200):
a = np.empty(128)
如果我%4 == 0:
对于范围内的j(128):
a [j] = j / 128.0;
l = [1,0,0,0]
elif i%4 == 1:
对于范围内的j(128):
a [j] =(128-j)/128.0;
l = [1,0,1,0]
elif i%4 == 2:
对于范围内的j(128):
a [j] =(j%6)/128.0;
l = [0,1,1,0]
elif i%4 == 3:
对于范围内的j(128):
a [j] =(j%4)* 4 / 128.0;
l = [1,0,1,1]
f ['data'] [i] = a
f ['label'] [i] = 1
f.close()
另外,不需要准确的图层,简单的删除就可以了。 下一个问题是损失层。 由于SoftmaxWithLoss只有一个输出(具有最大值的维度的索引),因此不能用于多标签问题。 感谢Adian和Shai,我发现SigmoidCrossEntropyLoss在这种情况下是很好的。
下面是完整的代码,从数据创build,培训networking,并获得testing结果:
main.py(从caffe lanet例子中修改)
import操作系统,系统
PROJECT_HOME ='... / project /'
CAFFE_HOME ='... / caffe /'
os.chdir(PROJECT_HOME)
sys.path.insert(0,CAFFE_HOME +'caffe / python')
import咖啡,h5py
从pylab导入*
从咖啡import层作为L.
def net(hdf5,batch_size):
n = caffe.NetSpec()
n.data,n.label = L.HDF5Data(batch_size = batch_size,source = hdf5,ntop = 2)
n.ip1 = L.InnerProduct(n.data,num_output = 50,weight_filler = dict(type ='xavier'))
n.relu1 = L.ReLU(n.ip1,in_place = True)
n.ip2 = L.InnerProduct(n.relu1,num_output = 50,weight_filler = dict(type ='xavier'))
n.relu2 = L.ReLU(n.ip2,in_place = True)
n.ip3 = L.InnerProduct(n.relu2,num_output = 4,weight_filler = dict(type ='xavier'))
n.loss = L.SigmoidCrossEntropyLoss(n.ip3,n.label)
返回n.to_proto()
打开(PROJECT_HOME +'auto_train.prototxt','w')为f:
f.write(str(net(PROJECT_HOME +'train.h5list',50)))
打开(PROJECT_HOME +'auto_test.prototxt','w')为f:
f.write(str(net(PROJECT_HOME +'test.h5list',20)))
caffe.set_device(0)
caffe.set_mode_gpu()
solver = caffe.SGDSolver(PROJECT_HOME +'auto_solver.prototxt')
solver.net.forward()
solver.test_nets [0]的.forward()
solver.step(1)
硝基= 200
test_interval = 10
train_loss =零(硝酸)
test_acc = zeros(int(np.ceil(niter * 1.0 / test_interval)))
打印len(test_acc)
输出=零((niter,8,4))
#主要求解器循环
在范围内(硝酸):
solver.step(1)#Caffe
train_loss [it] = solver.net.blobs ['loss']。data
solver.test_nets [0]的.forward(开始= '数据')
输出[it] = solver.test_nets [0] .blobs ['ip3']。data [:8]
如果它%test_interval == 0:
打印“迭代”,它,“testing...”
正确= 0
data = solver.test_nets [0] .blobs ['ip3']。data
label = solver.test_nets [0] .blobs ['label']。data
对于范围(100)中的test_it:
solver.test_nets [0]的.forward()
#正值映射到标签1,负值映射到标签0
我在范围内(len(数据)):
对于范围内的j(len(data [i])):
如果data [i] [j]> 0和label [i] [j] == 1:
正确+ = 1
elif data [i] [j]%lt; = 0和label [i] [j] == 0:
正确+ = 1
test_acc [int(it / test_interval)] = correct * 1.0 /(len(data)* len(data [0])* 100)
#完成训练和testing,输出stream行图
_,ax1 = subplots()
ax2 = ax1.twinx()
ax1.plot(arange(niter),train_loss)
ax2.plot(test_interval * arange(len(test_acc)),test_acc,'r')
ax1.set_xlabel( '迭代')
ax1.set_ylabel('火车丢失')
ax2.set_ylabel('test accuracy')
_.savefig( 'converge.png')
#检查最后一批的结果
打印solver.test_nets [0] .blobs ['ip3']。data
打印solver.test_nets [0] .blobs ['label']。data
h5list文件在每行中只包含h5文件的path:
train.h5list
/home/foo/bar/project/train.h5
test.h5list
/home/foo/bar/project/test.h5
和解决者:
auto_solver.prototxt
train_net:“auto_train.prototxt” test_net:“auto_test.prototxt” test_iter:10 test_interval:20 base_lr:0.01 动力:0.9 weight_decay:0.0005 lr_policy:“inv” γ:0.0001 功率:0.75 显示:100 max_iter:10000 快照:5000 snapshot_prefix:“sed” solver_mode:GPU
收敛图:
最后一批结果:
[[35.91593933 -37.46276474 -6.2579031 -6.30313492] [42.69248581 -43.00864792 13.19664764 -3.35134125] [-1.36403108 1.38531208 2.77786589 -0.34310576] [2.91686511 -2.88944006 4.34043217 0.32656598] ... [35.91593933 -37.46276474 -6.2579031 -6.30313492] [42.69248581 -43.00864792 13.19664764 -3.35134125] [-1.36403108 1.38531208 2.77786589 -0.34310576] [2.91686511 -2.88944006 4.34043217 0.32656598]] [[1.0.0.0] [1.0.1.0] [0.1.1.0] [1. 0. 1. 1] ... [1.0.0.0] [1.0.1.0] [0.1.1.0] [1. 0. 1. 1.]]
我认为这个代码还有很多东西需要改进。 任何build议表示赞赏。
您的准确性层没有意义。
准确性层的工作方式 : caffe准确性层期望两个input
(i)预测的概率向量和
(ii)地面实况相应的标量整数标签。
准确性层比检查预测标签的概率是否确实是最大(或在top_k内)。
因此,如果您必须对C不同的类进行分类,那么您的input将是属于每个C类的N样本的input预测概率Ninput(其中N是批量大小),以及N标签。
在networking中定义的方式 :您input准确性层数的N比4预测和N比4的标签 – 这对caffe毫无意义。