INT8-квантование: scale и zero point на Python
После калибровки известны границы значений, и теперь нужно построить целочисленную шкалу. Напишите quantize: рассчитайте масштаб, положение нуля и восстановленные значения. Правила округления, выхода за диапазон и нулевых границ заданы в условии.
Программа курса «Computer Vision Engineer: от детекции и Doc-AI до продакшна».
Масштаб и ноль шкалы
Задание
Калибровочный проход уже сделан: границы, в которых оказались значения, известны. Осталось построить по ним шкалу и уложить в неё числа.
Реализуйте функцию quantize(values, low, high). Аргумент values — значения, которые надо уложить, low и high — нижняя и верхняя границы, снятые калибровкой. Верните кортеж из четырёх элементов: масштаб, ноль шкалы, номера делений и восстановленные значения.
Как устроена шкала. Делений 256, их номера идут от −128 до 127. Настоящий ноль обязан попасть внутрь шкалы, поэтому границы сперва растягиваются до него: нижняя не может оказаться выше нуля, верхняя — ниже. Масштаб — цена одного деления — это расстояние между растянутыми границами, делённое на 255: делений 256, а промежутков между ними на один меньше.
Ноль шкалы — это номер деления, которому соответствует настоящий ноль: -128 - low / scale, где low — уже растянутая нижняя граница. Номер деления бывает только целым, поэтому результат округляется, а если он всё же вышел за шкалу, то обрезается по её краю; дальше в работе участвует уже обрезанное значение.
Номер деления для значения — это value / scale, округлённое и сдвинутое на ноль шкалы. Значение, оказавшееся за границами калибровки, даст номер вне шкалы — такой номер обрезается по ближайшему краю, от −128 до 127. Восстановленное значение получается обратным ходом: номер деления минус ноль шкалы, умноженное на масштаб.
Округление всюду идёт к ближайшему целому, а ровная половина — вверх, в сторону больших чисел: 2,5 даёт 3, а −2,5 даёт −2.
Отдельный случай — обе границы нулевые. Разность границ тогда тоже ноль, и делить на неё нельзя: масштаб в этом случае равен 1.0, ноль шкалы нулевой, все номера делений и все восстановленные значения — нули.
Пример
quantize([0.0, 2.0, -0.5, 3.0], -0.5, 2.0)
# (0.00980392156862745, -77, [-77, 127, -128, 127], [0.0, 2.0, -0.5, 2.0])
Отрезок длиной 2,5 поделён на 255 промежутков, нижняя граница пришлась на деление −128, поэтому настоящему нулю досталось деление −77. Последнее значение выходит за верхнюю границу калибровки, и его прижало к краю шкалы: 3,0 вернулось как 2,0.
Примечание
Вход уже разобран и приходит аргументами: список чисел с плавающей точкой и две границы, тоже числа, причём нижняя не выше верхней. Менять входной список нельзя. Масштаб и восстановленные значения сравниваются с точностью до одной миллиардной, подгонять округление в них не нужно, а вот номера делений и ноль шкалы сравниваются как целые числа — они должны быть типа int. Встроенный round на ровной половине округляет к чётному, а не вверх. Вызывать функцию вручную не нужно, проверка запускает её сама.
Что проверяется
Код проверок скрыт, так что вот полный список того, что в них разбирается:
- формат ответа: кортеж из четырёх элементов, положительный масштаб, целые ноль шкалы и номера делений в пределах от −128 до 127, оба списка длиной со вход;
- входной список после вызова не изменился;
- пример из условия;
- обе границы положительные — шкала растянута вниз до нуля;
- обе границы отрицательные — шкала растянута вверх до нуля;
- настоящий ноль восстанавливается ровно нулём;
- значения далеко за обеими границами калибровки;
- значение, попавшее ровно посередине между делениями;
- границы симметричны относительно нуля;
- обе границы нулевые;
- значения ровно на границах калибровки;
- одно значение;
- пустой вход.
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- Калибровка квантования: обрезка выбросов на Python
- Перцентили инференса после прогрева: задача Python
- Проверка модели после экспорта: допуски на Python
- TensorRT: выбор профиля под форму входа — задача
- Размер батча для инференса: p50, p95 и бюджет задержки
- Стоимость инференса: цена тысячи кадров на Python
