Нейронные сети обратного распространения. Среда разработки и причины ее выбора

Обратное распространение ошибки - стандартный способ обучения нейронной сети, хотя существуют и другие методы (о них в одной из следующих глав). Принцип работы примерно такой:

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

2. Полученные данные сравниваются с известными выходными данными для рассматриваемого входного набора. Разница между полученными и известными (опытными) данными - вектор ошибки.


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

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

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

Следует заметить, что ошибка может быть распространена на любой желаемый уровень (т.е. в нейронной сети может быть неограниченное количество скрытых слоев, для которых мы рассчитываем вектор ошибки по одной и той же схеме). Метод обратного распространения ошибки напоминает мне волны прибоя, - входные сигналы движутся в сторону выходного слоя (т.е. берега), а ошибки - в обратном направлении (как и морская волна вынуждена в конечном счете отступить от суши).

Сеть обучается путем предъявления каждого входного набора данных и последующего распространения ошибки. Этот цикл повторяется много раз. Например, если вы распознаете цифры от 0 до 9, то сначала обрабатывается символ "0", символ "1" и так далее до "9", затем весь цикл повторяется много раз. Не следует поступать иначе, а именно, обучать сеть по отдельности сначала символу "0" (n-ое количество раз), потом "1", потом "2" и т.д., т.к. сеть вырабатывает очень "четкие" весовые коэффициенты для последнего входного набора (то есть для "9"), "забывая" предыдущие. Например, к тысячному повтору обучения символу "1" теряются весовые коэффициенты для распознавания символа "0". Повторяя весь цикл для всего словарного набора входных данных, мы предполагаем, что каждый символ оказывает равноправное влияние на значения весовых коэффициентов.

Запомните
Обозначим через переменную NUM_HID количество нейронов в скрытом слое (нумерация начинается с индекса 1). NUM_OUT - количество нейронов в выходном слое.

Обратное распространение и формулы.
А теперь, настройтесь! Я собираюсь привести ниже множество математических выкладок.

    Во-первых, инициализируем пороговые значения и весовые коэффициенты небольшими случайными величинами (не более 0.4)

    Теперь прогоним сеть в режиме прямого функционирования - процедура run_network (см. прошлую главу)

    Вычислим ошибки для выходного слоя. При этом мы используем следующую формулу для каждого i-ого значения выходного слоя (т.е. проходим по всем узлам выходного слоя):

    E i = (t i - a i).a i .(1 - a i)

    Здесь E i - ошибка для i-ого узла выходного слоя, a i - активность данного узла, t i - требуемая активность для него же (т.е. требуемое выходное значение).

    Вот код на паскале:

    procedure calculate_output_layer_errors; var i : byte; {for loop variable} begin for i: = 1 to NUM_OUT do with ol[ i] do E: = (desired_output[ i] - a) * a * (1 - a) end ;

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

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

    E i = a i . (1 - a i) . S j E j .w ij

    Смысл переменных по сравнению с прошлой формулой изменился незначительно. индекс i используется для нейронов скрытого слоя (а не выходного), E i , следовательно, значение ошибки для нейрона скрытого слоя, и a i - сигнал на выходе нейрона. Индекс j относится к нейронам выходного слоя: wij - вес (весовой коэффициент) связи между i-ым скрытым нейроном и j-ым выходным нейроном, а E j - значение ошибки для выходного нейрона j. Суммирование проводится для всех весов связей между отдельно взятым i-ым нейроном и всеми нейронами выходного слоя.

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

    procedure calculate_hidden_layer_errors; var i,j : byte; sum : real ; begin for i: = 1 to NUM_HID do {обсчитываем весь скрытый слой} with hl[ i] do begin sum: = 0; {sum error values from O/P layer} for j: = 1 to NUM_OUT do sum: = sum + ol[ j] .E * ol[ j] .w[ i] {только веса, относящиеся к нейрону i} E: = a * (1 - a) * sum {no other w value} end ; end ;
  • Полученные значения ошибок для выходного слоя мы используем для изменения весовых коэффициентов между скрытым и выходным слоями.Мы должны вычислить все значения ошибок до модификации весовых коэффициентов, так как в формуле присутствуют и старые значения весов. Если же мы вычислим сначала весовые коэффициенты, а уже затем - значения ошибок, то процесс обучения застопорится.

    Применяем уравнение:

    new w ij = old w ij + h.d j .x i

    где w ij - вес связи между нейроном i скрытого слоя и нейроном j выходного, d j - приращение ошибки для выходного нейрона j и x i - сигнал на выходе скрытого нейрона i, h - константа. Эта константа используется для того, чтобы обучение не проводилось слишком быстро, то есть весовые коэффициенты не изменялись слишком сильно за один шаг обучения (что является причиной прыжков сходимости при обучении сети).

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

    new threshold = old threshold + h.d j .(-1)

    или (в более удобном виде):

    new threshold = old threshold - h.d j

    Данная процедура обучает весовые коэффициенты и пороговые уровни:

    В этом коде я использовал j для индексирования узлов выходного слоя, чтобы привести в соответствие с уравнением (т.е. E соответствует d j ). Таким же образом hl[i].out соответствует x i , а w[i] - w ij .

  • Наконец, мы должны модифицировать веса скрытого слоя. В реальности, если имеются дополнительные слои, приведенный код также работает.

    procedure update_hidden_weights; const LEARNING_RATE = 0.025; {нет никаких причин, чтобы это значение не отличалось от использованного для выходных узлов} var i,j : byte; begin for j : = 1 to NUM_HID do {обходим все скрытые узлы} with hl[ j] do begin {обрабатываем все связи от входного слоя к этому узлу} for i : = 1 to NUM_INP do w[ i] : = w[ i] + LEARNING_RATE * E * test_pat[ i] ; {модифицируем пороговый уровень этого узла} threshold : = threshold - LEARNING_RATE * E end end ;

Все то же самое на JAVA
Ниже приведена реализация нейронной сети, обучаемой методом обратного распространения ошибки на JAVA:

Если вам нужен исходный текст, то кликните . Конечно же, изменяйте его как хотите.

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

Сеть, как она здесь представлена, имеет фиксированное количество входов (6) и фиксированное количество выходов (5). Скрытые узлы в середине изображены синими кружками.

Обучающие наборы представлены по левую сторону. Для того, чтобы изменить входные наборы, желаемые выходные наборы, кликните на столбец из шести входных квадратов или на столбец из пяти выходных квадратов. Каждый клик мышью затемняет квадрат (белый - 0, светлосерый - 0.3, темносерый - 0.7, черный - 1).

Эта комбинация, например, обозначает, что для входного набора установлены данные (1, 0, 0, 0.3, 0, 0.7), а для выходного набора - (0, 0, 0.7, 0.7, 0). Кликните на символ + или - (около словосочетания "Training patterns") для изменения количества наборов.

Для того, чтобы обучить сеть, кликните на кнопку "Train". Для тестирования сети введите значение компонента входного набора в слот наверху, а затем кликните на компонент входного набора (на одно из тех текстовых значений в рамке слева на структурной схеме сети). Запустите сеть - кнопка "Run"

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

Обновление правила цепочки

Можно рассматривать как длинный ряд вложенных уравнений. Если вы так думаете о прямом распространении, то обратное распространение — это просто приложение правила цепочки (дифференцирования сложной функции) для поиска производных потерь по любой переменной во вложенном уравнении. С учётом функции прямого распространения:

F(x)=A(B(C(x)))

A, B, и C — на различных слоях. Пользуясь правилом цепочки, мы легко вычисляем производную f(x) по x:

F′(x)=f′(A)⋅A′(B)⋅B′(C)⋅C′(x)

Что насчёт производной относительно B ? Чтобы найти производную по B , вы можете сделать вид, что B (C(x)) является константой, заменить ее переменной-заполнителем B , и продолжить поиск производной по B стандартно.

F′(B)=f′(A)⋅A′(B)

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

