Как передать данные мульти-лейбла caffe в формате HDF5?

Я хочу использовать caffe с векторной меткой, а не целым числом. Я проверил некоторые ответы, и кажется, что 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)))

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

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

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

2 ответа

Решение

Ответ на заголовок этого вопроса:

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

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

импорт h5py, os
импортировать numpy как np

f = h5py.File ('train.h5', 'w')
# 1200 данных, каждый из которых представляет собой 128-мерный вектор
f.create_dataset('data', (1200, 128), dtype='f8')
# Метки данных, каждый из которых представляет собой 4-мерный вектор
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] = l

f.close ()

Кроме того, слой точности не требуется, просто удалив его нормально. Следующая проблема - уровень потерь. поскольку SoftmaxWithLoss имеет только один выход (индекс измерения с максимальным значением), его нельзя использовать для задачи с несколькими метками. Спасибо 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') импорт caffe, h5py из pylab import * из слоев импорта caffe в виде 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)

niter = 200
test_interval = 10
train_loss = нули (нитры) test_acc = нули (int(np.ceil(niter * 1.0 / test_interval)))
print len ​​(test_acc)
output = zeros((niter, 8, 4))

# Основной цикл решения для него в диапазоне (niter):
    solver.step(1)  # SGD от 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] если это% test_interval == 0: вывести 'Iteration', it, 'testing...'
        correct = 0
        data = solver.test_nets[0].blobs['ip3'].data
        label = solver.test_nets[0].blobs['label']. данные для test_it в диапазоне (100):
            solver.test_nets[0].forward()
            # Положительные значения отображаются на метку 1, а отрицательные значения отображаются на метка 0 для i в диапазоне (len (данные)): для j в диапазоне (len(data[i])): если data[i][j] > 0 и метка [i][j] == 1: правильно += 1
                    elif data[i][j] %lt;= 0 и метка [i][j] == 0: исправить += 1
        test_acc[int(it / test_interval)] = правильно * 1.0 / (len(данные) * len(данные [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('итерация')
ax1.set_ylabel('потеря поезда')
ax2.set_ylabel(' проверка точности ')
_.savefig('converge.png')

# Проверить результат последней пакетной печати solver.test_nets [0].blobs [' ip3 ']. data print solver.test_nets [0].blobs [' label ' ].данные 

Файлы 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
импульс: 0,9
вес_день: 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.]] 

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

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

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

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

Другие вопросы по тегам