Как да използвате трансферно обучение и фина настройка в Keras и Tensorflow, за да изградите система за разпознаване на изображения и да класифицирате (почти) всеки обект

Примерни изображения от набора от данни на CompCars (163 марки автомобили, 1713 модела автомобили)
Отидете направо до кода в GitHub тук!

В последната публикация разгледах как да използвам Keras за разпознаване на някоя от 1000 обектни категории в предизвикателството за визуално разпознаване на ImageNet. По-често обаче не категориите, които се интересуваме да предвидим, не са в този списък.

И така, какво да правим, ако искаме да класифицираме между различни модели слънчеви очила? или обувки? или изражения на лицето? или различни модели автомобили? или различни видове белодробни заболявания в рентгенови снимки?

В тази публикация ще ви покажа как да използвате трансферно обучение и фина настройка, за да идентифицирате всякакви персонализирани категории обекти! За да резюмирам, ето поредицата от публикации в блога, която ще следваме:

  1. Изградете система за разпознаване на изображение за 1000 ежедневни категории обекти (ImageNet ILSVRC) с помощта на Keras и TensorFlow
  2. Изградете система за разпознаване на изображения за всякакви персонализирани категории обекти, като използвате трансферно обучение и фина настройка в Keras и TensorFlow (тази публикация)
  3. Изградете система за откриване на обекти в реално време за стотици ежедневни категории обекти (PASCAL VOC, COCO)
  4. Създайте уеб услуга за всяка система за разпознаване на изображения или за откриване на обекти

Защо да използвате трансферно обучение / фина настройка?

Добре известно е, че конволюционните мрежи изискват значителни количества данни и ресурси за обучение. Например, ImageNet ILSVRC моделът е обучен на 1,2 милиона изображения за период от 2-3 седмици в множество графични процесори.

Стана норма, а не изключение, за изследователи и практикуващи да използват еднакво обучение за прехвърляне и фина настройка, тоест прехвърляне на мрежовите тежести, обучени по предишна задача като ImageNet, на нова задача.

И се справя поразително добре! Razavian et al (2014) показаха, че просто използвайки функциите, извлечени с помощта на теглата от обучен модел ImageNet ILSVRC, те постигнаха най-съвременни или близки до най-съвременните показатели на голямо разнообразие от компютърно зрение задачи.

Има два подхода, които можем да предприемем:

  1. Предаване на обучение: вземете ConvNet, който е предварително обучен на ImageNet, премахнете последния напълно свързан слой, след което третирайте останалата част от ConvNet като екстрактор на функции за новия набор от данни. След като извлечете функциите за всички изображения, обучете класификатор за новия набор от данни.
  2. Фина настройка: заменете и преквалифицирайте класификатора отгоре на ConvNet и също така прецизно настройте тежестите на предварително обучената мрежа чрез backpropagation.

Кое да използвам?

Има два основни фактора, които ще повлияят на вашия избор на подход:

  1. Вашият размер на базата данни
  2. Прилика на вашия набор от данни с предварително обучения набор от данни (обикновено ImageNet)
Взето от http://cs231n.github.io/

* също трябва да експериментирате и с тренировките от нулата.

Фигурата по-горе и куршумите по-долу описват някои общи съвети за това кога да изберете кой подход.

  • Подобни и малки набори от данни: избягвайте пренастройването, като не прецизирате тежестите на малък набор от данни и използвайте извлечени функции от най-високите нива на ConvNet, за да използвате приликата на базата данни.
  • Различен и малък набор от данни: избягвайте пренастройването, като не прецизирате тежестите на малък набор от данни и използвайте извлечени функции от по-ниски нива на ConvNet, които са по-обобщаващи.
  • Подобен и голям набор от данни: с голям набор от данни можем да прецизираме тежестите с по-малък шанс да надстроим данните за тренировките.
  • Различен и голям набор от данни: с голям набор от данни отново можем да прецизираме тежестите с по-малък шанс за превишаване.

Увеличаване на данни

Мощен и общ инструмент за увеличаване на размера на набора от данни и обобщаемостта на модела е увеличаване на данните. Всъщност всяко състезание, което печели ConvNet, използва използването на данни за увеличаване. По същество увеличаването на данни е процесът на изкуствено увеличаване на размера на вашия набор от данни чрез трансформации.

