如何以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预测概率N
input(其中N
是批量大小),以及N
标签。
在networking中定义的方式 :您input准确性层数的N
比4预测和N
比4的标签 – 这对caffe毫无意义。