Обратное распространение (BackPropagation)

искусственный интеллект алгоритм Нейронные сети продукт

вы можете прочитать здесьПредыдущий

яСюэ Иньлян,благодарныйАнглийские оригинальные онлайн-книги, эта книга, как мне кажется, очень подходит для новичков в процессе изучения машинного обучения. Ввиду духа обмена знаниями я надеюсь перевести его и поделиться им со всеми, кто хочет понять машинное обучение. Уровень моего перевода ограничен. Читатели могут задавать вопросы и находить ошибки, а также приветствуются рекомендации Дэниела. Из-за объема статьи статья будет разделена на несколько частей, если вам интересно, вы можете обратить внимание на мою антологию, и статья будет постоянно обновляться.


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

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

Причина, конечно же: понимание. Суть обратного распространения заключается в вычислении частной производной ∂C/∂w функции потерь C путем изменения веса w и смещения b в сети, чтобы найти экстремальное значение изменения потерь (если это предложение не понимает , я предлагаю вам сначала пойти и посмотреть на исчисление). Это выражение говорит нам, как быстро изменяется функция потерь, когда мы меняем веса w и смещения b. Хотя иногда это может быть сложно, у него может быть естественное интуитивное объяснение для каждого элемента, и на самом деле он дает нам подробный способ изменения весов и b-значений, чтобы изменить общее поведение сети. Это очень стоит изучить.

Разминка: матричный подход к быстрому вычислению выходных данных нейронной сети


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

Определить символы:

Этот символ представляет собой вес между K-м нейроном в (l-1)-м слое и j-м нейроном в l-м слое. Например, следующая картинка:

Определить символы:

представляет значение смещения b j-го нейрона в l-м слое.

представляет выходную активацию a (активацию) j-го нейрона в l-м слое. Как показано ниже:

Из всех символов выше: активация j-го нейрона в l-м слое равна:

Скобки приведенной выше формулы представляют собой: веса всех k нейронов в (l-1) слое (предыдущий слой) до j-го нейрона в (l) слое (более поздний слой) и (l-1) сумма выходные продукты всех k нейронов в слое плюс значение смещения (порог) j-го нейрона в l-м слое. Я верю, что когда вы увидите здесь, значение этих символов станет для вас очень ясным.

Мы векторизируем уравнение (23), обозначаемое σ(v). Например, уравнение f(x)=x^2, векторизация:

Векторизованное f возведет в квадрат каждый вектор.

Таким образом, формулу (23) можно векторизовать следующим образом:

Это выражение дает нам более глобальный способ мышления: как активации в одном слое связаны с активациями в предыдущем слое: мы просто применяем матрицу весов к активациям предыдущего слоя, затем добавляем вектор смещения (b) и, наконец, применяем к σ-функция. Проще и лаконичнее (по крайней мере, с меньшим количеством примененных индексов!), чем нейрон-нейрон, который мы сейчас берем. Это выражение также полезно на практике, так как большинство библиотек матриц предоставляют быстрые способы реализации умножения матриц, сложения векторов и векторизации. На самом деле код из предыдущей главы неявно использует это выражение для расчета поведения сети.

Определяем формулу:

взвешенный вход нейронов в первом слое. Если вы напишете это в компонентном стиле:

То есть он представляет собой взвешенный вклад функции активации нейронов j-го слоя в l-й слой.

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


Цель обратного распространения достигается путем вычисления частных производных ∂C/∂w и ∂C/∂b функции потерь C по отношению к весу w или смещению b в сети. Для этого нам нужно сделать два предположения о виде функции потерь. Прежде чем углубиться в эти предположения, мы обратимся к примеру функции потерь. Мы будем использовать квадратичную функцию потерь из предыдущего раздела (см. уравнение (6)). В обозначениях предыдущего раздела квадратичная функция потерь имеет вид:

где: n — общее количество обучающих примеров; x — каждый обучающий пример; y(x) — желаемый результат; L — количество слоев в сети, a^L(x) — результат, когда вход x это сеть.

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

Причина, по которой мы делаем это предположение, заключается в том, что мы находим частные производные ∂Cx/∂w и ∂Cx/∂b для каждого примера.

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

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

Произведение Адамара, с⊙т


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

Его можно выразить в следующем виде:

Это поэлементное произведение называется произведением Адамара.

Четыре уравнения, лежащие в основе обратного распространения ошибки


Целью алгоритма обратного распространения является улучшение функции потерь нейронной сети путем изменения (весов w и смещений b). В конечном итоге он измеряется путем взятия частных производных (∂C/∂w) и (∂C/∂b). Для этого сначала определим промежуточную величину: δ(l,j), которая представляет собой ошибку j-го нейрона в слое l. Мы будем использовать обратное распространение для вычисления этой ошибки. Для начала, чтобы понять эту промежуточную величину, давайте представим себе чертенка в нейронной сети:

