Ta strona została przetłumaczona przez Cloud Translation API.
Switch to English

Dodawanie metadanych do modeli TensorFlow Lite

Metadane TensorFlow Lite zapewniają standard opisów modeli. Metadane są ważnym źródłem wiedzy o tym, co robi model i jego danych wejściowych / wyjściowych. Metadane składają się z obu

Wszystkie modele obrazów opublikowane w modelach hostowanych przez TensorFlow Lite i TensorFlow Hub zostały wypełnione metadanymi.

Skonfiguruj narzędzia do metadanych

Przed dodaniem metadanych do modelu będziesz potrzebować konfiguracji środowiska programistycznego Python do uruchamiania TensorFlow. Jest to szczegółowy poradnik jak skonfigurować to tutaj .

Po skonfigurowaniu środowiska programowania Python będziesz musiał zainstalować dodatkowe narzędzia:

pip install tflite-support

Narzędzia do metadanych TensorFlow Lite obsługują zarówno język Python 2, jak i Python 3.

Dodawanie metadanych

Istnieją trzy części metadanych modelu w schemacie :

  1. Informacje o modelu - Ogólny opis modelu oraz elementy, takie jak postanowienia licencyjne. Zobacz ModelMetadata .
  2. Informacje wejściowe - opis danych wejściowych i wymaganego przetwarzania wstępnego, takiego jak normalizacja. Zobacz SubGraphMetadata.input_tensor_metadata .
  3. Informacje wyjściowe - opis wyjścia i wymaganego przetwarzania końcowego, takiego jak mapowanie na etykiety. Zobacz SubGraphMetadata.output_tensor_metadata .

Od TensorFlow Lite obsługuje tylko jeden podgrafu w tym momencie, generator kodu TensorFlow Lite i Binding Funkcja Android Studio ML użyje ModelMetadata.name i ModelMetadata.description zamiast SubGraphMetadata.name i SubGraphMetadata.description , podczas wyświetlania metadanych i generowania kodu.

Obsługiwane typy wejść / wyjść

Metadane TensorFlow Lite dotyczące danych wejściowych i wyjściowych nie są projektowane z myślą o określonych typach modeli, ale raczej o typach danych wejściowych i wyjściowych. Nie ma znaczenia, jakie funkcje wykonuje model, o ile typy danych wejściowych i wyjściowych składają się z następujących elementów lub ich kombinacji, jest to obsługiwane przez metadane TensorFlow Lite:

  • Funkcja - Liczby, które są liczbami całkowitymi bez znaku lub float32.
  • Obraz - obecnie metadane obsługują obrazy RGB i w skali szarości.
  • Obwiednia - Prostokątne ramki ograniczające. Schemat obsługuje różne schematy numeracji .

Spakuj powiązane pliki

Modele TensorFlow Lite mogą być dostarczane z różnymi powiązanymi plikami. Na przykład modele języka naturalnego zwykle zawierają pliki słowników, które odwzorowują fragmenty słów na identyfikatory słów; modele klasyfikacyjne mogą mieć pliki etykiet, które wskazują kategorie obiektów. Model nie będzie działał dobrze bez powiązanych plików (jeśli istnieją).

Powiązane pliki można teraz połączyć z modelem za pośrednictwem biblioteki metadanych Python. Nowy model TensorFlow Lite staje się plikiem zip zawierającym zarówno model, jak i powiązane pliki. Można go rozpakować za pomocą typowych narzędzi do zip. Ten nowy format modelu nadal używa tego samego rozszerzenia pliku, .tflite . Jest kompatybilny z istniejącą frameworkiem TFLite i tłumaczem. Aby uzyskać więcej informacji, zobacz Pakowanie mtadata i powiązanych plików do modelu .

Powiązane informacje o plikach mogą być ponownie zapisane w metadanych. W zależności od typu pliku i gdzie plik zostanie dołączony do (tj ModelMetadata , SubGraphMetadata i TensorMetadata ), kod generator TensorFlow Lite Android mogą stosować odpowiadające pre / post przetwarzanie automatycznie do obiektu. Aby uzyskać więcej informacji, zobacz sekcję <Codegen use> dla każdego skojarzonego typu pliku w schemacie.

Parametry normalizacji i kwantyzacji

Normalizacja to powszechna technika wstępnego przetwarzania danych w uczeniu maszynowym. Celem normalizacji jest zmiana wartości na wspólną skalę, bez zniekształcania różnic w przedziałach wartości.

Kwantyzacja modelu to technika, która pozwala na reprezentację wag z mniejszą precyzją i opcjonalnie aktywacje zarówno dla przechowywania, jak i obliczeń.

Jeśli chodzi o przetwarzanie wstępne i przetwarzanie końcowe, normalizacja i kwantyzacja to dwa niezależne kroki. Oto szczegóły.

Normalizacja Kwantyzacja

