Квантование можно определить как процесс преобразования значений из большого набора действительных чисел в значения из небольшого дискретного набора. Обычно это предполагает сопоставление непрерывных входных данных с фиксированными значениями на выходе. Распространенный способ добиться этого — округление или усечение. В случае округления мы вычисляем ближайшее целое число. Например, значение 1,8 становится 2. А значение 1,2 становится 1. В случае усечения мы слепо удаляем значения после десятичной дроби, чтобы преобразовать входные данные в целое число.
Какой бы путь мы ни выбрали, основной мотивацией квантования глубоких нейронных сетей является повышение скорости вывода, поскольку нет необходимости говорить, что вывод и обучение нейронных сетей требуют довольно больших вычислительных затрат. С появлением моделей большого языка количество параметров в этих моделях только увеличивается, а это означает, что объем памяти становится все больше и больше.
Со скоростью развития этих нейронных сетей растет спрос на их запуск на наших ноутбуках, мобильных телефонах и даже на таких крошечных устройствах, как часы. Все это невозможно без квантования.
Прежде чем углубиться в квантование, давайте не будем забывать, что обученные нейронные сети — это всего лишь плавающие числа, хранящиеся в памяти компьютера.
Некоторые из хорошо известных представлений или форматов для хранения чисел в компьютерах: float32 или FP32, float16 или FP16, int8, bfloat16, где B означает Google Brain или, с недавних пор, тензорный float 32 или TF32, специализированный формат для обработки матриц или тензоров. операции. Каждый из этих форматов занимает отдельный фрагмент памяти. Например, float32 выделяет 1 бит для знака, 8 бит для показателя степени и 23 бита для мантиссы.
Аналогично, float16 или FP16 выделяет 1 бит для знака, но только 5 бит для экспоненты и 10 бит для мантиссы. С другой стороны, BF16 выделяет 8 бит для экспоненты и только 7 бит для мантиссы.
Хватит представлений. Я хочу сказать, что преобразование из более высокого формата памяти в меньший формат памяти называется квантованием. Говоря в терминах глубокого обучения, Float32 называется одинарной или полной точностью, а Float16 и BFloat16 называются половинной точностью . По умолчанию модели глубокого обучения обучаются и сохраняются с полной точностью. Чаще всего используется преобразование из формата полной точности в формат int8.
Квантование может быть равномерным и неравномерным . В однородном случае отображение входа на выход представляет собой линейную функцию, приводящую к равномерному распределению выходных данных для равномерно расположенных входных данных. В неравномерном случае отображение входных данных на выходные данные является нелинейной функцией, поэтому выходные данные не будут расположены равномерно для однородного входного сигнала.
Говоря о едином типе, функция линейного отображения может представлять собой операцию масштабирования и округления. Таким образом, равномерное квантование включает в уравнение масштабный коэффициент S.
При преобразовании, скажем, из float16 в int8, обратите внимание, что мы всегда можем ограничиться значениями от -127 до плюс 127 и гарантировать, что ноль входных данных идеально сопоставляется с нулем выходных данных, что приводит к симметричному отображению, и поэтому такое квантование называется симметричным . квантование .
С другой стороны, если значения по обе стороны от нуля не совпадают, например, между -128 и +127. Кроме того, если мы сопоставляем нуль входного сигнала с каким-либо другим значением, отличным от нуля на выходе, это называется асимметричным квантованием . Поскольку теперь нулевое значение на выходе смещено, нам нужно учесть это в нашем уравнении, включив в уравнение нулевой коэффициент Z .
Чтобы узнать, как мы можем выбрать масштабный коэффициент и нулевую точку, давайте возьмем пример входных данных, распределенных, как показано на рисунке выше, на оси действительных чисел. Масштабный коэффициент по существу делит весь этот диапазон входных данных от минимального значения r_min до максимального значения r_max на однородные разделы. Однако мы можем в какой-то момент выбрать обрезку этого ввода, скажем, альфа для отрицательных значений и бета для положительных значений. Любое значение, выходящее за пределы альфа и бета, не имеет смысла, поскольку оно соответствует тому же выходному значению, что и значение альфа. В данном примере это -127 и +127. Процесс выбора этих значений отсечения альфа и бета и, следовательно, диапазона отсечения называется калибровкой .
Чтобы предотвратить чрезмерное отсечение, самым простым вариантом может быть установка альфа, равная r_min, а бета, равная r_max. И мы можем с радостью вычислить масштабный коэффициент S , используя эти значения r_min и r_max . Однако это может привести к тому, что вывод будет асимметричным. Например, r_max во входных данных может быть равно 1,5, но r_min может быть только -1,2. Таким образом, чтобы ограничить симметричное квантование, нам нужно, чтобы альфа и бета были максимальными значениями из двух, и, конечно же, установили нулевую точку равной 0.
Симметричное квантование — это именно то, что используется при квантовании весов нейронной сети, поскольку обученные веса уже предварительно вычисляются во время вывода и не будут меняться во время вывода. Вычисления также проще по сравнению с асимметричным случаем, поскольку нулевая точка установлена на 0.
Теперь давайте рассмотрим пример, где входные данные смещены в одном направлении, скажем, в положительную сторону. Это напоминает вывод некоторых наиболее успешных функций активации, таких как ReLU или GeLU. Кроме того, результаты активаций меняются вместе с входом. Например, вывод функций активации сильно отличается, когда мы показываем два изображения кошки. Итак, теперь вопрос: «Когда мы будем калибровать диапазон для квантования?» Это во время тренировки? Или во время вывода, и когда мы получим данные для прогнозирования?
Этот вопрос приводит к различным режимам квантования, особенно к квантованию после обучения (PTQ). В PTQ мы начинаем с предварительно обученной модели без проведения дополнительного обучения. Важнейшие данные, необходимые для модели, включают данные калибровки, которые используются для расчета диапазона отсечения, а затем масштабного коэффициента (S) и нулевой точки (Z). Обычно эти калибровочные данные получаются на основе весов моделей. После процесса калибровки мы можем приступить к квантованию модели, в результате чего получится квантованная модель.
В обучении с учетом квантования или сокращенно QAT мы квантоваем обученную модель, используя стандартную процедуру, но затем выполняем дальнейшую точную настройку или повторное обучение, используя свежие данные обучения, чтобы получить квантованную модель. QAT обычно выполняется для корректировки параметра модели, чтобы восстановить потерянную точность или любую другую метрику, которая нас беспокоит во время квантования. Таким образом, QAT имеет тенденцию предоставлять лучшие модели, чем квантование после обучения.
Для точной настройки модель должна быть дифференцируемой. Но операция квантования недифференцируема. Чтобы преодолеть это, мы используем фальшивые квантователи, такие как прямоточные оценщики. Во время тонкой настройки эти средства оценки оценивают ошибку квантования, и ошибки объединяются с ошибкой обучения для точной настройки модели для повышения производительности. Во время точной настройки проходы вперед и назад выполняются над квантованной моделью с плавающей запятой. Однако параметры квантуются после каждого обновления градиента.
Посмотрите видео ниже, объясняющее квантование модели в глубоком обучении.
Это в значительной степени охватывает основы квантования. Мы начали с необходимости квантования и различных типов квантования, таких как симметричное и асимметричное. Мы также быстро научились выбирать параметры квантования, а именно масштабный коэффициент и нулевую точку. И мы закончили с разными режимами квантования. Но как все это реализовано в PyTorch или TensorFlow? Это на другой день. Я надеюсь, что это видео дало вам некоторое представление о квантовании в глубоком обучении.
Надеюсь увидеть вас в моем следующем. А пока берегите себя!