Выполнение распределенного обучения с использованием встроенных функций TensorFlow 2.0 и его использование для обучения простой модели классификации изображений.

Глубокое обучение привело к различным технологическим достижениям в области машинного обучения, но оно по-прежнему страдает от значительного количества вычислительного времени, необходимого для обучения на больших наборах данных. Наборы данных для обучения, такие как ImageNet, используемые для тестов, могут занять одну систему с графическим процессором до недели. С другой стороны, распределенное обучение, при котором обучение делится между несколькими машинами или графическими процессорами, значительно сокращает время обучения.

TensorFlow предоставляет встроенные функции для выполнения распределенного обучения с использованием различных алгоритмов. Сегодня мы рассмотрим Зеркальную стратегию и реализуем ее в наборе данных beans.

Импорт зависимостей и загрузка набора данных

Во-первых, нам нужно загрузить необходимые библиотеки и набор данных, над которым мы будем работать.

Теперь, когда мы загрузили набор данных и соответствующие зависимости, мы можем перейти к написанию кода.

Начало работы с кодом

Теперь, прежде чем мы начнем обучение, необходимо сделать несколько важных шагов. Необходимо определить гиперпараметры и, что более важно, инициализировать алгоритм распределенного обучения.

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

Создание модели и дополнительных функций

Мы будем использовать простую модель CNN для обучения на этом наборе данных и демонстрации функции распределенного обучения. Нашему CNN также потребуются некоторые функции, которые мы определим по ходу дела.

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

Теперь мы можем приступить к созданию нашей CNN.

Наконец, нам нужно определить некоторые дополнительные функции, включая контрольную точку, снижение скорости обучения и обратный вызов.

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

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

Обучение модели

Это самая легкая часть кода, но самая важная часть работы нашего кода. Теперь мы можем обучить модель на наборе данных, и это будет происходить с использованием распределенного обучения!

Распределенные стратегии обучения

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

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

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

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

Все вышеперечисленные стратегии являются лишь некоторыми примерами алгоритмов распределения. Все они могут быть реализованы в TensorFlow с помощью библиотеки tf.distribute.

# To use Mirrored Strategy, we have used this in our code 
$ tf.distribute.MirroredStrategy()
# To use Multi Worker Mirrored Strategy
$ tf.distribute.MultiWorkerMirroredStrategy()
# To use Parameter Server Strategy
$ tf.distribute.ParameterServerStrategy()

Но все ли налаживается?

Поскольку разные стратегии различны и имеют свои положительные стороны, у них есть и свои недостатки.

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

Стратегия Multi Worker Mirrored позволяет получить более высокую производительность за счет синхронизации нескольких рабочих, имеющих собственный набор графических процессоров, но в то же время эта стратегия уязвима для системных ошибок. Если один из рабочих страдает системной ошибкой, поскольку процесс обучения должен быть синхронизирован между всеми рабочими, это приводит к тому, что TensorFlow приостанавливает процесс обучения до тех пор, пока рабочий не вернется в режим онлайн. Это действительно приводит к увеличению времени обучения, и чем дольше процесс обучения, тем больше шансов на сбой сети или системы и увеличение времени обучения. Кроме того, оценку контрольной точки не может выполнить ни один из рабочих, потому что, пока один работник оценивает контрольные точки, другим придется ждать, и это может привести к тайм-ауту связи. Таким образом, оценка контрольных точек выполняется главной системой, которая общается со всеми рабочими, и процесс полностью определяется мощностью одной машины.

Полную записную книжку кода можно найти на колабе здесь.