В этом сообщении блога мы обсуждаем способы сделать огромные модели, такие как BERT, меньше и быстрее. Ты выучишь:

  • Почему так важно сжимать самые эффективные на сегодняшний день модели (перейти в раздел)
  • Какие существуют способы сжатия моделей и почему ускорить модели сложнее, чем уменьшить их (перейти в раздел)
  • Что мы узнали при попытке сжать BERT методом квантования, используя TensorFlow Lite (перейти в раздел)

Мотивация

Модели (слишком) большие

Сегодняшние наиболее эффективные системы языковой обработки или компьютерного зрения используют огромные нейронные архитектуры. В качестве примера возьмем языковые модели: современными являются архитектуры на основе преобразователей, такие как BERT [1], XLNet [2] или ERNIE 2.0 [3], доступные в виде предварительно обученных моделей для всех, кто может использовать их для любого языка. задача. Эти модели часто имеют сотни миллионов параметров.

Большие модели медленные, нам нужно их ускорять

Несмотря на превосходную точность, огромные модели сложно использовать на практике. Предварительно обученные модели обычно необходимо настроить перед использованием, что требует больших ресурсов из-за большого количества параметров. Еще хуже обстоят дела с обслуживанием доведенной до мелочей модели. Для обработки одного сообщения требуется много памяти и времени. Чем хороша современная модель, если получившийся чат-бот сможет обрабатывать только одно сообщение в секунду? Чтобы подготовить их к масштабированию, мы стремимся ускорить работу современных хорошо работающих языковых моделей, в данном случае путем их сжатия.

Обзор сжатия модели

Если вы просто хотите увидеть наши эмпирические результаты, перейдите в этот раздел.

Что это?

Сжатие моделей может служить разным целям: сделать модель физически меньше, чтобы сэкономить дисковое пространство, уменьшить потребность в памяти во время вычислений или ускорить выполнение. Интуитивно эти цели взаимосвязаны: если вы сделаете модель меньше, она, вероятно, тоже будет быстрее. Фактически, многие из недавно предложенных методов сжатия стремятся сделать модели меньше и быстрее. Кратко подведем итоги исследований в этой области и укажем на ключевые концепции.

Сжатие во время тренировки и после тренировки

Сжатие модели означает уменьшение количества параметров (весов) или их точности. Самый простой способ - сжать модель после обучения (перед ее обслуживанием). Однако сеть не имеет возможности восстановиться после чрезмерно агрессивной обрезки и может значительно отстать. Во время обучения лучше применять сжатие небольшими шагами, чтобы модель могла восстановиться путем дальнейшего изучения данных. Что немаловажно, многие методы компрессии можно применять как после тренировки, так и во время тренировки. Выбор за вами: пост-тренировка может быть быстрее и часто не требует обучающих данных, в то время как сжатие во время тренировки может сохранить большую точность и привести к более высокой степени сжатия.

Квантование

Теоретический взгляд

Квантование означает снижение числовой точности весов модели. Один многообещающий метод [15,4] - это квантование k-средних: учитывая матрицу весов модели W чисел с плавающей запятой, мы группируем их все в N кластеров. Затем мы превращаем W в матрицу целых значений из [1..N], каждое из которых является указателем на один из центров N кластеров. Таким образом, мы сжали каждый элемент матрицы из 32-битных чисел с плавающей запятой до только log (N) -битных целых чисел. Компьютерные архитектуры обычно позволяют использовать только 8 или 1 бит. Обратите внимание, что последнее является редким случаем, потому что преобразование в двоичную форму весовой матрицы - включение в нее только двух различных значений - скорее всего, слишком сильно повредит модели.

Практика

