Обратное распространение ошибки — различия между версиями
Xroms (обсуждение | вклад) |
м (rollbackEdits.php mass rollback) |
||
(не показано 28 промежуточных версий 2 участников) | |||
Строка 1: | Строка 1: | ||
− | '''Метод обратного распространения ошибок''' (англ. ''backpropagation'') {{---}} метод вычисления градиента, который используется при обновлении весов в нейронной сети. | + | '''Метод обратного распространения ошибок''' (англ. ''backpropagation'') {{---}} метод вычисления градиента, который используется при обновлении весов в [[Нейронные_сети,_перцептрон|нейронной сети]]. |
==Обучение как задача оптимизации== | ==Обучение как задача оптимизации== | ||
− | + | Рассмотрим простую нейронную сеть без скрытых слоев, с двумя входными вершинами и одной выходной, в которых каждый нейрон использует линейную [[Практики реализации нейронных сетей#Функции активации|функцию активации]], (обычно, многослойные нейронные сети используют нелинейные функции активации, линейные функции используются для упрощения понимания) которая является взвешенной суммой входных данных. [[File:A simple neural network with two input units and one output unit.png|thumb|250px|Простая нейронная сеть с двумя входными вершинами и одной выходной | |
]] | ]] | ||
− | Изначально | + | Изначально веса задаются случайно. Затем, нейрон обучается с помощью тренировочного множества, которое в этом случае состоит из множества троек <math>(x_1, x_2, t)</math> где <math>x_1</math> и <math>x_2</math> {{---}} это входные данные сети и <math>t</math> {{---}} правильный ответ. Начальная сеть, приняв на вход <math>x_1</math> и <math>x_2</math>, вычислит ответ <math>y</math>, который вероятно отличается от <math>t</math>. Общепринятый метод вычисления несоответствия между ожидаемым <math>t</math> и получившимся <math>y</math> ответом {{---}} квадратичная функция потерь: |
:<math>E=(t-y)^2, </math> где <math>E</math> ошибка. | :<math>E=(t-y)^2, </math> где <math>E</math> ошибка. | ||
− | В качестве примера, | + | В качестве примера, обучим сеть на объекте <math>(1, 1, 0)</math>, таким образом, значения <math>x_1</math> и <math>x_2</math> равны 1, а <math>t</math> равно 0. Построим график зависимости ошибки <math>E</math> от действительного ответа <math>y</math>, его результатом будет парабола. Минимум параболы соответствует ответу <math>y</math>, минимизирующему <math>E</math>. Если тренировочный объект один, минимум касается горизонтальной оси, следовательно ошибка будет нулевая и сеть может выдать ответ <math>y</math> равный ожидаемому ответу <math>t</math>. Следовательно, задача преобразования входных значений в выходные может быть сведена к задаче оптимизации, заключающейся в поиске функции, которая даст минимальную ошибку. [[File:Error surface of a linear neuron for a single training case.png|right|thumb|250px|График ошибки для нейрона с линейной функцией активации и одним тренировочным объектом]] |
− | В таком случае, выходное значение нейрона | + | В таком случае, выходное значение нейрона {{---}} взвешенная сумма всех его входных значений: |
:<math>y=x_1w_1 + x_2w_2,</math> | :<math>y=x_1w_1 + x_2w_2,</math> | ||
− | где <math>w_1</math> и <math>w_2</math> {{---}} веса на ребрах, соединяющих входные вершины с выходной. Следовательно, ошибка зависит от весов, входящих в нейрон. И именно это нужно менять в процессе обучения. Распространенный алгоритм для поиска набора весов, минимизирующего ошибку | + | где <math>w_1</math> и <math>w_2</math> {{---}} веса на ребрах, соединяющих входные вершины с выходной. Следовательно, ошибка зависит от весов ребер, входящих в нейрон. И именно это нужно менять в процессе обучения. Распространенный алгоритм для поиска набора весов, минимизирующего ошибку {{---}} градиентный спуск. Метод обратного распространения ошибки используется для вычисления самого "крутого" направления для спуска. |
==Дифференцирование для однослойной сети== | ==Дифференцирование для однослойной сети== | ||
− | Метод градиентного спуска включает в себя вычисление дифференциала квадратичной функции ошибки относительно весов сети. Обычно это делается с помощью метода обратного распространения ошибки. Предположим, что выходной нейрон один, | + | Метод градиентного спуска включает в себя вычисление дифференциала квадратичной функции ошибки относительно весов сети. Обычно это делается с помощью метода обратного распространения ошибки. Предположим, что выходной нейрон один, (их может быть несколько, тогда ошибка {{---}} это квадратичная норма вектора разницы) тогда квадратичная функция ошибки: |
: <math>E = \tfrac 1 2 (t - y)^2,</math> где <math>E</math> {{---}} квадратичная ошибка, <math>t</math> {{---}} требуемый ответ для обучающего образца, <math>y</math> {{---}} действительный ответ сети. | : <math>E = \tfrac 1 2 (t - y)^2,</math> где <math>E</math> {{---}} квадратичная ошибка, <math>t</math> {{---}} требуемый ответ для обучающего образца, <math>y</math> {{---}} действительный ответ сети. | ||
− | Множитель <math>\textstyle\frac{1}{2}</math> добавлен чтобы предотвратить возникновение экспоненты во время дифференцирования. | + | Множитель <math>\textstyle\frac{1}{2}</math> добавлен чтобы предотвратить возникновение экспоненты во время дифференцирования. На результат это не повлияет, потому что позже выражение будет умножено на произвольную величину скорости обучения (англ. ''learning rate''). |
Для каждого нейрона <math>j</math>, его выходное значение <math>o_j</math> определено как | Для каждого нейрона <math>j</math>, его выходное значение <math>o_j</math> определено как | ||
:<math>o_j = \varphi(\text{net}_j) = \varphi\left(\sum_{k=1}^n w_{kj}o_k\right).</math> | :<math>o_j = \varphi(\text{net}_j) = \varphi\left(\sum_{k=1}^n w_{kj}o_k\right).</math> | ||
− | Входные значения <math>\text{net}_j</math> нейрона это взвешенная сумма выходных значений <math>o_k</math> предыдущих нейронов. Если нейрон в первом | + | Входные значения <math>\text{net}_j</math> нейрона {{---}} это взвешенная сумма выходных значений <math>o_k</math> предыдущих нейронов. Если нейрон в первом слое после входного, то <math>o_k</math> входного слоя {{---}} это просто входные значения <math>x_k</math> сети. Количество входных значений нейрона <math>n</math>. Переменная <math>w_{kj}</math> обозначает вес на ребре между нейроном <math>k</math> предыдущего слоя и нейроном <math>j</math> текущего слоя. |
Функция активации <math>\varphi</math> нелинейна и дифференцируема. Одна из распространенных функций активации {{---}} сигмоида: | Функция активации <math>\varphi</math> нелинейна и дифференцируема. Одна из распространенных функций активации {{---}} сигмоида: | ||
Строка 46: | Строка 46: | ||
: <math>\frac{\partial \text{net}_j}{\partial w_{ij}} = \frac{\partial}{\partial w_{ij}} \left(\sum_{k=1}^n w_{kj} o_k\right) = \frac{\partial}{\partial w_{ij}} w_{ij} o_i= o_i.</math> | : <math>\frac{\partial \text{net}_j}{\partial w_{ij}} = \frac{\partial}{\partial w_{ij}} \left(\sum_{k=1}^n w_{kj} o_k\right) = \frac{\partial}{\partial w_{ij}} w_{ij} o_i= o_i.</math> | ||
− | Если нейрон в первом слое после входного, то <math>o_i</math> это просто <math>x_i</math>. | + | Если нейрон в первом слое после входного, то <math>o_i</math> {{---}} это просто <math>x_i</math>. |
− | Производная выходного значения нейрона <math>j</math> по его входному значению это просто частная производная функции активации (предполагается что в качестве функции активации используется сигмоида): | + | Производная выходного значения нейрона <math>j</math> по его входному значению {{---}} это просто частная производная функции активации (предполагается что в качестве функции активации используется сигмоида): |
: <math>\frac{\partial o_j}{\partial\text{net}_j} = \frac {\partial}{\partial \text{net}_j} \varphi(\text{net}_j) = \varphi(\text{net}_j)(1-\varphi(\text{net}_j))</math> | : <math>\frac{\partial o_j}{\partial\text{net}_j} = \frac {\partial}{\partial \text{net}_j} \varphi(\text{net}_j) = \varphi(\text{net}_j)(1-\varphi(\text{net}_j))</math> | ||
Строка 68: | Строка 68: | ||
: <math>\frac{\partial E}{\partial o_j} = \sum_{\ell \in L} \left(\frac{\partial E}{\partial \text{net}_\ell}\frac{\partial \text{net}_\ell}{\partial o_j}\right) = \sum_{\ell \in L} \left(\frac{\partial E}{\partial o_\ell}\frac{\partial o_\ell}{\partial \text{net}_\ell}w_{j\ell}\right)</math> | : <math>\frac{\partial E}{\partial o_j} = \sum_{\ell \in L} \left(\frac{\partial E}{\partial \text{net}_\ell}\frac{\partial \text{net}_\ell}{\partial o_j}\right) = \sum_{\ell \in L} \left(\frac{\partial E}{\partial o_\ell}\frac{\partial o_\ell}{\partial \text{net}_\ell}w_{j\ell}\right)</math> | ||
− | Следовательно, производная по <math>o_j</math> может быть вычислена если | + | Следовательно, производная по <math>o_j</math> может быть вычислена если все производные по выходным значениям <math>o_\ell</math> следующего слоя известны. |
Если собрать все месте: | Если собрать все месте: | ||
Строка 81: | Строка 81: | ||
\end{cases}</math> | \end{cases}</math> | ||
− | Чтобы обновить вес <math>w_{ij}</math> используя градиентный спуск, нужно выбрать скорость обучения, <math>\eta >0</math>. Изменение в весах должно отражать влияние <math>E</math> на увеличение или уменьшение в <math>w_{ij}</math>. Если <math>\frac{\partial E}{\partial w_{ij}} > 0</math>, увеличение <math>w_{ij}</math> увеличивает <math>E</math>; наоборот, если <math>\frac{\partial E}{\partial w_{ij}} < 0</math>, увеличение <math>w_{ij}</math> уменьшает <math>E</math>. Новый <math>\Delta w_{ij}</math> добавлен к старым весам, и произведение скорости обучения на градиент, умноженный на <math>-1</math> гарантирует что <math>w_{ij}</math> изменения будут всегда уменьшать <math>E</math>. Другими словами, в следующем уравнении, <math>- \eta \frac{\partial E}{\partial w_{ij}}</math> всегда изменяет <math>w_{ij}</math> в такую сторону, что <math>E</math> уменьшается: | + | Чтобы обновить вес <math>w_{ij}</math> используя градиентный спуск, нужно выбрать скорость обучения, <math>\eta >0</math>. Изменение в весах должно отражать влияние <math>E</math> на увеличение или уменьшение в <math>w_{ij}</math>. Если <math>\frac{\partial E}{\partial w_{ij}} > 0</math>, увеличение <math>w_{ij}</math> увеличивает <math>E</math>; наоборот, если <math>\frac{\partial E}{\partial w_{ij}} < 0</math>, увеличение <math>w_{ij}</math> уменьшает <math>E</math>. Новый <math>\Delta w_{ij}</math> добавлен к старым весам, и произведение скорости обучения на градиент, умноженный на <math>-1</math>, гарантирует, что <math>w_{ij}</math> изменения будут всегда уменьшать <math>E</math>. Другими словами, в следующем уравнении, <math>- \eta \frac{\partial E}{\partial w_{ij}}</math> всегда изменяет <math>w_{ij}</math> в такую сторону, что <math>E</math> уменьшается: |
: <math> \Delta w_{ij} = - \eta \frac{\partial E}{\partial w_{ij}} = - \eta \delta_j o_i</math> | : <math> \Delta w_{ij} = - \eta \frac{\partial E}{\partial w_{ij}} = - \eta \delta_j o_i</math> | ||
+ | |||
+ | == Алгоритм == | ||
+ | |||
+ | * <math>\eta</math> - скорость обучения | ||
+ | * <math>\alpha</math> - коэффициент инерциальности для сглаживания резких скачков при перемещении по поверхности целевой функции | ||
+ | * <math>\{x_i^d, t^d\}_{i=1,d=1}^{n,m}</math> {{---}} обучающее множество | ||
+ | * <math>\textrm{steps}</math> {{---}} количество повторений | ||
+ | * <math>network(x)</math> {{---}} функция, подающая x на вход сети и возвращающая выходные значения всех ее узлов | ||
+ | * <math>layers</math> {{---}} количество слоев в сети | ||
+ | * <math>layer_i</math> {{---}} множество нейронов в слое i | ||
+ | * <math>output</math> {{---}} множество нейронов в выходном слое | ||
+ | |||
+ | |||
+ | '''fun''' BackPropagation<math>(\eta, \alpha, \{x_i^d, t^d\}_{i=1,d=1}^{n,m}, \textrm{steps})</math>: | ||
+ | '''init''' <math>\{w_{ij}\}_{i,j} </math> | ||
+ | '''repeat''' <math>\textrm{steps}</math>: | ||
+ | '''for''' <math>d</math> = <math>1</math> to <math>m</math>: | ||
+ | <math>o</math> = <math>network(\{x_i^d\}) </math> | ||
+ | '''for''' <math>k \in output</math>: | ||
+ | <math>\delta _k</math> = <math>\sigma'(o_k)(t_k - o_k)</math> | ||
+ | '''for''' <math>i</math> = <math>layers - 1</math> to <math>1</math>: | ||
+ | '''for''' <math>j \in layer_i</math>: | ||
+ | <math>\delta _j</math> = <math>\sigma'(o_j)\sum_{k \in layer_{i + 1}} \delta _k w_{j,k}</math> | ||
+ | '''for''' <math>\forall w_{i,j}</math>: | ||
+ | <math>\Delta w_{i,j}^{n}</math> = <math>\alpha \Delta w_{i,j}^{n-1} + ( 1 - \alpha ) \eta \delta _j o_{i}</math> | ||
+ | <math>w_{i,j}^{n}</math> = <math>w_{i,j}^{n-1} + \Delta w_{i,j}^{n}</math> | ||
+ | '''return''' <math>w_{ij}</math> | ||
== Недостатки алгоритма == | == Недостатки алгоритма == | ||
Строка 90: | Строка 117: | ||
=== Паралич сети === | === Паралич сети === | ||
− | В процессе обучения сети значения весов могут в результате коррекции стать очень большими величинами. Это может привести к тому, что все или большинство нейронов будут функционировать при очень больших значениях | + | В процессе обучения сети значения весов могут в результате коррекции стать очень большими величинами. Это может привести к тому, что все или большинство нейронов будут функционировать при очень больших выходных значениях, а производная активирующей функции будет очень мала. Так как посылаемая обратно в процессе обучения ошибка пропорциональна этой производной, то процесс обучения может практически замереть. |
=== Локальные минимумы === | === Локальные минимумы === | ||
Градиентный спуск с обратным распространением ошибок гарантирует нахождение только локального минимума функции; также, возникают проблемы с пересечением плато на поверхности функции ошибки. | Градиентный спуск с обратным распространением ошибок гарантирует нахождение только локального минимума функции; также, возникают проблемы с пересечением плато на поверхности функции ошибки. | ||
− | == | + | ==Примечания== |
− | + | *[https://habr.com/ru/post/198268/ Алгоритм обучения многослойной нейронной сети методом обратного распространения ошибки] | |
− | + | *[https://frnsys.com/ai_notes/machine_learning/neural_nets.html Neural Nets] | |
− | + | *[http://cs231n.stanford.edu/slides/2018/cs231n_2018_lecture04.pdf Understanding backpropagation] | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
==См. также== | ==См. также== | ||
− | *[[:Нейронные_сети,_перцептрон| | + | *[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]] |
*[[:Стохастический градиентный спуск|Стохастический градиентный спуск]] | *[[:Стохастический градиентный спуск|Стохастический градиентный спуск]] | ||
+ | *[[:Настройка_глубокой_сети|Настройка глубокой сети]] | ||
+ | *[[:Практики_реализации_нейронных_сетей|Практики реализации нейронных сетей]] | ||
== Источники информации == | == Источники информации == |
Текущая версия на 19:32, 4 сентября 2022
Метод обратного распространения ошибок (англ. backpropagation) — метод вычисления градиента, который используется при обновлении весов в нейронной сети.
Содержание
Обучение как задача оптимизации
Рассмотрим простую нейронную сеть без скрытых слоев, с двумя входными вершинами и одной выходной, в которых каждый нейрон использует линейную функцию активации, (обычно, многослойные нейронные сети используют нелинейные функции активации, линейные функции используются для упрощения понимания) которая является взвешенной суммой входных данных.Изначально веса задаются случайно. Затем, нейрон обучается с помощью тренировочного множества, которое в этом случае состоит из множества троек
где и — это входные данные сети и — правильный ответ. Начальная сеть, приняв на вход и , вычислит ответ , который вероятно отличается от . Общепринятый метод вычисления несоответствия между ожидаемым и получившимся ответом — квадратичная функция потерь:- где ошибка.
В таком случае, выходное значение нейрона — взвешенная сумма всех его входных значений:
где
и — веса на ребрах, соединяющих входные вершины с выходной. Следовательно, ошибка зависит от весов ребер, входящих в нейрон. И именно это нужно менять в процессе обучения. Распространенный алгоритм для поиска набора весов, минимизирующего ошибку — градиентный спуск. Метод обратного распространения ошибки используется для вычисления самого "крутого" направления для спуска.Дифференцирование для однослойной сети
Метод градиентного спуска включает в себя вычисление дифференциала квадратичной функции ошибки относительно весов сети. Обычно это делается с помощью метода обратного распространения ошибки. Предположим, что выходной нейрон один, (их может быть несколько, тогда ошибка — это квадратичная норма вектора разницы) тогда квадратичная функция ошибки:
- где — квадратичная ошибка, — требуемый ответ для обучающего образца, — действительный ответ сети.
Множитель
добавлен чтобы предотвратить возникновение экспоненты во время дифференцирования. На результат это не повлияет, потому что позже выражение будет умножено на произвольную величину скорости обучения (англ. learning rate).Для каждого нейрона
, его выходное значение определено какВходные значения
нейрона — это взвешенная сумма выходных значений предыдущих нейронов. Если нейрон в первом слое после входного, то входного слоя — это просто входные значения сети. Количество входных значений нейрона . Переменная обозначает вес на ребре между нейроном предыдущего слоя и нейроном текущего слоя.Функция активации
нелинейна и дифференцируема. Одна из распространенных функций активации — сигмоида:у нее удобная производная:
Находим производную ошибки
Вычисление частной производной ошибки по весам
выполняется с помощью цепного правила:Только одно слагаемое в
зависит от , так чтоЕсли нейрон в первом слое после входного, то
— это просто .Производная выходного значения нейрона
по его входному значению — это просто частная производная функции активации (предполагается что в качестве функции активации используется сигмоида):По этой причине данный метод требует дифференцируемой функции активации. (Тем не менее, функция ReLU стала достаточно популярной в последнее время, хоть и не дифференцируема в 0)
Первый множитель легко вычислим, если нейрон находится в выходном слое, ведь в таком случае
иТем не менее, если
произвольный внутренний слой сети, нахождение производной по менее очевидно.Если рассмотреть
как функцию, берущую на вход все нейроны получающие на вход значение нейрона ,и взять полную производную по
, то получим рекурсивное выражение для производной:Следовательно, производная по
может быть вычислена если все производные по выходным значениям следующего слоя известны.Если собрать все месте:
и
Чтобы обновить вес
используя градиентный спуск, нужно выбрать скорость обучения, . Изменение в весах должно отражать влияние на увеличение или уменьшение в . Если , увеличение увеличивает ; наоборот, если , увеличение уменьшает . Новый добавлен к старым весам, и произведение скорости обучения на градиент, умноженный на , гарантирует, что изменения будут всегда уменьшать . Другими словами, в следующем уравнении, всегда изменяет в такую сторону, что уменьшается:Алгоритм
- - скорость обучения
- - коэффициент инерциальности для сглаживания резких скачков при перемещении по поверхности целевой функции
- — обучающее множество
- — количество повторений
- — функция, подающая x на вход сети и возвращающая выходные значения всех ее узлов
- — количество слоев в сети
- — множество нейронов в слое i
- — множество нейронов в выходном слое
fun BackPropagation: init repeat : for = to : = for : = for = to : for : = for : = = return
Недостатки алгоритма
Несмотря на многочисленные успешные применения обратного распространения, оно не является универсальным решением. Больше всего неприятностей приносит неопределённо долгий процесс обучения. В сложных задачах для обучения сети могут потребоваться дни или даже недели, она может и вообще не обучиться. Причиной может быть одна из описанных ниже.
Паралич сети
В процессе обучения сети значения весов могут в результате коррекции стать очень большими величинами. Это может привести к тому, что все или большинство нейронов будут функционировать при очень больших выходных значениях, а производная активирующей функции будет очень мала. Так как посылаемая обратно в процессе обучения ошибка пропорциональна этой производной, то процесс обучения может практически замереть.
Локальные минимумы
Градиентный спуск с обратным распространением ошибок гарантирует нахождение только локального минимума функции; также, возникают проблемы с пересечением плато на поверхности функции ошибки.
Примечания
- Алгоритм обучения многослойной нейронной сети методом обратного распространения ошибки
- Neural Nets
- Understanding backpropagation
См. также
- Нейронные сети, перцептрон
- Стохастический градиентный спуск
- Настройка глубокой сети
- Практики реализации нейронных сетей