Заметки об исследовании нейронной сети — обратное распространение

алгоритм

Сегодня седьмой день моего ноябрьского испытания обновлений.

Backpropagation backpropagation — быстрый алгоритм вычисления градиента функции стоимости

Используйте матрицы для быстрого вычисления выходных данных

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

image.png

такое же определениеbjlb^l_jво-первыхllпервоеjjСмещение нейронов:

image.png

Исходя из вышеприведенного определения, мы можем получитьllпервоеjjзначение активации нейронаajla^l_j(это значение иl1l-1значение активации слояakl1a^{l-1}_kСвязанный):

ajl=о(kwjklakl1+bjl)a^l_j=\sigma(\sum_kw^l_{jk}a^{l-1}_k+b^l_j)

вkwjklakl1\sum_kw^l_{jk}a^{l-1}_kсерединаkkвыражатьl1l-1количество всех нейронов в слое для каждого слояllопределить весовую матрицуwlw^l,wlw^lЭлементы вl1l-1слой доllвеса соединений слоев, поэтомуwjklw^l_{jk}можно понимать какl1l-1средний слойkkнейроны кllслойjjВеса соединений каждого нейрона.

Приведенную выше формулу можно упростить до:

al=о(wlal1+bl)a^l=\sigma(w^la^{l-1}+b^l)

в вычисленияхala^lнужно вычислить промежуточныйzl=wlal1+blz^l=w^la^{l-1}+b^l,будетzlz^lназываетсяllслой нейроноввзвешенный ввод, поэтому приведенную выше формулу можно упростить доal=о(zl)a^l=\sigma(z^l).

Два предположения о функции стоимости

Целью алгоритма обратного распространения является вычисление функции стоимостиCCоколо двух параметровwwиbbчастная производная отCw,Cb\frac{\partial C}{\partial w},\frac{\partial C}{\partial b}. будетCCОпределяется как квадратичная функция стоимости:

C=12nxy(x)aL(x)2C=\frac{1}{2n}\sum_x||y(x)-a^L(x)||^2

nnпредставляет собой общее количество обучающих выборок,x\sum_xУказывает, что все образцы были пройдены,y=y(x)y=y(x)входxxКогда соответствующий ожидаемый целевой результат,LLпредставляет количество сетевых слоев,aL=aL(x)a^L=a^L(x)это когда входxxВектор значения активации, выдаваемый сетью.

Чтобы применить алгоритм обратного распространения, функция стоимости должна бытьCCСделайте два предположения:

  • Функция стоимости может быть записана в видеxxфункция стоимости наCxC_xсреднее значениеC=1nxCxC=\frac{1}{n}\sum_xC_x, где стоимость каждой независимой выборкиCx=12yaL2C_x=\frac{1}{2}||y-a^L||^2.
  • Функция стоимости может быть записана как выходная функция нейронной сети:cost C=C(aL)cost\ C = C(a^L), при этом предположенииCxC_xДалее можно записать так:
C=12yaL2=12j(yjajL)2C=\frac{1}{2}||y-a^L||^2=\frac{1}{2}\sum_j(y_j-a^L_j)^2

Общие сведения о продукте Адамара/продукте Шура:sts\odot t

sts\odot tпредставляет поэлементный продукт,(st)j=sjtj(s\odot t)_j=s_jt_j,Следующее:image.png

Дифференциация, градиент и градиентный спуск

четыре основные формулы

Ядром алгоритма обратного распространения является вычисление частных производныхCwjkl,Cbjl\frac{\partial C}{\partial w^l_{jk}},\frac{\partial C}{\partial b^l_j}, с целью введения сначала промежуточной величиныδjl\delta^l_j, представляющий первыйllслойjjОшибка на нейронах:

δjl=Czjl\delta^l_j=\frac{\partial C}{\partial z^l_j}

Эта формула основана на эвристическом знании того, чтоCzjl\frac{\partial C}{\partial z^l_j}является мерой нейронной ошибки.

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

Формула 1

ошибка выходного слояδL\delta^LФормула:

δjL=Cajlо'(zjL)(1)\delta^L_j=\frac{\partial C}{\partial a^l_j}\sigma'(z^L_j) \tag{1}

формулаCajl\frac{\partial C}{\partial a^l_j}выразить ценуCCС первымllслойjjзначение активации нейронного выходаскорость изменения,о'(zjL)\sigma'(z^L_j)представляет функцию активациио\sigmaсуществуетzjLz^L_jскорость изменения при . Для квадратичной функции стоимостиC=12j(yjaj)2C=\frac{1}{2}\sum_j(y_j-a_j)^2,Cajl=(ajyj)\frac{\partial C}{\partial a^l_j}=(a_j-y_j).

Для удобства расчета формулу (1) перепишем в матричной форме:

δL=aCо'(zL)\delta^L=\nabla_aC\odot\sigma'(z^L)

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

δL=(aLy)о'(zL)\delta^L=(a^L-y)\odot\sigma'(z^L)

Формула 2

