Модули изображений Tensorflow Hub: ясность при предварительной обработке и выводимых значениях

Большое спасибо за поддержку! В настоящее время я использую TF Slim - и TF Hub кажется очень полезным дополнением для трансферного обучения. Однако из документации неясно следующее:

1. Выполняется ли предварительная обработка неявно? Это основано на параметре "trainable = True / False" в конструкторе модуля?

module = hub.Module("https://tfhub.dev/google/imagenet/inception_v3/feature_vector/1", trainable=True)

Когда я использую Tf-slim, я использую метод предварительной обработки:

inception_preprocessing.preprocess_image(image, img_height, img_width, is_training)

2. Как получить доступ к AuxLogits для начальной модели? Кажется, отсутствует:

import tensorflow_hub as hub
import tensorflow as tf

img = tf.random_uniform([10,299,299,3])
module = hub.Module("https://tfhub.dev/google/imagenet/inception_v3/feature_vector/1", trainable=True)
outputs = module(dict(images=img), signature="image_feature_vector", as_dict=True)

На выходе

dict_keys(['InceptionV3/Mixed_6b', 'InceptionV3/MaxPool_5a_3x3', 'InceptionV3/Mixed_6c', 'InceptionV3/Mixed_6d', 'InceptionV3/Mixed_6e', 'InceptionV3/Mixed_7a', 'InceptionV3/Mixed_7b', 'InceptionV3/Conv2d_2a_3x3', 'InceptionV3/Mixed_7c', 'InceptionV3/Conv2d_4a_3x3', 'InceptionV3/Conv2d_1a_3x3', 'InceptionV3/global_pool', 'InceptionV3/MaxPool_3a_3x3', 'InceptionV3/Conv2d_2b_3x3', 'InceptionV3/Conv2d_3b_1x1', 'default', 'InceptionV3/Mixed_5b', 'InceptionV3/Mixed_5c', 'InceptionV3/Mixed_5d', 'InceptionV3/Mixed_6a'])

person Maverick    schedule 20.04.2018    source источник


Ответы (1)


Это отличные вопросы; позвольте мне попытаться дать хорошие ответы также для читателей, менее знакомых с TF-Slim.

1. Предварительная обработка не выполняется модулем, потому что это много о ваших данных, а не столько об архитектуре CNN в модуле. Модуль обрабатывает только преобразование входных значений из канонического диапазона [0,1] в то, что ожидает предварительно обученная CNN в модуле.

Длительное обоснование: предварительная обработка изображений для обучения CNN обычно состоит из декодирования входного JPEG (или чего-то еще), выбора из него (достаточно большого) случайного кадрирования, случайных фотометрических и геометрических преобразований (искажение цветов, поворот влево / вправо и т. Д.), и изменение размера до обычного размера изображения для пакета вводимых обучающих данных. Модули TensorFlow Hub, реализующие https://tensorflow.org/hub/common_signatures/images, оставляют все это в ваш код вокруг модуля.

Основная причина заключается в том, что подходящие случайные преобразования во многом зависят от вашей обучающей задачи, но не от архитектуры или обученных весов состояний модуля. Например, искажения цвета помогут, если вы классифицируете автомобили против собак, но, вероятно, не для спелых и незрелых бананов и т. Д.

Кроме того, пакет изображений, которые были декодированы, но еще не обрезаны / изменены, трудно представить в виде одного тензора (если вы не сделаете его одномерным тензором закодированных строк, но это создает другие проблемы, такие как разрыв обратного распространения в модуль входы для расширенного использования).

Итог: код Python, использующий модуль, должен выполнять предварительную обработку изображения (кроме значений масштабирования), например, как в https://github.com/tensorflow/hub/blob/master/examples/image_retraining/retrain.py

Тонкие методы предварительной обработки объединяют случайные преобразования, специфичные для набора данных (настроенные для Imagenet!), С масштабированием до диапазона значений архитектуры (что модуль Hub делает за вас). Это означает, что они здесь не применимы напрямую.

2. Действительно, вспомогательные головки отсутствуют в первоначальном наборе модулей, опубликованном в tfhub.dev/google / ..., но я ожидаю, что они все равно будут нормально работать при повторном обучении.

Дополнительные сведения: не все архитектуры имеют вспомогательные головки, и даже в исходной статье говорится, что их влияние было «относительно незначительным» [Szegedy & al. 2015; §5]. Использование модуля вектора функций изображения для задачи настраиваемой классификации обременило бы код потребителя модуля проверкой вспомогательных функций и, если они были обнаружены, помещением вспомогательных логитов и терма потерь на первое место.

Это осложнение, казалось, не помогло, но дальнейшие эксперименты могут опровергнуть эту оценку. (Пожалуйста, поделитесь в проблеме на GitHub, если вы о ней знаете.)

На данный момент это единственный способ добавить голову в https://tfhub.dev/google/imagenet/inception_v3/feature_vector/1 - это скопировать и вставить несколько строк из https://github.com/tensorflow/models/blob/master/research/slim/nets/inception_v3.py (найдите «Вспомогательные логиты головы») и примените это к " Inception_V3 / Mixed_6e ", который вы видели.