Этот демон стоит на j-м нейроне в слое l, и когда поступает ввод, он немного меняет взвешенный ввод (z определено выше):

Вызывает изменение выхода нейрона:

Наконец, функция потерь изменяется:

Теперь предположим, что этот хороший демон пытается помочь вам улучшить точность вашего вывода. Он пытается настроить Δz для вас, чтобы ошибка вывода была минимальной. Исходя из приведенного выше представления, мы определяем ошибку j-го нейрона в l-м слое по следующей формуле:

По соглашению удалите j в приведенной выше формуле, чтобы представить вектор ошибки (δ ^ l) l-го слоя. Обратное распространение дает нам способ вычислить его и объединить ошибку с реальными данными через: ∂C/∂w и ∂C/∂b.

Обратное распространение основано на четырех фундаментальных уравнениях. Вместе эти уравнения дают нам способ вычислить ошибку δ и градиент функции потерь. НоУведомлениеВот в чем дело: вы не должны ожидать, что поймете все эти четыре уравнения сразу. Такие ожидания могут вас разочаровать. Потому что уравнения обратного распространения настолько богаты, что для их понимания требуется значительное количество времени и терпения.

Предварительный просмотр представлен здесь, и мы дадим более подробное описание в следующих главах. Вот несколько простых доказательств, которые помогут нам понять их.

Уравнение для ошибки выходного слоя:

Первая часть правой части выражения представляет: скорость (наклон) изменения потерь C при изменении выхода j-го нейрона. Если изменения выхода нейрона уже не могут слишком сильно изменить C, то ошибка будет небольшой, чего мы и ожидаем. Второе уравнение справа говорит: измерьте скорость изменения функции активации σ при изменении взвешенного входа.

Запись BP1 в виде вектора:

Первая часть справа от знака равенства представляет собой вектор, вы можете думать о нем как о векторной матрице частной производной потерь C по отношению к выходу, легко видеть, что (BP1a) и (BP1) равны. По этой причине с этого момента мы заменим приведенное выше уравнение на BP1. Мы обратимся к примеру в уравнении квадратичной среднеквадратичной ошибки, чтобы понять, и его функция потерь:

Можно вывести:

так:

Подстановка в уравнение (BP1a) дает:

Как видите, каждая часть выражения имеет векторный формат, поэтому его можно легко вычислить с помощью Numpy.

Ошибка (l)-го слоя представлена ​​ошибкой (l + 1)-го слоя

Вы можете думать об этом так: ошибки распространяются по сети.

Изменение ошибки, связанное со смещением b:

С помощью BP1 и BP2 мы можем просто представить BP3:

Изменения ошибок, связанные с весами:

Краткий формат:

a(in) можно понимать как входную активацию веса w, а δ(out) можно понимать как ошибку нейрона при вводе веса w. Значок:

Когда значение a в уравнении мало и близко к 0, значение формулы будет небольшим.В это время мы говорим, что обучение под этим весом происходит медленно, а это означает, что оно не может быстро изменить градиент.

Давайте посмотрим на эти 4 формулы с точки зрения выходного слоя, посмотрим на формулу BP1 и вспомним график сигмовидной функции в предыдущем разделе, когда функция близка к 0 или 1, она становится очень горизонтальной. В настоящее время:

Если выходной нейрон имеет низкую активацию (≈0) или высокую активацию (≈1), корректировка веса обучается медленно. В этом случае говорят, что выходные нейроны насыщаются и веса перестают обучаться, и аналогичное утверждение имеет место для отклонения b выходных нейронов. Этот метод также похож на BP2.

Подводя итог, мы уже знаем, что если входные нейроны имеют низкую активацию или если выходные нейроны насыщены, то есть имеют высокую или низкую активацию, эффективность обучения веса будет очень низкой.

Уведомление: Вышеуказанные четыре формулы, я надеюсь, читатели смогут проверить сами, что может дать вам более глубокое понимание. Это может занять много времени, но это необходимо.

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

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

  • BP1
    Мы знаем, что выражение ошибки:

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

Приведенная выше формула представляет собой сумму k нейронов в выходном слое.Конечно, выход активации k-го нейрона в выходном слое зависит только от взвешенного входа z (j) j-го нейрона в выходном слое. Итак, кроме этого, другие предметы исчезли, а затем:

И a=σ(z), поэтому:

  • BP2

Это формула, представляющая отношение ошибок между двумя соседними слоями, которую можно получить из формулы (36):

Из цепного правила получаем:

Тогда известно, что:

Взяв от него частную производную, получим:

Подставляем в (42), чтобы получить:

Это компонентная ситуация уравнения 2.

