Давайте получим общее представление о том, что такое нейронные сети, а затем перейдем к математике. Здесь, в этой статье, архитектура нейронной сети с прямой связью зафиксирована как трехуровневая сеть (входной уровень + скрытый уровень + выходной уровень). После математики, давайте код! (Учебник для начинающих)

Интуиция

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

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

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

Учебный процесс

Процесс обучения основан на 3 шагах: прямое распространение, вычисление ошибок и обратное распространение.

  • Прямое распространение - это, по сути, прогноз (Y) для заданного входа (X) и параметров (W и B).
  • Вычисление ошибки - это просто сравнение этого прогноза (Y) с фактическим ответом (Y * также называется «меткой»).
  • Обратное распространение - это просто поиск новых параметров, которые минимизируют эту ошибку. Есть много алгоритмов оптимизации, здесь мы воспользуемся самым известным: градиентным спуском.

Мы собираемся повторить эти шаги для всех данных набора данных (размера N). В общем, однократного просмотра набора данных недостаточно, поэтому мы повторяем снова «Эпохи», что означает, что мы собираемся обновить параметры N x Эпох.

После тренировочного процесса параметры W и B будут оптимальными для выполнения задачи. Теперь пора делать прогнозы на основе невидимых данных.

Вещи становятся интересными, не так ли? Есть еще пара идей, которые нужно развить, прежде чем погрузиться в математику.

Функция стоимости и градиентный спуск

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

Как было сказано ранее, чтобы «изучить» нашу нейронную сеть, необходимо минимизировать ошибку. Ошибка также называется функцией стоимости. Функция стоимости обычно обозначается как выпуклая функция. Есть несколько функций, которые позволяют моделировать ошибку, вот 2 примера:

Сумма квадратичной ошибки (SSE) и среднеквадратичной ошибки (MSE): (квадратные функции дают выпуклые функции)

Алгоритм градиентного спуска:

Самый простой способ увидеть алгоритм градиентного спуска - это увидеть, как теннисный мяч спускается с горы. Мяч будет следовать по склону горы. Здесь, с точки зрения математики, наклон соответствует производной функции стоимости в данной точке. Градиенты - это всего лишь производные!

Не забывайте, что мы хотим минимизировать функцию стоимости, чтобы найти параметры W и B. Итак, мы смотрим на производную функции стоимости в зависимости от этих параметров. Если вы внимательно посмотрите на них (особенно с визуализацией), вы легко поймете, что знак этой производной указывает, как вы должны двигаться по абсциссе (это параметры W и B).

  • Если производная положительна (/), вы хотите переместиться в левую сторону, поэтому вам нужно выбрать противоположную производную.
  • Если производная отрицательна (\), вы хотите переместиться вправо, поэтому вам нужно взять (положительную) производную.

Если обобщить ситуацию, мы минимизируем функцию стоимости, обновляя параметры благодаря градиентам:

Здесь α называется скоростью обучения, это константа, которая регулирует, какой процент производной должен быть изменен. Обычно это очень маленькое значение (например, α = 0,01). Если скорость обучения слишком высока, это может привести к расхождению.

Архитектура нейронной сети

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

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

  • Входной слой (1, i) имеет столько нейронов, сколько входов (i). Например, если на входе изображение размером 28x28 (пикселей), то во входном слое будет 28x28 = 784 нейрона.
  • Скрытый слой (1, j) имеет произвольное количество нейронов (j), определенное разработчиком. . В общем, количество нейронов зависит от сложности вашей задачи (например, для задач классификации изображений большого размера требуется большое количество нейронов в их скрытых слоях).
  • Уровень вывода (1, k) имеет столько нейронов, сколько требуется выходов (k). Например, если ваша нейронная сеть предназначена для вывода одного прогноза, ваш выходной слой будет содержать только один нейрон. Для задач классификации будет столько нейронов, сколько классов (если есть 2 класса кошки и собаки, в выходном слое будет 2 нейрона).

Параметры W и B связывают вместе уровни, поэтому, если есть 3 уровня, будет 4 параметра W (1), W (2), B (1), B (2).

Посмотрим с точки зрения математики, что происходит внутри одного нейрона:

Функция активации

Почему нужно активировать нейрон?