Применение правила цепочки

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

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

Cost=C(R(Z(XW)))

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

C′(W)=C′(R)⋅R′(Z)⋅Z′(W)=(y^−y)⋅R′(Z)⋅X

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

Какова производная от потери по Wo ?

C′(WO)=C′(y^)⋅y^′(ZO)⋅Z′O(WO)=(y^−y)⋅R′(ZO)⋅H

А что насчет Wh ? Чтобы узнать это, мы просто продолжаем возвращаться в нашу функцию, рекурсивно применяя правило цепочки, пока не доберемся до функции, которая имеет элемент Wh .

C′(Wh)=C′(y^)⋅O′(Zo)⋅Z′o(H)⋅H′(Zh)⋅Z′h(Wh)=(y^−y)⋅R′(Zo)⋅Wo⋅R′(Zh)⋅X

И просто забавы ради, что, если в нашей сети было бы 10 скрытых слоев. Что такое производная потери для первого веса w1?

C(w1)=(dC/dy^)⋅(dy^/dZ11)⋅(dZ11/dH10)⋅(dH10/dZ10)⋅(dZ10/dH9)⋅(dH9/dZ9)⋅(dZ9/dH8)⋅(dH8/dZ8)⋅(dZ8/dH7)⋅(dH7/dZ7)⋅(dZ7/dH6)⋅(dH6/dZ6)⋅(dZ6/dH5)⋅(dH5/dZ5)⋅(dZ5/dH4)⋅(dH4/dZ4)⋅(dZ4/dH3)⋅(dH3/dZ3)⋅(dZ3/dH2)⋅(dH2/dZ2)⋅(dZ2/dH1)⋅(dH1/dZ1)⋅(dZ1/dW1)

Заметили закономерность? Количество вычислений, необходимых для расчёта производных потерь, увеличивается по мере углубления нашей сети. Также обратите внимание на избыточность в наших расчетах производных . Производная потерь каждого слоя добавляет два новых элемента к элементам, которые уже были вычислены слоями над ним. Что, если бы был какой-то способ сохранить нашу работу и избежать этих повторяющихся вычислений?

Сохранение работы с мемоизацией

Мемоизация — это термин в информатике, имеющий простое значение: не пересчитывать одно и то же снова и снова . В мемоизации мы сохраняем ранее вычисленные результаты, чтобы избежать пересчета одной и той же функции. Это удобно для ускорения рекурсивных функций, одной из которых является обратное распространение. Обратите внимание на закономерность в уравнениях производных приведённых ниже.

Каждый из этих слоев пересчитывает одни и те же производные! Вместо того, чтобы выписывать длинные уравнения производных для каждого веса, можно использовать мемоизацию, чтобы сохранить нашу работу, так как мы возвращаем ошибку через сеть. Для этого мы определяем 3 уравнения (ниже), которые вместе выражают в краткой форме все вычисления, необходимые для обратного распространения. Математика та же, но уравнения дают хорошее сокращение, которое мы можем использовать, чтобы отслеживать те вычисления, которые мы уже выполнили, и сохранять нашу работу по мере продвижения назад по сети.

Для начала мы вычисляем ошибку выходного слоя и передаем результат на скрытый слой перед ним. После вычисления ошибки скрытого слоя мы передаем ее значение обратно на предыдущий скрытый слой. И так далее и тому подобное. Возвращаясь назад по сети, мы применяем 3-ю формулу на каждом слое, чтобы вычислить производную потерь по весам этого слоя. Эта производная говорит нам, в каком направлении регулировать наши веса , чтобы уменьшить общие потери.

Примечание: термин ошибка слоя относится к производной потерь по входу в слой. Он отвечает на вопрос: как изменяется выход функции потерь при изменении входа в этот слой?

Ошибка выходного слоя

Для расчета ошибки выходного слоя необходимо найти производную потерь по входу выходному слою, Zo . Это отвечает на вопрос: как веса последнего слоя влияют на общую ошибку в сети? Тогда производная такова:

