Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Нейронные сети Лаба 4

.pdf
Скачиваний:
113
Добавлен:
14.04.2015
Размер:
547.5 Кб
Скачать

Лабораторная работа 4 «Исследование самоорганизующихся слоев Кохонена»

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

4.2 Методические указания по самостоятельной работе студентов

План работы:

1.Установка среды и библиотек (SciPy, Neurolab). Проверка работоспособности модулей numpy, matplotlib, neurolab.

2.Изучение визуальной среды по предлагаемым и встроенным примерам.

3.Повторение теоретического материала самоорганизующихся картах, выполнение численных экспериментов.

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

5.Проведение контрольных экспериментов по вариантам.

Каждый пункт должен быть отражѐн в отчѐте.

4.2.1 Теоретические сведения

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

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

На рис. 1.1 представлена архитектура слоя Кохонена.

Вход

Конкурирующий слой

 

 

 

cn1 ci

 

 

 

 

 

 

 

 

 

IW11

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

p

 

 

 

 

n1

 

a1

 

 

 

ndist

 

 

 

 

 

ci×1

 

 

 

 

 

 

 

 

 

 

 

 

C

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

cn1 1

1

1

 

cn1 1

b

 

 

 

 

 

 

 

 

 

cn1

ci

cn1 1

 

 

 

 

 

Рисунок 1.1 – Архитектура слоя Кохонена

Это слой конкурирующего типа, поскольку в нем применена конкурирующая функция активации C. Кроме того, архитектура этого слоя очень напоминает архитектуру скрытого слоя радиально-базисной сети. Здесь использован блок ndist для вычисления отрицательного евклидова расстояния между вектором входа p и строками матрицы весов IW11. Вход функции активации n1 – это результат суммирования вычисленного расстояния с вектором смещения b. Если все смещения нулевые, максимальное значение n1 не может превышать 0. Нулевое значение n1 возможно только когда вектор входа р оказывается равным вектору веса одного из нейронов. Если смещения отличны от 0, то возможны и положительные значения для элементов вектора n1.

Конкурирующая функция активации анализирует значения элементов вектора n1 и формирует выходы нейронов, равные 0 для всех нейронов, кроме одного нейрона-победителя, имеющего на входе максимальное значение. Т.о., вектор выхода слоя а1 имеет единственный элемент, равный 1, который соответствует нейрону-победителю, а остальные равны 0.

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

Программно архитектура сети реализована следующим образом. Команда создания карты Кохонена: newc(minmax, cn) возвращает объект Net с cn нейронов, и len(minmax) входов. minmax – это матрица размера ci×2, определяющая диапазон входных значений (нужна для правильной начальной инициализации весов).

Создадим сеть с 2 входами и 10 нейронами:

>>>import neurolab as nl

>>>net = nl.net.newc([[-1, 1], [-1, 1]], 10)

Посмотрим свойства объекта Net:

>>>print net.__doc__

Neural Network class

:Parameters:

Диапазон входных значений inp_minmax: minmax: list ci x 2

Количество выходов co: int

Слои сети

layers: list of Layer

Схема соединения слоёв connect: list of list

Функция самообучения trainf: callable

Функция измерения ошибки errorf: callable

Это общий класс для всех типов нейросетей. Мы будем обращаться только к части из этих свойств.

Большинство свойств конкретной сети определяется входящими в неѐ объектами типа layers (слои). В случае карты Кохонена есть единственный слой (нулевой). Общие свойства типа не слишком интересны, рассмотрим лучше характеристики слоя созданной нами сети, используя команду

__dict__:

>>> net.layers[0].__dict__

{'ci': 2, #количество входов 'cn': 4, #количество нейронов 'co': 4, #количество выходов

#функция расчёта расстояния:

'distf': <function euclidean at 0x11714F70>,

#функция инициализации:

'initf':<function midpoint at 0x054567F0>,

#вектор для входных значений:

'inp': array([ 0., 0.]),

#диапазон входных значений:

 

 

'inp_minmax': array([[ 0.,

1.],

 

 

[ 0.,

1.]]),

 

 

 

#структура для хранения весов и сдвигов:

 

 

'np': {'conscience': array([ 1., 1., 1.,

1.]),

 

'w': array([[ 0.5,

0.5],

 

 

[ 0.5,

0.5],

 

 

 

[ 0.5,

0.5],

 

 

 

[ 0.5,

0.5]])},

 

 

 

#вектор для выходных значений:

 

 

'out': array([ 0., 0., 0., 0.]),

 

 

#диапазон выходных значений:

 

 

'out_minmax': array([[ 0.,

1.],

 

 

[ 0.,

1.],

 

 

 

[ 0.,

1.],

 

 

 

[ 0.,

1.]]),

 

 

 

#передаточная функция:

 

 

 

'transf':

<neurolab.trans.Competitive

instance

at

0x05B10DF0>}

 

 

 

 

Веса созданной нами сети net инициализованы с помощью функции средних значений nl.init.midpoint(), то есть определены как середина диапазона входных значений.

Матрица весов является частью структуры словаря. Получить к ней

доступ можно по ключу net.layers[0].np['w']

Инициализация весов смещений каждого нейрона conscience производится единицами. Получить к ним доступ можно аналогично весам:

net.layers[0].np['conscience']

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

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

Функция learn рассчитывает приращение весов dW в зависимости от вектора входа P, выхода а, весов w и параметра скорости настройки lr в соответствии с правилом Кохонена:

lr * ( p' w),a j

0;

dw

0.

 

0, a j

 

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

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

Функция learn производит такую корректировку смещений следующим образом.

В начале процедуры настройки сети всем нейронам присваивается одинаковый характер активности с0 = 1/S. В процессе настройки эта величина для активных нейронов увеличивается, а для неактивных нейронов уменьшается:

c lr * (ai c),

где lr – параметр скорости настройки,

a * – вектор, элемент і* которого равен

 

i

1, а остальные – 0.

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

b exp(1 log(c)) b

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

Реализацию данных алгоритмов можно рассмотреть, обратившись к документации классов neurolab.train.train_wta (без использования смещений) и neurolab.train.train_cwta (со смещениями).

4.3 Ход работы

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

Импортируем необходимые библиотеки:

import numpy as np import neurolab as nl import pylab as pl

Зададим выборку для обучения слоя. Это массив из 4 двухэлементных векторов (точек на 2-мерной плоскости), которые надо разделить на два класса:

P = np.array([[.9,.8,.8,.9],[.2,.1,.1,.8]]) P.shape = (4, 2)

Создание карты Кохонена из двух нейронов:

net = nl.net.newc([[0, 1],[0, 1]], 2)

Можем назначить ей функцию обучения:

net.trainf = nl.train.train_cwta

Осуществим обучение, подав на вход обучающую выборку. Ввиду простоты задачи, сократим количество эпох обучения до 50.

error = net.train(P, epochs = 50, show = 10, lr = 0.1, goal = 0.01)

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

Выведем результат на экран

w = net.layers[0].np['w'] pl.title('Classification Problem') pl.subplot(211)

pl.plot(error) pl.xlabel('Epoch number')

pl.ylabel('error (default MAE)') pl.subplot(212)

pl.plot(P[:, 0], P[:, 1], 'o', w[:, 0], w[:, 1], 'D') pl.legend(['train samples', 'train centers'], loc = 'best')

Проведѐм тестирование сети, задав другой набор точек в том же диапазоне:

m = linspace(0,1,10) m.shape = (5,2) print(net.sim(m))

pl.plot(m[:, 0], m[:, 1], '.')

Рис. 1.2. Изменение ошибки со временем (вверху) и положение нейронов сети относительно входного набора (обозначен «+») и тестового (обозначен «.»)

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

[[ 1. 0.] [ 1. 0.] [ 1. 0.] [ 0. 1.] [ 0. 1.]]

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

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

#определим минимумы и максимумы по каждому измерению.

d1, d2 = np.around(nl.tool.minmax(input))*1.5 #input - выборка, на которой обучалась сеть, 1.5 - параметр масштаба

#создадим равномерную сеть 100*100 точек в найденном диапазоне. За подробностями обратитесь к help(meshgrid).

xx, yy = np.meshgrid(np.linspace(min(d1), max(d1), 100), np.linspace(min(d2), max(d2), 100))

#сформируем тестовую выборку из точек сети: xx.shape = (xx.size, 1)

yy.shape = (yy.size, 1)

grid = np.concatenate((xx, yy), axis=1)

#проведѐм симуляцию out = net.sim(grid)

#вывод на экран:

for i in range(k): #k - число нейронов сети, оно же число кластеров cluster = np.transpose([inp for w,inp in zip(out, grid) if w[i] == 1])

#используется генератор списков (см. Основы Python) if cluster.any(): #если кластер не пуст

pl.plot(cluster[0], cluster[1], ',')

Иллюстрация приведена на рисунке 1.3. Используйте эту функцию в други х экспериментах.

Рис. 1.3. Разбиение на 2 кластера (слева) и на 16 (справа)

2. Создать слой Кохонена, который для 48 случайных векторов формирует 8 кластеров. Например, так:

# -*- coding: utf-8 -*-

import numpy as np import neurolab as nl

import pylab as pl

import numpy.random as rand

k = 8 # количество кластеров

n = 6 # наблюдений в каждом кластере

x = array([[-10, 10],[-5, 5]]) # диапазон наблюдений

#генерация случайных центроидов: centers = np.zeros((k, 2))

centers[: 0] = rand.randint(x[0, 0],x[0, 1],k) centers[:, 1] = rand.randint(x[1, 0],x[1, 1],k) d = .5 # дисперсия наблюдений от центроидов

#генерация наблюдений:

input = np.zeros((n*k, 2) cursor = 0

for z in range(k): for q in range(n)

input[cursor, 0] = rand.normal(centers[z, 0],d) input[cursor, 1] = rand.normal(centers[z, 1]d) cursor += 1

net = nl.net.newc(x, 8) net.trainf = nl.train.train_cwta

error = net.trаin(input, epochs = 50, show = 10, lr = 101, goal = 99)

# вывод результатов: pl.title('Classification Problem') pl.subplot(211)

pl.plot(error) pl.xlabel('Epoch number')

pl.ylabel('error (default MAE)') w = net.layers[0].np['w'] pl.subplot(212)

pl.plot(input[:, 0], input[:,1], '.', \ centers[:, 0], centers[:, 1] , 'yv', \ w[:, 0], w[:,1], 'D')

pl.legend(['train samples', 'real centers', 'neurons'], loc = 'best') pl.show()

3.Проанализировать примеры 1, 2 и neurolab/example/newc.py.

4.Визуализировать процесс обучения сети, описать влияние на результат

исходных данных

условий обучения

параметров обучения

параметров сети.

алгоритма настройки

5.Исследовать критические режимы работы сети (не менее трѐх).

4.4 Содержание отчета

1.Титульный лист.

2.Цель работы.

3.Ход работы (результаты выполнения каждого из заданий).

4.Расширенные выводы.