Типичная упрощенная схема обучения персептрона состоит из следующих этапов:
1. Весь набор исходных примеров делится на обучающий набор и тестовый набор примеров
2. Создается персептрон со всеми возможными связями при заданном количестве слоев и нейронов. Веса синаптических связей инициализируются случайными значениями, чаще всего взятых на отрезке [-1,+1]. Выбор начального количества слоев и нейронов обычно отдается на откуп опыта и интуиции человека.
3. Осуществляется оптимизация весов синапсов с целью минимизации функции ошибки на обучающей множестве примеров.
4. Если не удалось минимизировать функцию ошибки до требуемого уровня, то усложняют сеть путем добавления новых слоев и нейронов, и повторяют этап 3.
5. Если функция ошибки на тестовом множестве примеров выше приемлемого уровня, то сеть упрощают и переходят к этапу 3.
На практике приведенную выше схему дополняют периодическим применением возмущения весов синапсов, введением в функцию ошибки регуляризирующих составляющих, различными итерационными алгоритмами обучения и т. п. Но почти во всех случаях присутствуют одни и те же проблемы попадания в локальные минимумы функции ошибки и высокий уровень ошибок на тестовом множестве. Слабые обобщающие способности обученных нейронных сетей частично объясняются неадекватностью их структур, следствие малого внимания к структуре сети. Для выхода из локального минимума обычно применяют нехитрую процедуру относительно небольшого случайного возмущения весов синапсов с последующим продолжением процедуры оптимизации. Более эффективно было бы изменение структуры сети и как следствие изменение поведения функции ошибки.
Для устранения проблемы локальных решений часто предлагается использовать методы генетического программирования. Однако во всех известных автору методах не решена принципиально проблема вырождения популяции. Эта проблема фактически снова приводит к проблеме локальности находимых решений.
Предлагаемый здесь алгоритм обучения многослойного персептрона базируется на методе направленной эволюции (см. описание МНЭ) дополненного некоторым методом параметрической оптимизации. Данный алгоритм принципиально снимает проблему локальности находимых решений и уделяет большое внимание как весам синаптических связей сети, так и структуре сети. Получаемые нейронные сети обладают высокой обобщающей способностью. Для применения МНЭ к задаче обучения персептрона требуется только определить реализацию оператора мутации и способ создания сети с начальной структурой и весовыми коэффициентами.
Персептрон состоит из пронумерованных по порядку слоев. За нулевой слой принимается набор внешних источников сигнала (рецепторное поле). Выходной слой имеет максимальный номер max_l. Чем ближе слой к выходному слою, тем больше его номер. Каждый нейрон в персептроне адресуется номером слоя содержащего его и номером в слое.
Введем универсальный набор операторов модификации структуры персептрона X:
· OP1(X, l) - добавить нейрон в существующий слой с номером l, l > 0
· OP2(X) - Добавить нейрон в новый слой. Равновероятно выбирается номер l1 из диапазона [0, max_l). Все слои с номерами l > l1 увеличивают свой номер путем добавления 1 к старому номеру. Новому слою присваивается номер l2 = l1 + 1.
· OP3(X, i, l, n) – добавить синапс проводящий внешний сигнал от i-го источника внешних сигналов в n-й нейрон в l-м слое. Начальный вес синапса выбирается равновероятно из диапазона [-1, 1].
· OP4(X, l1, l2, n1, n2) – добавить синапс проводящий сигнал от n1-го нейрона из l1-го слоя к n2-му нейрону в l2-м слое, l1 < l2. Начальный вес синапса выбирается равновероятно из диапазона [-1, 1].
· OP5(X, l, n) - удалить n-й нейрон из слоя l и все связанные с этим нейроном синапсы. l не может быть номером выходного слоя
· OP6(X, l, n) - удалить произвольный синапс передающий сигнал в n-й нейрон в l-м слое
С помощью этого набора операций можно сконструировать персептрон любой структуры. Однако операции OP1 и OP2 всегда должны применятся в связке с операциями OP3 и OP4. По этому введем две дополнительные процедуры:
· EOP7(X, l1, l2, n):
1. OP1(X, l1), n1 – номер, присвоенный добавленному нейрону
2. b := random(0,1) /*присвоить b равновероятно 1 или 0*/
3. Если b = 0 или l1 = 1 то переход к пункту 4, иначе к пункту 5
4. Из множества источников внешнего сигнала равновероятно выбрать источник с номером i; OP3(X, i, l1, n1); перейти к пункту 6
5. Равновероятно выбрать номер слоя l3 из диапазона [1, l1); Равновероятно выбрать номер нейрона n2 из l3-го слоя; OP4(X, l3, l1, n2, n1)
6. OP4(X, l1, l2, n1, n)
· EOP8(X):
1. OP2(X), n – номер, присвоенный добавленному нейрону, l – номер присвоенный добавленному слою
2. Равновероятно выбирается номер l1 из диапазона (l, max_l]
3. Равновероятно выбираем нейрон с номером n1 из l1-го слоя
4. b := random(0,1) //присвоить b равновероятно 1 или 0
5. Если b = 0 или l = 1 то переход к пункту 6, иначе к пункту 7
6. Из множества источников внешнего сигнала равновероятно выбрать источник с номером i; OP3(X, i, l, n); перейти к пункту 10
7. Равновероятно выбрать номер слоя l2 из диапазона [1, l)
8. Равновероятно выбрать номер нейрона n2 из l2-го слоя
9. OP4(X, l2, l, n2, n)
10. OP4(X, l, l1, n, n1)
Удобно ввести один универсальный оператор добавления нейрона и связанных с ним синапсов:
EOP9(X)
1. b := random(0,1) /*присвоить b равновероятно 1 или 0*/
2. Если b = 0 то перейти к пункту 3, иначе перейти к пункту 10
3. Строим список S всех номеров слоев X, кроме номера выходного слоя
4. Из списка S равновероятно выбираем номер l1 и удаляем его из S
5. Включаем в список S номер выходного слоя
6. Из списка S равновероятно выбираем номер l2
7. S1 := [l1, l2]; Сортируем список S1 по возрастанию /*S1[1] > S1[0]*/
8. Равновероятно выбираем из S1[1]-го слоя нейрон с номером n
9. EOP7(X, S1[0], S1[1], n); СТОП
10. EOP8(X)
Все ранее введенные операции либо усложняют, либо упрощают структуру нейронной сети. Однако необходимо иметь операции изменяющие структуру сети, но не влияющие на ее сложность (не изменяющие количество синапсов и нейронов). Для этого введем еще две дополнительные процедуры:
· EOP10(X) – перемещение синапса:
1. Из списка всех синапсов сети X равновероятно выбирается один синапс, который затем удаляется из X.
2. b := random(0,1) /*присвоить b равновероятно 1 или 0*/
3. Если b = 0 то перейти к пункту 4
4. Построить множество S всех возможных троек <l, n, i> где l – ненулевой номер слоя, n – номер нейрона в l-м слое, i – номер источника внешнего сигнала не связанного синапсом с n-м нейроном в l-м слое.
5. Если S=Æ то перейти к пункту 7
6. Из S равновероятно выбрать пару <l, n, i> и выполнить OP3(X, i, l, n); СТОП
7. Построить множество S всех возможных четверок <l1, l2, n1, n2> где l1, l2 – ненулевые номера слоев, l1 < l2, n1 – номер нейрона в l1-м слое, n2 – номер нейрона в l2-м слое, нейрон n1 не связан с нейроном n2 синапсом
8. Если S=Æ то перейти к пункту 4
9. Из S равновероятно выбрать четверку <l1, l2, n1, n2> и выполнить OP4(X, ,l1, l2, n1, n2), СТОП
· EOP11(X) – переместить нейрон:
1. Из списка всех нейронов сети X, кроме выходного нейрона, равновероятно выбирается один нейрон, который затем удаляется из X. Все связанные с удаленным нейроном синапсы так же удаляются. Количество удаленных синапсов сохраняется в переменной n.
2. Добавить нейрон EOP9(X); n := n – 2 /*EOP9 добавляет один нейрон и два синапса*/
3. Построить множество S1 всех возможных троек <l, n, i> где l – номер слоя, n – номер нейрона в l-м слое, i – номер входного сигнала не передаваемого в n-й нейрон.
4. Построить множество S2 всех возможных четверок <l1, l2, n1, n2> где l1, l2 – номера слоев, l1 < l2, n1 – номер нейрона в l1-м слое, n2 – номер нейрона в l2-м слое, нейрон n1 не связан с нейроном n2 синапсом
5. Если n = 0 то СТОП
6. b := random(0,1) /*присвоить b равновероятно 1 или 0*/
7. Если b = 0 и S1¹Æ то перейти к пункту 8, иначе к пункту 10
8. Из S1 равновероятно выбрать пару <l, n, i>, исключить ее из S1 и выполнить OP3(X, i, l, n)
9. n := n – 1; перейти к пункту 5
10. Если S2¹Æ то перейти к пункту 11, иначе перейти к пункту 8
11. Из S2 равновероятно выбрать четверку <l1, l2, n1, n2>, исключить ее из S2 и выполнить OP4(X, l1, l2, n1, n2)
12. n := n – 1; перейти к пункту 5
В результате модификации персептрона могут появиться некорректные структуры. В персептроне могут появиться нейроны, не принимающие ни каких сигналов или не передающие никуда сигналы. Для приведения структуры персептрона X к корректному виду вводится процедура CORRECT(X). В результате модификации структуры может появиться «пустой» персептрон содержащий только выходной нейрон, не принимающий ни каких сигналов. Условимся, что «пустой» персептрон всегда возвращает 0.
Введем обобщенную операцию изменения структуры персептрона X:
MSTRUCT(X):
1. OP_LIST := [9] //всегда можно добавить нейрон и два синапса
2. Если X не «пустой», то OP_LIST := OP_LIST + [10, 6] /*В «непустом» персептроне можно удалить или переместить синапс*/
3. Если в X кроме выходного слоя и нулевого имеются еще слои, то OP_LIST := OP_LIST + [11, 5] /*можно удалить или переместить нейрон и все связанные с ним синапсы*/
4. Если в X имеются нейрон и источник внешних сигналов не связанные, непосредственно, синапсом, то OP_LIST := OP_LIST + [3] /*можно добавить синапс проводящий внешний сигнал*/
5. Если в X имеются нейроны из различных слоев не связанные непосредственно синапсом, то OP_LIST := OP_LIST + [4] /*можно добавить синапс проводящий сигнал от одного нейрона к другому*/.
6. _len := LEN(OP_LIST) /*получить длину списка OP_LIST*/
7. b := random(0, _len - 1) /*получить равновероятно целое число из диапазона [0, _len - 1]*/
8. k := OP_LIST[b] /*определяем номер операции модификации структуры сети*/
9. Если k = 9, то EOP9(X); СТОП /*добавить нейрон и два синапса*/
10. Если k = 10, то EOP10(X); СТОП /*переместить синапс*/
11. Если k = 6, то: /*удалить синапс*/
11.1. Выбрать равновероятно номер l слоя X, кроме нулевого номера
11.2. Выбрать равновероятно номер n нейрона в l-ом слое
11.3. OP6(X, l, n); СТОП
12. Если k = 11, то EOP11(X); СТОП /*переместить нейрон и связанные с ним синапсы*/
13. Если k = 5, то: /*удалить нейрон и связанные с ним синапсы*/
13.1. Выбрать равновероятно номер l слоя X, кроме нулевого номера и номера выходного слоя
13.2. Выбрать равновероятно номер n нейрона в l-ом слое
13.3. OP5(X, l, n); СТОП
14. Если k = 3, то: /*добавить синапс, проводящий внешний сигнал*/
14.1. Выбрать равновероятно номер l слоя X, кроме нулевого номера, содержащего нейрон не связанный непосредственно синапсами со всеми источниками внешних сигналов
14.2. Выбрать равновероятно номер n нейрона в l-ом слое, не связанного непосредственно синапсами со всеми источниками внешних сигналов
14.3. Построить список S всех номеров внешних источников сигнала не связанных непосредственно синапсом с n-м нейроном из l-го слоя
14.4. Равновероятно выбрать номер i из списка S
14.5. OP3(X, i, l, n); СТОП
15. Если k = 4, то: /*добавить синапс, проводящий сигнал от нейрона*/
15.1. Построить множество S всех возможных четверок <l1, l2, n1, n2>, где l1, l2 – номера слоев сети X и l2 > l1 > 0, n1 – номер нейрона в l1-ом слое, n2 – номер нейрона в l2-ом слое
15.2. Исключить из S все четверки <l1, l2, n1, n2> такие, что в X n1-й нейрон из ll-го слоя связан непосредственно синапсом с n2-м нейроном из l2-го слоя
15.3. Из S равновероятно выбрать четверку <l1, l2, n1, n2>; OP4(X, l1, l2, n1, n2); СТОП
Теперь можно описать алгоритм оператора мутации персептрона X
M(X):
1. MSTRUCT(X) /*случайно модифицируем структуру персептрона*/
2. CORRECT(X) /*приводим структуру персептрона к корректному виду*/
3. Оптимизация весов синапсов с целью уменьшить ошибку на обучающем наборе примеров. Алгоритм параметрической оптимизации не регламентируется[1]. В качестве начальных весов синапсов принимаются их текущие значения.
4. Для оценки модифицированного персептрона X вычисляется ошибка на тестовом[2] наборе примеров
Способ создания начального персептрона для стартовой популяции МНЭ
В качестве стартовой конфигурации сети выбирается несложная случайно сконфигурированная сеть. В пределе в качестве начальной сети можно выбрать «пустой» персептрон содержащий один выходной нейрон, не принимающий ни каких сигналов.
[1] Автор использовал покоординатный спуск с ограничением на минимальный шаг коррекции веса синапса (в качестве минимального шага бралось значение 0.01). На ряде тестовых задач этот метод вел себя лучше простого алгоритма обратного распространения ошибки.
[2] Оптимизация и тестирование проводится на разных наборах примеров, что позволяет оценить степень адекватности структуры персептрона. Если структура персептрона не адекватна, то при оптимизации произойдет так называемый эффект «переобучения» сети и ошибка на тестовом наборе будет значительно выше, чем на обучающем наборе.