Мультиклассовая и мультиметочная классификация изображений с использованием Caffe - PullRequest
0 голосов
/ 29 октября 2018

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

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

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

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

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

до

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 не нужно скупое двоичное имя?

Далее, как должен измениться выходной слой, чтобы вывести несколько вероятностей меток? Я думаю, мне нужен кросс-энтропийный слой вместо 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 }
}

1 Ответ

0 голосов
/ 29 октября 2018

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

Хотя слой входных данных 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" с соответственно:

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_*").
Когда у вас есть прогноз для каждой метки, вам нужна потеря (опять же, потеря для каждой метки).

...