С возвращением, сети в обучении! На прошлой неделе мы представили Multilayer Perceptron (MLP) - нашу первую искусственную нейронную сеть (ANN). Мы создали довольно строгую реализацию (у нее был один фиксированный скрытый слой), и я попросил вас сделать ее более гибкой.

Хотя есть много способов сделать это, вот мое решение:

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

Этот код создаст экземпляр MLP с одним входом, пятью скрытыми слоями - каждый с 1024 нейронами - и одним выходом.

По поводу распространения

Отчасти элегантность ИНС заключается в том, что каждый уровень сети «активируется» последовательно. Это можно увидеть в приведенном выше методе «активировать» - данные проходят по сети в виде простого цикла for, а выходные данные предыдущего уровня используются в качестве входных данных для следующего. Это известно как прямое распространение. Здесь все становится по-настоящему интересным: сеть может учиться на своих ошибках, работая в обратном направлении, что известно как обратное распространение или обратное распространение.

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

Обучение ИНС с контролируемым обучением

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

Обучение ИНС - это итеративный процесс, в котором примеры обучающих данных передаются в сеть один за другим, а значения весов корректируются каждый раз. После того, как все примеры проходят через сеть, заканчивается одна эпоха обучения, и часто процесс начинается заново. На этом этапе ИНС учится предсказывать правильный результат на основе входных примеров и, надеюсь, может обобщить предсказание на другие данные, аналогичные входным примерам. Это называется обучение с учителем (SL).

На этапе обучения мы передаем в сеть пример обучения, а затем сравниваем рассчитанные сетью значения выходных узлов с «правильными» значениями. Затем мы вычисляем значение ошибки. Затем эта ошибка может быть передана в обратном направлении, и веса соединения в скрытых слоях могут быть скорректированы с надеждой, что выходные значения, вычисленные в следующий раз, будут ближе к правильным значениям.

Механика обратного распространения ошибки

Хватит теории - вернемся к коду!

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

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

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

y = x * (1.0 — x)

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

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

Собираем все вместе

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

Начнем с данных, создав игрушечный набор чисел:

Мы постараемся научить нашу сеть изучить это простое отображение с помощью программы обучения.

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

Эпоха завершена

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

А пока у меня есть для вас простое следственное задание:

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

Как всегда, исходный код всех вышеперечисленных примеров вы можете найти на нашем GitHub.

Чтобы начать обучение программированию AI с первого дня, перейдите здесь.

И дайте нам подписаться, чтобы получать обновления о наших последних сообщениях.