Важно отметить, что такие методы, как квантование k-средних, не улучшают требований к памяти или скорости. Почему? Поскольку во время вывода, перед использованием, каждая матрица весов должна быть восстановлена, то есть снова заполнена 32-битными числами с плавающей запятой (центрами кластеров). Следовательно, мы называем это псевдоквантованием в отличие от реального квантования, когда каждый вес постоянно кодируется с использованием меньшего количества битов. Один простой метод реализован в наборе инструментов TensorFlow Lite. Он превращает матрицу 32-битных чисел с плавающей запятой в 8-битные целые числа, применяя к ней простое преобразование центр и масштаб: W₈ = W₃₂ / scale + shift (scale и shift определяются индивидуально для каждой матрицы весов). Таким образом, 8-битное W используется в матричном умножении, и только результат затем корректируется путем применения операции центрировать и масштабировать в обратном порядке. Вариант, который должен еще больше ускорить вычисления, - это полное квантование (также часть TensorFlow Lite), где квантуются не только весовые матрицы, но и вся математическая модель модели (в частности, активации). Требования к памяти в обоих случаях в 4 раза ниже. Однако любое ускорение зависит от того, насколько быстрее архитектура вашего компьютера может умножать целочисленные матрицы. Именно здесь исследования машинного обучения сталкиваются с реальностью вычислительной инфраструктуры.

Квантование моделей во время обучения

Помимо обсуждаемого до сих пор квантования после обучения, вы можете добиться еще большего с помощью обучения с учетом квантования [5] (также доступного в TensorFlow Lite). Затем модифицированный поток обучения выглядит следующим образом: для каждого шага обучения 1. квантовать веса, 2. вычислять потери в такой квантованной сети, 3. вычислять градиенты потерь относительно неквантованных весов, 4. обновлять неквантованные веса. . После обучения вы, наконец, квантовываете веса модели и используете квантованную модель для прогнозирования. Таким образом, сеть учится оптимизировать производительность своей квантованной версии.

Обрезка

Удаление весовых соединений

При обрезке части модели удаляются, чтобы сделать ее меньше и быстрее. Очень популярный метод - сокращение веса [6, 7], при котором удаляются отдельные веса соединений. Эту технику иногда сравнивают с ранним развитием человеческого мозга, когда одни связи укрепляются, а другие отмирают. Простое сокращение значения веса удаляет веса, наиболее близкие к 0, используя величину как меру важности соединения. Связи удаляются путем установки для соответствующих элементов весовой матрицы значения 0. Обратите внимание, что это не уменьшает весовую матрицу и не ускоряет вычисления. Чтобы реально сэкономить место в хранилище или памяти, вы должны использовать весовые матрицы в разреженном матричном формате. Тогда любое ускорение зависит от конкретной реализации умножения разреженных матриц. На момент написания этой статьи разреженное умножение в TensorFlow не намного быстрее обычного (плотного) умножения (см. Эти результаты тестирования), но есть многообещающие обходные пути, такие как этот от OpenAI для более быстрого разреженного умножения на графических процессорах . Если вам интересно, инструментарий TensorFlow для оптимизации моделей теперь предоставляет инструменты для применения сокращения веса к моделям Keras.

Удаление нейронов

По сравнению с сокращением веса обрезка нейронов удаляет целые нейроны. Это означает удаление столбцов (или строк) в весовых матрицах. В качестве меры важности нейрона хорошо работает комбинация активаций нейронов и градиентов ошибок (вычисленных на репрезентативном наборе данных) [8]. В отличие от отсечения веса, здесь весовые матрицы сделаны физически меньше, а любые вычисления с ними быстрее. В настоящее время мы изучаем сокращение нейронов, применяемое к предварительно обученной модели BERT на этапе тонкой настройки. Чередуя этапы обрезки и тонкой настройки, оставшиеся нейроны имеют шанс компенсировать удаленные.

Удаление матриц весов

В последнее время обрезка вышла на новый уровень: в [9] авторы полностью удаляют внимательные головы из больших моделей на основе трансформаторов с минимальными потерями точности. Естественно, такой простой подход привлекателен. Однако удаление целых весовых матриц игнорирует важность отдельных нейронов. Мы предполагаем, что обрезка на более детальном уровне может в конечном итоге позволить нам больше сжимать модели. С другой стороны, более высокая степень сжатия не гарантирует лучшего ускорения: отсечение нейронов может привести к разным размерам весовых матриц, что затрудняет эффективное распараллеливание матричных умножений.