Przykład wartości parametrów obrazu wejściowego w MobileNet odpowiednio dla modeli zmiennoprzecinkowych i ilościowych.
Model pływaka :
- średnia: 127,5
- standard: 127,5
Model ilościowy :
- średnia: 127,5
- standard: 127,5
Model pływaka :
- zeroPoint: 0
- skala: 1,0
Model ilościowy :
- zeroPoint: 128,0
- skala: 0,0078125f




Kiedy wzywać?


Dane wejściowe : Jeśli dane wejściowe są znormalizowane podczas uczenia, dane wejściowe wnioskowania muszą zostać odpowiednio znormalizowane.
Wyjścia: dane wyjściowe nie zostaną znormalizowane w ogóle.
Modele typu float nie wymagają kwantyzacji.
Model kwantowany może, ale nie musi, wymagać kwantyzacji w przetwarzaniu wstępnym / końcowym. Zależy to od typu danych tensorów wejścia / wyjścia.
- tensory typu float: nie jest wymagana kwantyzacja w przetwarzaniu wstępnym / końcowym. Quant op i dekwanty op są umieszczane na wykresie modelu.
- tensory int8 / uint8: wymagają kwantyzacji w przetwarzaniu wstępnym / końcowym.


Formuła


normalized_input = (wejście - średnia) / std
Kwantyzacja dla danych wejściowych :
q = f / skala + zeroPoint
Dekwantyzuj dla wyjść :
f = (q - zeroPoint) * skala

Gdzie są parametry
Wypełniane przez twórcę modelu i przechowywane w metadanych modelu jako NormalizationOptions Wypełniane automatycznie przez konwerter TFLite i przechowywane w pliku modelu tflite.
Jak uzyskać parametry? Poprzez interfejs API MetadataExtractor [2] Poprzez TFLite Tensor API [1] lub przez MetadataExtractor API [2]
Czy modele zmiennoprzecinkowe i ilościowe mają tę samą wartość? Tak, modele zmiennoprzecinkowe i kwantowe mają te same parametry normalizacji Nie, model float nie wymaga kwantyzacji.
Czy generator kodu TFLite lub powiązanie Android Studio ML automatycznie generuje je podczas przetwarzania danych?
tak

tak

[1] TensorFlow Lite Java API i TensorFlow Lite C ++ API .
[2] Biblioteka ekstraktora metadanych

Podczas przetwarzania danych obrazu dla modeli uint8 normalizacja i kwantyzacja są czasami pomijane. Można to zrobić, gdy wartości pikseli mieszczą się w zakresie [0, 255]. Generalnie jednak należy zawsze przetwarzać dane zgodnie z parametrami normalizacji i kwantyzacji, jeśli ma to zastosowanie.

Przykłady

Przykłady wypełniania metadanych dla różnych typów modeli można znaleźć tutaj:

Klasyfikacja obrazu

Pobierz tutaj skrypt, który wypełnia metadane do mobilenet_v1_0.75_160_quantized.tflite . Uruchom skrypt w następujący sposób:

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

Aby wypełnić metadane dla innych modeli klasyfikacji obrazów, dodaj do skryptu specyfikację modelu, taką jak ta . W pozostałej części tego przewodnika omówimy niektóre kluczowe sekcje w przykładzie klasyfikacji obrazu, aby zilustrować kluczowe elementy.

Zagłęb się w przykład klasyfikacji obrazu

Informacje o modelu

Metadane rozpoczynają się od utworzenia informacji o nowym modelu:

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.")

Informacje o wejściu / wyjściu

W tej sekcji pokazano, jak opisać sygnaturę wejścia i wyjścia modelu. Te metadane mogą być używane przez automatyczne generatory kodu do tworzenia kodu przed i po przetwarzaniu. Aby utworzyć informacje wejściowe lub wyjściowe o tensorze:

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

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

Wejście obrazu

Obraz jest typowym typem danych wejściowych w uczeniu maszynowym. Metadane TensorFlow Lite obsługują informacje, takie jak przestrzeń kolorów i informacje o wstępnym przetwarzaniu, takie jak normalizacja. Wymiar obrazu nie wymaga ręcznej specyfikacji, ponieważ jest już zapewniony przez kształt tensora wejściowego i można go automatycznie wywnioskować.

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

Wyjście etykiety

TENSOR_AXIS_LABELS można odwzorować na tensor wyjściowy za pośrednictwem skojarzonego pliku przy użyciu 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]

Utwórz metadane Flatbuffers

Poniższy kod łączy informacje o modelu z informacjami wejściowymi i wyjściowymi:

# 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()

Spakuj metadane i powiązane pliki do modelu

Po utworzeniu metadanych Flatbuffers metadane i plik etykiety są zapisywane do pliku TFLite za pomocą metody 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()

Za pomocą load_associated_files można spakować dowolną liczbę powiązanych plików do modelu. Jednak wymagane jest spakowanie przynajmniej tych plików, które są udokumentowane w metadanych. W tym przykładzie spakowanie pliku etykiety jest obowiązkowe.

Wizualizuj metadane

Możesz użyć Netron do wizualizacji metadanych lub możesz odczytać metadane z modelu TensorFlow Lite do formatu json za pomocą 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 obsługuje również wyświetlanie metadanych za pomocą funkcji wiązania Android Studio ML .

