Path: blob/master/site/es-419/lite/performance/quantization_spec.md
25118 views
Especificación de la cuantización de 8 bits de TensorFlow Lite
El siguiente documento esboza la especificación para el esquema de cuantización de 8 bits de TensorFlow Lite. Con ello se pretende ayudar a los desarrolladores de hardware a proporcionar soporte de hardware para la inferencia con modelos cuantificados de TensorFlow Lite.
Resumen de especificaciones
Facilitamos una especificación y sólo podemos ofrecer algunas garantías de comportamiento si se sigue la especificación. También entendemos que los distintos tipos de hardware pueden tener preferencias y restricciones que pueden causar ligeras desviaciones al implementar la especificación que resulten en implementaciones que no sean exactas en cuanto a bits. Aunque eso puede ser aceptable en la mayoría de los casos (y vamos a dar un conjunto de pruebas que, hasta donde sabemos, incluyen tolerancias por operación que hemos recopilado de varios modelos), la naturaleza del aprendizaje automático (y del aprendizaje profundo en el caso más común) hace que sea imposible dar garantías firmes.
La cuantización de 8 bits aproxima los valores de punto flotante usando la siguiente fórmula.
Las ponderaciones por eje (también llamadas "por canal" en las ops Conv) o por tensor se representan mediante valores de complemento a dos de int8
en el intervalo [-127, 127]
con un punto cero igual a 0. Las activaciones/entradas por tensor están representadas por valores de complemento a dos de int8
en el rango [-128, 127]
, con un punto cero en el rango [-128, 127]
.
Hay otras excepciones para operaciones concretas que se documentan a continuación.
Nota: En el pasado, nuestras herramientas de cuantización usaban una cuantización por tensor, asimétrica, uint8
. Las nuevas herramientas, kernels de referencia y kernels optimizados para la cuantización de 8 bits usarán esta especificación.
Entero con signo vs entero sin signo
La cuantización de TensorFlow Lite priorizará principalmente herramientas y kernels para la cuantización int8
para 8 bits. Esto es por la conveniencia de la cuantización simétrica que se representa por punto cero igual a 0. Además, muchos backends tienen optimizaciones adicionales para la acumulación de int8xint8
.
Por eje vs por tensor
La cuantización por tensor significa que habrá una escala y/o punto cero por tensor entero. La cuantización por eje significa que habrá una escala y/o zero_point
por sección en la quantized_dimension
. La dimensión cuantizada especifica la dimensión de la forma del tensor a la que corresponden las escalas y los puntos cero. Por ejemplo, un tensor t
, con dims=[4, 3, 2, 1]
con parámetros de cuantización scale=[1.0, 2.0, 3.0]
, zero_point=[1, 2, 3]
, quantization_dimension=1
se cuantizará en la segunda dimensión de t
:
A menudo, la quantized_dimension
es el output_channel
de las ponderaciones de las convoluciones, pero en teoría puede ser la dimensión que corresponde a cada producto punto en la implementación del kernel, lo que permite una mayor granularidad de la cuantización sin implicaciones para el rendimiento. Esto supone grandes mejoras en la precisión.
TFLite tiene soporte por eje para un número creciente de operaciones. Al momento de redactar este documento, existe soporte para Conv2d y DepthwiseConv2d.
Simétrico vs asimétrico
Las activaciones son asimétricas: pueden tener su punto cero en cualquier lugar dentro del rango de int8
con signo [-128, 127]
. Muchas activaciones son asimétricas por naturaleza y un punto cero es una forma relativamente barata de conseguir efectivamente hasta un bit binario extra de precisión. Dado que las activaciones sólo se multiplican por ponderaciones constantes, el valor constante del punto cero puede optimizarse bastante.
Las ponderaciones son simétricas: obligadas a tener el punto cero igual a 0. Los valores de ponderación se multiplican por los valores dinámicos de entrada y de activación. Esto significa que existe un costo de runtime inevitable de multiplicar el punto cero de la ponderación por el valor de activación. Al imponer que el punto cero sea 0 podemos evitar este costo.
Explicación matemática: es similar a la sección 2.3 de arXiv:1712.05877, salvo por la diferencia de que permitimos que los valores de escala sean por eje. Esto se generaliza fácilmente, como sigue:
es una matriz de ParseError: KaTeX parse error: Undefined control sequence: \veces at position 3: m \̲v̲e̲c̲e̲s̲ ̲n de activaciones cuantizadas.
es una matriz de ParseError: KaTeX parse error: Undefined control sequence: \veces at position 3: n \̲v̲e̲c̲e̲s̲ ̲p de ponderaciones cuantizadas.
Consideremos multiplicar la fila -ésima de , por la columna -ésima de , , ambas de longitud . Los valores enteros cuantizados y los valores de los puntos cero son , y , respectivamente.
El término (\sum_{i=0}^{n} q_{a}^(i)} q_{b}^{(i)}) no puede evitarse, ya que está realizando el producto escalar del valor de entrada y el valor de ponderación.
Los términos ParseError: KaTeX parse error: Expected 'EOF', got '}' at position 25: …}^{n} q_{b}^(i)}̲ z_a y están formados por constantes que siguen siendo las mismas por cada invocación de inferencia, por lo que pueden calcularse previamente.
El término (\sum_{i=0}^{n} q_{a}^(i)} z_b) debe calcularse en cada inferencia, ya que la activación cambia en cada una. Al obligar a que las ponderaciones sean simétricas podemos eliminar el costo de este término.
Especificaciones del operador cuantizado int8
Aquí describimos los requisitos de cuantización de nuestros kernels tflite int8: