В следующем документе описана спецификация 8-битной схемы квантования LiteRT. Она призвана помочь разработчикам оборудования обеспечить аппаратную поддержку вывода с использованием квантованных моделей LiteRT.
Краткое описание спецификаций
Мы предоставляем спецификацию и можем гарантировать лишь определённое поведение при её соблюдении. Мы также понимаем, что у разного оборудования могут быть свои предпочтения и ограничения, которые могут привести к небольшим отклонениям при реализации спецификации, приводящим к реализации с побитовой точностью. Хотя в большинстве случаев это приемлемо (и мы предоставим набор тестов, который, насколько нам известно, включает пооперационные допуски, полученные нами из нескольких моделей), природа машинного обучения (и глубокого обучения в наиболее распространённом случае) не позволяет дать каких-либо жёстких гарантий.
8-битное квантование аппроксимирует значения с плавающей запятой с помощью следующей формулы.
\[real\_value = (int8\_value - zero\_point) \times scale\]
Веса по осям (в Conv-операциях они также называются весами по каналам) или потензорам представлены значениями int8 в дополнительном коде в диапазоне [-127, 127] с нулевой точкой, равной 0. Активации/входы потензоров представлены значениями int8 в дополнительном коде в диапазоне [-128, 127] с нулевой точкой в диапазоне [-128, 127] .
Существуют и другие исключения для отдельных операций, которые описаны ниже.
Знаковое целое число против беззнакового целого числа
Квантование LiteRT будет в первую очередь отдавать приоритет инструментам и ядрам для квантования int8 для 8-битных чисел. Это сделано для удобства симметричного квантования, представленного нулевой точкой, равной 0. Кроме того, многие бэкенды имеют дополнительные оптимизации для накопления int8xint8 .
По-оси против по-тензору
Квантование по тензору означает, что на весь тензор будет приходиться одна шкала и/или нулевая точка. Квантование по оси означает, что на каждый срез в quantized_dimension будет приходиться одна шкала и/или zero_point . Квантованное измерение определяет размерность формы тензора, которой соответствуют шкалы и нулевые точки. Например, тензор t с dims=[4, 3, 2, 1] и параметрами квантования: scale=[1.0, 2.0, 3.0] , zero_point=[1, 2, 3] , quantization_dimension=1 будет квантован по второму измерению t :
t[:, 0, :, :] will have scale[0]=1.0, zero_point[0]=1
t[:, 1, :, :] will have scale[1]=2.0, zero_point[1]=2
t[:, 2, :, :] will have scale[2]=3.0, zero_point[2]=3
Часто quantized_dimension представляет собой output_channel весов сверток, но теоретически это может быть измерение, соответствующее каждому скалярному произведению в реализации ядра, что позволяет повысить гранулярность квантования без ущерба для производительности. Это значительно повышает точность.
TFLite поддерживает всё больше операций по каждой оси. На момент написания этого документа поддерживались Conv2d и DepthwiseConv2d.
Симметричный против асимметричного
Активации асимметричны: их нулевая точка может находиться где угодно в диапазоне знакового int8 [-128, 127] . Многие активации асимметричны по своей природе, и нулевая точка — это относительно недорогой способ эффективно увеличить точность на один дополнительный двоичный бит. Поскольку активации умножаются только на постоянные веса, постоянное значение нулевой точки может быть существенно оптимизировано.
Веса симметричны: нулевая точка принудительно равна 0. Значения весов умножаются на динамические входные данные и значения активации. Это означает неизбежные затраты времени выполнения на умножение нулевой точки веса на значение активации. Обеспечивая, чтобы нулевая точка была равна 0, мы можем избежать этих затрат.
Пояснение к математическим расчётам: это похоже на раздел 2.3 в arXiv:1712.05877 , за исключением того, что мы допускаем масштабные значения по каждой оси. Это легко обобщается следующим образом:
$A$ — это матрица размером $m \times n$ квантованных активаций.
$B$ — это матрица квантованных весов размером $n \times p$.
Рассмотрим умножение $j$-й строки матрицы $A$, $a_j$, на $k$-й столбец матрицы $B$, $b_k$, оба имеют длину $n$. Квантованные целые значения и нулевые значения равны $q_a$, $z_a$ и $q_b$, $z_b$ соответственно.
\[a_j \cdot b_k = \sum_{i=0}^{n} a_{j}^{(i)} b_{k}^{(i)} = \sum_{i=0}^{n} (q_{a}^{(i)} - z_a) (q_{b}^{(i)} - z_b) = \sum_{i=0}^{n} q_{a}^{(i)} q_{b}^{(i)} - \sum_{i=0}^{n} q_{a}^{(i)} z_b - \sum_{i=0}^{n} q_{b}^{(i)} z_a + \sum_{i=0}^{n} z_a z_b\]