C′(Zo)=(y^−y)⋅R′(Zo)

Чтобы упростить запись, практикующие МО обычно заменяют последовательность (y^−y)∗R"(Zo) термином Eo . Итак, наша формула для ошибки выходного слоя равна:

Eo=(y^−y)⋅R′(Zo)

Ошибка скрытого слоя

Для вычисления ошибки скрытого слоя нужно найти производную потерь по входу скрытого слоя, Zh .

Eh=Eo⋅Wo⋅R′(Zh)

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

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

Вернемся к нашей формуле для производной потерь по весу выходного слоя Wo .

C′(WO)=(y^−y)⋅R′(ZO)⋅H

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

C′(Wo)=Eo⋅H

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

C′(w)=CurrentLayerError⋅CurrentLayerInput

Примечание: вход относится к активации с предыдущего слоя, а не к взвешенному входу, Z.

Подводя итог

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

Вот процесс, визуализированный с использованием нашего примера нейронной сети выше:

Обратное распространение: пример кода

def relu_prime(z): if z > 0: return 1 return 0 def cost(yHat, y): return 0.5 * (yHat - y)**2 def cost_prime(yHat, y): return yHat - y def backprop(x, y, Wh, Wo, lr): yHat = feed_forward(x, Wh, Wo) # Layer Error Eo = (yHat - y) * relu_prime(Zo) Eh = Eo * Wo * relu_prime(Zh) # Cost derivative for weights dWo = Eo * H dWh = Eh * x # Update weights Wh -= lr * dWh Wo -= lr * dWo

Прудников Иван Алексеевич
МИРЭА(МТУ)

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

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

Теоретическая часть

Данный материал предполагает знакомство с основами нейронных сетей, однако я считаю возможным ввести читателя в курс темы без излишних мытарств по теории нейронных сетей. Итак, для тех, кто впервые слышит словосочетание «нейронная сеть», предлагаю воспринимать нейронную сеть в качестве взвешенного направленного графа, узлы (нейроны) которого расположены слоями. Кроме того, узел одного слоя имеет связи со всеми узлами предыдущего слоя. В нашем случае у такого графа будут иметься входной и выходной слои, узлы которых выполняют роль входов и выходов соответственно. Каждый узел (нейрон) обладает активационной функцией - функцией, ответственной за вычисление сигнала на выходе узла (нейрона). Также существует понятие смещения, представляющего из себя узел, на выходе которого всегда появляется единица. В данной статье мы будем рассматривать процесс обучения нейронной сети, предполагающий наличие «учителя», то есть процесс обучения, при котором обучение происходит путем предоставления сети последовательности обучающих примеров с правильными откликами.
Как и в случае с большинством нейронных сетей, наша цель состоит в обучении сети таким образом, чтобы достичь баланса между способностью сети давать верный отклик на входные данные, использовавшиеся в процессе обучения (запоминания), и способностью выдавать правильные результаты в ответ на входные данные, схожие, но неидентичные тем, что были использованы при обучении (принцип обобщения). Обучение сети методом обратного распространения ошибки включает в себя три этапа: подачу на вход данных, с последующим распространением данных в направлении выходов, вычисление и обратное распространение соответствующей ошибки и корректировку весов. После обучения предполагается лишь подача на вход сети данных и распространение их в направлении выходов. При этом, если обучение сети может являться довольно длительным процессом, то непосредственное вычисление результатов обученной сетью происходит очень быстро. Кроме того, существуют многочисленные вариации метода обратного распространения ошибки, разработанные с целью увеличения скорости протекания процесса обучения.
Также стоит отметить, что однослойная нейронная сеть существенно ограничена в том, обучению каким шаблонам входных данных она подлежит, в то время, как многослойная сеть (с одним или более скрытым слоем) не имеет такого недостатка. Далее будет дано описание стандартной нейронной сети с обратным распространением ошибки.

Архитектура

На рисунке 1 показана многослойная нейронная сеть с одним слоем скрытых нейронов (элементы Z).

