Время прочтения: 6 мин.

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

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

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

Размышление, которые привели меня к использованию алгоритма обратного распределения:

  1. Прежде всего, если я хочу создать нейронную сеть мне нужно инициализировать некоторые веса.
  2. Какие бы значения я ни выбрала для весов, я не знаю насколько они верны.
  3. Чтобы проверить правильность или неправильность выбранных значений веса, я должна вычислить ошибку модели.
  4. Предположим, моя ошибка модели произошла слишком много раз.
  5. Это означает, что мой прогнозируемый результат сильно отличается от фактического. Так что мне делать? Постараюсь минимизировать ошибку.

Описание схемы:

  1. Здесь мы пытаемся минимизировать нашу ошибку, как мы это сделаем?
  2. Что мы действительно хотим сделать, так это научить нашу модель изменять веса автоматически, чтобы получить наименьшее количество ошибок.
  3. Как показано на приведенной выше диаграмме, мы сначала вычислили ошибку нашей модели, после этого мы увидели, что если ошибка минимальна, то наша модель готова для прогнозирования.
  4. Если ошибка не минимизирована, мы обновим параметры (веса) и снова вычислим ошибку.
  5. Эти процессы будут выполняться до тех пор, пока ошибка нашей модели не будет сведена к минимуму.

Как работает алгоритм обратного распространения?

Предположим, у нас есть нейронная сеть с входным, скрытым и выходным слоями.

  • Шаг 1: Сначала мы присваиваем модели случайные веса.
  • Шаг 2: Прямое распространение (расчет обычной нейронной сети).
  • Шаг 3: Вычислить общую ошибку.
  • Шаг 4: Обратное распространение (градиентный спуск), обновление параметров (веса и смещение).
  • Шаг 5: Пока ошибка не будет минимизирована (прогнозируемый результат будет примерно равен исходному результату).

ПЕРЕДАЧА РАСПРОСТРАНЕНИЯ

  1. Рассчитать значение h1

2. Рассчитать выход h1

3. Рассчитать погрешность вывода h1

4. Вычислить общую погрешность модели

Теперь будет распространяться в обратном направлении

ОБРАТНОЕ РАСПРОСТРАНЕНИЕ

Здесь мы пишем процесс и формулы для обновления нашего веса w5.

Для этого мы должны знать, какая общая ошибка произошла по отношению к весу w5.

  1. Вычисление нашей общей полной ошибки относительно выходного

2. Расчет нашего общего output1по отношению к чистому output1

3. Расчет чистого output1 относительно weight5

4. Расчет обновленного веса

Аналогичным образом мы можем рассчитать и другие значения веса (весь этот процесс происходит в модели).

Как реализовано обратное распространение на Python?

Инициализация значения переменных:

import numpy as np
input_data = np.array(([2, 9], [1, 5], [3, 6]), dtype=float)
print("small x",input_data)
original_output  = np.array(([92], [86], [89]), dtype=float)
max_in_axis = input_data /np.amax(input_data ,axis=0) #максимум по первой оси 
print("Capital X",max_in_axis )
#Определение сигмоидной функции для вывода 
def sigmoid input_data ):
    return (1/(1 + np.exp(-input_data )))
#Производный от сигмовидной функции
def sigmoid_derivatives(input_data ):
    return input_data  * (1 - input_data )
#Инициализация переменных
epoch=7000 #Настройка итераций обучения
lr=0.1 #Установка скорости обучения
inputlayer_neurons_layer  = 2 #количество нейронов входного слоя 
hiddenlayer_neurons_layer  = 3 #количество нейронов скрытых слоев
output_neurons_layer = 1 #количество нейронов на выходном слое

Пояснение:

В этом коде мы определили сигмовидную функцию и ее производную функцию.

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

# Определение веса и смещения для скрытого и выходного слоя 
bout=np.random.uniform(size=(1,output_neurons_layer))
weight=np.random.uniform(size=(inputlayer_neurons_layer ,hiddenlayer_neurons_layer ))
wout=np.random.uniform(size=(hiddenlayer_neurons_layer ,output_neurons_layer ))
bias=np.random.uniform(size=(1,hiddenlayer_neurons_layer ))

Пояснение:

Здесь мы определили случайные веса и смещение

Мы должны сначала определить wights и Bias для первого (здесь у нас только один скрытый слой) скрытого слоя.

После этого мы определили веса и смещение для выходного слоя.

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

Размер смещения (количество нейронов в выходном слое, количество нейронов в слое, для которого мы определили смещения)

#Прямое распространение 
for i in range(epoch):
    hinp1=np.dot(max_in_axis ,weight) 
    hinp=hinp1 + bias
    hlayer_act = sigmoid(hinp)
    outinp1=np.dot(hlayer_act,wout)
    outinp= outinp1+ bout
    output = sigmoid(outinp)

Пояснение:

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

np.dot используется для скалярного произведения двух матриц

#Backpropagation алгоритм
EO = y-output
outgrad = sigmoid_derivatives(output)
d_output = EO* outgrad
EH = d_output.dot(wout.T)
hiddengrad = sigmoid_derivatives(hlayer_act)

#сколько скрытых слоев привело к ошибке
d_hiddenlayer = EH * hiddengrad
wout += hlayer_act.T.dot(d_output) *lr
bout += np.sum(d_output, axis=0,keepdims=True) *lr
#Обновление веса
weight += max_in_axis.T.dot(d_hiddenlayer) *lr
print("Actual Output: \n" + str(y))
print("Predicted Output: \n" ,output)

В этом коде сначала мы вычислили ошибку выходного слоя.

Как мы знаем из формулы, мы должны выяснить, какой вклад скрытого слоя в общую ошибку, а также вклад веса в общую ошибку.

После этого мы обновили наши веса и смещения, пока не получим минимальную ошибку.