Используйте ошибку следующего слояδl+1\delta^{l+1}для представления ошибки текущего слояδl\delta^l:

δl=((wl+1)Tδl+1)о'(zl)(2)\delta^l=((w^{l+1})^T\delta^{l+1})\odot\sigma'(z^l) \tag{2}

Формула (2) дает метод получения ошибки текущего слоя из ошибки следующего слоя, который является методом обратного распространения.обеспечить регрессСмысл , то есть его можно рассматривать как перемещение ошибки в обратном направлении по сети, а ошибку любого слоя можно вычислить, комбинируя формулу (1) и формулу (2).

Формула 3

Функция стоимости и скорость изменения, связанные с любым смещением в сети:

Cbjl=δjl(3)\frac{\partial C}{\partial b^l_j}=\delta^l_j \tag{3}

Уравнение (3) доказывает ошибкуδjl\delta^l_jи значения частных производныхCbjl\frac{\partial C}{\partial b^l_j}точно так же.

Формула 4

Функция стоимости и скорость изменения, связанные с любым весом:

Cwjkl=akl1δjl(4)\frac{\partial C}{\partial w^l_{jk}}=a^{l-1}_k\delta^l_j \tag{4}

Уравнение (4) дает частную производнуюCwjkl\frac{\partial C}{\partial w^l_{jk}}, который можно упростить до:

Cw=ainδout\frac{\partial C}{\partial w}=a_{in}\delta_{out}

aina_{in}представляет весwwЗначение активации ввода по ссылке ,δout\delta_{out}представляет весwwОшибка вывода по ссылке показана на следующем рисунке:image.png

Характерный порядок сигмовидной функциио\sigmaИзменение будет очень небольшим вблизи 0 или 1, что также замедлит обучение веса, для такой ситуации, уже называемой выходным нейроном.насыщенность, а затем обучение веса будет прекращено (или обучение будет очень медленным).Из приведенной выше формулы видно, что скорость обучения ио'\sigma'Связанный.

Доказательство четырех формул

жизненный опыт

Формула многомерного цепного правила исчисления:

dwdt=i=1nwxidxidt\frac{dw}{dt}=\sum^n_{i=1}\frac{\partial w}{\partial x_i}\frac{dx_i}{dt}

Уравнение 1 Доказательство

вспомнить ошибку выводаδ\deltaОпределение:

δjL=CzjL\delta^L_j=\frac{\partial C}{\partial z^L_j}

Основываясь на вышеуказанных базовых знаниях, уравнение 1 можно переписать как:

δjL=kCakLakLzjL\delta^L_j =\sum_k \frac{\partial C}{\partial a^L_k}\frac{\partial a^L_k}{\partial z^L_j}

kkпредставляет все нейроны в выходном слое, первыйkkнейронныйakLa^L_kзависеть только отk=jk=jввод веса, когдаzjLz^L_j, то естьkjk \neq jВремяakLzjL\frac{\partial a^L_k}{\partial z^L_j}Не существует, основываясь на предыдущей теории, приведенную выше формулу можно преобразовать в:

δjL=CajLajLzjL\delta^L_j = \frac{\partial C}{\partial a^L_j}\frac{\partial a^L_j}{\partial z^L_j}

на основеajL=о(zjL)a^L_j=\sigma(z^L_j)Правая часть приведенной выше формулы может быть записана како'(zjL)\sigma'(z^L_j), поэтому уравнение 1 может быть получено:

δjL=Cajlо'(zjL)(1)\delta^L_j=\frac{\partial C}{\partial a^l_j}\sigma'(z^L_j) \tag{1}

Уравнение 2 Доказательство

Продолжайте расширять ошибкуδ\delta:

δjl=Czjl\delta^l_j=\frac{\partial C}{\partial z^l_j}

По-прежнему используя цепное правило, основная идея уравнения 2 состоит в том, чтобы использовать следующий уровень ошибки для представления текущей ошибки, поэтому мы должны найти способ ввестиδkl+1\delta^{l+1}_kδkl+1=Czjl+1\delta^{l+1}_k=\frac{\partial C}{\partial z^{l+1}_j}, по-видимому, чтобы найти способ ввестиzjl+1\partial z^{l+1}_jв формулу ошибки:

δjl=Czjl=kCzkl+1zkl+1zjl=kzkl+1zjlδkl+1\delta^l_j=\frac{\partial C}{\partial z^l_j} =\sum_k \frac{\partial C}{\partial z^{l+1}_k}\frac{\partial z^{l+1}_k}{\partial z^{l}_j}=\sum_k \frac{\partial z^{l+1}_k}{\partial z^{l}_j} \delta^{l+1}_k

Зависит отzzможно определить как:

zkl+1=jwkjl+1ajl+bkl+1=jwkjl+1о(zjl)+bkl+1z^{l+1}_k=\sum_jw^{l+1}_{kj}a^l_j+b^{l+1}_k=\sum_j w^{l+1}_{kj}\sigma(z^l_j)+b^{l+1}_k