Нейроны, представляющие собой выходы сети (обозначены Y), и скрытые нейроны могут иметь смещение(как показано на изображении). Смещение, соответствующий выходу Y k обозначен w ok , скрытому элементу Z j - V oj . Эти смещения служат в качестве весов на связях, исходящих от нейронов, на выходе которых всегда появляется 1 (на рисунке 1 они показаны, но обычно явно не отображаются, подразумеваясь). Кроме того, на рисунке 1 стрелками показано перемещение информации в ходе фазы распространения данных от входов к выходам. В процессе обучения сигналы распространяются в обратном направлении.

Описание алгоритма

Алгоритм, представленный далее, применим к нейронной сети с одним скрытым слоем, что является допустимой и адекватной ситуацией для большинства приложений. Как уже было сказано ранее, обучение сети включает в себя три стадии: подача на входы сети обучающих данных, обратное распространение ошибки и корректировка весов. В ходе первого этапа каждый входной нейрон X i получает сигнал и широковещательно транслирует его каждому из скрытых нейронов Z 1 ,Z 2 ...,Z p . Каждый скрытый нейрон затем вычисляет результат его активационной функции (сетевой функции) и рассылает свой сигнал Z j всем выходным нейронам. Каждый выходной нейрон Y k , в свою очередь, вычисляет результат своей активационной функции Y k , который представляет собой ничто иное, как выходной сигнал данного нейрона для соответствующих входных данных. В процессе обучения, каждый нейрон на выходе сети сравнивает вычисленное значение Y k с предоставленным учителем t k (целевым значением), определяя соответствующее значение ошибки для данного входного шаблона. На основании этой ошибки вычисляется σ k (k = 1,2,...m). σ k используется при распространении ошибки от Y k до всех элементов сети предыдущего слоя (скрытых нейронов, связанных с Y k), а также позже при изменении весов связей между выходными нейронами и скрытыми. Аналогичным образом вычисляется σj (j = 1,2,...p) для каждого скрытого нейрона Z j . Несмотря на то, что распространять ошибку до входного слоя необходимости нет, σj используется для изменения весов связей между нейронами скрытого слоя и входными нейронами. После того как все σ были определены, происходит одновременная корректировка весов всех связей.

Обозначения:

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

X Входной вектор обучающих данных X = (X 1 , X 2 ,...,X i ,...,X n).
t Вектор целевых выходных значений, предоставляемых учителем t = (t 1 , t 2 ,...,t k ,...,t m)
σ k Составляющая корректировки весов связей w jk , соответствующая ошибке выходного нейрона Y k ; также, информация об ошибке нейрона Y k , которая распространяется тем нейронам скрытого слоя, которые связаны с Y k .
σ j Составляющая корректировки весов связей v ij , соответствующая распространяемой от выходного слоя к скрытому нейрону Z j информации об ошибке.
a Скорость обучения.
X i Нейрон на входе с индексом i. Для входных нейронов входной и выходной сигналы одинаковы - X i .
v oj Смещение скрытого нейрона j.
Z j Скрытый нейрон j; Суммарное значение подаваемое на вход скрытого элемента Z j обозначается Z_in j: Z_in j = v oj +∑x i *v ij
Сигнал на выходе Z j (результат применения к Z_in j активационной функции) обозначается Z j: Z j = f (Z_in j)
w ok Смещение нейрона на выходе.
Y k Нейрон на выходе под индексом k; Суммарное значение подаваемое на вход выходного элемента Y k обозначается Y_in k: Y_in k = w ok + ∑ Z j *w jk . Сигнал на выходе Y k (результат применения к Y_in k активационной функции) обозначается Y k:

Функция активации

Функция активация в алгоритме обратного распространения ошибки должна обладать несколькими важными характеристиками: непрерывностью, дифференцируемостью и являться монотонно неубывающей. Более того, ради эффективности вычислений, желательно, чтобы ее производная легко находилась. Зачастую, активационная функция также является функцией с насыщением. Одной из наиболее часто используемых активационных функций является бинарная сигмоидальная функция с областью значений в (0, 1) и определенная как:

