В данной статье мы рассмотрим прямое распространение сигнала и обратное распространение ошибки в полносвязной нейронной сети прямого распространения. В результате получим весь набор формул, необходимых для программной реализации нейронной сети. В завершении статьи рассмотрим численный пример.   «Полносвязная» (fully connected) — означает, что каждый нейрон предыдущего слоя соединён с каждым нейроном следующего слоя. «Прямого распространения» (feedforward) — означает, что сигнал проходит через нейронную сеть в одном направлении от входного к выходному слою. Полносвязная нейронная сеть прямого распространения («перцептрон») — это простейший и наиболее типичный пример искусственной нейронной сети. Нейронная сеть как функция Дизайн нейронной сети Прямое распространение сигнала Обратное распространение ошибки и обновление 4.1. Вычисление новых весов матрицы W^3 4.2. Вычисление новых смещений вектора b^3 4.3. Вычисление новых весов матрицы W^2 4.4. Вычисление новых смещений вектора b^2 Численный пример Обобщение для произвольного числа слоёв Искусственная нейронная сеть является математической функцией, а точнее — композицией (суперпозицией) функций. Было доказано (George Cybenko, 1989), что полносвязная нейронная сеть прямого распространения с хотя бы одним скрытым слоем и достаточным количеством нейронов потенциально может аппроксимировать любую непрерывную функцию, т.е. по своей сути она — универсальный аппроксиматор. «Свойства универсальной аппроксимации встречаются в математике чаще, чем можно было бы ожидать. Например, теорема Вейерштрасса — Стоуна доказывает, что любая непрерывная функция на замкнутом интервале может быть приближена многочленной функцией. Если ослабить наши критерии далее, можно использовать ряды Тейлора и ряды Фурье, предлагающие некоторые возможности универсальной аппроксимации (в пределах их областей схождения). Тот факт, что универсальная сходимость — довольно обычное явление в математике, дает частичное обоснование эмпирического наблюдения, что существует много малых вариантов полносвязных сетей, которые, судя по всему, дают свойство универсальной аппроксимации». — Рамсундар Б., Заде Р.Б. TensorFlow для глубокого обучения. Спб., 2019. С. 101.    Запишем нейронную сеть, которую мы будем рассматривать в данной статье, в виде функции: где — вектор входных значений — первый слой, — второй, скрытый и — третий слои нейронной сети, ,  — векторы смещений и ,  — матрицы весов второго и третьего слоёв соответственно,  — вектор-функция активации второго слоя, — вектор-функция активации третьего, последнего слоя и, соответственно, вектор выходных значений нейронной сети. Мы будем использовать принятую в литературе по нейронам сетям запись , где  — вектор-столбец (в литературе по математике под вектором стандартно (по умолчанию) понимается вектор-столбец). Произведение матриц  определено, если число столбцов  равно числу строк . Таким образом число столбцов  матрицы равно числу строк  векторов  и . Для комфортного чтения статьи необходимо обладать некоторым знанием линейной алгебры (обязательный минимум — операции над матрицами), производной сложной функции и частных производных. Нейронная сеть имеет три слоя с тремя нейронами в каждом из них. Нелинейное изменение проходящего через сеть сигнала обеспечивает функция активации сигмоид (sigmoid) на скрытом и выходном слоях: Поскольку на практике большинство реальных данных имеют нелинейный характер, используются нелинейные функции активации, позволяющие извлекать нелинейные зависимости в данных. Перепишем уравнение рассматриваемой сети для заданных параметров: Функция активации поэлементно применяется к каждому элементу соответствующего вектора . Запишем уравнения для прямого прохождения сигнала через нейронную сеть: и функцию стоимости (cost function) где — номер соответствующего целевого (вектора ) и выходного значений,  — число выходных значений. Таким образом, функция стоимости для нашей нейронной сети в развёрнутом виде: Функция стоимости показывает нам насколько сильно отличаются текущие значения нейронной сети от целевых. В сущности, для реализации алгоритма обратного распространения ошибки используется довольно простая идея. Градиент (в общем случае) — вектор, определяющий направление наискорейшего роста функции нескольких переменных. Вычитая из текущих значений весов и смещений соответствующие значения частных производных как элементов градиента функции стоимости , мы будем приближаться к одному из ближайших (относительно начальной точки) минимумов функции стоимости и, таким образом, уменьшать величину ошибки. Согласно необходимому условию экстремума, в точках экстремума функции многих переменных её градиент равен нулю, . Этот подход называется алгоритмом градиентного спуска. Иногда может возникать путаница или отождествление этих двух алгоритмов, поскольку они тесно взаимосвязаны и один используется для реализации другого. Несмотря на простоту и эффективность, алгоритм градиентного спуска в общем случае имеет свои ограничения, например, седловая точка, локальный минимум, перетренировка (overtraining) (попадание в глобальный минимум). Найдём частные производные по всем элементам матрицы : поскольку  — константа, то , Преобразуем функцию активации сигмоид и найдём её производную: В производной по матрице мы находим производную по каждому из её элементов. Раскроем сумму для переменной  матрицы : Найдём частную производную по переменной . Поскольку Преобразуем сигмоид и получим окончательную форму выражения для : Обратное распространение ошибки является частным случаем автоматического дифференцирования, для реализации которого нам и необходимо привести все вычислительные выражения к определённому виду. Таким же образом для переменных и  получим: Найдём новые значения (обновлённые веса) для переменных ,  и : где  (и́та) — буква греческого алфавита, обычно используемая для обозначения скорости обучения (learning rate), её значение должно быть установлено на промежутке от 0 до 1; * — новое значение переменной. Найдём остальные частные производные для матрицы . Раскроем сумму для : Найдём частную производную по переменной : Преобразуем сигмоид и получим окончательную форму выражения для : Таким же образом для переменных  и  получим: Найдём новые значения (обновлённые веса) для переменных ,  и: Раскроем сумму для : Найдём частную производную по переменной : Преобразуем сигмоид и получим окончательную форму выражения для : Таким же образом для переменных  и  получим: Найдём новые значения (обновлённые веса) для переменных ,  и : Теперь найдём частные производные по всем элементам вектора : Найдём частную производную по : Преобразуем сигмоид и получим окончательную форму выражения для : Найдём новое значение для смещения : Вычислим частные производные по  и : Найдём новые значения для  и: Найдём частные производные по всем элементам матрицы . Раскроем сумму для переменной  матрицы . Поскольку в свою очередь, тогда сумма для переменной  матрицы : Найдём новое значение (обновлённый вес) для переменной : Найдём остальные частные производные и их новые значения для матрицы . Теперь найдём частные производные по всем элементам вектора . Раскроем сумму для переменной : Найдём новое значение для : Найдём остальные частные производные для вектора : Найдём новые значения для переменных  и : Задача обучения нейронной сети состоит в аппроксимации некоторой неизвестной функции, которая отображает в . Другими словами, существует некоторая неизвестная нам функция , которая для набора значений независимых переменных  выдаёт результат, соответствующий набору значений зависимых переменных . Задача нейронной сети в результате обучения «заменить», приблизить, т.е. аппроксимировать неизвестную функцию . В случае успешного решения задачи, значения нашей нейронной сети на выходном слое  будут приблизительно равны значениям вектора  аппроксимируемой функции. Выберем случайным образом следующие начальные значения для нашей нейронной сети: А также входные и целевые значения:  После первого прямого прохождения сигнала значения скрытого и выходного слоёв: Для скорости обучения установим значение . Вычислим для первой эпохи (epoch) обучения нейронной сети обновлённые значения весов и : Новые значения других весов и смещений находятся аналогичным образом, в соответствии с полученными ранее формулами. После 10 000 эпох обучения матрицы весов и выходной слой имеют следующие значения: Мы рассмотрели частный случай алгоритма обратного распространения ошибки для нейронной сети с одним скрытым слоем. Запишем формулы для реализации нейронной сети с произвольным числом скрытых слоёв. где — номер выходного слоя, — индекс строки матрицы весов, — число выходных значений. — обобщённое дельта-правило (delta rule). Надеемся, что статья будет интересной и полезной для всех, кто приступает к изучению глубинного обучения и нейронных сетей!