рассчитатьzkl+1zjl \frac{\partial z^{l+1}_k}{\partial z^{l}_j}получить:

zkl+1zjl=wkjl+1о'(zjl)\frac{\partial z^{l+1}_k}{\partial z^{l}_j}=w^{l+1}_{kj}\sigma'(z^l_j)

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

когдаj=1j=1Время:

zkl+1z1l=wk1l+1о'(z1l)\frac{\partial z^{l+1}_k}{\partial z^{l}_1}=w^{l+1}_{k1}\sigma'(z^l_1)

когдаj=2j=2Время:

zkl+1z2l=wk2l+1о'(z2l)\frac{\partial z^{l+1}_k}{\partial z^{l}_2}=w^{l+1}_{k2}\sigma'(z^l_2)

когдаj=mj=mВремя:

zkl+1zml=wkml+1о'(zml)\frac{\partial z^{l+1}_k}{\partial z^{l}_m}=w^{l+1}_{km}\sigma'(z^l_m)

Доказательство завершено

Комбинируя приведенные выше формулы, можно получить формулу 2:

δjl=kwkjl+1δkl+1о'(zjl)=((wl+1)Tδl+1)о'(zl)\delta^l_j=\sum_k w^{l+1}_{kj}\delta^{l+1}_k\sigma'(z^l_j)= ((w^{l+1})^T\delta^{l+1})\odot\sigma'(z^l)

Доказательство уравнения 3

Cbjl=Czjlzjlbjl=δjl×1\frac{\partial C}{\partial b^l_j}=\frac{\partial C}{\partial z^l_j}\frac{\partial z^l_j}{\partial b^l_j}=\delta^l_j \times 1

Уравнение 4 Доказательство

Cwjkl=Czjlzjlwjkl=δjl(kwjklakl1+bjl)wjkl=akl1δjl\frac{\partial C}{\partial w^l_{jk}}=\frac{\partial C}{\partial z^l_{j}}\frac{\partial z^l_{j}}{\partial w^l_{jk}}=\delta^l_j\frac{\partial (\sum_k w^l_{jk}a^{l-1}_k+b^l_j)}{\partial w^l_{jk}}=a^{l-1}_k\delta^l_j

Процесс алгоритма обратного распространения

  • input x: установите значение активации для входного слояa1a^1
  • Прямое распространение: для запуска со второго слояl=2,3,4...,Ll=2,3,4...,LВычислить медиануzl=wlal1+blz^l=w^la^{l-1}+b^lиal=о(zl)a^l=\sigma(z^l)
  • ошибка выходного слояδL\delta^L: вычислить ошибку последнего слоя (выходного слоя).δL=aCо'(zL)\delta^L=\nabla_aC\odot\sigma'(z^L)
  • Обратное распространение ошибок: основано наδL\delta^LОбратить ошибку предыдущего слоя (l=L1,L2,...,2l=L-1,L-2,...,2), рассчитатьδl=((wl+1)Tδl+1)о'(zl)\delta^l=((w^{l+1})^T\delta^{l+1})\odot\sigma'(z^l)
  • Выход: вычислить градиент функции стоимости, т.е.Cbjl=δjl\frac{\partial C}{\partial b^l_j}=\delta^l_j,Cwjkl=akl1δjl\frac{\partial C}{\partial w^l_{jk}}=a^{l-1}_k\delta^l_j.

На основе алгоритма обратного распространения применяется метод градиентного спуска для обновления процесса параметров:

image.png

Реализация алгоритма

# 反向传播算法
    # 返回一个元祖,nabla_b, nabla_w表示损失函数C_x的梯度
    def backprop(self,x,y):
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        # feedforward 前向传播
        #设置输入层激活值activation=a^1
        #activations 用来存储每层的激活值
        activation = x
        activations = [x]
        # zs用来存储每一层的中间值z
        zs = [] #
        for b, w in list(zip(self.biases, self.weights)):
            # 中间值z的计算
            z = np.dot(w, activation) + b
            zs.append(z)
            # 基于z计算激活值
            activation = sigmoid(z)
            activations.append(activation)
        # backward pass 反向传播
        # cost_derivative 计算网络输出值和期望输出的差值 即nabla C
        # sigmoid_prime返回sigmoid函数的导数
        # 计算误差delta
        delta = self.cost_derivative(activations[-1], y) * sigmoid_prime(zs[-1])
        # 计算参数b和w的梯度
        nabla_b[-1] = delta
        nabla_w[-1] = np.dot(delta, activations[-2].transpose())
        # 从后往前(反向)逆推前面层的误差delta
        for l in range(2, self.num_layers):
            # 反向因此此处是-l
            z = zs[-l]
            sp = sigmoid_prime(z)
            delta = np.dot(self.weights[-l + 1].transpose(), delta) * sp
            # 存储对应层的nabla b和 nabla w
            nabla_b[-l] = delta
            nabla_w[-l] = np.dot(delta, activations[-l - 1].transpose())
        return nabla_b, nabla_w