Etiquetas de teste para regressão caffe, float não permitido?

Eu estou fazendo regressão usando o caffe, e meus arquivos test.txt e train.txt são assim:

 /home/foo/caffe/data/finetune/flickr/3860781056.jpg 2.0 /home/foo/caffe/data/finetune/flickr/4559004485.jpg 3.6 /home/foo/caffe/data/finetune/flickr/3208038920.jpg 3.2 /home/foo/caffe/data/finetune/flickr/6170430622.jpg 4.0 /home/foo/caffe/data/finetune/flickr/7508671542.jpg 2.7272 

Meu problema é que parece que o caffe não permite labels flutuantes como o 2.0, quando eu uso labels flutuantes durante a leitura, por exemplo, o arquivo 'test.txt' o caffe só reconhece

um total de 1 imagens

o que está errado.

Mas quando eu por exemplo mudo o 2.0 para 2 no arquivo e as linhas seguintes mesmo, o caffe agora dá

um total de 2 imagens

implicando que os labels flutuantes são responsáveis ​​pelo problema.

Alguém pode me ajudar aqui, para resolver esse problema, eu definitivamente preciso usar labels float para regressão, para que alguém saiba sobre um trabalho ou solução para isso? Desde já, obrigado.

EDIT Para quem enfrenta um problema semelhante, usar o caffe para treinar o Lenet com dados CSV pode ser útil . Graças a @Shai.

Ao usar a camada de input do dataset de imagem (com backend leveldb ou leveldb ), o caffe suporta apenas um label inteiro por imagem de input.

Se você quiser fazer regressão e usar labels de ponto flutuante, tente usar a camada de dados HDF5. Veja por exemplo esta questão .

Em python você pode usar o pacote h5py para criar arquivos hdf5.

 import h5py, os import caffe import numpy as np SIZE = 224 # fixed size to all images with open( 'train.txt', 'r' ) as T : lines = T.readlines() # If you do not have enough memory split data into # multiple batches and generate multiple separate h5 files X = np.zeros( (len(lines), 3, SIZE, SIZE), dtype='f4' ) y = np.zeros( (len(lines),1), dtype='f4' ) for i,l in enumerate(lines): sp = l.split(' ') img = caffe.io.load_image( sp[0] ) img = caffe.io.resize( img, (SIZE, SIZE, 3) ) # resize to fixed size # you may apply other input transformations here... # Note that the transformation should take img from size-by-size-by-3 and transpose it to 3-by-size-by-size # for example # transposed_img = img.transpose((2,0,1))[::-1,:,:] # RGB->BGR X[i] = transposed_img y[i] = float(sp[1]) with h5py.File('train.h5','w') as H: H.create_dataset( 'X', data=X ) # note the name X given to the dataset! H.create_dataset( 'y', data=y ) # note the name y given to the dataset! with open('train_h5_list.txt','w') as L: L.write( 'train.h5' ) # list all h5 files you are going to use 

Depois de ter todos os arquivos h5 e os arquivos de teste correspondentes listando-os, você pode adicionar uma camada de input HDF5 ao seu train_val.prototxt :

  layer { type: "HDF5Data" top: "X" # same name as given in create_dataset! top: "y" hdf5_data_param { source: "train_h5_list.txt" # do not give the h5 files directly, but the list. batch_size: 32 } include { phase:TRAIN } } 

Esclarecimento :
Quando digo “caffe suporta apenas um label inteiro por imagem de input” não quero dizer que os containers leveldb / lmdb são limitados, eu quis dizer as ferramentas do caffe, especificamente a ferramenta convert_imageset .
Em uma inspeção mais próxima, parece que o caffe armazena dados do tipo Datum em leveldb / lmdb e a propriedade “label” desse tipo é definida como integer (veja caffe.proto ), portanto, ao usar a interface caffe para leveldb / lmdb você está restrito a único label int32 por imagem.

A resposta de Shai já cobre salvar etiquetas flutuantes no formato HDF5. Caso o LMDB seja obrigatório / preferido, aqui está um trecho sobre como criar um LMDB a partir de dados flutuantes (adaptado deste comentário do github):

 import lmdb import caffe def scalars_to_lmdb(scalars, path_dst): db = lmdb.open(path_dst, map_size=int(1e12)) with db.begin(write=True) as in_txn: for idx, x in enumerate(scalars): content_field = np.array([x]) # get shape (1,1,1) content_field = np.expand_dims(content_field, axis=0) content_field = np.expand_dims(content_field, axis=0) content_field = content_field.astype(float) dat = caffe.io.array_to_datum(content_field) in_txn.put('{:0>10d}'.format(idx) dat.SerializeToString()) db.close() 

Acabei transpondo, trocando a ordem do canal e usando ints não assinados em vez de floats para obter resultados. Eu sugiro a leitura de uma imagem de volta do seu arquivo HDF5 para se certificar de que ele seja exibido corretamente.

Primeiro leia a imagem como ints não assinados:

img = np.array(Image.open('images/' + image_name))

Em seguida, altere a ordem do canal de RGB para BGR:

img = img[:, :, ::-1]

Finalmente, mude de altura x largura x canais para canais x altura x largura:

img = img.transpose((2, 0, 1))

Simplesmente mudando a forma vai embaralhar sua imagem e arruinar seus dados!

Para ler de volta a imagem:

 with h5py.File(h5_filename, 'r') as hf: images_test = hf.get('images') targets_test = hf.get('targets') for i, img in enumerate(images_test): print(targets_test[i]) from skimage.viewer import ImageViewer viewer = ImageViewer(img.reshape(SIZE, SIZE, 3)) viewer.show() 

Aqui está um script que eu escrevi que lida com dois labels (direção e velocidade) para uma tarefa de carro autônomo: https://gist.github.com/crizCraig/aa46105d34349543582b177ae79f32f0

Além da resposta de @ Shai acima, eu escrevi uma camada MultiTaskData compatível com labels typescripts float .

Sua idéia principal é armazenar os labels no campo float_data do Datum , e o MultiTaskDataLayer irá analisá-los como labels para qualquer número de tarefas de acordo com o valor de task_num e label_dimension definido em net.prototxt . Os arquivos relacionados incluem: caffe.proto , multitask_data_layer.hpp/cpp , io.hpp/cpp .

Você pode facilmente adicionar essa camada ao seu próprio caffe e usá-la assim (este é um exemplo para a tarefa de aprendizado de distribuição de label de expressão facial em que o “exp_label” pode ser vetores tipados float como [0.1, 0.1, 0.5, 0.2, 0.1 ] representando a distribuição de probabilidade das expressões faciais (5 classs).):

  name: "xxxNet" layer { name: "xxx" type: "MultiTaskData" top: "data" top: "exp_label" data_param { source: "expression_ld_train_leveldb" batch_size: 60 task_num: 1 label_dimension: 8 } transform_param { scale: 0.00390625 crop_size: 60 mirror: true } include:{ phase: TRAIN } } layer { name: "exp_prob" type: "InnerProduct" bottom: "data" top: "exp_prob" param { lr_mult: 1 decay_mult: 1 } param { lr_mult: 2 decay_mult: 0 } inner_product_param { num_output: 8 weight_filler { type: "xavier" } bias_filler { type: "constant" } } } layer { name: "exp_loss" type: "EuclideanLoss" bottom: "exp_prob" bottom: "exp_label" top: "exp_loss" include:{ phase: TRAIN } }