Другой широко распространенной активационной функцией является биполярный сигмоид с областью значений (-1, 1) и определенный как:


Алгоритм обучения

Алгоритм обучения выглядит следующим образом:

Инициализация весов (веса всех связей инициализируются случайными небольшими значениями).

До тех пор пока условие прекращения работы алгоритма неверно, выполняются шаги 2 - 9.

Для каждой пары { данные, целевое значение } выполняются шаги 3 - 8.

Распространение данных от входов к выходам:

Шаг 3.
Каждый входной нейрон (X i , i = 1,2,...,n) отправляет полученный сигнал X i всем нейронам в следующем слое (скрытом).

Каждый скрытый нейрон (Z j , j = 1,2,...,p) суммирует взвешенные входящие сигналы: z_in j = v oj + ∑ x i *v ij и применяет активационную функцию: z j = f (z_in j) После чего посылает результат всем элементам следующего слоя (выходного).

Каждый выходной нейрон (Y k , k = 1,2,...m) суммирует взвешенные входящие сигналы: Y_in k = w ok + ∑ Z j *w jk и применяет активационную функцию, вычисляя выходной сигнал: Y k = f (Y_in k).

Обратное распространение ошибки:

Каждый выходной нейрон (Y k , k = 1,2,...m) получает целевое значение - то выходное значение, которое является правильным для данного входного сигнала, и вычисляет ошибку: σ k = (t k - y k)*f " (y_in k), так же вычисляет величину, на которую изменится вес связи w jk: Δw jk = a * σ k * z j . Помимо этого, вычисляет величину корректировки смещения: Δw ok = a*σ k и посылает σ k нейронам в предыдущем слое.

Каждый скрытый нейрон (z j , j = 1,2,...p) суммирует входящие ошибки (от нейронов в последующем слое) σ_in j = ∑ σ k * w jk и вычисляет величину ошибки, умножая полученное значение на производную активационной функции: σ j = σ_in j * f " (z_in j), так же вычисляет величину, на которую изменится вес связи vij: Δv ij = a * σ j * x i . Помимо этого, вычисляет величину корректировки смещения: v oj = a * σ j

Шаг 8. Изменение весов.

Каждый выходной нейрон (y k , k = 1,2,...,m) изменяет веса своих связей с элементом смещения и скрытыми нейронами: w jk (new) = w jk (old) + Δw jk
Каждый скрытый нейрон (z j , j = 1,2,...p) изменяет веса своих связей с элементом смещения и выходными нейронами: v ij (new) = v ij (old) + Δv ij

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

Итак, сегодня мы продолжим обсуждать тему нейронных сетей на нашем сайте, и, как я и обещал в первой статье (), речь пойдет об обучении сетей . Тема эта очень важна, поскольку одним из основных свойств нейронных сетей является именно то, что она не только действует в соответствии с каким-то четко заданным алгоритмом, а еще и совершенствуется (обучается) на основе прошлого опыта. И в этой статье мы рассмотрим некоторые формы обучения, а также небольшой практический пример.

Давайте для начала разберемся, в чем же вообще состоит цель обучения. А все просто – в корректировке весовых коэффициентов связей сети. Одним из самых типичных способов является управляемое обучение . Для его проведения нам необходимо иметь набор входных данных, а также соответствующие им выходные данные. Устанавливаем весовые коэффициенты равными некоторым малым величинам. А дальше процесс протекает следующим образом…

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

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

Дельта правило (правило Видроу-Хоффа).

Определим ошибку :

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

Дельта-правило заключается в следующем – изменение величины весового коэффициента должно быть равно:

Где – норма обучения. Это число мы сами задаем перед началом обучения. – это сигнал, приходящий к элементу k от элемента j . А – ошибка элемента k .

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

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

Алгоритм обратного распространения ошибок.

