Google I/O — это обертка! Наверстать упущенное в сеансах TensorFlow Просмотреть сеансы

Добавление метаданных в модели TensorFlow Lite

Метаданные TensorFlow Lite обеспечивают стандарт для описания модели. Метаданные являются важным источником знаний о том, что делает модель, и ее входной/выходной информации. Метаданные состоят из обоих

Все модели изображений, опубликованные в TensorFlow Hub , были заполнены метаданными.

Модель с форматом метаданных

model_with_metadata
Рис. 1. Модель TFLite с метаданными и соответствующими файлами.

Метаданные модели определяются в файле metadata_schema.fbs FlatBuffer . Как показано на рис. 1, он хранится в поле метаданных схемы модели TFLite под именем "TFLITE_METADATA" . Некоторые модели могут поставляться с соответствующими файлами, такими как файлы классификационных меток . Эти файлы объединяются в конец исходного файла модели в виде ZIP-файла с использованием режима «дополнения » ZipFile (режим 'a' ). Интерпретатор TFLite может использовать новый формат файла так же, как и раньше. Дополнительные сведения см. в разделе Упаковка связанных файлов .

См. инструкцию ниже о том, как заполнять, визуализировать и читать метаданные.

Настройте инструменты метаданных

Перед добавлением метаданных в вашу модель вам потребуется настроить среду программирования Python для запуска TensorFlow. Здесь есть подробная инструкция, как это настроить.

После настройки среды программирования Python вам потребуется установить дополнительные инструменты:

pip install tflite-support

Инструменты метаданных TensorFlow Lite поддерживают Python 3.

Добавление метаданных с помощью Flatbuffers Python API

В схеме метаданные модели состоят из трех частей:

  1. Информация о модели — общее описание модели, а также такие элементы, как условия лицензии. См. Метаданные модели .
  2. Входная информация — описание входных данных и необходимая предварительная обработка, например нормализация. См. SubGraphMetadata.input_tensor_metadata .
  3. Выходная информация — описание требуемых выходных данных и постобработки, например сопоставление с метками. См. SubGraphMetadata.output_tensor_metadata .

Поскольку на данный момент TensorFlow Lite поддерживает только один подграф, генератор кода TensorFlow Lite и функция привязки Android Studio ML будут использовать ModelMetadata.name и ModelMetadata.description вместо SubGraphMetadata.name и SubGraphMetadata.description при отображении метаданных и создании кода.

Поддерживаемые типы ввода/вывода

Метаданные TensorFlow Lite для ввода и вывода разрабатываются не с учетом конкретных типов моделей, а скорее с учетом типов ввода и вывода. Неважно, что функционально делает модель, пока типы ввода и вывода состоят из следующих или их комбинации, они поддерживаются метаданными TensorFlow Lite:

  • Особенность - числа, которые являются целыми числами без знака или float32.
  • Изображение. В настоящее время метаданные поддерживают изображения RGB и оттенки серого.
  • Ограничивающая рамка — ограничивающие рамки прямоугольной формы. Схема поддерживает множество схем нумерации .

Упакуйте связанные файлы

Модели TensorFlow Lite могут поставляться с разными связанными файлами. Например, модели естественного языка обычно имеют словарные файлы, которые сопоставляют части слов с идентификаторами слов; модели классификации могут иметь файлы меток, которые указывают категории объектов. Без связанных файлов (если они есть) модель не будет работать должным образом.

Связанные файлы теперь можно объединить с моделью через библиотеку метаданных Python. Новая модель TensorFlow Lite становится zip-файлом, содержащим как модель, так и связанные файлы. Его можно распаковать обычными zip-инструментами. Этот новый формат модели продолжает использовать то же расширение файла, .tflite . Он совместим с существующей структурой TFLite и интерпретатором. Дополнительные сведения см. в разделе «Упаковать метаданные и связанные файлы в модель» .

Соответствующая информация о файле может быть записана в метаданные. В зависимости от типа файла и места прикрепления файла (например, ModelMetadata , SubGraphMetadata и TensorMetadata ) генератор кода TensorFlow Lite для Android может автоматически применять к объекту соответствующую предварительную/постобработку. Дополнительную информацию см. в разделе <Использование Codegen> каждого связанного типа файла в схеме.

Параметры нормализации и квантования

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

Квантование модели — это метод, который позволяет представлять веса с уменьшенной точностью и, при необходимости, активировать как для хранения, так и для вычислений.

С точки зрения предварительной обработки и постобработки нормализация и квантование являются двумя независимыми шагами. Вот подробности.

Нормализация Квантование