Повечето библиотеки с дълбоко обучение имат готови функции за типични трансформации. За нашата система за разпознаване на изображения задачата, която имате, е да решите кои трансформации имат смисъл за вашите данни (например, рентгеновите изображения вероятно не трябва да се завъртат с повече от 45 градуса, защото това би означавало, че е възникнала грешка в придобиването на изображението стъпка).

Увеличаване на данни чрез хоризонтално обръщане и произволно изрязване

Примерни трансформации: Пиксел цвят трептене, въртене, срязване, произволно изрязване, хоризонтално прелистване, разтягане, корекция на лещата.

Трансфер на обучение и внедряване на фина настройка

Отидете направо до кода в GitHub тук!

Подготовка на данни

Примерни изображения от набора от данни на Kaggle за Cat срещу Dog

Ще използваме нашият пример на Kaggle's Dogs vs Cats и ще настроим данните си с указател за обучение и директория за валидиране по този начин:

train_dir /
  куче /
  котка /
val_dir /
  куче /
  котка /

изпълнение

Да започнем с подготовката на нашите генератори на данни:

train_datagen = ImageDataGenerator (
    preprocessing_function = preprocess_input,
    rotation_range = 30,
    width_shift_range = 0.2,
    height_shift_range = 0.2,
    shear_range = 0.2,
    zoom_range = 0.2,
    horizontal_flip = True
)
test_datagen = ImageDataGenerator (
    preprocessing_function = preprocess_input,
    rotation_range = 30,
    width_shift_range = 0.2,
    height_shift_range = 0.2,
    shear_range = 0.2,
    zoom_range = 0.2,
    horizontal_flip = True
)
train_generator = train_datagen.flow_from_directory (
  args.train_dir,
  target_size = (IM_WIDTH, IM_HEIGHT),
  batch_size = batch_size,
)
validation_generator = test_datagen.flow_from_directory (
  args.val_dir,
  target_size = (IM_WIDTH, IM_HEIGHT),
  batch_size = batch_size,
)

Спомнете си от предишната ни публикация в блога относно разпознаването на изображението важността на стъпката за предварителна обработка. Това се задава чрез preprocessing_function = precess_input, където preprocess_input е от модула keras.applications.inception_v3.

Сигналите за параметри на въртене, изместване, срязване, увеличаване и прелистване варират за съответните трансформации за увеличаване на данните.

След това ще активираме InceptionV3 мрежата от модула keras.applications.

base_model = InceptionV3 (weights = 'imagenet', include_top = False)

Използваме флага include_top = False, за да изключим тежестите на последния напълно свързан слой, тъй като това е специфично за състезанието ImageNet, от което тежестите бяха предварително тренирани. Ще добавим и инициализираме нов последен слой:

def add_new_last_layer (base_model, nb_classes):
  "" "Добавете последния слой към convnet
  аргументи:
    base_model: модел керас, с изключение на горната част
    nb_classes: # от класове
  Се завръща:
    нов модел керас с последен слой
  "" "
  x = base_model.output
  x = GlobalAveragePooling2D () (x)
  x = Плътна (FC_SIZE, активиране = 'relu') (x)
  прогнози = плътна (nb_classes, активиране = 'softmax') (x)
  model = Модел (input = base_model.input, output = прогнози)
  обратен модел

GlobalAveragePooling2D преобразува изхода на тензора MxNxC в тензор 1xC, където C е # на каналите.

След това добавяме напълно свързан плътн слой с размер 1024 и функция softmax на изхода за изтласкване на стойностите между [0,1].

В тази програма ще демонстрирам както трансферно обучение, така и фина настройка. Можете да използвате едно или и двете, ако желаете.

  1. Трансферно обучение: замразете всички освен предпоследния слой и претренирайте последния Плътен слой
  2. Фина настройка: освободете долните слоени слоеве и преквалифицирайте повече слоеве

Извършването на двете в този ред ще осигури по-стабилно и последователно обучение. Това е така, защото големите актуализации на градиента, задействани от случайно инициализирани тежести, могат да разрушат наученото тегло в спиралната основа, ако не бъдат замразени. След като последният слой се стабилизира (трансферно обучение), тогава преминаваме към преквалификация на повече слоеве (фина настройка).

Трансферно обучение

