Для удобства работы с текстом повторим операторы задания обучающей последовательности и формирования LVQ-сети
P = [–3 –2 –2 0 0 0 0 2 2 3;
0 1 –1 2 1 –1 –2 1 –1 0];
Tc = [1 1 1 2 2 2 2 1 1 1];
T = full(ind2vec(Tc));
Выполним синтез LVQ-сети:
net = newlvq(minmax(P),4,[.6.4]);
net.inputWeights{1}
ans =
delays: 0
initFcn: 'midpoint'
learn: 1
learnFcn: 'learnlv2'
learnParam: [1´1 struct]
size: [4 2]
userdata: [1´1 struct]
weightFcn: 'negdist'
Для обучения сети применим М-функцию train, задав количество циклов обучения равным 2000, и значение параметра скорости обучения 0.05:
net.trainParam.epochs = 2000;
net.trainParam.show = 100;
net.trainParam.lr = 0.05;
net = train(net,P,T);
В результате обучения получим следующие весовые коэффициенты нейронов конкурирующего слоя, которые определяют положения центров кластеризации:
V = net.IW{1,1}
V =
–2.3639 0.0074775
2.3461 0.033489
0 –1.4619
0 1.4731
Построим картину распределения входных векторов по кластерам (рис. 7.19):
I1 = find(Tc==1); I2 = find(Tc==2);
axis([–4,4,–3,3]), hold on
P1 = P(:,I1); P2 = P(:,I2);
plot(P1(1,:),P1(2,:),'+k')
plot(P2(1,:),P2(2,:),'xb')
plot(V(:,1),V(:,2),'or') % Рис.7.19
Рис. 7.19
В свою очередь, массив весов линейного слоя указывает, как центры кластеризации распределяются по классам:
|
|
net.LW{2}
ans =
1 1 0 0
0 0 1 1
Нетрудно видеть, что обучение сети выполнено правильно. Чтобы проверить функционирование сети, подадим на ее вход массив обучающих векторов P:
Y = sim(net,P)
Yc = vec2ind(Y)
Yc = 1 1 1 2 2 2 2 1 1 1
Результат подтверждает, что классификация выполнена правильно.
Теперь построим границу, разделяющую области точек, принадлежащих к двум классам. Для этого покроем сеткой прямоугольную область и определим принадлежность каждой точки к тому или иному классу. Текст соответствующего сценария и вспомогательной М-функции приведен ниже
x = –4:0.2:4; y = –3:0.2:3; P = mesh2P(x,y); Y = sim(net,P); Yc = vec2ind(Y); I1 = find(Yc==1); I2 = find(Yc==2); plot(P(1,I1),P(2,I1),'+k'), hold on plot(P(1,I2),P(2,I2),'*b') % Рис.7.20 | function P = mesh2P(x,y) % Вычисление массива координат прямоугольной сетки [X,Y] = meshgrid(x,y); P = cat(3,X,Y); [n1,n2,n3] = size(P); P = permute(P,[3 2 1]); P = reshape(P, [n3 n1*n2]); |
Результат работы этого сценария представлен на рис. 7.20. Здесь же отмечены вычисленные ранее центры кластеризации для синтезированной LVQ-сети. Анализ рисунка подтверждает, что граница между областями не является прямой линией.
Рис. 7.20
Наряду с процедурой обучения можно применить и процедуру адаптации в течение 200 циклов для 10 векторов, что равносильно 2000 циклам обучения с использованием функции train:
net.adaptparam.passes = 200;
Обучающая последовательность при использовании функции adapt должна быть представлена в виде массивов ячеек:
Pseq = con2seq(P);
Tseq = con2seq(T);
net = adapt(net,Pseq,Tseq);
net.IW{1,1}
ans =
–2.3244 –0.0033588
2.3311 –0.0033019
–0.0003663 1.4704
–0.0003663 –1.4754
Промоделируем сеть, используя массив входных векторов обучающей последовательности:
Y = sim(net,P);
Yc = vec2ind(Y)
|
|
Yc = 1 1 1 2 2 2 2 1 1 1
Результаты настройки параметров сети в процессе адаптации практически совпадают с результатами обучения.
Единственное, что можно было бы напомнить при этом, что при обучении векторы входа выбираются в случайном порядке и поэтому в некоторых случаях обучение может давать лучшие результаты, чем адаптация.
Можно было бы и процедуру адаптации реализовать с использованием случайной последовательности входов, например следующим образом: сформируем 2000 случайных векторов и выполним лишь 1 цикл адаптации:
TS = 2000;
ind = floor(rand(1,TS)*size(P,2))+1;
Pseq = con2seq(P(:,ind));
Tseq = con2seq(T(:,ind));
net.adaptparam.passes = 1;
net = adapt(net,Pseq,Tseq);
net.IW{1,1}
ans =
2.354 –0.061991
–2.362 –0.093345
0 –1.4834
0 1.4539
Y = sim(net,P);
Yc = vec2ind(Y)
Yc = 1 1 1 2 2 2 2 1 1 1
В результате получаем LVQ-сеть, подобную тем, которые были получены ранее с помощью процедур обучения и адаптации.
Читатель может продолжить изучение LVQ-сетей, обратившись к демонстрационной программе demolvq1.