Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Пороговое значение




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

   
a =  
  -(Si aiwi - Q)
  1 + e  

где
a - активность нейрона,
ai - активность i-ого нейрона предыдущего слоя (или i-ое входное значение, если мы вычисляем активность нейрона входного слоя),
wi - вес связи между данным нейроном и i-ым нейроном предыдущего слоя.

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

procedure run_network;var i,j: byte; {счетчики для циклов 'for'} sum: real;begin{Обходим все нейроны входного слоя. Вычисляем сумму взвешенных сигналов для входного набора данных}for i:=1 to MAX_INP do with ipl[i] do {i-ый нейрон входного слоя} begin sum:=0; for j:=1 to NUM_INPUTS do sum:=sum + w[j] * test_pat[j]; a:=sigmoid(sum - threshold) end; {Обходим все нейроны скрытого слоя. Действуем так же, как с нейронами входного слоя}for i:=1 to MAX_HID do with hl[i] do begin sum:=0; for j:=1 to MAX_INP do sum:=sum + w[j] * ipl[j].a; a:=sigmoid(sum - threshold) end; {Все то же самое для выходного слоя}for i:=1 to MAX_OUT do with ol[i] do begin sum:=0; for j:=1 to MAX_HID do sum:=sum + w[j] * hl[j].a; a:=sigmoid(sum - threshold); end;end;

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

with ipl[i] do w[j]:=...

полностью аналогичен:

ipl[i].w[j]:=...

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

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

Например, если нейронная сеть используется для того, чтобы определить, персона какого пола запечатлена на фотографии, то возможно существование двух нейронов в выходном слое: для мужского пола на выходе "М" должно появиться значение 1, а на выходе "Ж" - 0. Соответственно, при предъявлении сети женской фотографии, выходные нейроны выдают обратные значения ("М"=0, "Ж"=1). На практике, если на выходе "М" - число 0.0261, а на выходе "Ж" - число 0.9932, то сеть выдает заключение о том, что на фотографии - женское лицо (точных значений 1 или 0 вряд ли можно добиться).

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

 

 

Обучение сети - обратное распространение [ошибки]
Обратное распространение ошибки - стандартный способ обучения нейронной сети, хотя существуют и другие методы (о них в одной из следующих глав). Принцип работы примерно такой:
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-ого значения выходного слоя (т.е. проходим по всем узлам выходного слоя):

Ei = (ti - ai).ai.(1 - ai)

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

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

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;

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

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

Ei = ai. (1 - ai). Sj Ej.wij

Смысл переменных по сравнению с прошлой формулой изменился незначительно. индекс i используется для нейронов скрытого слоя (а не выходного), Ei, следовательно, значение ошибки для нейрона скрытого слоя, и ai - сигнал на выходе нейрона. Индекс j относится к нейронам выходного слоя: wij - вес (весовой коэффициент) связи между i-ым скрытым нейроном и j-ым выходным нейроном, а Ej - значение ошибки для выходного нейрона 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 wij = old wij + h.d j.xi

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

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

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

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

new threshold = old threshold - h.d j

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

procedure update_output_weights;const LEARNING_RATE = 0.025;var i,j: byte;begin for j:= 1 to NUM_OUT do {для всех выходных узлов} with ol[j] do begin {для всех связей от скрытого слоя к этому выходному узлу} for i:= 1 to NUM_HID do w[i]:= w[i] + LEARNING_RATE * E * hl[i].out; {обучение порогового уровня} threshold:= threshold - LEARNING_RATE * E endend;

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

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

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 endend;
Обучающие наборы представлены по левую сторону. Для того, чтобы изменить входные наборы, желаемые выходные наборы, кликните на столбец из шести входных квадратов или на столбец из пяти выходных квадратов. Каждый клик мышью затемняет квадрат (белый - 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"

 

 

Альтернативы обратному распространению
Обратное распространение ошибки - не единственный метод обучения нейронной сети, хотя и наиболее часто используемый. Когда я только начинал свое знакомство с нейронными сетями, то не мог добиться, чтобы обратное распространение работало. Поэтому я решил тогда воспользоваться другим методом. Это была идея, обсуждение которой я видел на каком-то телеканале, и она показалась мне достаточно разумной. В конце концов, эволюция привела к появлению самой совершенной нейронной сети - человеческого мозга, - так почему бы не поработать с небольшой моделью такого рода эволюции. Метод состоит в том, что имеется некоторая "популяция" сетей, все с различными случайными весовыми коэффициентами и пороговыми уровнями. ВЫ заставляете каждую из них обрабатывать тренировочный набор данных. В результате получаете полный хаос и неразбериху в выходных наборах. Однако, часть нейронных сетей менее неправильно вычисляет треубемые значения. Для каждой сети существует счет - сумма общих ошибок данной сети. Напрмиер, если сеть должна выдавать на выходе два значения - 1 и 0, но выдает 0.3 и 0.1, то общая ошибка будет равна (1-0.3) + (0.1-0) = 0.8. Эти самые ошибки и складываются для всех входных наборов данных. В конце каждого цикла обучения ошибки сетей сравниваются. Сети с наихудшими показателями (ошибки максимальны) - уничтожаются, с наилучшими - используются для "вскармливания" следующих поколений. Вот пример: Предположим, что имеется популяция из 8 сетей, тестируемая на "словаре" из 10 наборов данных. Общая ошибка для каждой сети представлена в таблице
сеть общая ошибка
  1.00431
  2.65520
  1.35425
  1.94233
  1.35462
  0.97766
  1.38752
  1.17584

Только часть этих сетей будет использоваться в дальнейшем. В данном случае выберем две штуки (6 и 1) и копируем их в другие слоты (2, 3, 4 и т.д.), при этом слегка их изменяя. Это и есть те "мутации", которые должны улучшить качество расчетов. Мутации, вызывающие увеличение ошибок, - отбрасываются.

Работает ли эта идея. - Да, она действительно работает, но очень медленно! Если вы думаете, что метод обратного распространения медленный, то сравните с этим монстром. То, что может быть сделано с помощью обратного распространения за полчаса, займет всю ночь.

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

 

 

 




Поделиться с друзьями:


Дата добавления: 2015-06-04; Просмотров: 1136; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.011 сек.