Кистилляция знаний

Учим маленькие модели у больших

Извлечение знаний - это не метод сжатия моделей, но он имеет те же цели и эффекты. После обучения большой и медленной модели (учитель) меньшая модель (ученик) обучается имитировать поведение учителя - будь то его результаты или его внутренние представления данных. Это приводит к очень простым улучшениям как в скорости, так и в размере в различных типах сетей, от CNN [10] до LSTM [11]. Очень интересен эффект архитектурных различий между учителем и учеником: в то время как [10] рекомендуют учеников глубже и тоньше, чем учителя, [12] и [13] представляют уловки для лучшей передачи знаний между очень разными архитектурами. В [14] авторы даже успешно выучили из BERT небольшого студента Bi-LSTM.

Соединение дистилляции знаний с другими методами

Мы думаем, что лучшее понимание больших сетей может помочь в обобщении знаний: если вы знаете, как ведут себя различные части BERT, вы можете более разумно проектировать сети учеников (например, с меньшим количеством голов) или позволить им изучить наиболее важные внутренние представления учителя. В этом смысле квантование и отсечение - это инструменты, которые помогут вам анализировать ваши модели, видя, какие части и насколько агрессивно можно упростить или удалить. Конечно, вполне может быть, что вы останетесь довольны успеваемостью очень простого ученика: учителя с одинаковым упором.

Практическое занятие: сжатие BERT с квантованием

Давайте ускорим BERT

Теперь давайте поделимся нашими собственными выводами о сжатии трансформаторов с помощью квантования. Позже будет опубликовано сообщение в блоге, посвященное обрезке. Цель состоит в том, чтобы ускорить вывод BERT, чтобы мы могли использовать модель для лучшей классификации намерений и распознавания именованных сущностей в конвейере NLU. Прямо сейчас нашему классификатору намерений на основе BERT требуется ~ 120 мсек на ЦП для обработки одного сообщения, в то время как другие наши классификаторы часто примерно в 100 раз быстрее.

Подробная информация о настройке

Для начала мы сжали облегченный классификатор намерений, состоящий из двухуровневого кодировщика двунаправленного преобразователя, которому предшествуют и за которым следуют отдельные слои встраивания. Позже мы перешли к классификатору BERT (на основе предварительно обученного нематериального базового варианта со 110 миллионами параметров, см. Здесь). С обоими классификаторами мы использовали увеличенную версию данных NLU из демонстрационного бота Сара Расы. Точность модели измерялась как средний макроуровень F1. Весь наш код использует TensorFlow, и вы даже можете покопаться в нашем коде в этой ветке репозитория Rasa.

Псевдоквантование

Знакомство с моделями, не ускоряя их

Чтобы получить представление о том, сколько моделей на основе трансформаторов можно квантовать, мы применили посттренировочное псевдоквантование k-средних к небольшому классификатору. Перед сжатием F1 на тестовой порции данных было 0,80. Мы нашли это:

  • Группировка значений каждой весовой матрицы всего в 4 кластера работает хорошо (F1 остается на 0,79, относительное падение на 1,6%). Это означает 16-кратное сжатие (от 32 до 2 бит на вес). Использование всего 1 бита, то есть преобразование каждой весовой матрицы в двоичную форму, резко ухудшило F1.
  • Слои внедрения более чувствительны к квантованию, чем кодер-преобразователь. Бинаризация весовых матриц кодера при сохранении 8-битных квантованных слоев внедрения (т.е. с 256 кластерами) дает те же значения F1, что и несжатая модель.

Ясно, что небольшой классификатор можно квантовать агрессивно, и реальное 8-битное квантование после обучения вряд ли повлияет на точность.

Реальное квантование с TensorFlow Lite

Что такое TFLite

Чтобы реально ускорить работу классификаторов, мы обратились к TensorFlow Lite (или сокращенно TFLite) - инструментарию для развертывания моделей TensorFlow на небольших устройствах. Он имеет преобразователь, который превращает модели TensorFlow в 8-битные квантованные модели TFLite после обучения и, при необходимости, применяет дополнительные оптимизации. Чтобы ускорить вывод, конвертер эффективно заменяет операторы TensorFlow в вычислительном графе их 8-битными аналогами TFLite.