3. Вы не спрашивали, но: Для обучения документация модуля рекомендует передавать hub.Module (..., tags = {"train"}), иначе пакетная норма работает в режиме вывода (и выпадения, если в модуле были).

Надеюсь, это объясняет, как и почему.

Арно (от разработчиков TensorFlow Hub)

person arnoegw    schedule 25.04.2018
comment
Большое спасибо за потрясающе подробный ответ. Не могли бы вы расширить это. Кроме того, пакет изображений, которые были декодированы, но еще не обрезаны / изменены в размере, трудно представить в виде одного тензора (если вы не сделаете его одномерным тензором закодированных строк, но это приносит другие проблемы, такие как разбиение обратного распространения на входы модуля для расширенного использования). - person Maverick; 28.04.2018
comment
Скрытые предположения здесь заключаются в том, что (а) в вашем наборе данных есть изображения разных размеров, и (б) вы хотите запускать модуль на пакетах по N изображений в каждом (для скорости и для преимущества пакетной нормы). 1) Почему бы не заставить модуль принимать тензор формы [N] и строку dtype с некоторой кодировкой изображений? Представьте себе использование модуля как части модели, которая каким-то образом извлекает / генерирует входные данные. Вы не могли обучить его от начала до конца, потому что кодирование / декодирование ввода модуля нарушило бы обратную передачу. (подлежит уточнению) - person arnoegw; 30.04.2018
comment
(продолжение) 2) Почему бы не поместить все изображения в один тензор формы [N, H, W, C] и оставить некоторые записи неиспользованными? Для этого потребуется передать дополнительную информацию о фактически используемых размерах и соответствующим образом проанализировать ввод. Это было бы обременительно и в конечном итоге привело бы к неэффективному графику переходов. --- Но это все вторично. Основная причина, как указано выше, заключается в следующем: увеличение данных, которое происходит в рамках предварительной обработки, должно зависеть от набора данных, а не от архитектуры CNN в модуле, поэтому имеет смысл оставить это потребителю модуля (возможно, с использованием библиотечного кода. ). - person arnoegw; 30.04.2018
comment
Еще раз большое спасибо - следующий вопрос о снижении веса: В tf-slim по умолчанию снижение веса устанавливается inception_arg_scope как weight_decay = 0.00004. Я предполагаю, что в настоящее время он будет установлен на 1.0, чтобы это можно было обрабатывать извне. Это верно? - person Maverick; 06.05.2018
comment
hub.Module (..., trainable = True) вводит коллекцию REGULARIZATION_LOSSES графа модуля, в данном случае члены убывания веса с коэффициентом, изначально установленным в тонком коде. Если вы сделаете обычное дело и включите результат tf.get_regularization_losses () в потерю, передаваемую оптимизатору, тогда будут учтены все потери от обучаемых модулей в вашей модели. - person arnoegw; 08.05.2018
comment
Итак, я понимаю, что уменьшение веса l2 жестко запрограммировано, когда мы получаем доступ к модели через tf-hub - это правильно? Я считаю, что это гиперпараметр, который должен быть доступен конечным пользователям для точной настройки. Ты согласен? Возможные способы реализации (а) Добавить аргумент, позволяющий передать это в модель (б) жесткое уменьшение веса кода как 1.0 в коде - и пользователи могут масштабировать его вместе со всеми потерями регуляризации вместе. например (reg_loss = l2_reg_const * sum(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES))) - person Maverick; 10.05.2018
comment
Да, для опытных пользователей было бы хорошо взять силу регуляризации в свои руки. Не могли бы вы подать проблему GitHub, в особенности? если у вас есть эксперименты, подчеркивающие важность этого? На данный момент в качестве обходного пути вы можете вручную проверить, что hub.Module(...) добавляет к tf.get_collection_ref(REGULARIZATION_LOSSES), удалить их и добавить обратно в увеличенном масштабе. - person arnoegw; 15.05.2018
comment
Еще раз спасибо - открою вопрос на github. (а) Я не уверен, как проверить вручную - мне не удалось найти код, в котором это добавлено - не могли бы вы уточнить? (б) Вопрос по дизайну API: получаем обучаемый параметр - зачем нам теги (поезд / тест)? Если обучаемый - True, то выполнить график поездов - в противном случае - тестовый график. Что мне не хватает? - person Maverick; 17.05.2018
comment
(a) Просто проверьте список tf.get_collection_ref (REGULARIZATION_LOSSES) до и после. (b) Графические версии, вероятно, будут полезны для более тонких различий (например, тонкая настройка с фиксированной нормой партии или без нее; или оптимизация, специфичная для GPU / TPU), поэтому я стесняюсь просто приравнивать trainable <->["train"] и not trainable <-> set(). - person arnoegw; 18.05.2018
comment
Большое спасибо arnoegw. Я поднял новую проблему с github: github.com/tensorflow/hub/issues/63 - person Maverick; 29.05.2018