Итак, я нравлюсь вам, вы начали с Tensorflow версии 2 и полностью пропустили TFv1, вы иногда сталкиваетесь с (сбивающими с толку) примерами кода, которые вызывают (сбивающие с толку) сообщения об ошибках. Например, когда вы пытаетесь использовать некоторые из (более старых) моделей на хабе Tensorflow, например mobilenetv2:

object_detector = hub.Module("https://tfhub.dev/google/openimages_v4/ssd/mobilenet_v2/1")
detector_output = object_detector(your_image_tensor_here, as_dict=True)

Это не будет работать в TF2v2, вероятно, выдавая сообщение об ошибке, похожее на:

RuntimeError: Exporting/importing meta graphs is not supported when eager execution is enabled. No graph exists when eager execution is enabled.

Погуглив и еще немного запутавшись, вы, вероятно, обнаружите, что в TFv2 активное выполнение (не буду объяснять это здесь), включенное по умолчанию, и код hub.Module(), если TFv1 и не работает «как есть» для TFv2. Погуглив еще немного, вы, вероятно, обнаружите, что следующий код работает волшебным образом:

mod = hub.load("https://tfhub.dev/google/openimages_v4/ssd/mobilenet_v2/1")
obj_detector = mod.signatures["default"]
res = obj_detector(your_image_tensor_here)

Здорово! Проблема решена.

Если, конечно, вы не цените магию и не любите писать код, который не имеет для вас смысла. В этом случае вам будет интересно, что это за «подписи».

Сигнатура — это просто некоторая информация о том, какой ввод и вывод ожидает модель. (Сложная) модель может иметь несколько сигнатур, что означает, что одну и ту же модель можно использовать по-разному, при этом разные входные данные приводят к разным выходным данным. Похоже, что у большинства моделей есть одна сигнатура, которая обычно называется «по умолчанию». Однако вы можете убедиться во всем этом сами, используя такой код, как (продолжение кода выше):

print(list(mod.signatures.keys()))
print(obj_detector.structured_input_signature)
print(obj_detector.structured_outputs)

Обратите внимание, что сигнатура ‘None’ input (как в случае с моделью mobilenetv2) означает, что модель может обрабатывать тензор (в данном случае изображение) произвольного размера.

Остается вопрос, если подпись всего одна (как в случае с mobilenetv2) и она называется default (по умолчанию), то зачем мне код для доступа к ней? Возможно, это связано с тем, что hub.load() имеет немного низкий уровень, а предпочтительный способ v2:

hublayer = hub.KerasLayer(“https://tfhub.dev/google/openimages_v4/ssd/mobilenet_v2/1", signature_outputs_as_dict=True)
res =hublayer(your_image_tensor_here)

hub.KerasLayer() также принимает поле signature, но по умолчанию это ‘default’, так что все в порядке. Однако в случае множественного вывода, как в случае с mobilenetv2, который возвращает словарь тензоров, вам нужно либо указать параметр output_key , если вы хотите выводить только один тензор, либо указать signature_outputs_as_dict=True , если вы хотите, чтобы возвращались все результаты.

Итак, все еще добавляю код «подписей», хотя и немного лучше, чем hub.load(). Это поднимает вопрос о том, что настройка signature_outputs_as_dict=False делает или означает? В документации об этом ничего не сказано, да и смысла в этом нет. Однако я думаю, что имеет смысл то, что если output_key не указано, а слой keras возвращает словарь, по умолчанию должен быть возвращен весь словарь. Это избавит вас от установки дополнительного параметра signature_outputs_as_dict .