Что касается уравнений 3 и 4, то я надеюсь, что читатель сможет доказать для себя, что это также относительно легко согласно цепному правилу.

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

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

  • ввод обучающих данных
  • Выполните следующие шаги, чтобы установить активацию a (x, 1) для каждого тренировочного данных:

    • Рассчитаем a и z для каждого слоя l=2,3,…,L:
      • Обратное распространение вычисляет ошибку для каждого слоя:
  • Градиентный спуск, обновление w и b для каждого слоя:

Кроме того, вам нужны мини-пакеты внешнего цикла для повторения всего набора обучающих данных.

### Код обратного распространения

Разберитесь с абстрактной концепцией обратного распространения, давайте разберемся с кодом в предыдущем разделе. Помните, что в классе Network есть методы update_mini_batch и backprop. Эти два метода напрямую переводятся из приведенной выше формулы. Метод update_mini_batch обновляет вес (w) и значение смещения (b), вычисляя градиент текущего обучающего набора (mini_batch ):

class Network(object):
...
    def update_mini_batch(self, mini_batch, eta):
        """Update the network's weights and biases by applying
        gradient descent using backpropagation to a single mini batch.
        The "mini_batch" is a list of tuples "(x, y)", and "eta"
        is the learning rate."""
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        for x, y in mini_batch:
            delta_nabla_b, delta_nabla_w = self.backprop(x, y)
            nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
            nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
        self.weights = [w-(eta/len(mini_batch))*nw 
                        for w, nw in zip(self.weights, nabla_w)]
        self.biases = [b-(eta/len(mini_batch))*nb 
                       for b, nb in zip(self.biases, nabla_b)]

Большую часть работы выполняет строка delta_nabla_b, delta_nabla_w = self.backprop(x, y). Эта строка вычисляет частные производные от b и w по C с помощью метода обратного распространения ошибки. Этот метод заключается в следующем:

class Network(object):
...
   def backprop(self, x, y):
        """Return a tuple "(nabla_b, nabla_w)" representing the
        gradient for the cost function C_x.  "nabla_b" and
        "nabla_w" are layer-by-layer lists of numpy arrays, similar
        to "self.biases" and "self.weights"."""
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        # feedforward
        activation = x
        activations = [x] # list to store all the activations, layer by layer
        zs = [] # list to store all the z vectors, layer by layer
        for b, w in zip(self.biases, self.weights):
            z = np.dot(w, activation)+b
            zs.append(z)
            activation = sigmoid(z)
            activations.append(activation)
        # backward pass
        delta = self.cost_derivative(activations[-1], y) * \
            sigmoid_prime(zs[-1])
        nabla_b[-1] = delta
        nabla_w[-1] = np.dot(delta, activations[-2].transpose())
        # Note that the variable l in the loop below is used a little
        # differently to the notation in Chapter 2 of the book.  Here,
        # l = 1 means the last layer of neurons, l = 2 is the
        # second-last layer, and so on.  It's a renumbering of the
        # scheme in the book, used here to take advantage of the fact
        # that Python can use negative indices in lists.
        for l in xrange(2, self.num_layers):
            z = zs[-l]
            sp = sigmoid_prime(z)
            delta = np.dot(self.weights[-l+1].transpose(), delta) * sp
            nabla_b[-l] = delta
            nabla_w[-l] = np.dot(delta, activations[-l-1].transpose())
        return (nabla_b, nabla_w)

...

    def cost_derivative(self, output_activations, y):
        """Return the vector of partial derivatives \partial C_x /
        \partial a for the output activations."""
        return (output_activations-y) 

def sigmoid(z):
    """The sigmoid function."""
    return 1.0/(1.0+np.exp(-z))

def sigmoid_prime(z):
    """Derivative of the sigmoid function."""
    return sigmoid(z)*(1-sigmoid(z))

###Что означает алгоритм обратного распространения?
Представим небольшое изменение весов в сети:

Это небольшое изменение приведет к изменению выхода активации соответствующего нейрона:

Затем это приведет к изменению всех выходных активаций следующего слоя:

В конечном итоге это повлияет на функцию потерь:

Его можно выразить формулой так:

Мы знаем, что изменение активации в одном слое вызовет изменение вывода в следующем слое, здесь мы сначала сосредоточимся на изменении одного из следующих слоев.

В сочетании с формулой (48):

Как вы можете себе представить, когда есть много слоев (каждый слой предполагает затронутый вывод):

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

Комбинат (47):

Рассчитайте скорость изменения c относительно определенного веса Формула показывает, что частная производная активации каждого слоя по отношению к активации следующего слоя является коэффициентом скорости. На рисунке показано:

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

Если моя статья будет вам полезна, я предлагаю вам подписаться на мою коллекцию или дать вознаграждение, я предлагаю вознаграждение в размере 5 иен. Конечно, вы также можете давать награды по желанию.

微信
WeChat

支付宝
Alipay

Если у вас есть какие-либо вопросы, пожалуйста, свяжитесь со мной, чтобы обсудить space-x@qq.com, Я постараюсь ответить вовремя.