Давайте перенесем опыт Keras в PyTorch

Вступление
Книга Франсуа Шоле (создателя Keras) «Deep Learning with Python» была тем, что привело меня в мир глубокого обучения. С тех пор я влюбился в стиль Кераса.
Keras был моим первым фреймворком, потом я немного перешел на Tensorflow, а затем перешел в PyTorch, остальное уже история.
Если честно, меня очень взволновала полоса прогресса, которая появляется во время обучения моделей в Керасе, это просто потрясающе :)
Итак, почему бы не попробовать перенести опыт обучения моделей Keras в PyTorch?
Этот вопрос заставил меня начать, и в итоге я воссоздал плотный слой, сверточный слой и плоский слой Keras со всеми этими причудливыми индикаторами выполнения.
Модели можно создавать, накладывая один слой на другой, и обучать, просто вызывая метод подгонки, аналогичный тому, как это делает Керас.
Давай построим это
Для тех из вас, кто не работал с Keras, создание и обучение модели в Keras выглядит примерно так:
1. Импортируйте необходимые библиотеки
Возможно, вы не знакомы с библиотечной панелью pkbar, она используется для отображения Keras, например, индикатора выполнения.
2. Входной слой и плотный слой
Входной слой просто принимает форму одного экземпляра данных, которые будут переданы в нейронную сеть и возвращены, для полносвязных сетей это будет что-то вроде (1, 784), а для сверточной нейронной сети он будет быть размерами изображения (высота × ширина × каналы).
Использование заглавных букв для наименования функции python противоречит правилам, но мы пока будем пренебрегать этим (некоторые части исходного кода Keras используют такое же соглашение).
Плотный класс инициализируется путем передачи количества выходных нейронов и функции активации для этого слоя. Когда вызывается плотный слой, предыдущие слои передаются как входные.
Теперь у нас есть информация о предыдущем слое. Если предыдущий слой является входным, создается линейный слой PyTorch с формой, возвращаемой из входного слоя, и количеством выходных нейронов, предоставленных в качестве аргумента во время инициализации плотного класса.
Если предыдущий слой является плотным, мы расширяем нейронную сеть, добавляя линейный слой PyTorch и слой активации, предоставляемый пользователем плотному классу.
А если предыдущий слой является слоем свертки или сглаживания, мы создадим служебную функцию с именем get_conv_output (), чтобы получить выходную форму изображения после прохождения через свертывание и сглаживание слоев. Это измерение требуется, потому что мы не можем создать линейный слой в PyTorch, не передав значение аргументу in_features.
Функция get_conv_output () принимает в качестве входных данных форму изображения и модель сверточной нейронной сети. Затем он создает фиктивный тензор той же формы, что и изображение, и передает его в сверточную сеть (со сглаженным слоем) и возвращает размер данных, выходящих из него, этот размер передается как значение аргументу in_features в линейном параметре PyTorch. слой.
3. Свести слой
С целью создания плоского слоя мы создадим собственный класс слоя, называемый плоским слоем, который принимает на вход тензор и возвращает сглаженную версию тензора во время прямого распространения.
Мы создадим еще один класс с именем flatten, когда этот слой вызывается, предыдущие слои передаются в качестве входных данных, затем класс flatten расширяет сеть, добавляя наш созданный нами класс плоского слоя поверх предыдущих слоев.
Таким образом, все данные, поступающие на плоский слой, выравниваются с использованием нашего специально созданного класса плоского слоя.
4. Сверточный слой
Мы инициализируем слой Conv2d, передав количество фильтров, размер ядра, шаги, заполнение, расширение и функцию активации.
Теперь, когда вызывается слой Conv2d, ему передаются предыдущие слои, если предыдущий слой является входным слоем, один слой PyTorch Conv2d с предоставленными значениями количества фильтров, размера ядра, шагов, заполнения, расширения и функции активации. создается, где значение in_channels берется из количества каналов во входной форме.
Если предыдущий слой является сверточным, предыдущий уровень расширяется путем добавления слоя PyTorch Conv2d и функции активации со значением in_channels, взятым из out_channels предыдущего слоя.
В случае заполнения, если пользователю необходимо сохранить размеры данных, выходящих из этого уровня, тогда значение заполнения может быть указано как «то же самое» вместо целого числа.
Если значение заполнения указано как 'same', тогда служебная функция с именем same_pad () используется для получения значения заполнения, чтобы сохранить размеры для заданного размера ввода, размера ядра, шага и расширение.
Размер ввода можно получить с помощью служебной функции get_conv_output (), описанной ранее.
5. Класс модели
После построения архитектуры нашей модели класс Model инициализируется путем передачи входного и выходного уровней. Но я привел дополнительный аргумент под названием device, которого нет в Keras, этот аргумент принимает значение либо «CPU», либо «CUDA», которое переместит всю модель на указанное устройство.
Метод параметров класса модели используется для возврата параметров модели, которые должны быть переданы оптимизатору PyTorch.
Класс модели имеет метод под названием compile, который принимает оптимизатор и функцию потерь, необходимую для обучения модели. Метод Summary класса модели отображает сводку созданной модели с помощью библиотеки torchsummary.
Метод подгонки используется для обучения модели, этот метод принимает входной набор функций, целевой набор данных и количество эпох в качестве аргумента. Он отображает потери, рассчитанные с помощью функции потерь, и прогресс обучения с использованием библиотеки pkbar.
Метод оценки используется для расчета потерь и точности данных испытаний.
Fit_generator, calculate_generator и pred_generator используются, когда данные загружаются с помощью загрузчика данных PyTorch. Fit_generator принимает в качестве аргументов загрузчик данных обучающего набора и эпохи. Assessment_generator и pred_generator используют загрузчик данных набора проверки и загрузчик тестовых данных соответственно, чтобы измерить, насколько хорошо модель работает с невидимыми данными.
Последние мысли
Я протестировал код на наборе данных CIFAR100, CIFAR10 и MNIST, используя как плотные слои, так и сверточные нейронные сети. Он работает нормально, но есть большие возможности для улучшения.
Это был забавный проект, над которым я работал в течение 3-4 дней, и он действительно расширил мои границы программирования с PyTorch.
Вы можете взглянуть на полный код с обучением, проведенным на вышеупомянутых наборах данных здесь, или вы можете свободно настроить код по своему вкусу в colab.