Esta página foi traduzida pela API Cloud Translation.
Switch to English

Quantização pós-treinamento

A quantização pós-treinamento é uma técnica de conversão que pode reduzir o tamanho do modelo e, ao mesmo tempo, melhorar a latência da CPU e do acelerador de hardware, com pouca degradação na precisão do modelo. Você pode quantizar um modelo flutuante do TensorFlow já treinado ao convertê-lo para o formato TensorFlow Lite usando o TensorFlow Lite Converter .

Métodos de Otimização

Existem várias opções de quantização pós-treinamento para escolher. Aqui está uma tabela de resumo das opções e os benefícios que elas oferecem:

Técnica Benefícios Hardware
Quantização de faixa dinâmica 4x menor, aumento 2x-3x CPU
Quantização inteira completa 4x menor, 3x + aceleração CPU, Edge TPU, microcontroladores
Quantização Float16 2x menor, aceleração de GPU CPU, GPU

A seguinte árvore de decisão pode ajudar a determinar qual método de quantização pós-treinamento é o melhor para o seu caso de uso:

opções de otimização pós-treinamento

Quantização de faixa dinâmica

A forma mais simples de quantização pós-treinamento quantiza estaticamente apenas os pesos do ponto flutuante ao inteiro, que tem 8 bits de precisão:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quant_model = converter.convert()

Na inferência, os pesos são convertidos de 8 bits de precisão para ponto flutuante e calculados usando kernels de ponto flutuante. Essa conversão é feita uma vez e armazenada em cache para reduzir a latência.

Para melhorar ainda mais a latência, os operadores de "faixa dinâmica" quantizam dinamicamente as ativações com base em sua faixa de 8 bits e realizam cálculos com pesos e ativações de 8 bits. Essa otimização fornece latências próximas à inferência de ponto fixo totalmente. No entanto, as saídas ainda são armazenadas usando ponto flutuante, de modo que a aceleração com operações de faixa dinâmica seja menor do que um cálculo de ponto fixo completo.

Quantização inteira completa

Você pode obter mais melhorias de latência, reduções no uso de memória de pico e compatibilidade com dispositivos de hardware ou aceleradores somente inteiros, certificando-se de que toda a matemática do modelo seja quantizada por inteiro.

Para a quantização inteira completa, você precisa medir a faixa dinâmica de ativações e entradas, fornecendo dados de entrada de amostra para o conversor. Consulte a função representative_dataset_gen() usada no código a seguir.

Inteiro com float fallback (usando a entrada / saída padrão do float)

Para quantizar totalmente o número inteiro de um modelo, mas usar operadores flutuantes quando eles não tiverem uma implementação de número inteiro (para garantir que a conversão ocorra sem problemas), use as seguintes etapas:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
def representative_dataset_gen():
  for _ in range(num_calibration_steps):
    # Get sample input data as a numpy array in a method of your choosing.
    yield [input]
converter.representative_dataset = representative_dataset_gen
tflite_quant_model = converter.convert()

Apenas inteiro

A criação de modelos somente inteiros é um caso de uso comum para TensorFlow Lite para Microcontroladores e TPUs Coral Edge .

Além disso, para garantir a compatibilidade com dispositivos apenas de número inteiro (como microcontroladores de 8 bits) e aceleradores (como o Coral Edge TPU), você pode aplicar a quantização inteira de número inteiro para todas as operações, incluindo a entrada e a saída, usando as seguintes etapas:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
def representative_dataset_gen():
  for _ in range(num_calibration_steps):
    # Get sample input data as a numpy array in a method of your choosing.
    yield [input]
converter.representative_dataset = representative_dataset_gen
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8  # or tf.uint8
converter.inference_output_type = tf.int8  # or tf.uint8
tflite_quant_model = converter.convert()

Quantização Float16

Você pode reduzir o tamanho de um modelo de ponto flutuante quantizando os pesos para float16, o padrão IEEE para números de ponto flutuante de 16 bits. Para habilitar a quantização float16 de pesos, use as seguintes etapas:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float16]
tflite_quant_model = converter.convert()

