Глубокие нейронные сети предлагают непревзойденную производительность для многих приложений, но выполнение логических выводов может быть ресурсоемким. Здесь на помощь приходит оптимизация модели, сокращающая дисковое пространство, использование памяти или требования к вычислительным ресурсам. Это может быть полезно для развертывания на периферии (для запуска моделей там, где в противном случае это было бы невозможно), а также для облака и локально (для более быстрого запуска моделей или для одновременного хранения большего количества моделей в памяти). . Кроме того, снижение энергопотребления оптимизированных моделей может помочь уменьшить нагрузку, которую все большее количество моделей оказывает на окружающую среду.

Методы оптимизации моделей направлены на сжатие моделей без ущерба для точности. Например:

  • Сокращение веса можно использовать для удаления весов модели, которые мало влияют на выходные данные сети.
  • Кластеризация весов, как следует из названия, группирует веса каждого слоя и заменяет каждый отдельный вес индексом его центроида кластера. Сохранение значений центроидов только один раз и повторное использование индексов этих центроидов в матрице весов снижает сложность модели.
  • Дистилляция знаний — это процедура, при которой меньшая (сжатая) сеть обучается имитировать более крупную модель.
  • Квантование модели аппроксимирует хранение и вывод нейронной сети, используя разрядность, которая меньше, чем точность с плавающей запятой (например, используя int8 или float16 вместо float32).

Я кратко продемонстрирую квантование модели, которое может быть применено к любой модели после обучения без необходимости тонкой настройки и обычно дает хорошие результаты из коробки. Я буду использовать TFLite, фреймворк, специально предназначенный для логического вывода. Он предлагает несколько методов квантования, как показано на следующей диаграмме решений:

Мы будем использовать квантование динамического диапазона, которое отображает 32-битные веса с плавающей запятой в 8-битные целые числа, чтобы добиться 4-кратного уменьшения размера модели. Конечно, нам понадобится модель для сжатия, и для этого примера я выбрал модель ResNet50, которую я недавно обучил выполнять классификацию масок для лица. Эта сеть была обучена на лицах с искусственно сгенерированными масками и достигает точности 90% на реальных масках. Если вы хотите более подробно проследить за этим небольшим экспериментом, вы можете заглянуть в эту записную книжку.

Оптимизация сети

TFlite позволяет невероятно легко выполнять сжатие. После того, как мы загрузили нашу модель тензорного потока, преобразовать ее в формат TFlite и применить квантование динамического веса так же просто, как это:

import tensorflow as tf
  model_dir = Path('models')
  model = tf.keras.models.load_model(str(model_dir / 'mask_classifier.h5'))
  converter = tf.lite.TFLiteConverter.from_keras_model(model)
  converter.optimizations = [tf.lite.Optimize.DEFAULT]
  tflite_model = converter.convert()
  with open(model_dir / 'mask_classifier_quantized.tflite', 'wb') as f:
      f.write(tflite_model)

В то время как наш исходный файл модели ResNet50 весил 94 МБ, наша квантованная версия занимает всего 23 МБ или примерно 1/4 исходного размера, как и ожидалось.

Проверка точности сжатой сети

Можно было бы ожидать, что отбрасывание 3/4 битов, представляющих веса сети, может значительно повлиять на точность, но на практике квантование часто дает очень небольшой эффект. Интуитивно нейронные сети обучены быть устойчивыми к зашумленным входным данным, и эта устойчивость позволяет им справляться с шумом, вызванным снижением точности. Наша исходная модель имеет точность 90,7%. Мы можем создать интерпретатор TFLite, чтобы делать выводы, и применить его к каждому из наших тестовых изображений, чтобы проверить точность нашей квантованной модели (полный код см. в блокноте):

interpreter = tf.lite.Interpreter(str(model_dir / 'mask_classifier_quantized.tflite'))
  input_details = interpreter.get_input_details()
  output_details = interpreter.get_output_details()
  interpreter.allocate_tensors()

  preds = []
  for batch_idx in range(len(test_generator)):
      for img in test_generator[batch_idx][0]:
          interpreter.set_tensor(input_details[0]['index'], np.expand_dims(img, axis=0))
          interpreter.invoke()
          output_data = interpreter.get_tensor(output_details[0]['index'])
          preds.append(output_data[0][0])
   preds = [x > 0.5 for x in preds]

   tflite_acc = metrics.accuracy_score(test_generator.labels, preds)
   print(f"The quantized TFlite model accuracy = {tflite_acc:.3f}")

Выяснилось, что наша квантованная модель достигает точности 91,89%, неожиданно превосходя даже нашу исходную модель. В целом, однако, можно ожидать небольшого снижения точности. Если ваше падение точности неприемлемо, вы можете использовать тренировку с учетом квантования, чтобы улучшить свои результаты.

Проверка потребления памяти

Мы уже знаем, что наша модель занимает меньше места на диске, но нас также интересует ее потребление памяти во время вывода. TFLite предоставляет хороший инструмент для сравнительного анализа для оценки этого. Это запускает вашу модель с некоторыми случайно сгенерированными входными данными и при этом собирает статистику о задержке и потреблении памяти. В нашем случае исходная модель занимала 104 МБ памяти, тогда как квантованная модель потребляла всего 25 МБ.

Наконец, я хочу отметить, что оптимизация модели — это только один аспект обработки логических выводов в средах с ограниченными ресурсами, и в зависимости от вашего варианта использования вы можете принять во внимание другие аспекты. Например, даже без внесения каких-либо изменений в модель выбор платформы вывода может значительно повлиять на время вывода и использование памяти (например, TensorRT делает умные вещи, такие как слияние слоев и тензоров или использует динамическую тензорную память для уменьшения потребления памяти модели). ). Если вы с самого начала знаете свои ограничения, вы также можете выбрать архитектуру модели, разработанную с учетом низкой стоимости, например MobileNet или EfficientNet.

Если вы хотите узнать больше по этой теме, вы можете ознакомиться с документацией по оптимизации модели tensorflow или со списком интересных указателей, собранных на Обзорной странице Awesome ML Model Compression.