Классификация изображений с несколькими классами и метками с использованием Caffe

Я пытаюсь создать в кафе единую многоклассовую и многоклассовую сетевую конфигурацию.

Скажем, классификация собак: собака маленькая или большая? (класс) Какого цвета? (класс) у него есть ошейник? (метка)

Возможно ли это с помощью кофе? Как правильно это сделать?

Просто пытаюсь понять практический способ .. После создания 2 текстовых файлов (один для обучения и один для проверки), содержащих все теги изображений, например:

/train/img/1.png 0 4 18
/train/img/2.png 1 7 17 33
/train/img/3.png 0 4 17

Запускаем скрипт py:

import h5py, os
import caffe
import numpy as np

SIZE = 227 # 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

И создание train.h5 и val.h5 (содержит ли набор данных X изображения, а Y - метки?).

Замените мои сетевые входные слои из:

layers { 
 name: "data" 
 type: DATA 
 top:  "data" 
 top:  "label" 
 data_param { 
   source: "/home/gal/digits/digits/jobs/20181010-191058-21ab/train_db" 
   backend: LMDB 
   batch_size: 64 
 } 
 transform_param { 
    crop_size: 227 
    mean_file: "/home/gal/digits/digits/jobs/20181010-191058-21ab/mean.binaryproto" 
    mirror: true 
  } 
  include: { phase: TRAIN } 
} 
layers { 
 name: "data" 
 type: DATA 
 top:  "data" 
 top:  "label" 
 data_param { 
   source: "/home/gal/digits/digits/jobs/20181010-191058-21ab/val_db"  
   backend: LMDB 
   batch_size: 64
 } 
 transform_param { 
    crop_size: 227 
    mean_file: "/home/gal/digits/digits/jobs/20181010-191058-21ab/mean.binaryproto" 
    mirror: true 
  } 
  include: { phase: TEST } 
} 

to

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

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

Полагаю, HDF5 не нуждается в mean.binaryproto?

Затем, как должен измениться выходной слой, чтобы вывести множественные вероятности меток? Полагаю, мне нужен слой кросс-энтропии вместо softmax? Это текущие выходные слои:

layers {
  bottom: "prob"
  bottom: "label"
  top: "loss"
  name: "loss"
  type: SOFTMAX_LOSS
  loss_weight: 1
}
layers {
  name: "accuracy"
  type: ACCURACY
  bottom: "prob"
  bottom: "label"
  top: "accuracy"
  include: { phase: TEST }
}

person Gal Dalali    schedule 29.10.2018    source источник


Ответы (1)


Среднее вычитание

Хотя уровень входных данных lmdb может обрабатывать различные входные преобразования за вас, слой "HDF5Data" не поддерживает эту функцию.
Поэтому вы должны позаботиться обо всех входных преобразованиях (в частности, о среднем вычитании), когда вы создаете свои файлы hdf5.
Посмотрите, где написано в вашем коде

# you may apply other input transformations here...

Несколько этикеток

Хотя ваш .txt содержит несколько меток для каждого изображения, вы сохраняете только первую в файл hdf5. Если вы хотите использовать эти метки, вы должны скармливать их сети.
Проблема, которая сразу же возникает из вашего примера, заключается в том, что у вас нет фиксированного количества меток для каждого обучающего изображения - почему? что это означает?
Предположим, у вас есть три метки для каждого изображения (в файлах .txt):

‹Имя файла>‹ размер собаки> ‹цвет собаки>‹ есть ошейник>

Тогда вы можете иметь y_size, y_color и y_collar (вместо одного y) в вашем hdf5.

y_size[i] = float(spl[1])
y_color[i] = float(spl[2])
y_collar[i] = float(spl[3])

Ваш уровень входных данных будет иметь больше "top"s соответственно:

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

Прогноз

В настоящее время ваша сеть предсказывает только одну метку (слой с top: "prob"). Вам нужна ваша сеть для предсказания всех трех меток, поэтому вам нужно добавить слои, которые вычисляют top: "prob_size", top: "prob_color" и top: "prob_collar" (разные слои для каждого "prob_*").
Как только у вас есть прогноз для каждой метки, вам понадобится потеря (опять же, потеря для каждой метки).

person Shai    schedule 29.10.2018
comment
Так понятнее. У меня есть фиксированное количество ярлыков, но как мне его представить? Допустим, у меня есть 5 этикеток: большой, маленький, белый, черный, воротник. Если изображение 1 содержит большую белую собаку с ошейником, тег будет выглядеть следующим образом: /train/img/1.png 1 0 1 0 1? - person Gal Dalali; 29.10.2018
comment
И как мне представить это правильно, потому что он как бы смешан между классами и метками: Размер - это класс, содержащий 2 метки. Color - это класс, содержащий (допустим) 5 меток. а воротник - это просто ярлык, который может быть верным или ложным. - person Gal Dalali; 29.10.2018