Wersjonowanie metadanych

Schemat metadanych jest wersjonowany zarówno przez numer wersji semantycznej, który śledzi zmiany pliku schematu, jak i przez identyfikację pliku Flatbuffers, co wskazuje na prawdziwą zgodność wersji.

Numer wersji semantycznej

Schemat metadanych jest wersjonowany według numeru wersji semantycznej , na przykład MAJOR.MINOR.PATCH. Śledzi zmiany schematu zgodnie z regułami tutaj . Zobacz historię pól dodanych po wersji 1.0.0 .

Identyfikacja pliku Flatbuffers

Wersjonowanie semantyczne gwarantuje zgodność, jeśli przestrzega się reguł, ale nie oznacza prawdziwej niezgodności. Zwiększenie liczby MAJOR niekoniecznie oznacza zerwanie kompatybilności wstecznej. Dlatego używamy identyfikacji pliku Flatbuffers , file_identifiler , aby oznaczyć prawdziwą zgodność schematu metadanych. Identyfikator pliku ma dokładnie 4 znaki. Jest on powiązany z określonym schematem metadanych i nie podlega zmianom przez użytkowników. Jeśli z jakiegoś powodu wsteczna kompatybilność schematu metadanych musi zostać naruszona, identyfikator_pliku zwiększy się, na przykład, z „M001” do „M002”. Oczekuje się, że File_identifiler będzie zmieniany znacznie rzadziej niż metadata_version.

Minimalna wymagana wersja parsera metadanych

Minimalna wymagana wersja parsera metadanych to minimalna wersja parsera metadanych (kod wygenerowany przez Flatbuffers), który może w całości odczytać metadane Flatbuffers. Wersja jest faktycznie największym numerem wersji spośród wersji wszystkich wypełnionych pól i najmniejszą zgodną wersją wskazaną przez identyfikator pliku. Minimalna wymagana wersja parsera metadanych jest automatycznie wypełniana przez MetadataPopulator gdy metadane są wypełniane w modelu TFLite. Zobacz ekstraktor metadanych, aby uzyskać więcej informacji o tym, jak jest używana minimalna wymagana wersja parsera metadanych.

Przeczytaj metadane z modeli

Biblioteka Metadata Extractor to wygodne narzędzie do odczytywania metadanych i powiązanych plików z modeli na różnych platformach (patrz wersja Java i wersja C ++ ). Możesz zbudować własne narzędzie do ekstrakcji metadanych w innych językach, korzystając z biblioteki Flatbuffers.

Przeczytaj metadane w Javie

Aby skorzystać z biblioteki Metadata Extractor w aplikacji na Androida, zalecamy użycie TensorFlow Lite Metadata AAR hostowanego w JCenter . Zawiera klasę MetadataExtractor , a także powiązania Java FlatBuffers dla schematu metadanych i schematu modelu .

Możesz to określić w zależnościach build.gradle w następujący sposób:

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

Możesz zainicjować obiekt MetadataExtractor za pomocą ByteBuffer który wskazuje na model:

public MetadataExtractor(ByteBuffer buffer);

ByteBuffer musi pozostać niezmieniony przez cały okres istnienia obiektu MetadataExtractor . Inicjalizacja może się nie powieść, jeśli identyfikator pliku Flatbuffers metadanych modelu nie jest zgodny z identyfikatorem parsera metadanych. Aby uzyskać więcej informacji, zobacz wersjonowanie metadanych .

Z pasującymi identyfikatorami plików, ekstraktor metadanych z powodzeniem odczyta metadane wygenerowane ze wszystkich przeszłych i przyszłych schematów dzięki mechanizmowi zgodności wstecznej i wstecznej Flatbuffers. Jednak pól z przyszłych schematów nie można wyodrębniać za pomocą starszych ekstraktorów metadanych. Minimalna wymagana wersja parsera metadanych wskazuje minimalną wersję parsera metadanych, która może w całości odczytać metadane Flatbuffers. Możesz użyć następującej metody, aby sprawdzić, czy spełniony jest warunek minimalnej niezbędnej wersji parsera:

public final boolean isMinimumParserVersionSatisfied();

Dozwolone jest przekazywanie modelu bez metadanych. Jednak wywoływanie metod, które odczytują metadane, spowoduje błędy w czasie wykonywania. Możesz sprawdzić, czy model ma metadane, wywołując metodę hasMetadata :

public boolean hasMetadata();

MetadataExtractor zapewnia wygodne funkcje do pobierania metadanych tensorów wejścia / wyjścia. Na przykład,

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);

Możesz także czytać powiązane pliki poprzez ich nazwy za pomocą metody getAssociatedFile :

public InputStream getAssociatedFile(String fileName);

Chociaż schemat modelu TensorFlow Lite obsługuje wiele podgrafów, TFLite Interpreter obsługuje obecnie tylko jeden podgraf. Dlatego MetadataExtractor pomija indeks podgrafu jako argument wejściowy w swoich metodach.