Работа с молодым набором инструментов

На момент написания этого сообщения в блоге TFLite - это интересный проект, находящийся в активной разработке. Многие операторы TensorFlow до сих пор не реализовали свои 8-битные эквиваленты (см. Этот список). Например, преобразователь выйдет из строя на модели, в которой используется tf.cum_prod или tf.scatter_nd. В качестве временного решения TFLite позволяет переносить таких неподдерживаемых операторов из TensorFlow (ценой отсутствия их оптимизации). К сожалению, функция переноса (отмеченная как экспериментальная) приводила к сбою конвертера при применении дальнейших оптимизаций модели. Мы даже столкнулись с этой причудливой ошибкой, возникающей в Linux, но не в MacOS. В меньшем классификаторе нам пришлось переписать код, чтобы удалить все неподдерживаемые операторы, при этом преобразование BERT прошло гладко. Помимо квантования только весов, мы хотели попробовать полное квантование, реализованное в TFLite. К сожалению, мы столкнулись с ошибками конвертера, которые было слишком сложно отладить, и мы решили не идти дальше.

Может ли TFLite улучшить логический вывод на больших устройствах?

На данный момент TFLite оптимизирует модели для мобильных устройств и устройств Интернета вещей. На настольном ЦП время вывода классификатора BERT увеличилось с ~ 120 мс до ~ 600 мс на сообщение (без дополнительной оптимизации TFLite). Применение любой из двух оптимизаций - OPTIMIZE_FOR_SIZE или OPTIMIZE_FOR_LATENCY - увеличило время вывода до ~ 2 с / сообщение. Это показывает, что оптимизации не обязательно распространяются на настольные или серверные архитектуры. Однако дорожная карта TFLite 2019 выглядит многообещающей, и мы надеемся, что набор инструментов будет больше совпадать с нашими вариантами использования. Прямо сейчас это вряд ли поможет нам ускорить наши модели.

Квантование с TFLite: результаты

  • Настоящее 8-битное квантование после обучения не повлияло на точность моделей. F1 у простого трансформаторного энкодера уменьшился только на 0,2% относительно. F1 классификатора BERT не изменился после квантования и снизился только на 0,3% относительно после применения любой из дальнейших оптимизаций TFLite.
  • Что касается размера модели, квантование действительно сделало обе модели в 4 раза меньше (с 32 до 8 бит на вес), что может быть важным результатом, если у вас есть большие модели и ограниченное дисковое пространство или память.
  • Если вы хотите ускорить вывод моделей на настольных или серверных процессорах, TensorFlow Lite, вероятно, вам не поможет. В нашем случае квантованные модели были примерно в 5 раз медленнее.
  • Увидев увеличение времени выполнения, мы пришли к выводу, что TFLite сейчас не подходит для наших сценариев использования. Однако мы рекомендуем вам изучить полное квантование TFLite (квантование всей математической модели), а также обучение с учетом квантования.

Заключение

Мы сделали обзор основных концепций и подходов к сжатию моделей. Как уже говорилось, сжатие моделей для размера диска или использования памяти с незначительными потерями точности вполне реально. С другой стороны, сжатие ради скорости на практике непросто. Это может зависеть от более быстрого целочисленного умножения или умножения разреженных матриц.

В нашем практическом исследовании мы показали, как небольшой трансформатор и кодеры BERT можно резко квантовать без значительной потери точности, хотя ускорить вывод сложно. 8-битное квантование после обучения с использованием TensorFlow Lite замедлило вывод BERT примерно в 5 раз.

В качестве следующего шага мы исследуем вес и обрезку нейронов применительно к BERT. Предварительные результаты многообещающие, так что следите за будущими публикациями в блоге. В более долгосрочной перспективе мы можем попробовать дистилляцию знаний, спроектировав лучшие студенческие сети, используя идеи из других экспериментов по сжатию.