Этот алгоритм определяет два “потока” в сети. Входные сигналы двигаются в прямом направлении, в результате чего мы получаем выходной сигнал, из которого мы получаем значение ошибки. Величина ошибки двигается в обратном направлении, в результате происходит корректировка весовых коэффициентов связей сети. В конце статьи мы рассмотрим пример, наглядно демонстрирующий эти процессы.

Итак, для корректировки весовых значений мы будем использовать дельта-правило, которое мы уже обсудили. Вот только необходимо определить универсальное правило для вычисления ошибки каждого элемента сети после, собственно, прохождения через элемент (при обратном распространении ошибок).

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

Функция – это функция активности элемента. Давайте использовать логистическую функцию, для нее:

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

В этой формуле:

Наверняка сейчас еще все это кажется не совсем понятным, но не переживайте, при рассмотрении практического примера все встанет на свои места 😉

Собственно, давайте к нему и перейдем.

Перед обучением сети необходимо задать начальные значения весов – обычно они инициализируются небольшими по величине случайными значениями, к примеру из интервала (-0.5, 0.5). Но для нашего примера возьмем для удобства целые числа.

Рассмотрим нейронную сеть и вручную проведем расчеты для прямого и обратного “потоков” в сети.

На вход мы должны подать образец, пусть это будет (0.2, 0.5) . Ожидаемый выход сети – 0.4 . Норма обучения пусть будет равна 0.85 . Давайте проведем все расчеты поэтапно. Кстати, совсем забыл, в качестве функции активности мы будем использовать логистическую функцию:

Итак, приступаем…

Вычислим комбинированный ввод элементов 2 , 3 и 4 :

Активность этих элементов равна:

Комбинированный ввод пятого элемента:

Активность пятого элемента и в то же время вывод нейронной сети равен:

С прямым “потоком” разобрались, теперь перейдем к обратному “потоку”. Все расчеты будем производить в соответствии с формулами, которые мы уже обсудили. Итак, вычислим ошибку выходного элемента:

Тогда ошибки для элементов 2 , 3 и 4 равны соответственно:

Здесь значения -0.014, -0.028 и -0.056 получаются в результате прохода ошибки выходного элемента –0.014 по взвешенным связям в направлении к элементам 2 , 3 и 4 соответственно.

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

Аналогичным образом производим расчеты и для остальных элементов:

Теперь новые весовые коэффициенты будут равны сумме предыдущего значения и величины поправки.

На этом обратный проход по сети закончен, цель достигнута 😉 Именно так и протекает процесс обучения по алгоритму обратного распространения ошибок. Мы рассмотрели этот процесс для одного набора данных, а чтобы получить полностью обученную сеть таких наборов должно быть, конечно же, намного больше, но алгоритм при этом остается неизменным, просто повторяется по кругу много раз для разных данных)

По просьбе читателей блога я решил добавить краткий пример обучения сети с двумя скрытыми слоями:

Итак, добавляем в нашу сеть два новых элемента (X и Y), которые теперь будут выполнять роль входных. На вход также подаем образец (0.2, 0.5) . Рассмотрим алгоритм в данном случае:

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

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

3. Теперь нам нужно вычислить ошибки элементов 2, 3 и 4.

Для обучения многослойной сети в 1986 г. Руммельхартом и Хинтоном (Rummelhart D.E., Hinton G.E., Williams R.J., 1986) был предложен алгоритм обратного распостранения ошибок (error back propagation). Многочисленные публикации о промышленных применениях многослойных сетей с этим алгоритмом обучения подтвердили его принципиальную работоспособность на практике.

В начале возникает резонный вопрос - а почему для обучения многослойного персептрона нельзя применить уже известное -правило Розенблатта (см. Лекцию 4)? Ответ состоит в том, что для применения метода Розенблатта необходимо знать не только текущие выходы нейронов y, но и требуемыеправильные значенияY . В случае многослойной сети эти правильные значения имеются только для нейроноввыходного слоя. Требуемые значения выходов для нейронов скрытых слоев неизвестны, что и ограничивает применение-правила.

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

