2015-10-15 2 views
8

Я хочу использовать кофе с векторной меткой, а не целой. Я проверил несколько ответов, и, кажется, HDF5 - лучший способ. Но тогда я stucked с ошибкой, как:Как подавать данные с несколькими метками caffe в формате HDF5?

accuracy_layer.cpp:34] Check failed: outer_num_ * inner_num_ == bottom[1]->count() (50 vs. 200) Number of labels must match number of predictions; e.g., if label axis == 1 and prediction shape is (N, C, H, W), label count (number of labels) must be N*H*W , with integer values in {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))) 

Кажется, я должен увеличить количество этикеток и помещайте вещи в целое число, а не в массив, но если я это сделаю, caffe жалуется, что число данных и метка не равно, а затем существует.

Итак, каков правильный формат для подачи данных с несколькими метками?

Кроме того, я так удивляюсь, почему никто просто не просто пишет формат данных, как HDF5 сопоставляет с капотами?

+0

не должен 'data' типа' f4' также? – Shai

+0

Изменение на f4 не изменяет ошибку. –

+1

Возможно, ценный ресурс: http://stackoverflow.com/questions/33112941/multiple-category-classification-in-caffe –

ответ

21

Ответ на этот вопрос титул в:

Файл HDF5 должен иметь два набора данных в корневом каталоге, с именем «данные» и «метки», соответственно. Форма (data amount, dimension). Я использую только одномерные данные, поэтому я не уверен, что составляет channel, width и height. Может быть, это неважно. dtype должно быть плавающим или двойным.

пример кода создания набора поезд с h5py является:

 
import h5py, os 
import numpy as np 

f = h5py.File('train.h5', 'w') 
# 1200 data, each is a 128-dim vector 
f.create_dataset('data', (1200, 128), dtype='f8') 
# Data's labels, each is a 4-dim vector 
f.create_dataset('label', (1200, 4), dtype='f4') 

# Fill in something with fixed pattern 
# Regularize values to between 0 and 1, or SigmoidCrossEntropyLoss will not work 
for i in range(1200): 
    a = np.empty(128) 
    if i % 4 == 0: 
     for j in range(128): 
      a[j] = j/128.0; 
     l = [1,0,0,0] 
    elif i % 4 == 1: 
     for j in range(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 имеет только один вывод (индекс измерения с максимальным значением), он не может использоваться для проблемы с несколькими метками. Спасибо Adian и Shai, я нахожу, что SigmoidCrossEntropyLoss хорош в этом случае.

Ниже приведен полный код, от создания данных, обучения сети, и получения результата теста:

main.py (modified from caffe lanet example)

 
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 layers 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() 

with open(PROJECT_HOME + 'auto_train.prototxt', 'w') as 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 main solver loop 
for it in range(niter): 
    solver.step(1) # SGD by Caffe 
    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] 

    if it % test_interval == 0: 
     print 'Iteration', it, 'testing...' 
     correct = 0 
     data = solver.test_nets[0].blobs['ip3'].data 
     label = solver.test_nets[0].blobs['label'].data 
     for test_it in range(100): 
      solver.test_nets[0].forward() 
      # Positive values map to label 1, while negative values map to label 0 
      for i in range(len(data)): 
       for j in range(len(data[i])): 
        if data[i][j] > 0 and label[i][j] == 1: 
         correct += 1 
        elif data[i][j] %lt;= 0 and label[i][j] == 0: 
         correct += 1 
     test_acc[int(it/test_interval)] = correct * 1.0/(len(data) * len(data[0]) * 100) 

# Train and test done, outputing convege graph 
_, 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 accuracy') 
_.savefig('converge.png') 

# Check the result of last batch 
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 график: 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.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.]] 

Я думаю, что этот код все еще есть много вещей, чтобы улучшить. Любое предложение приветствуется.

+0

Можете ли вы объяснить, как определяется метка, является ли она бинарной системой? –

+0

Да, я только пытался использовать двоичную систему. ON - 1, а OFF - 0. –

+0

. Какова версия для caffe? Для меня есть ошибка 'ImportError: невозможно импортировать слои имен – tidy

1

Ваш уровень точности не имеет смысла.

Способ точность слой работает: в точность слой ожидает, два входа
(I) предсказанный вектор вероятность и
(II) основной истина, соответствующий скалярного целого метку.
Уровень точности, чем проверка того, действительно ли вероятность прогнозируемой метки действительно максимальная (или в пределах top_k).
Поэтому, если у вас есть для классификации C различных классов, ваши входы будет NC матрицы с размерностью (где N является размером партии) вход предсказывал вероятности для N образцов, принадлежащих каждый из классов C и N этикеток.

Как это определенно в ваших чистых: введеная точности слой N их-4 предсказаний и N их-4 этикетки - это не имеет никакого смысла для CAFFE.

+0

Кажется, я неправильно понял уровень точности. Но если я удалю его, то уровень потерь возвращает мне ту же ошибку. Может, мне нужен еще один слой Loss для векторной метки? Я не могу найти список доступных уровней потерь. –

+0

Я попробовал EuclideanLoss (без уровня точности), но он возвращает массивный nan. –

+1

@ RomulusUrakagiTs'ai это 'NaN' для самого начала? может быть, что потеря слишком высока, заставляя вас градиенты «взорваться», бросая ваше обучение. Постарайтесь * значительно * уменьшить «loss_weight» уровня потерь. – Shai

Смежные вопросы