Этот пост является продолжением обучающей серии Learn Coding Neural Network in C#. Если вы не знаете, с чего начать, пожалуйста, сначала прочитайте этот пост.
В этом посте мы реализуем обратное распространение для вычисления градиентов параметров слоя, чтобы их можно было оптимизировать с помощью функции оптимизатора. В примерах до сих пор мы использовали 2 полносвязных слоя, переданных функции стоимости для расчета разницы потерь. Когда эти слои и функция стоимости были вызваны, мы перенаправили данные X между этими слоями и, наконец, получили прогноз и значение стоимости. Теперь, когда нам нужно найти градиенты, расчет будет двигаться назад от стоимости ко всем слоям (последний -> первый).
Что такое обратное распространение?
Это просто метод реализации нейронных сетей, который позволяет нам вычислять градиент параметров, чтобы выполнить градиентный спуск и минимизировать нашу функцию стоимости. Многие ученые описывают обратное распространение как, пожалуй, наиболее математически сложную часть нейронной сети.
Нахождение градиента — это, по сути, нахождение производной функции. Однако в нашем случае, поскольку есть много независимых переменных, которые мы можем настроить (все веса и смещения), мы должны найти производные по каждой переменной. Это известно как частная производная с символом ∂.
Частные производные:
Вычислить частную производную простых функций легко: просто примите любую другую переменную в уравнении как константу и найдите обычную скалярную производную. Вот несколько правил скалярной производной в качестве напоминания:
Рассмотрим частную производную по x (т. е. как y изменяется при изменении x) в функции f(x,y) = 3x²y. Рассматривая y как константу, мы можем найти часть x:
Точно так же мы можем найти часть y:
Градиент функции f(x,y) = 3x²y представляет собой горизонтальный вектор, состоящий из двух частей:
Есть много постов, в которых подробно объясняется обратное распространение, я покажу вам, как это реализовано в нашем существующем проекте «NeuroSimple».
Откройте проект и перейдите в класс «BaseLayer». Нам нужно добавить новые свойства для хранения рассчитанных градиентов. Ниже приведены дополнительные свойства BaseLayer.
/// <summary> /// Gradient of the Input /// </summary> public NDArray InputGrad { get; set; } /// <summary> /// List of all parameters gradients calculated during back propagation. /// </summary> public Dictionary<string, NDArray> Grads { get; set; }
Добавьте еще один виртуальный метод Назад, который будет реализован отдельным слоем и классом активации. Я добавил вспомогательную функцию PrintParam для визуализации параметров. Параметр град в обратной функции предназначен для получения производной внутренней функции и использования ее для нахождения производной внешней функции. Поскольку полная архитектура нейронной сети вместе с функцией потерь будет одной составной функцией, мы применим цепное правило, чтобы найти производную для отдельного слоя. Подробнее о цепном правиле здесь
/// <summary> /// Calculate the gradient of the layer. Usually a prtial derivative implemenation of the forward algorithm /// </summary> /// <param name="grad"></param> public virtual void Backward(NDArray grad) { } public void PrintParams(bool printGrads = true) { foreach (var item in Parameters) { item.Value.Print(string.Format("Parameter: {0}", item.Key)); if(printGrads && Grads.ContainsKey(item.Key)) { Grads[item.Key].Print(string.Format("Grad: {0}", item.Key)); } } }
Обратное распространение для полносвязного слоя
Во время прямого прохода слой FC принимает входные данные X формы N x D и весовую матрицу формы D x M, вычисляя выходные данные, выполняя скалярное произведение Y = X * W. Конечный результат имеет форму N x M. После прямого прохода мы предполагаем, что выходные данные будут использоваться в других частях сети и в конечном итоге будут использованы для вычисления скалярных потерь L. Во время обратного прохода через слой FC мы предполагаем, что производная ∂L /∂Y уже вычислено, что является выводом функции стоимости.
Производная веса по производной внутренней функции, которая в данном случае является потерей, равна
И производная входа X по Loss будет
Давайте реализуем обратную функцию для слоя FC, реализуя следующий код
/// <summary> /// Calculate the gradient of the layer. Usually a prtial derivative implemenation of the forward algorithm /// </summary> /// <param name="grad"></param> public override void Backward(NDArray grad) { //Activation was invoked in Forward after calculating output. //In backpropagation we need to reverse the flow, so Activation Backward will be invoked first then the layer gradient code. if(Activation != null) { Activation.Backward(grad); grad = Activation.InputGrad; } InputGrad = Dot(grad, Parameters["w"].Transpose()); Grads["w"] = Dot(Input.Transpose(), grad); }
Обратное распространение для функций активации
Мы начнем с реализации обратной функции функций активации, которая представляет собой ReLU и Sigmoid.
Выпрямленная линейная единица (ReLU) определяется как f(x)=max(0,x). Производная:
Итак, если мы откроем класс «ReLU» в папке Layers/Activations и переопределим функцию Backward, мы сможем реализовать следующее:
public override void Backward(NDArray grad) { InputGrad = grad * (Input > 0); }
Производная сигмоиды хорошо объяснена в этом посте. Итак, если мы упростим, это будет
Давайте реализуем обратный метод для класса Sigmoid, который будет простым, как показано ниже.
public override void Backward(NDArray grad) { InputGrad = grad * Output * (1 - Output); }
Помните, что выход — это не что иное, как сигмоид входа, поэтому мы можем просто повторно использовать вычисленное значение для нахождения частной производной.
В этом посте мы немного разобрались с техникой обратного распространения и реализовали ее для слоев и функции активации. В следующем посте мы продолжим то же самое, реализовав функцию стоимости и запустив пример, чтобы увидеть результат. Оставайтесь с нами 🙂
Исходный код: https://github.com/deepakkumar1984/tech-quantum/tree/master/Learn-NN-CSharp/Post4
Ссылка: https://towardsdatascience.com/step-by-step-the-math-behind-neural-networks-ac15e178bbd
Первоначально опубликовано на https://www.tech-quantum.com 21 марта 2019 г.