Подтвердить что ты не робот

Тестовые этикетки для регрессионного кофе, поплавок не допускаются?

Я делаю регрессию с помощью caffe, а файлы test.txt и train.txt выглядят следующим образом:

/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

Моя проблема заключается в том, что, похоже, caffe не допускает float-меток типа 2.0, когда я использую ярлыки float во время чтения, например, только для файла 'test.txt' file caffe распознает

всего 1 изображение

что неверно.

Но когда я, например, меняю 2.0 на 2 в файле и на следующие строки, caffe теперь дает

всего 2 изображения

подразумевая, что метки с плавающей точкой несут ответственность за проблему.

Может ли кто-нибудь помочь мне здесь, чтобы решить эту проблему, мне определенно нужно использовать float-метки для регрессии, так кто-нибудь знает о работе или решении для этого? Спасибо заранее.

ИЗМЕНИТЬ Для тех, кто сталкивается с аналогичной проблемой, использовать caffe для обучения Lenet с данными CSV может оказаться полезным. Благодаря @Shai.

4b9b3361

Ответ 1

При использовании входного слоя набора данных изображения (с помощью или leveldb) caffe поддерживает только один ярлык целочисленный для каждого входного изображения.

Если вы хотите сделать регрессию и использовать метки с плавающей запятой, вы должны попробовать и использовать уровень данных HDF5. См. Например этот вопрос.

В python вы можете использовать пакет h5py для создания файлов 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

Как только у вас есть все файлы h5 и соответствующие им тестовые файлы, вы можете добавить входной уровень HDF5 к вашему 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 }
 }

Разъяснение:
Когда я говорю: "caffe поддерживает только одну целую метку для каждого входного изображения", я не имею в виду, что контейнеры leveldb/lmdb ограничены, я имел в виду инструменты caffe, в частности convert_imageset.
При ближайшем рассмотрении кажется, что данные хранилища хранятся в типе Datum в leveldb/lmdb, а свойство label (метка) этого типа определяется как целое число (см. caffe.proto), поэтому при использовании интерфейса caffe для leveldb/lmdb вы ограничены одной меткой int32 для каждого изображения.

Ответ 2

Ответ Shai уже охватывает сохранение меток float в формате HDF5. В случае необходимости/предпочтительности LMDB здесь приведен фрагмент того, как создать LMDB из данных с плавающей запятой (адаптирован из этот комментарий 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()

Ответ 3

Я закончил перенос, переключив порядок каналов и используя unsigned ints, а не floats, чтобы получить результаты. Я предлагаю прочитать изображение из файла HDF5, чтобы убедиться, что оно отображается правильно.

Сначала прочитайте изображение как unsigned ints:

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

Затем измените порядок каналов от RGB до BGR:

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

Наконец, переключитесь с Height x Width x Каналы на каналы x Высота x Ширина:

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

Простое изменение формы будет искажать ваше изображение и разрушать ваши данные!

Чтобы прочитать изображение:

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

Здесь script я написал, что касается двух ярлыков (руля и скорости) для самозанятого автомобильного задания: https://gist.github.com/crizCraig/aa46105d34349543582b177ae79f32f0

Ответ 4

Помимо @Shai answer выше, я написал MultiTaskData, поддерживающий float типизированные метки.

Его основная идея - хранить метки в float_data поле Datum, а MultiTaskDataLayer будет анализировать их как метки для любого количества задач в соответствии со значениями task_num и label_dimension, установленными в net.prototxt. Связанные файлы включают в себя: caffe.proto, multitask_data_layer.hpp/cpp, io.hpp/cpp.

Вы можете легко добавить этот слой в свой собственный кофе и использовать его как это (это пример для задачи обучения распределению меток выражения лица, в которой "exp_label" может быть вложенными векторами типа float, такими как [0,1, 0,1, 0,5, 0,2, 0,1], представляющие распределение вероятностей выражения (5 классов).):

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