7.4. Carregar um modelo

ml.Model lê um ficheiro de modelo a partir da flash, analisa-o, aloca a RAM que a rede necessita durante a inferência e devolve um objeto que contém tudo o que o resto do script precisa de saber sobre a rede carregada.

7.4.1. O construtor

O construtor recebe um caminho e um pós-processador opcional:

model = ml.Model("/rom/blazeface_front_128.tflite",
                 postprocess=BlazeFace())

Os modelos em /rom/ (o sistema de ficheiros residente na flash) são lidos diretamente no local: os pesos da rede permanecem na flash e o modelo carregado consome apenas a RAM correspondente à arena de tensores. Os modelos em /sdcard/ são copiados para a RAM no momento do carregamento, pelo que o custo total é o tamanho do ficheiro do modelo mais a arena de tensores. Qualquer um dos caminhos funciona; a troca é RAM.

Se existir um ficheiro .txt irmão com o mesmo nome base, o seu conteúdo é carregado automaticamente em labels. A palavra-chave postprocess= regista um callable que predict() executa após cada inferência.

7.4.2. Propriedades de só leitura

Um modelo carregado expõe um pequeno conjunto de propriedades de só leitura que descrevem a rede sem que seja necessário executá-la.

Ficheiro e memória.

  • len – tamanho do ficheiro do modelo em disco, em bytes.

  • ram – tamanho da arena de tensores que a rede necessita para as suas ativações intermédias durante a inferência, em bytes.

Tensores de entrada.

  • input_shape – lista de tuplos, um por tensor de entrada, que indica a forma esperada pela rede. As redes de visão têm uma entrada com a forma (1, H, W, C).

  • input_dtype – lista de códigos dtype de um único caráter ('b' int8, 'B' uint8, 'h' int16, 'H' uint16, 'f' float32), um por entrada.

  • input_scale e input_zero_point – os parâmetros de quantização que convertem entre a entrada de valor real utilizada no treino da rede e a representação inteira que a câmara executa.

Tensores de saída. Espelho do conjunto de entrada: output_shape, output_dtype, output_scale, output_zero_point. As redes de deteção produzem dois ou três tensores de saída (caixas, pontuações de confiança, e por vezes probabilidades por classe); as redes de classificação produzem um.

Extras. labels é a lista de nomes de classes carregada do ficheiro .txt irmão, ou None. postprocess é o pós-processador registado, ou None.

7.4.3. Inspecionar o BlazeFace

Ao carregar o modelo BlazeFace incluído e imprimir cada propriedade, obtêm-se os valores reais:

import ml
from ml.postprocessing.mediapipe import BlazeFace

model = ml.Model("/rom/blazeface_front_128.tflite",
                 postprocess=BlazeFace())

print("file size:    ", model.len, "bytes")
print("tensor arena: ", model.ram, "bytes")
print("input shape:  ", model.input_shape)
print("input dtype:  ", model.input_dtype)
print("input scale:  ", model.input_scale)
print("input zp:     ", model.input_zero_point)
print("output shape: ", model.output_shape)
print("output dtype: ", model.output_dtype)
print("output scale: ", model.output_scale)
print("output zp:    ", model.output_zero_point)

Os valores identificam concretamente a interface da rede: um único tensor de entrada int8 de forma (1, 128, 128, 3) e duas saídas int8 – uma para coeficientes de regressão de caixa, outra para pontuações de confiança por âncora. Os parâmetros de quantização descrevem como esses valores int8 mapeiam para os floats reais utilizados no treino da rede; o pós-processador usa-os para desfazer a quantização antes de descodificar as caixas.

Cada propriedade é a única fonte de verdade para o que descreve. Os scripts leem input_shape para saber a resolução de captura, leem output_scale e output_zero_point para descodificar tensores manualmente, e leem labels para obter nomes de classes legíveis por humanos – nunca codificados a rígido, nunca assumidos.