Пример значений параметров входного изображения в MobileNet для плавающей и количественной моделей соответственно.
Поплавковая модель :
- среднее: 127,5
- станд.: 127,5
Квантовая модель :
- среднее: 127,5
- станд.: 127,5
Поплавковая модель :
- нулевая точка: 0
- масштаб: 1,0
Квантовая модель :
- нулевая точка: 128,0
- масштаб: 0,0078125f




Когда вызывать?


Входные данные: если входные данные нормализуются при обучении, входные данные вывода необходимо нормализовать соответствующим образом.
Выходы : выходные данные в целом не будут нормализованы.
Плавающие модели не нуждаются в квантовании.
Квантовая модель может нуждаться или не нуждаться в квантовании в предварительной/постобработке. Это зависит от типа данных входных/выходных тензоров.
- Плавающие тензоры: не требуется квантование в предварительной/постобработке. Квантовые и деквантовые операции встраиваются в граф модели.
- тензоры int8/uint8: требуется квантование в предварительной/постобработке.


Формула


normalized_input = (ввод - среднее значение) / станд.
Квантование для входов :
q = f/масштаб + нулевая точка
Деквантовать для выходов :
f = (q - нулевая точка) * шкала

Где параметры
Заполняется создателем модели и сохраняется в метаданных модели как NormalizationOptions . Заполняется автоматически конвертером TFLite и сохраняется в файле модели tflite.
Как получить параметры? Через API MetadataExtractor [2] Через API TFLite Tensor [1] или через API MetadataExtractor [2]
Имеют ли плавающие и количественные модели одно и то же значение? Да, плавающие и количественные модели имеют одинаковые параметры нормализации. Нет, модель с плавающей запятой не нуждается в квантовании.
Генерирует ли генератор кода TFLite или привязка Android Studio ML автоматически при обработке данных?
Да

Да

[1] TensorFlow Lite Java API и TensorFlow Lite C++ API .
[2] Библиотека извлечения метаданных

При обработке данных изображения для моделей uint8 нормализация и квантование иногда пропускаются. Это нормально делать, когда значения пикселей находятся в диапазоне [0, 255]. Но в целом всегда следует обрабатывать данные в соответствии с параметрами нормализации и квантования, когда это применимо.

Библиотека задач TensorFlow Lite может выполнить нормализацию за вас, если вы настроите NormalizationOptions в метаданных. Обработка квантования и деквантования всегда инкапсулирована.

Примеры

Вы можете найти примеры заполнения метаданных для различных типов моделей здесь:

Классификация изображений

Загрузите скрипт здесь , который заполняет метаданными файл mobilenet_v1_0.75_160_quantized.tflite . Запустите скрипт следующим образом:

python ./metadata_writer_for_image_classifier.py \
    --model_file=./model_without_metadata/mobilenet_v1_0.75_160_quantized.tflite \
    --label_file=./model_without_metadata/labels.txt \
    --export_directory=model_with_metadata

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

Глубокое погружение в пример классификации изображений

Информация о модели

Метаданные начинаются с создания новой информации о модели:

from tflite_support import flatbuffers
from tflite_support import metadata as _metadata
from tflite_support import metadata_schema_py_generated as _metadata_fb

""" ... """
"""Creates the metadata for an image classifier."""

# Creates model info.
model_meta = _metadata_fb.ModelMetadataT()
model_meta.name = "MobileNetV1 image classifier"
model_meta.description = ("Identify the most prominent object in the "
                          "image from a set of 1,001 categories such as "
                          "trees, animals, food, vehicles, person etc.")
model_meta.version = "v1"
model_meta.author = "TensorFlow"
model_meta.license = ("Apache License. Version 2.0 "
                      "http://www.apache.org/licenses/LICENSE-2.0.")

Входная/выходная информация

В этом разделе показано, как описать входную и выходную сигнатуру вашей модели. Эти метаданные могут использоваться автоматическими генераторами кода для создания кода предварительной и последующей обработки. Чтобы создать входную или выходную информацию о тензоре:

# Creates input info.
input_meta = _metadata_fb.TensorMetadataT()

# Creates output info.
output_meta = _metadata_fb.TensorMetadataT()

Ввод изображения

Изображение является распространенным типом ввода для машинного обучения. Метаданные TensorFlow Lite поддерживают такую ​​информацию, как цветовое пространство, и данные предварительной обработки, такие как нормализация. Размер изображения не требует указания вручную, поскольку он уже задан формой входного тензора и может быть определен автоматически.

input_meta.name = "image"
input_meta.description = (
    "Input image to be classified. The expected image is {0} x {1}, with "
    "three channels (red, blue, and green) per pixel. Each value in the "
    "tensor is a single byte between 0 and 255.".format(160, 160))
