Os metadados LiteRT fornecem um padrão para descrições de modelos. A metadados são uma fonte importante de conhecimento sobre o que o modelo faz e a informações de entrada / saída. Os metadados consistem em
- partes legíveis que transmitem a prática recomendada ao usar o modelo, e
- partes legíveis por máquina que podem ser aproveitadas por geradores de código, como Código LiteRT do Android gerador e o Android Studio ML Binding recurso.
Todos os modelos de imagem publicados no Kaggle Os modelos foram preenchidos com metadados.
Modelo com formato de metadados
![model_with_metadata](https://ai.google.dev/edge/litert/images/convert/model_with_metadata.png?hl=pt-br)
Os metadados do modelo são definidos em
metadata_schema.fbs (em inglês),
por
FlatBuffer
. Como mostrado na figura 1, ele é armazenado
metadados
campo do modelo TFLite
esquema,
abaixo do nome, "TFLITE_METADATA"
. Alguns modelos podem vir com arquivos associados,
como o rótulo de classificação
.tf.
Esses arquivos são concatenados ao final do arquivo de modelo original como um arquivo
usando o ZipFile "append"
(modo 'a'
). TFLite
O intérprete pode consumir o novo formato de arquivo da mesma forma que antes. Consulte Pacote
os arquivos associados para mais informações.
Consulte as instruções abaixo sobre como preencher, visualizar e ler metadados.
Configurar as ferramentas de metadados
Antes de adicionar metadados ao seu modelo, você precisará de um configuração do ambiente para executar o TensorFlow. Há um guia detalhado sobre como configure aqui.
Depois de configurar o ambiente de programação Python, instale outras ferramentas:
pip install tflite-support
As ferramentas de metadados da LiteRT são compatíveis com o Python 3.
Como adicionar metadados usando a API Flatbuffers Python
Os metadados do modelo se dividem em três partes esquema:
- Informações do modelo: descrição geral do modelo e dos itens
como termos de licença. Consulte
ModelMetadata.
- Informações de entrada: descrição das entradas e do pré-processamento
necessárias, como a normalização. Consulte
SubGraphMetadata.input_tensor_metadata.
- Informações de saída: descrição da saída e exige o pós-processamento, como o mapeamento para rótulos. Consulte SubGraphMetadata.output_tensor_metadata.
- Informações de entrada: descrição das entradas e do pré-processamento
necessárias, como a normalização. Consulte
SubGraphMetadata.input_tensor_metadata.
Como o LiteRT suporta somente um subgráfico neste momento, o
Gerador de código LiteRT
e o Android Studio ML Binding
recurso
vai usar ModelMetadata.name
e ModelMetadata.description
, em vez de
SubGraphMetadata.name
e SubGraphMetadata.description
, ao exibir
metadados e geração de códigos.
Tipos de entrada / saída compatíveis
Os metadados LiteRT para entrada e saída não são projetados com informações tipos de modelo em mente, mas sim tipos de entrada e saída. Não importa o que funcionalmente, desde que os tipos de entrada e saída consistam em dos itens a seguir ou uma combinação das opções abaixo, ela é aceita pelo TensorFlow Metadados do Lite:
- Recurso: números que sejam números inteiros não assinados ou float32.
- Imagem: no momento, os metadados são compatíveis com imagens RGB e escala de cinza.
- Caixa delimitadora: caixas delimitadoras de forma retangular. O esquema oferece suporte a uma variedade de numeração esquemas.
Empacotar os arquivos associados
Os modelos LiteRT podem vir com diferentes arquivos associados. Por exemplo: os modelos de linguagem natural geralmente têm arquivos de vocabulário que mapeiam IDs os modelos de classificação podem ter arquivos identificadores que indicam as categorias de objetos. Um modelo não funciona bem sem os arquivos associados (se houver).
Os arquivos associados agora podem ser agrupados com o modelo por meio dos metadados
biblioteca Python. O novo modelo LiteRT se torna um arquivo ZIP que contém
o modelo e os arquivos associados. Ele pode ser descompactado com um CEP comum
ferramentas de visualização. Esse novo formato de modelo continua usando a mesma extensão de arquivo, .tflite
. Ela
é compatível com o framework TFLite e o intérprete existentes. Consulte Metadados do pacote
e arquivos associados no
model para mais detalhes.
As informações dos arquivos associados podem ser gravadas nos metadados. Dependendo
o tipo de arquivo e onde ele está anexado (por exemplo, ModelMetadata
,
SubGraphMetadata
e TensorMetadata
), o código LiteRT do Android
gerador pode aplicar os critérios pré/pós-testes
automaticamente ao objeto. Consulte a página <Uso do Codegen> seção de
cada arquivo associado
tipo
no esquema para saber mais.
Parâmetros de normalização e quantização
A normalização é uma técnica comum de pré-processamento de dados em machine learning. A o objetivo da normalização é alterar os valores para uma escala comum, sem diferenças que distorçam os intervalos de valores.
A quantização de modelo é uma técnica que reduz a precisão das representações de pesos e, opcionalmente, e ativações para armazenamento e computação.
Em termos de pré e pós-processamento, normalização e quantização são duas etapas independentes. Veja os detalhes abaixo:
Normalização | Quantização. | |
---|---|---|
Um exemplo do do parâmetro imagem de entrada em MobileNet para dados flutuantes e modelos quantitativos, respectivamente. |
Modelo de ponto flutuante: - média: 127,5 - std: 127,5 Modelo quantitativo: - média: 127,5 - std: 127,5 |
Modelo de ponto flutuante: - zeroPoint: 0 - escala: 1,0 Modelo quantitativo: - zeroPoint: 128,0 - scale:0.0078125f |
Quando invocar? |
Entradas: se entrada os dados são normalizados o treinamento, a entrada dados de necessidades de inferência para ser normalizado de acordo. Saídas: output. os dados não serão normalizados em geral. |
Os modelos flutuantes
não precisam de quantização. O modelo quantizado pode talvez não precisem quantização antes/depois processamento. Depende sobre o tipo de dados tensores de entrada/saída. - tensores flutuantes: não quantização antes/depois processamento necessário. Quant op e dequant op são incorporada ao modelo gráfico. - tensores int8/uint8: precisam de quantização pré/pós-processamento. |
Fórmula |
normalized_input = (entrada - média) / std |
Quantize para entradas:
q = f / escala + zeroPoint Desquantize para saídas: f = (q - zeroPoint) * escala |
Onde estão os parâmetros |
Preenchido pelo criador do modelo
e armazenados no modelo
metadados, conforme
NormalizationOptions |
Preenchido automaticamente por conversor do TFLite armazenadas no modelo do tflite . |
Como obter o parâmetros? | Durante o
API MetadataExtractor
[2]
|
Pelo TFLite
API Tensor [1] ou
através do
API MetadataExtractor
[2] |
Flutuar e quantificar têm os mesmos valor? | Sim, ponto flutuante e quant os modelos têm a mesma Normalização parâmetros | Não, o modelo de flutuação não precisam de quantização. |
O TFLite codifica ou Android Vinculação de ML do Studio gerar automaticamente no processamento de dados? | Sim |
Sim |
[1] A LiteRT Java
API
e a ferramenta LiteRT C++
API.
[2] A biblioteca de extratores de metadados
Ao processar dados de imagem para modelos uint8, a normalização e a quantização são pode ser ignorado. É possível fazer isso quando os valores de pixel estiverem no intervalo de [0, 255]. Mas, em geral, você deve sempre processar os dados de acordo com o normalização e quantização, quando aplicável.
Exemplos
Você pode encontrar exemplos de como os metadados devem ser preenchidos para diferentes tipos de modelos aqui:
Classificação de imagens
Fazer o download do script aqui , que preenche os metadados para mobilenet_v1_0.75_160_quantized.tflite. Execute o script desta forma:
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
Para preencher metadados de outros modelos de classificação de imagem, adicione as especificações do modelo. marcação "gostei" este no script. O restante deste guia destacará algumas das principais seções no exemplo de classificação de imagem para ilustrar os elementos-chave.
Análise detalhada do exemplo de classificação de imagens
Informações do modelo
Os metadados começam com a criação de uma nova informação de modelo:
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.")
Informações de entrada / saída
Nesta seção, mostramos como descrever a assinatura de entrada e saída do seu modelo. Esses metadados podem ser usados por geradores de código automáticos para criar pré e pós- o código de processamento. Para criar informações de entrada ou saída sobre um tensor:
# Creates input info.
input_meta = _metadata_fb.TensorMetadataT()
# Creates output info.
output_meta = _metadata_fb.TensorMetadataT()
Entrada de imagem
A imagem é um tipo de entrada comum para machine learning. Metadados do LiteRT suporta informações como espaço de cores e informações de pré-processamento, como normalização. A dimensão da imagem não requer especificação manual porque já é fornecido pela forma do tensor de entrada e pode ser inferidos automaticamente.
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
Saída do rótulo
O identificador pode ser mapeado para um tensor de saída por meio de um arquivo associado usando
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]
Criar os Flatbuffers de metadados
O código a seguir combina as informações do modelo com as entradas e saídas informações:
# 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()
Empacotar metadados e arquivos associados no modelo
Após a criação dos metadados Flatbuffers, os metadados e o arquivo de rótulo são
gravado no arquivo TFLite usando o método 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()
É possível empacotar quantos arquivos associados quiser no modelo
load_associated_files
: No entanto, é necessário empacotar pelo menos esses arquivos
documentadas nos metadados. Neste exemplo, empacotar o arquivo de rótulo
obrigatórios.
visualizar os metadados
Você pode usar o Netron para visualizar seus
metadados, ou os metadados de um modelo LiteRT podem ser lidos em um arquivo JSON
usando o 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)
O Android Studio também oferece suporte à exibição de metadados pela API Android Studio ML Vinculação .
Controle de versão de metadados
Os metadados esquema o controle de versão é baseado no número do controle de versão semântico, que rastreia as alterações do no arquivo de esquema e pela identificação do arquivo Flatbuffers, que indica o compatibilidade real de versão.
O número do controle de versão semântico
O esquema de metadados é controlado pelo controle de versão semântico
número,
como MAJOR.MINOR.PATCH. Ele rastreia as mudanças no esquema de acordo com as regras.
aqui.
Consulte a história da
campos
adicionado após a versão 1.0.0
.
A identificação do arquivo Flatbuffers
O controle de versões semântico garante a compatibilidade se seguir as regras, mas não implica a verdadeira incompatibilidade. Ao encontrar o número MAJOR, não significa necessariamente que a compatibilidade com versões anteriores não está funcionando. Portanto, use o arquivo Flatbuffers identificação, file_identifier, para denotar a compatibilidade real do esquema de metadados. O identificador do arquivo é exatamente 4 caracteres. for fixa em um determinado esquema de metadados e não e está sujeita a alterações pelos usuários. Se a compatibilidade com versões anteriores do esquema de metadados precisar ser corrompido, o campo file_identifier aparecerá, por exemplo, de "M001" para "M002". Espera-se que o valor de "file_identifier" seja bem menor frequentemente que a metadata_version.
A versão mínima necessária do analisador de metadados
O analisador de metadados mínimo necessário
versão
é a versão mínima do analisador de metadados (o código gerado por Flatbuffers) que
pode ler os Flatbuffers de metadados por completo. Efetivamente, a versão é
maior número de versão entre as versões de todos os campos preenchidos e o
menor versão compatível indicada pelo identificador do arquivo. O mínimo
versão necessária do analisador de metadados é preenchida automaticamente pelo
MetadataPopulator
quando os metadados são preenchidos em um modelo do TFLite. Consulte a
extrator de metadados para mais informações sobre como
é usada a versão mínima necessária do analisador de metadados.
Ler os metadados dos modelos
A biblioteca Metadata Extractor é uma ferramenta conveniente para ler os metadados e arquivos associados a partir de um modelo em diferentes plataformas (consulte a documentação Java versão e a linguagem C++ versão). Você pode criar sua própria ferramenta de extração de metadados em outros idiomas usando o Flatbuffers.
Ler os metadados em Java
Para usar a biblioteca Metadata Extractor em seu app Android, recomendamos o uso de
AAR de metadados da LiteRT hospedada em
MavenCentral.
Ele contém a classe MetadataExtractor
e a classe FlatBuffers Java
vinculações para os metadados
esquema
e o modelo
esquema.
É possível especificar isso nas dependências build.gradle
da seguinte maneira:
dependencies {
implementation 'org.tensorflow:tensorflow-lite-metadata:0.1.0'
}
Para usar os snapshots noturnos, confira se você adicionou o snapshot do Sonatype repositório.
É possível inicializar um objeto MetadataExtractor
com um ByteBuffer
que aponta
ao modelo:
public MetadataExtractor(ByteBuffer buffer);
O ByteBuffer
precisa permanecer inalterado durante todo o ciclo de vida do
objeto MetadataExtractor
. A inicialização pode falhar se o arquivo Flatbuffers
identificador dos metadados do modelo não corresponde ao identificador do analisador de metadados. Consulte
controle de versão de metadados para mais informações.
Se houver identificadores de arquivo correspondentes, o extrator de metadados fará a leitura metadados gerados por todos os esquemas passados e futuros devido ao efeito mecanismo de compatibilidade com versões anteriores e posteriores. No entanto, os campos de dados futuros esquemas não podem ser extraídos por extratores de metadados mais antigos. O mínimo necessário versão do analisador dos metadados indica a versão mínima do analisador de metadados que pode ler os metadados Flatbuffers na totalidade. Você pode usar o método a seguir para verificar se o mínimo que a condição necessária da versão do analisador seja atendida:
public final boolean isMinimumParserVersionSatisfied();
É permitido transmitir um modelo sem metadados. No entanto, invocar métodos que
uma leitura de metadados causará erros de tempo de execução. É possível verificar se um modelo tem
metadados invocando o método hasMetadata
:
public boolean hasMetadata();
O MetadataExtractor
fornece funções convenientes para você receber
tensores de entrada/saída' metadados. Por exemplo,
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);
Embora o modelo LiteRT
esquema
suporta vários subgráficos, o TFLite Interpreter atualmente oferece suporte apenas a um
um único subgráfico. Portanto, MetadataExtractor
omite o índice do subgráfico como uma entrada
em seus métodos.
Ler os arquivos associados dos modelos
O modelo LiteRT com metadados e arquivos associados é essencialmente uma zip que pode ser descompactado com ferramentas zip comuns para obter os arquivos associados. Por exemplo, descompactar mobilenet_v1_0.75_160_quantized e extraia o arquivo do rótulo no modelo da seguinte maneira:
$ 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
Você também pode ler arquivos associados pela biblioteca Metadata Extractor.
Em Java, transmita o nome do arquivo ao MetadataExtractor.getAssociatedFile
:
public InputStream getAssociatedFile(String fileName);
Da mesma forma, em C++, isso pode ser feito com o método,
ModelMetadataExtractor::GetAssociatedFile
:
tflite::support::StatusOr<absl::string_view> GetAssociatedFile(
const std::string& filename) const;