[Основы нейронных сетей] Принцип и две реализации алгоритма BP

Нейронные сети
[Основы нейронных сетей] Принцип и две реализации алгоритма BP

1. Алгоритм БП

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

1. Сначала кратко представим каждый параметр:

m: указывает количество выборок.

y: реальное значение каждой выборки, размер m*1

n^{[l]}: Указывает количество нейронов в l-м слое.

a^{[l]}: представляет входную переменную l-го слоя, который также является l-1-м слоем.z^{[l]}Результат после обработки функцией активации. Его размеры обычноa^{[l]}=n^{[l]}*m

w^{[l]}: представляет весовой параметр l-го слоя, и его размер обычно равенw^{[l]}=n^{[l]}*n^{[l-1]}

b^{[l]}: Представляет параметр смещения l-го слоя, и его размер обычноb^{[l]}=n^{[l]}*m

z^{[l]}: представляет результат после линейного преобразования l-го слоя, и его размер обычноz^{[l]}=n^{[l]}*m

2. Процесс расчета прямого распространения:

  • входной слойa^{[0]}Являетсяn^{[0]}*mМатрица , т. е. m отсчетов, каждый отсчет содержитn^{[0]}функции, в данном случае 3*5.
  • Скрытый слой имеетn^{[1]}скрытая единица. Скрытый слой включает в себя два шага вычислений,

Один из них - линейное преобразование,w_{[i]}^{[1]}i-й параметр скрытого модуля первого скрытого слоя,b_{[i]}^{[1]}— смещение i-й скрытой единицы первого скрытого слоя;z^{[1]}=w^{[1]}*a^{[0]}+b^{[1]}

Второй шаг - это функция активации, нелинейное преобразование и преобразование значения от 0 до 1. В этом примере в качестве функции активации выбрана сигмоидальная функция.a^{[1]}=sigmoid(z^{[1]})

  • Выходной слой имеет только один узел,n^{[2]}=1, для этого слоя вводa^{[1]}, окончательное прогнозируемое значение получается после линейного преобразования и обработки функции активацииa^{[2]}, и рассчитать функцию потерь L(y, a) по среднеквадратической ошибке.

3. Процесс обратного распространения, обновить значения параметров:

Обратное распространение — это процесс получения частных производных каждого параметра с использованием цепного правила. Наша цель обучения — минимизировать функцию потерь, и метод градиентного спуска используется в нейронной сети для обновления параметров w и b, чтобы минимизировать значение функции потерь L. Если вы понимаете градиентный спуск, вы должны знать, что способ обновления параметров в градиентном спуске состоит в том, чтобы заставить каждый параметр падать в самом быстром направлении функции с определенным размером шага (скорость обучения), Быстрое направление — это направление, противоположное направлению градиент) до тех пор, пока не будет найдено глобальное или локальное оптимальное решение.

сначала, чтобы быть яснымz^{[k]}иa^{[k]}происхождение:

z^{[k]}=w^{[k]}*a^{[k-1]}+b^{[k]}

a^{[k]}=f(z^{[k]})#f — функция активации

Затем найдите частные производные w и b k-го слоя и k-1-го слоя.

\frac{{\partial L(y,a)}}{{\partial w^{[k]}}} = \frac{{\partial L(y,a)}}{{\partial z^{[k]}}}*\frac{{\partial z^{[k]}}}{{\partial w^{[k]}}}

\frac{{\partial L(y,a)}}{{\partial b^{[k]}}} = \frac{{\partial L(y,a)}}{{\partial z^{[k]}}}*\frac{{\partial z^{[k]}}}{{\partial b^{[k]}}}

Один - спросить\delta^{[k]}=\frac{{\partial L(y,a)}}{{\partial z^{[k]}}},определение\delta^{[k]}— член ошибки k-го слоя, отражающий влияние этого слоя на итоговую суммарную ошибку. По цепному правилу:

\delta^{[k]}=\frac{{\partial a^{[k]}}}{{\partial z^{[k]}}}*\frac{{\partial z^{[k+1]}}}{{\partial a^{[k]}}}*\frac{{\partial L(y,a)}}{{\partial z^{[k+1]}}} = f'(z^{[k]}) (w^{[k+1]})^{T}\delta^{[k+1]}

Второй - спросить\frac{{\partial z^{[k]}}}{{\partial w^{[k]}}}и\frac{{\partial z^{[k]}}}{{\partial b^{[k]}}}:

\frac{{\partial z^{[k]}}}{{\partial w^{[k]}}} =a^{[k-1]}

\frac{{\partial z^{[k]}}}{{\partial b^{[k]}}}=1

Следовательно, нахождение частной производной k-го слоя зависит от значения частной производной k+1-го слоя, что отражает смысл обратного распространения.

\frac{{\partial L(y,a)}}{{\partial w^{[k]}}} =\delta^{[k]}*(a^{[k-1]})^{T}

\frac{{\partial L(y,a)}}{{\partial b^{[k]}}}=\delta^{[k]}

Затем обновите параметры до:

w^{[k]}-=lr*\frac{{\partial L(y,a)}}{{\partial w^{[k]}}}

b^{[k]}-=lr*\frac{{\partial L(y,a)}}{{\partial b^{[k]}}}

В нескольких итерациях цикла непрерывно выполняется прямое распространение для вычисления значения функции потерь и обратное распространение для обновления параметров, и, наконец, потери находятся в определенном диапазоне.

2. Python реализует нейронную сеть BP

#coding:utf-8
#BP算法的python实现
import numpy as np

def sigmoid(x):
    return 1/(1+np.exp(-x))

def derivative(x):
    return (1-x)*x

class nn(object):
    def __init__(self,layer):
        np.random.seed(2)
        self.w=[]
        for i in range(1,len(layer)):
            # np.random.random((1000,20))代表生成1000行 20列的浮点数,浮点数都是从0-1中随机。
            self.w.append(2*np.random.random((layer[i-1],layer[i]))-1)

    def train(self,x,y,lr,echo):
        a=[x]
        for ech in range(echo):
            for i in range(0,len(self.w)):
                a.append(sigmoid(np.dot(a[i],self.w[i])))
            if(ech%100==0):
                print('echo',ech,'-error %f:',np.mean((a[-1]-y)**2))
            l_error=-(y-a[-1])
            for k in range(len(self.w)-1,-1,-1):
                l_delta = l_error*derivative(np.array(a[k+1]))
                w_update=np.dot(a[k].T,l_delta)
                l_error=np.dot(l_delta,self.w[k].T)
                self.w[k]-=lr*w_update
        return self.w

    def predict(self,w,test):
        l1 = sigmoid(np.dot(test, self.w[0]))
        l2 = sigmoid(np.dot(l1, self.w[1]))
        if l2 >= 0.5:
            print(l2,"1")
        else:
            print(l2,"0")

layer=[3,4,1]
x = np.array([[0, 0, 1],[0, 1, 1],[1, 0, 1],[1, 1, 1],[0, 0, 1]])
y = np.array([[0],[1],[1],[0],[0]])
nn=nn(layer)
w=nn.train(x,y,0.1,2000)
nn.predict(w,[1,1,0])

3. Tensorflow реализует нейронную сеть BP

待更新