input_meta.content = _metadata_fb.ContentT()
input_meta.content.contentProperties = _metadata_fb.ImagePropertiesT()
input_meta.content.contentProperties.colorSpace = (
    _metadata_fb.ColorSpaceType.RGB)
input_meta.content.contentPropertiesType = (
    _metadata_fb.ContentProperties.ImageProperties)
input_normalization = _metadata_fb.ProcessUnitT()
input_normalization.optionsType = (
    _metadata_fb.ProcessUnitOptions.NormalizationOptions)
input_normalization.options = _metadata_fb.NormalizationOptionsT()
input_normalization.options.mean = [127.5]
input_normalization.options.std = [127.5]
input_meta.processUnits = [input_normalization]
input_stats = _metadata_fb.StatsT()
input_stats.max = [255]
input_stats.min = [0]
input_meta.stats = input_stats

Вывод этикетки

Метка может быть сопоставлена ​​с выходным тензором через связанный файл с помощью TENSOR_AXIS_LABELS .

# Creates output info.
output_meta = _metadata_fb.TensorMetadataT()
output_meta.name = "probability"
output_meta.description = "Probabilities of the 1001 labels respectively."
output_meta.content = _metadata_fb.ContentT()
output_meta.content.content_properties = _metadata_fb.FeaturePropertiesT()
output_meta.content.contentPropertiesType = (
    _metadata_fb.ContentProperties.FeatureProperties)
output_stats = _metadata_fb.StatsT()
output_stats.max = [1.0]
output_stats.min = [0.0]
output_meta.stats = output_stats
label_file = _metadata_fb.AssociatedFileT()
label_file.name = os.path.basename("your_path_to_label_file")
label_file.description = "Labels for objects that the model can recognize."
label_file.type = _metadata_fb.AssociatedFileType.TENSOR_AXIS_LABELS
output_meta.associatedFiles = [label_file]

Создайте метаданные Flatbuffers

Следующий код объединяет информацию о модели с входной и выходной информацией:

# Creates subgraph info.
subgraph = _metadata_fb.SubGraphMetadataT()
subgraph.inputTensorMetadata = [input_meta]
subgraph.outputTensorMetadata = [output_meta]
model_meta.subgraphMetadata = [subgraph]

b = flatbuffers.Builder(0)
b.Finish(
    model_meta.Pack(b),
    _metadata.MetadataPopulator.METADATA_FILE_IDENTIFIER)
metadata_buf = b.Output()

Упакуйте метаданные и связанные файлы в модель

После создания метаданных Flatbuffers метаданные и файл метки записываются в файл TFLite с помощью метода populate :

populator = _metadata.MetadataPopulator.with_model_file(model_file)
populator.load_metadata_buffer(metadata_buf)
populator.load_associated_files(["your_path_to_label_file"])
populator.populate()

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

Визуализируйте метаданные

Вы можете использовать Netron для визуализации ваших метаданных или прочитать метаданные из модели TensorFlow Lite в формат json с помощью MetadataDisplayer :

displayer = _metadata.MetadataDisplayer.with_model_file(export_model_path)
export_json_file = os.path.join(FLAGS.export_directory,
                    os.path.splitext(model_basename)[0] + ".json")
json_file = displayer.get_metadata_json()
# Optional: write out the metadata as a json file
with open(export_json_file, "w") as f:
  f.write(json_file)

Android Studio также поддерживает отображение метаданных с помощью функции Android Studio ML Binding .

Управление версиями метаданных

Схема метаданных версионируется как по семантическому номеру версии, который отслеживает изменения файла схемы, так и по идентификации файла Flatbuffers, что указывает на истинную совместимость версии.

Семантический номер версии

Схема метаданных управляется номером семантической версии , например MAJOR.MINOR.PATCH. Он отслеживает изменения схемы в соответствии с правилами здесь . Смотрите историю полей, добавленных после версии 1.0.0 .

Идентификация файла Flatbuffers

Семантическое управление версиями гарантирует совместимость при соблюдении правил, но не означает истинной несовместимости. Повышение ОСНОВНОГО номера не обязательно означает, что обратная совместимость нарушена. Поэтому мы используем идентификацию файла Flatbuffers, file_identifier , для обозначения истинной совместимости схемы метаданных. Идентификатор файла состоит ровно из 4 символов. Он привязан к определенной схеме метаданных и не подлежит изменению пользователями. Если по какой-либо причине обратная совместимость схемы метаданных должна быть нарушена, идентификатор файла поднимется, например, с «М001» до «М002». Ожидается, что File_identifier будет изменяться гораздо реже, чем metadata_version.