As vantagens da quantização float16 são as seguintes:

  • Ele reduz o tamanho do modelo pela metade (uma vez que todas as gramaturas tornam-se metade do tamanho original).
  • Isso causa perda mínima de precisão.
  • Ele oferece suporte a alguns delegados (por exemplo, o delegado GPU) que podem operar diretamente em dados float16, resultando em uma execução mais rápida do que cálculos float32.

As desvantagens da quantização float16 são as seguintes:

  • Não reduz a latência tanto quanto uma quantização para matemática de ponto fixo.
  • Por padrão, um modelo quantizado float16 irá "desquantizar" os valores dos pesos para float32 quando executado na CPU. (Observe que o delegado da GPU não realizará essa desquantização, pois pode operar em dados float16.)

Apenas inteiro: ativações de 16 bits com pesos de 8 bits (experimental)

Este é um esquema de quantização experimental. É semelhante ao esquema "somente inteiro", mas as ativações são quantizadas com base em sua faixa de 16 bits, os pesos são quantizados em inteiros de 8 bits e o bias é quantizado em inteiros de 64 bits. Isso é conhecido como quantização 16x8 adicional.

A principal vantagem dessa quantização é que ela pode melhorar a precisão significativamente, mas apenas aumentar ligeiramente o tamanho do modelo.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
def representative_dataset_gen():
  for _ in range(num_calibration_steps):
    # Get sample input data as a numpy array in a method of your choosing.
    yield [input]
converter.representative_dataset = representative_dataset_gen
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
tflite_quant_model = converter.convert()

Se a quantização de 16x8 não for compatível com alguns operadores no modelo, o modelo ainda poderá ser quantizado, mas os operadores sem suporte serão mantidos em flutuação. A seguinte opção deve ser adicionada ao target_spec para permitir isso.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
def representative_dataset_gen():
  for _ in range(num_calibration_steps):
    # Get sample input data as a numpy array in a method of your choosing.
    yield [input]
converter.representative_dataset = representative_dataset_gen
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
tf.lite.OpsSet.TFLITE_BUILTINS]
tflite_quant_model = converter.convert()

Exemplos de casos de uso em que as melhorias de precisão fornecidas por este esquema de quantização incluem: * super-resolução, * processamento de sinal de áudio, como cancelamento de ruído e formação de feixe, * redução de ruído de imagem, * reconstrução HDR de uma única imagem.

A desvantagem dessa quantização é:

  • Atualmente, a inferência é notavelmente mais lenta do que o inteiro completo de 8 bits devido à falta de implementação otimizada do kernel.
  • Atualmente, é incompatível com os delegados TFLite acelerados por hardware existentes.

Um tutorial para este modo de quantização pode ser encontrado aqui .

Precisão do modelo

Como os pesos são quantizados após o treinamento, pode haver uma perda de precisão, especialmente para redes menores. Modelos totalmente quantizados pré-treinados são fornecidos para redes específicas no repositório de modelos do TensorFlow Lite . É importante verificar a precisão do modelo quantizado para verificar se qualquer degradação na precisão está dentro dos limites aceitáveis. Existem ferramentas para avaliar a precisão do modelo TensorFlow Lite .

Alternativamente, se a queda da precisão for muito alta, considere o uso de treinamento ciente de quantização . No entanto, fazer isso requer modificações durante o treinamento do modelo para adicionar nós de quantização falsos, enquanto as técnicas de quantização pós-treinamento nesta página usam um modelo pré-treinado existente.

Representação para tensores quantizados

A quantização de 8 bits aproxima os valores de ponto flutuante usando a seguinte fórmula.

$$real\_value = (int8\_value - zero\_point) \times scale$$

A representação tem duas partes principais:

  • Pesos por eixo (também conhecidos por canal) ou por tensor representados por int8 valores de complemento de dois no intervalo [-127, 127] com ponto zero igual a 0.

  • Ativações / entradas por tensor representadas por int8 valores de complemento de dois no intervalo [-128, 127], com um ponto zero no intervalo [-128, 127].

Para uma visão detalhada de nosso esquema de quantização, consulte nossas especificações de quantização . Os fornecedores de hardware que desejam se conectar à interface delegada do TensorFlow Lite são incentivados a implementar o esquema de quantização aqui descrito.