Есть ли у вас какие-нибудь любимые приемы сжатия моделей? Мы хотели бы обсудить их с вами на нашем форуме сообщества Rasa. Мы также рекомендуем вам использовать Rasa для изучения новых методов: очень легко создать свой собственный компонент - например, классификатор намерений - и сделать его частью всего конвейера NLU. В Rasa мы любим открытый исходный код, и структура, использованная в этом сообщении в блоге, общедоступна.

Источники

[1] Девлин, Дж., Чанг, М., Ли, К., и Тутанова, К. (2018). BERT: Предварительная подготовка глубоких двунаправленных преобразователей для понимания языка. Источник https://arxiv.org/abs/1810.04805

[2] Янг, З., Дай, З., Янг, Ю., Карбонелл, Дж., Салахутдинов, Р., и Ле, К. (2019). XLNet: Обобщенное предварительное обучение авторегрессии для понимания языка. Получено с https://arxiv.org/abs/1906.08237.

[3] Сунь, Ю., Ван, С., Ли, Ю., Фэн, С., Тиан, Х., Ву, Х., и Ван, Х. (2019). ERNIE 2.0: Система непрерывного предварительного обучения для понимания языка. Источник https://arxiv.org/abs/1907.12412

[4] Cheong, R., & Daniel, R. (2019). transformers.zip: сжатие трансформаторов с обрезкой и квантованием. Получено с http://web.stanford.edu/class/cs224n/reports/custom/15763707.pdf

[5] Джейкоб, Б., Клигис, С., Чен, Б., Чжу, М., Тан, М., Ховард, А., Адам, Х., и Калениченко, Д. (2017). Квантование и обучение нейронных сетей для эффективного целочисленного арифметического вывода. Источник https://arxiv.org/abs/1712.05877

[6] Гейл Т., Элсен Э. и Хукер С. (2019). Состояние разреженности в глубоких нейронных сетях. Получено с https://arxiv.org/abs/1902.09574.

[7] Хан, С., Пул, Дж., Тран, Дж., И Далли, В. (2015). Изучение весов и соединений для эффективных нейронных сетей. Получено с https://arxiv.org/abs/1506.02626.

[8] Молчанов, П., Тайри, С., Каррас, Т., Айла, Т., и Каутц, Дж. (2016). Сокращение сверточных нейронных сетей для ресурсоэффективного вывода. Источник https://arxiv.org/abs/1611.06440

[9] Мишель П., Леви О. и Нойбиг Г. (2019). Действительно ли шестнадцать голов лучше одной? Получено с https://arxiv.org/abs/1905.10650.

[10] Ромеро, А., Баллас, Н., Каху, С., Чассанг, А., Гатта, К., и Бенжио, Ю. (2014). FitNets: подсказки для тонких глубоких сетей. Источник https://arxiv.org/abs/1412.6550

[11] Ким, Ю., и Раш, А. (2016). Концентрация знаний на уровне последовательности. Источник https://arxiv.org/abs/1606.07947

[12] Ло, П., Чжу, З., Лю, З., Ван, X., & Тан, X. (2016). Сжатие модели лица путем извлечения знаний из нейронов. Получено с https://www.aaai.org/ocs/index.php/AAAI/AAAI16/paper/download/11977/12130 »

[13] Мирзаде, С., Фараджтабар, М., Ли, А., и Гасемзаде, Х. (2019). Улучшенное извлечение знаний с помощью помощника учителя: устранение разрыва между учеником и учителем. Получено с https://arxiv.org/abs/1902.03393.

[14] Тан, Р., Лу, Ю., Лю, Л., Моу, Л., Вечтомова, О., и Лин, Дж. (2019). Преобразование специфических знаний из BERT в простые нейронные сети. Получено с https://arxiv.org/abs/1903.12136v1.

[15] Хань С., Мао Х. и Далли В. (2015). Глубокое сжатие: сжатие глубоких нейронных сетей с сокращением, обученным квантованием и кодированием Хаффмана. Источник https://arxiv.org/abs/1510.00149

Первоначально опубликовано на https://blog.rasa.com 8 августа 2019 г.