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 TensorFlow flutuante já treinado ao convertê-lo no formato TensorFlow Lite usando o Conversor TensorFlow Lite .

Métodos de otimização

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

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

A seguinte árvore de decisão pode ajudar a determinar qual método de quantização pós-treinamento é 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 quantifica estaticamente apenas os pesos do ponto flutuante ao número inteiro, que possui 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" quantificam dinamicamente as ativações com base em sua faixa para 8 bits e executam cálculos com pesos e ativações de 8 bits. Essa otimização fornece latências próximas à inferência de ponto totalmente fixo. No entanto, as saídas ainda são armazenadas usando ponto flutuante, para que a aceleração com operações de faixa dinâmica seja menor que uma computação completa de ponto fixo.

Quantização inteira inteira

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

Para quantização de número inteiro completo, é necessário medir a faixa dinâmica de ativações e entradas fornecendo dados de entrada de amostra ao conversor. Consulte a função representative_dataset_gen() usada no código a seguir.

Inteiro com fallback de flutuação (usando entrada / saída de flutuação padrão)

Para quantificar totalmente um modelo, mas use operadores float 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()

Somente inteiro

Criar modelos somente inteiros é um caso de uso comum para o TensorFlow Lite para microcontroladores e TPUs Coral Edge .

Além disso, para garantir a compatibilidade com dispositivos somente inteiros (como microcontroladores de 8 bits) e aceleradores (como o TPU Coral Edge), você pode aplicar a quantização inteira de todas as operações, incluindo entrada e 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 de Float16

Você pode reduzir o tamanho de um modelo de ponto flutuante quantificando os pesos para flutuar16, o padrão IEEE para números de ponto flutuante de 16 bits. Para habilitar a quantização de pesos float16, 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 do float16 são as seguintes:

  • Reduz o tamanho do modelo em até metade (uma vez que todos os pesos se tornam metade do tamanho original).
  • Causa perda mínima de precisão.
  • Ele suporta alguns delegados (por exemplo, o delegado da GPU) que podem operar diretamente nos dados do float16, resultando em uma execução mais rápida do que os cálculos do float32.

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

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

Somente número inteiro: ativações de 16 bits com pesos de 8 bits (experimental)

Este é um esquema de quantização experimental. É semelhante ao esquema "somente número inteiro", mas as ativações são quantizadas com base em seu intervalo de 16 bits, os pesos são quantificados em número inteiro de 8 bits e o viés é quantificado em número inteiro de 64 bits. Isso é conhecido como quantização 16x8 adicional.

A principal vantagem dessa quantização é que ela pode melhorar significativamente a precisão, 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 16x8 não for suportada por alguns operadores no modelo, o modelo ainda poderá ser quantizado, mas os operadores não suportados permanecerão flutuantes. A opção a seguir 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 esse esquema de quantização incluem: * super-resolução, * processamento de sinal de áudio, como cancelamento de ruído e formação de feixe, * ausência de ruído na imagem, * reconstrução HDR a partir de uma única imagem.

A desvantagem dessa quantização é:

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

Precisão do modelo

Como os pesos são quantizados após o treinamento, pode haver uma perda de precisão, principalmente para redes menores. Modelos totalmente quantizados e 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 .

Como alternativa, se a queda de precisão for muito alta, considere o uso de treinamento com reconhecimento de quantização . No entanto, 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 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 conhecido por canal) ou por tensor representados pelos valores de complemento de int8 dois no intervalo [-127, 127] com o 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 conectar-se à interface de delegação do TensorFlow Lite são incentivados a implementar o esquema de quantização descrito lá.