tutorial learning instalar caffe2 cafe python neural-network deep-learning caffe

python - learning - instalar caffe



¿Cómo alimentar los datos de múltiples etiquetas de caffe en formato HDF5? (2)

Tu capa de precisión no tiene sentido.

La forma en que funciona la capa de precisión : en la capa de precisión de caffe se esperan dos entradas
(i) un vector de probabilidad pronosticado y
(ii) etiqueta de entero escalar correspondiente a tierra-verdad.
La capa de precisión que comprueba si la probabilidad de la etiqueta predicha es de hecho la máxima (o dentro de top_k ).
Por lo tanto, si tiene que clasificar C clases diferentes, sus entradas van a ser N by- C (donde N es el tamaño de lote) ingrese las probabilidades pronosticadas para N muestras que pertenecen a cada una de las clases C , y N etiquetas.

La forma en que se define en su red : usted ingresa la precisión de la capa predicciones N -by-4 y etiquetas N -by-4, esto no tiene sentido para caffe.

Quiero usar caffe con una etiqueta de vector, no entera. He verificado algunas respuestas, y parece que HDF5 es una mejor manera. Pero luego estoy atónito con el error como:

accuracy_layer.cpp: 34] Verificación fallida: outer_num_ * inner_num_ == bottom[1]->count() (50 vs. 200) El número de etiquetas debe coincidir con el número de predicciones; por ejemplo, si el eje de etiqueta == 1 y la forma de predicción es (N, C, H, W), el recuento de etiquetas (número de etiquetas) debe ser N*H*W , con valores enteros en {0, 1, ..., C-1}.

con HDF5 creado como:

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

Mi red es generada por:

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

Parece que debería aumentar el número de etiqueta y poner las cosas en un entero en lugar de una matriz, pero si hago esto, caffe se queja de que la cantidad de datos y la etiqueta no son iguales, entonces existe.

Entonces, ¿cuál es el formato correcto para alimentar datos de etiquetas múltiples?

Además, me pregunto por qué nadie simplemente escribe el formato de datos de cómo HDF5 se asigna a las manchas de café.


Responda al título de esta pregunta:

El archivo HDF5 debe tener dos conjuntos de datos en la raíz, llamados "datos" y "etiqueta", respectivamente. La forma es ( data amount , dimension ). Estoy usando solo datos de una dimensión, por lo que no estoy seguro de cuál es el orden de channel , width y height . Tal vez no importa. dtype debe ser flotante o doble.

Un ejemplo de creación de código de tren configurado con h5py es:

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

Además, la capa de precisión no es necesaria, simplemente eliminarla está bien. El siguiente problema es la capa de pérdida. Como SoftmaxWithLoss tiene solo una salida (índice de la dimensión con valor máximo), no se puede usar para problemas de etiquetas múltiples. Gracias a Adian y Shai, creo que SigmoidCrossEntropyLoss es bueno en este caso.

A continuación se muestra el código completo, desde la creación de datos, la red de capacitación y el resultado de la prueba:

main.py (modificado del ejemplo de 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 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

Los archivos h5list simplemente contienen rutas de archivos h5 en cada línea:

train.h5list

/home/foo/bar/project/train.h5

test.h5list

/home/foo/bar/project/test.h5

y el solucionador:

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

Gráfico convergente:

Último resultado del lote:

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

Creo que este código todavía tiene muchas cosas que mejorar. Cualquier sugerencia es apreciada.