web-dev-qa-db-ja.com

HDF5形式でカフェマルチラベルデータをフィードする方法

整数ではなく、ベクトルラベル付きのカフェを使用したい。いくつかの回答を確認しましたが、HDF5がより良い方法のようです。しかし、それから私は次のようなエラーに行き詰まっています:

precision_layer.cpp:34]チェックに失敗しました:outer_num_ * inner_num_ == bottom[1]->count()(50対200)ラベルの数は予測の数と一致する必要があります。たとえば、ラベル軸== 1で予測形状が(N、C、H、W)の場合、ラベル数(ラベル数)はN*H*W、{0、1、...、C-1}の整数値。

hDF5を次のように作成:

f = h5py.File('train.h5', 'w')
f.create_dataset('data', (1200, 128), dtype='f8')
f.create_dataset('label', (1200, 4), dtype='f4')

私のネットワークは以下によって生成されます:

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がカフェBlobにマップするかをデータ形式だけで記述しないのはなぜでしょうか。

10

この質問のタイトルへの回答:

HDF5ファイルのルートには、それぞれ「data」と「label」という2つのデータセットが必要です。形状は(data amountdimension)です。 1次元のデータのみを使用しているため、channelwidthheightの順序がわかりません。多分それは問題ではありません。 dtypeは、floatまたはdoubleでなければなりません。

h5pyでトレインセットを作成するサンプルコードは次のとおりです。

 import h5py、os 
 import numpy as np 
 
 f = h5py.File( 'train.h5'、 'w')
# 1200個のデータ、それぞれが128次元のベクトルです
 f.create_dataset( 'data'、(1200、128)、dtype = 'f8')
#データのラベル、それぞれが4次元ですvector 
 f.create_dataset( 'label'、(1200、4)、dtype = 'f4')
 
#固定パターンで何かを入力
#正規化0と1の間の値、またはSigmoidCrossEntropyLossは機能しません
 for i in range(1200):
 a = np.empty(128)
 if i%4 == 0 :
 j for range(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:
 for j in range(128):
 a [j] =(j%6)/ 128.0; 
 l = [0,1,1,0] 
 Elif i%4 == 3:
 for j in range(128):
 a [j] = (j%4) * 4/128.0; 
 l = [1,0,1,1] 
 f ['data'] [i] = a 
 f ['label'] [i ] = l 
 
 f.close()

また、精度レイヤーは不要で、単に削除するだけで問題ありません。次の問題は損失層です。 SoftmaxWithLossには出力(最大値を持つ次元のインデックス)が1つしかないため、マルチラベル問題には使用できません。 AdianとShaiのおかげで、この場合はSigmoidCrossEntropyLossが良いと思います。

以下は、データ作成、ネットワークのトレーニング、およびテスト結果の取得からの完全なコードです。

main.py(caffe lanetの例から変更)

 import os、sys 
 
 PROJECT_HOME = '.../project /'
 CAFFE_HOME =' .../caffe /'
 os .chdir(PROJECT_HOME)
 
 sys.path.insert(0、CAFFE_HOME + 'caffe/python')
 import caffe、h5py 
 
 from pylab import * 
 from caffe import layer as 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)
 return n.to_proto()
 
 open(PROJECT_HOME + 'auto_train.prototxt'、 'w')with f:
 f.write(str(net(PROJECT_HOME + 'train.h5list'、50)))
 with open(PROJECT_HOME + 'auto_test.prototxt'、 'w')as 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)
 
 niter = 200 
 test_interval = 10 
 train_loss = zeros(niter)
 test_acc = zeros(int(np .ceil(niter * 1.0/test_interval)))
 print len(test_acc)
 output = zeros((niter、8、4))
 
#Theメインソルバーループ
それの範囲内(niter):
 solver.step(1)#CaffeによるSGD 
 train_loss [it] = solver.net.blobs ['loss' ] .data 
 solver.test_nets [0] .forward(start = 'data')
 output [it] = solver.test_nets [0] .blobs ['ip3']。data [: 8] 
 
もしそれが%test_interval == 0の場合:
 print 'Iteration'、 it、 'testing ...' 
正しい= 0 
 data = solver.test_nets [0] .blobs ['ip3']。data 
 label = solver.test_nets [0 ] .blobs ['label']。data 
 test_it for range(100):
 solver.test_nets [0] .forward()
#正の値はラベル1にマップされます、負の値は、範囲内のiのラベル0 
にマップされます(len(data)):
範囲内のjの場合(len(data [i])):
データの場合[i] [j]> 0およびラベル[i] [j] == 1:
正+ = 1 
 Elifデータ[i] [j]%lt; = 0およびラベル[ i] [j] == 0:
正しい+ = 1 
 test_acc [int(it/test_interval)] =正しい* 1.0 /(len(data)* len(data [0]) * 100)
 
#トレーニングとテストが完了し、収束グラフを出力します
 _、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( 'iteration')
 ax1.set_ylabel( 'train loss')
 ax2.set_ylabel( 'test precision')
 _。savefig ( 'converge.png')
 
#最後のバッチの結果を確認します
 print solver.test_nets [0] .blobs ['ip3']。data 
 print solver.test_nets [0] .blobs ['label']。data 

h5listファイルには、各行にh5ファイルのパスが含まれています。

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 
 momentum: 0.9 
 weight_decay:0.0005 
 lr_policy: "inv" 
 gamma:0.0001 
 power:0.75 
 display:100 
 max_iter: 10000 
 snapshot:5000 
 snapshot_prefix: "sed" 
 solver_mode:GPU 

収束グラフ: Converge graph

最後のバッチ結果:

 [[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.8894 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。]]] 

このコードにはまだ改善すべき点がたくさんあると思います。任意の提案をいただければ幸いです。

23

精度レイヤーは意味がありません。

精度レイヤーの動作方法caffe で精度レイヤーは2つの入力を想定しています
(i)予測確率vectorおよび
(ii)対応するスカラー整数ラベル。
精度レイヤーは、予測されたラベルの確率が実際に最大である(またはtop_k)。
したがって、C異なるクラスを分類する必要がある場合、入力はN- by -Cになります(ここでNはバッチサイズ)NクラスとCラベルのそれぞれに属するNサンプルの入力予測確率。

ネットでの定義方法:精度レイヤーを入力N- by-4予測とN- by-4ラベル-これはカフェには意味がありません。

1
Shai