Минимально необходимая версия парсера метаданных

Минимальная необходимая версия анализатора метаданных — это минимальная версия анализатора метаданных (код, сгенерированный Flatbuffers), который может полностью считывать Flatbuffers метаданных. Версия фактически является наибольшим номером версии среди версий всех заполненных полей и наименьшей совместимой версией, указанной идентификатором файла. Минимальная необходимая версия парсера метаданных автоматически заполняется MetadataPopulator при заполнении метаданных в модели TFLite. См. экстрактор метаданных для получения дополнительной информации о том, как используется минимально необходимая версия анализатора метаданных.

Чтение метаданных из моделей

Библиотека извлечения метаданных — удобный инструмент для чтения метаданных и связанных файлов из моделей на разных платформах (см. версию для Java и версию для C++ ). Вы можете создать свой собственный инструмент для извлечения метаданных на других языках, используя библиотеку Flatbuffers.

Чтение метаданных в Java

Чтобы использовать библиотеку извлечения метаданных в приложении для Android, мы рекомендуем использовать AAR метаданных TensorFlow Lite, размещенный на MavenCentral . Он содержит класс MetadataExtractor , а также привязки Java FlatBuffers для схемы метаданных и схемы модели .

Вы можете указать это в своих зависимостях build.gradle следующим образом:

dependencies {
    implementation 'org.tensorflow:tensorflow-lite-metadata:0.1.0'
}

Чтобы использовать ночные снимки, убедитесь, что вы добавили репозиторий снимков Sonatype .

Вы можете инициализировать объект MetadataExtractor с помощью ByteBuffer , который указывает на модель:

public MetadataExtractor(ByteBuffer buffer);

ByteBuffer должен оставаться неизменным в течение всего времени существования объекта MetadataExtractor . Инициализация может завершиться ошибкой, если идентификатор файла Flatbuffers метаданных модели не совпадает с идентификатором анализатора метаданных. Дополнительные сведения см. в разделе Управление версиями метаданных .

С совпадающими идентификаторами файлов средство извлечения метаданных будет успешно считывать метаданные, сгенерированные из всех прошлых и будущих схем благодаря механизму прямой и обратной совместимости Flatbuffers. Однако поля из будущих схем не могут быть извлечены более старыми экстракторами метаданных. Минимальная необходимая версия анализатора метаданных указывает минимальную версию анализатора метаданных, которая может полностью считывать Flatbuffers метаданных. Вы можете использовать следующий метод, чтобы проверить, соблюдается ли условие минимально необходимой версии парсера:

public final boolean isMinimumParserVersionSatisfied();

Допускается передача модели без метаданных. Однако вызов методов, считывающих метаданные, вызовет ошибки времени выполнения. Вы можете проверить, есть ли у модели метаданные, вызвав метод hasMetadata :

public boolean hasMetadata();

MetadataExtractor предоставляет удобные функции для получения метаданных тензоров ввода/вывода. Например,

public int getInputTensorCount();
public TensorMetadata getInputTensorMetadata(int inputIndex);
public QuantizationParams getInputTensorQuantizationParams(int inputIndex);
public int[] getInputTensorShape(int inputIndex);
public int getoutputTensorCount();
public TensorMetadata getoutputTensorMetadata(int inputIndex);
public QuantizationParams getoutputTensorQuantizationParams(int inputIndex);
public int[] getoutputTensorShape(int inputIndex);

Хотя схема модели TensorFlow Lite поддерживает несколько подграфов, интерпретатор TFLite в настоящее время поддерживает только один подграф. Поэтому MetadataExtractor опускает индекс подграфа в качестве входного аргумента в своих методах.

Чтение связанных файлов из моделей

Модель TensorFlow Lite с метаданными и связанными файлами по сути представляет собой zip-файл, который можно распаковать с помощью обычных инструментов zip, чтобы получить связанные файлы. Например, вы можете разархивировать mobilenet_v1_0.75_160_quantized и извлечь файл метки в модели следующим образом:

$ unzip mobilenet_v1_0.75_160_quantized_1_metadata_1.tflite
Archive:  mobilenet_v1_0.75_160_quantized_1_metadata_1.tflite
 extracting: labels.txt

Вы также можете прочитать связанные файлы с помощью библиотеки извлечения метаданных.

В Java передайте имя файла в метод MetadataExtractor.getAssociatedFile :

public InputStream getAssociatedFile(String fileName);

Точно так же в C++ это можно сделать с помощью метода ModelMetadataExtractor::GetAssociatedFile :

tflite::support::StatusOr<absl::string_view> GetAssociatedFile(
      const std::string& filename) const;