def setup_to_transfer_learn (модел, base_model):
  "" "Замразете всички слоеве и компилирайте модела" ""
  за слой в base_model.layers:
    layer.trainable = Грешно
  model.compile (оптимизатор = 'rmsprop',
                загуба = 'categorical_crossentropy',
                показатели = [ 'точност'])

Фина настройка

def setup_to_finetune (модел):
   "" "Замразете долната част NB_IV3_LAYERS и преквалифицирайте останалата горна част
      слоеве.
   забележка: NB_IV3_LAYERS съответства на първите 2 начални блока в
         архитектурата inceptionv3
   аргументи:
     модел: керас модел
   "" "
   за слой в model.layers [: NB_IV3_LAYERS_TO_FREEZE]:
      layer.trainable = Грешно
   за слой в model.layers [NB_IV3_LAYERS_TO_FREEZE:]:
      layer.trainable = Вярно
   model.compile (оптимизатор = SGD (lr = 0,0001, импулс = 0,9),
                 загуба = 'categorical_crossentropy)

При фина настройка е важно да намалите скоростта на учене спрямо скоростта, използвана при тренировка от нулата (lr = 0,0001), в противен случай оптимизацията може да се дестабилизира и загубите да се разминават.

обучение

Сега сме готови за тренировки. Използвайте fit_generator както за трансферно обучение, така и за фина настройка.

история = model.fit_generator (
  train_generator,
  samples_per_epoch = nb_train_samples,
  nb_epoch = nb_epoch,
  validation_data = validation_generator,
  nb_val_samples = nb_val_samples,
  class_weight = 'автомобил'
)
model.save (args.output_model_file)

Ще използваме екземпляр Amazon EC2 g2.2xgege за обучение. Ако не сте запознати с AWS, прегледайте този урок (вместо да използвате предписаните им AMI, потърсете AMI на общността за „задълбочено обучение“ - за тази публикация използвах ami-638c1eo3in US-West-Oregon).

Можем да начертаем точността и загубата на обучение, използвайки обекта история

def plot_training (история):
  acc = история.history ['acc']
  val_acc = история.history ['val_acc']
  загуба = история.история ['загуба']
  val_loss = история.history ['val_loss']
  epochs = обхват (len (acc))
  
  plt.plot (epochs, acc, 'r.')
  plt.plot (epochs, val_acc, 'r')
  plt.title („Точност на обучение и валидиране“)
  
  plt.figure ()
  plt.plot (епохи, загуба, 'r.')
  plt.plot (епохи, val_loss, 'r-')
  plt.title („Загуба на обучение и валидиране“)
  plt.show ()

предвиждане

Сега, когато имаме запазен keras.model, можем да модифицираме същата функция предсказване (), която написахме в последната публикация в блога, за да прогнозираме класа на локален файл с изображения или всеки файл чрез уеб URL. Вижте github за пълната програма.

python predict.py - изображение куче.001.jpg --model dc.model
python predict.py --image_url https://goo.gl/Xws7Tp --model dc.model

Готови сме!

Като пример, аз обучих модел на базата данни кучета срещу котки, използвайки 24000 изображения за обучение и 1000 изображения за валидиране за 2 епохи. Дори и след само 2 епохи, представянето е доста високо:

Дневник на показателите след 2 епохи
Изтеглете обучения модел тук *

* модел, съвместим с кераси == 1.2.2

Примери

python predict.py --image_url https://goo.gl/Xws7Tp --model dc.model

python predict.py --image_url https://goo.gl/6TRUol --model dc.model

Следете за следващата публикация от поредицата:

  1. Изградете система за разпознаване на изображение за 1000 ежедневни категории обекти (ImageNet ILSVRC) с помощта на Keras и TensorFlow
  2. Изградете система за разпознаване на изображения за всякакви персонализирани категории обекти, като използвате трансферно обучение и фина настройка в Keras и TensorFlow (тази публикация)
  3. Изградете система за откриване на обекти в реално време за стотици ежедневни категории обекти (PASCAL VOC, COCO)
  4. Създайте уеб услуга за всяка система за разпознаване на изображения или за откриване на обекти

Ако имате някакви въпроси, свържете се с мен на greg.ht.chu@gmail.comи ме изпратете на LinkedIn!

Ако ви е харесало това, моля натиснете ❤