Сложные проблемы обычно не моделируются линейно. Нелинейность - ключевой элемент нейронных сетей. Таким образом, основная цель функции активации - добавить модели нелинейности. Кроме того, он преобразует входной сигнал (от -∞ до ∞) в выходной сигнал (обычно от -1 до 1 или -0 до 1 в зависимости от используемой функции), который станет входом для следующего слоя. Следовательно, функции активации можно рассматривать как передаточные функции. Термин «активирован» означает, что нейрон готов перейти к следующему этапу прямого распространения. Три наиболее часто используемых функции активации:

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

Математика

Все действительно интересно! Пора окунуться в математику. Не пугайтесь, если разбирать уравнения шаг за шагом, все будет предельно ясно.

Прямое распространение

Вот математика, лежащая в основе прямого распространения.

  • От входного слоя до скрытого слоя:

H (^) - это предварительно активированные нейроны, полученные из Скрытого слоя. Таким образом, вектор H (^) зависит от значений нейронов X (из входного слоя) и параметров W (1) и B (1), которые связывают входной слой и скрытый слой вместе.

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

  • От скрытого слоя до выходного слоя:

Y (^) - это предварительно активированные нейроны, полученные из выходного слоя. Таким образом, вектор Y (^) зависит от значений нейронов H (из скрытого слоя) и параметров W (2) и B (2), которые связывают скрытый слой и выходной слой вместе.

Затем нам нужно активировать Y (^), чтобы получить наш последний слой Y. Эти нейроны будут рассматриваться как окончательный результат нейронной сети. Обратите внимание, что выходной размер Y равен количеству нейронов в выходном слое (k). Наше прямое распространение теперь выполняется для одной точки данных. Мы можем сравнить этот результат с меткой и вычислить ошибку.

Вычисление ошибок

Насколько хорошо наш прогноз основан на текущей модели?

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

Обратное распространение

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

Целью обратного распространения является найти некоторые новые параметры W и B, которые минимизируют ошибку с помощью градиентного спуска.

Однако наши предыдущие обозначения градиентного спуска, описанные выше, были недостаточно подробными. Это лучшие обозначения.

Вам нужно обновить 4 параметра. Каждый из этих параметров имеет определенную форму в зависимости от его местоположения в сети. Если вы внимательно посмотрите на эти формулы, неизвестные переменные - это только градиенты (производная от E по параметрам). Давайте их вычислим!

Хорошо, здесь нам нужно обновить параметры в правильном порядке, от выходного уровня до входного. Следовательно, мы будем обновлять в этом порядке W (2), B (2), W (1), B (1). Этот порядок важен, потому что в математике вы увидите, что W (1) и B (1) зависят от W (2). Давайте начнем!

Производная dE / dW (2) была записана в виде суммы в первой строке, а не в последней строке. Почему? Потому что, когда мы применили градиент к W (2), большинство элементов стали нулевыми, за исключением того, который находится в правом индексе (j, k).

Производная dE / dB (2) была записана как сумма в первой строке, а не в последней строке. Почему? Потому что, когда мы применили градиент к B (2), большинство элементов стало нулевым, за исключением смещения.

Мы на полпути! Мы уже обновили все параметры между выходным слоем и скрытым слоем. Теперь давайте переместимся еще дальше «назад» между скрытым слоем и входным слоем.

Здесь есть некоторые дополнительные трудности, потому что W (1) косвенно связано с yk (вам придется пройти через hj), поэтому вам нужно выполнить двойное разложение. Не убегай, мы почти у цели!

Давай, еще один! Давайте обновим B (1), и вы будете готовы реализовать это в своем коде.

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

Реализация Python3

Надеюсь, вы пережили математику! Пора кофе, сделай хороший перерыв и возвращайся, готовый к написанию кода!

Результаты

[INFO]: epoch = 1 | error = 0.17833722318123282
[INFO]: epoch = 2 | error = 0.17569493660525415
...
[INFO]: epoch = 9998 | error = 0.0017202127419873423
[INFO]: epoch = 9999 | error = 0.0017198195936561878
[INFO]: epoch = 10000 | error = 0.0017194266110162218
Input [[0 0][0 1][1 0][1 1]]
Predition [[0.][1.][1.][0.]]
Label [[0][1][1][0]]

Репозиторий GitHub



Что дальше?

«Создайте свою собственную библиотеку машинного обучения»

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



Спасибо за внимание, не стесняйтесь присылать мне свои вопросы! Оставьте хлопок (или несколько), если вам понравилось;)