Keras переносят обучение с помощью замораживания conv_base дает низкую точность по сравнению с обучаемыми «предварительно кэшированными» функциями - PullRequest
0 голосов
/ 20 мая 2018

Я занимаюсь трансферным обучением с Keras 2.1.6 двумя хорошо известными стандартными способами.Оба из них подробно описаны в главе 5 книги Чоллет и в https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/5.3-using-a-pretrained-convnet.ipynb

2 способа кратко:

A) Кэширование представления из conv_base и затем тренировка на вашем FC отдельно,Это считается быстрым, но не допускает увеличения данных в Keras.

B) Расширьте модель conv_base с помощью FC, заморозьте веса conv_base и тренируйте все в конец.Это дорого тренировать на CPU, но даст большую гибкость, в частности, добавление данных.

Для моего конкретного набора данных и использования MobileNet (вместо VGG) я пробовал оба способа.Метод (A) даст мне около 75% точности проверки после 10 эпох, но метод (B) даст мне только ~ 58% (без увеличения данных).Тем не менее, я ожидаю, что они будут примерно одинаковыми.Я попытался отладить и посмотреть, что я сделал в основном неправильно, но не смог обнаружить ничего.

Одна вещь, которую я прочитал, - это веса, которые предположительно были заморожены в методе B), возможно, не будут заморожены из-за ошибок в прошлом.Но текущая версия 2.1.6 Keras должна быть свободной от этого.Вот как я заморозил веса в conv_base.

conv_base.trainable = False
for layer in conv_base.layers:
    layer.trainable = False

Цикл может не понадобиться, но я добавил его на всякий случай.Я проверил, что веса на самом деле были заморожены, проверив их после нескольких эпох.Так что это, вероятно, не то, что вызывает проблему.

Любой, у кого есть подсказка о том, как отлаживать или что может пойти не так, пожалуйста, дайте мне знать.

Я опубликовал оба прогона в виде гистограмм GitHub.Я запустил это на Google Colab и экспортировал их.Соответствующая часть должна начинаться с импорта Keras.

Метод A): https://gist.github.com/kechan/38b4e6c85501246a2a49deadd26aefd7

Метод B): https://gist.github.com/kechan/f3fea62279ac847e9adc100351b7e9e8

Обновление

Iдалее объединили 2 способа переноса обучения в одну записную книжку и постарались сохранить все остальное "постоянным" в максимально возможной степени.вот новая суть:

https://gist.github.com/kechan/9487fad4dfeaede212e3d9899fb21105

1 Ответ

0 голосов
/ 04 марта 2019

Это похоже на эффект слоев BatchNormalization (BN) или любых других слоев, которые работают по-разному в обучении и выводе.BN, в частности, использует сохраненные статистические данные о населении в выводе, но текущие статистические данные по мини-партиям в процессе обучения.Что происходит, когда вы замораживаете веса слоя BN в своей базовой модели, а затем тренируетесь, так это то, что будет использоваться статистика мини-партии.Это может привести к плохим результатам, так как соседние слои конвоя ожидают, что входные данные нормализуются с использованием сохраненной статистики населения.

Вы не увидите никаких плохих эффектов, если сначала извлечете объекты, используя базовую модель, поскольку базовая модель находится в логическом выводеиспользуется режим и статистика населения.

Решение состоит в том, чтобы создать подкласс BatchNormalization и переопределить метод __call__, установив для флага training значение False.Примерно так:

class InferenceBatchNormalization(BatchNormalization):
    def __init__(self, **kwargs):
        super(BatchNormalization, self).__init__(**kwargs)

    def call(self, inputs, training=None):
        return super(BatchNormalization, self).__call__(inputs, training=False)

Посмотрите на код keras, и он станет понятен: https://github.com/keras-team/keras/blob/master/keras/layers/normalization.py#L132

...