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

  • количество слоев в общей сети
  • количество сверточных фильтров
  • размер сверточных ядер
  • размер ядра пула
  • количество плотных фильтров
  • процент узлов, которые «выпадают»
  • тип активации слоев (relu, elu, линейный, экспоненциальный и т. д.)
  • тип объединения (максимальное, среднее и т. д.)
  • и т.д

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

Поэтому я сначала перечислил все параметры, которые я хотел бы изменить, это был в основном маркированный список выше с некоторыми дополнительными параметрами, такими как тип оптимизатора, активация выхода и функция потерь. Как я быстро понял, такое количество параметров невозможно обработать на 40 ядрах — я просил обучить 1,38 x 10¹⁸ разных нейронных сетей!

Итак, после долгих размышлений и размышлений, я, наконец, сузил список до:

  • размер ядра свертки (3, 6, 9)
  • количество сверточных фильтров (5, 15, 25, 35, 45)
  • количество шагов в сверточном слое (1, 2, 3)
  • процент отсева (0, 0,5, 1)

Теперь это выглядит как 3 * 5 * 3 * 3 = 135 параметров, но моя базовая архитектура состоит из трех сверточных слоев, за каждым из которых следует слой с максимальным объединением, затем два плотных слоя, за каждым из которых следует выпадающий слой, затем последний выходной слой. . Таким образом, количество параметров на самом деле было (3 * 5 * 3)³ * (3)² = 820 125 перестановок.

Однако была спасительная благодать. Оказывается, не все из этих 820 125 наборов параметров на самом деле приведут к правильной архитектуре. По мере того, как мы переходим от одного сверточного слоя к другому, размер входных данных для каждого слоя уменьшается. Таким образом, если мы выберем слишком большой шаг или размер ядра свертки, третий сверточный слой будет иметь входной размер меньше требуемого, что приведет к ошибке. Быстрый пример для пояснения:

Скажем, у нас есть размер ядра = 9 и шаг = 3 для всех трех сверточных слоев. При начальном размере входных данных 100 x 100 пикселей после первого сверточного слоя мы получим изображение размером 31 x 31 пиксель. После максимального слоя пула (который имеет размер пула 2 x 2) мы получим изображение размером 15 x 15 пикселей в качестве нашего следующего ввода. Итак, для нашего второго сверточного слоя мы получим изображение размером 7 x 7 пикселей. И после слоя с максимальным объединением мы получаем изображение размером 3 x 3 пикселя для следующего ввода. НО ЖДАТЬ. У нас есть ядро ​​размером 9, которое не может рисовать из изображения 3 x 3, поэтому наша программа вернет ошибку.

Чтобы исправить эту проблему, я ввел фильтр, который вычисляет окончательный размер изображения после сверточных слоев. Если это число меньше или равно 0, то параметры не используются. Используя этот фильтр, мне удалось снизить количество перестановок до 249 750. Хотя это все еще очень большое число, оно гораздо более управляемо, чем изначально 10¹⁸ перестановок.

Результаты

После нескольких дней обучения на кластере были обучены все 249 750 сетей. Я написал несколько коротких скриптов на Python, чтобы упорядочить файлы точности для облегчения анализа. Во время обучения я записывал только точность обучения, а не точность проверки. Чтобы проверить точность проверки, я взял тридцать лучших результатов обучения и загрузил соответствующие веса моделей в Jupyter Notebook, чтобы найти соответствующую точность проверки.

На приведенном выше графике по оси X отложен i-й набор весов модели, а по оси Y — разница между точностью проверки и обучения. Для всех 30 точек данных точность обучения варьировалась в пределах 59–67%. Таким образом, точки ниже оси Y имели более высокую точность проверки, чем точность обучения, а точки выше оси X имели более низкую точность проверки, чем точность обучения. Как мы видим, некоторые точки (например, точка данных № 2) исключительно далеки от нуля, с разницей в точности около 45%, что приводит к точности проверки около 20%.

Теперь, когда у нас также есть данные о точности проверки, мы можем посмотреть, оказали ли определенные параметры большее влияние на точность, чем другие. Построив график значений параметров в зависимости от разницы в точности для каждого параметра, мы можем увидеть, существует ли взаимосвязь (например, чем меньше разница между точностью, тем меньше/больше размер ядра).

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

Выводы

В целом, возможность создавать пространства перестановок и перебирать эти параметры на 40 параллельных ядрах значительно экономит время и значительно помогает в поисках лучшей архитектуры нейронной сети. В дополнение к изменению различных параметров мне нужно выяснить, повлияют ли дополнительные манипуляции с данными перед тренировкой (например, изменение контраста, создание изображений RBG вместо оттенков серого и т. д.) на точность. Наконец, дальнейшая оптимизация процесса путем написания большего количества вспомогательных скриптов на Python позволит мне более эффективно тестировать и отображать веса и точности.