Как передать данные мульти-лейбла 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
этикетки.
Как это определено в вашей сети: вы вводите слой точности N
4 прогноза и N
-по 4 ярлыкам - это не имеет смысла для кофе.