Перейдем к подробному рассмотрению этого алгоритма. Для упрощения обозначений ограничимся ситуацией, когда сеть имеет только один скрытый слой. Матрицу весовых коэффициентов от входов к скрытому слою обозначим W, а матрицу весов, соединяющих скрытый и выходной слой - как V. Для индексов примем следующие обозначения: входы будем нумеровать только индексом i, элементы скрытого слоя - индексом j, а выходы, соответственно, индексом k.

Пусть сеть обучается на выборке (X,Y),=1..p. Активности нейронов будем обозначать малыми буквами y с соотвествующим индексом, а суммарные взвешенные входы нейронов - малыми буквами x.

Общая структура алгоритма аналогична рассмотренной в Лекции 4, с усложнением формул подстройки весов.

Таблица 6.1. Алгоритм обратного распространения ошибки.

Начальные значения весов всех нейронов всех слоев V(t=0) и W(t=0) полагаются случайными числами.

Сети предъявляется входной образ X, в результате формируется выходной образ yY. При этом нейроны последовательно от слоя к слою функционируют по следующим формулам:

скрытый слой

выходной слой

Здесь f(x) - сигмоидальная функция, определяемая по формуле (6.1)

Функционал квадратичной ошибки сети для данного входного образа имеет вид:

Данный функционал подлежит минимизации. Классический градиентный метод оптимизации состоит в итерационном уточнении аргумента согласно формуле:

Функция ошибки в явном виде не содержит зависимости от веса V jk , поэтому воспользуемся формулами неявного дифференцирования сложной функции:

Здесь учтено полезное свойство сигмоидальной функции f(x): ее производная выражается только через само значение функции, f’(x)=f(1-f). Таким образом, все необходимые величины для подстройки весов выходного слоя V получены.

На этом шаге выполняется подстройка весов скрытого слоя. Градиентный метод по-прежнему дает:

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

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

Шаги 1-3 повторяются для всех обучающих векторов. Обучение завершается по достижении малой полной ошибки или максимально допустимого числа итераций, как и в методе обучения Розенблатта.

Как видно из описания шагов 2-3, обучение сводится к решению задачи оптимизации функционала ошибки градиентным методом. Вся “соль” обратного распространения ошибки состоит в том, что для ее оценки для нейронов скрытых слоев можно принять взвешенную сумму ошибок последующего слоя.

Параметр h имеет смысл темпа обучения и выбирается достаточно малым для сходимости метода. О сходимости необходимо сделать несколько дополнительных замечаний. Во-первых, практика показывает что сходимость метода обратного распространения весьма медленная. Невысокий тепм сходимости является “генетической болезнью” всех градиентных методов, так как локальное направление градиента отнюдь не совпадает с направлением к минимуму. Во-вторых, подстройка весов выполняется независимо для каждой пары образов обучающей выборки. При этом улучшение функционирования на некоторой заданной паре может, вообще говоря, приводить к ухудшению работы на предыдущих образах. В этом смысле, нет достоверных (кроме весьма обширной практики применения метода) гарантий сходимости.

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

В завершение лекции сделаем замечание относительно настройки порогов нейронов. Легко заметить, что порог нейрона может быть сделан эквивалентным дополнительному весу, соединенному с фиктивным входом, равным -1. Действительно, выбирая W 0 =, x 0 =-1 и начиная суммирование с нуля, можно рассматривать нейрон с нулевым порогом и одним дополнительным входом:

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



Последние материалы раздела:

Изменение вида звездного неба в течение суток
Изменение вида звездного неба в течение суток

Тема урока «Изменение вида звездного неба в течение года». Цель урока: Изучить видимое годичное движение Солнца. Звёздное небо – великая книга...

Развитие критического мышления: технологии и методики
Развитие критического мышления: технологии и методики

Критическое мышление – это система суждений, способствующая анализу информации, ее собственной интерпретации, а также обоснованности...

Онлайн обучение профессии Программист 1С
Онлайн обучение профессии Программист 1С

В современном мире цифровых технологий профессия программиста остается одной из самых востребованных и перспективных. Особенно высок спрос на...