
- •Содержание
- •3.2. Многослойный персептрон 34
- •12.1. Обоснование выбора темы и области применения разработки 142
- •12.2. Оценка ожидаемой экономической целесообразности разработки, изготовления и использования проектируемой системы 144
- •12.3. Выводы 151
- •7. Работа с сетью Кохонена. 170
- •Введение
- •Глава 1. Введение в искусственные нейронные сети
- •1.1. Проблемы, решаемые в контексте инс
- •1.2. Краткий исторический обзор
- •1.3. Модель технического нейрона
- •Математическая модель нейрона:
- •1.4. Архитектура нейронной сети
- •1.5. Обучение нейронных сетей
- •1.6. Многослойные сети прямого распространения
- •1.6.1. Многослойный персептрон
- •1.6.3. Нерешенные проблемы
- •1.7. Самоорганизующиеся карты Кохонена
- •1.8. Модели теории адаптивного резонанса
- •1.9. Сеть Хопфилда
- •1.9.1 Ассоциативная память
- •1.9.2. Минимизация энергии
- •Глава 2. Основные функциональные возможности программ моделирования нейронных сетей
- •2.1. Формирование (создание) нейронной сети.
- •2.2. Обучение нейронной сети
- •2.3. Имитация функционирования (тестирование) обученной нейронной сети
- •Глава 3. Персептроны
- •3.1. Однослойный персептрон
- •3.2. Многослойный персептрон
- •3.2.1. Архитектура сети
- •3.2.2. Алгоритм обратного распространения
- •3.2.3. Модификации алгоритма обратного распространения и rprop-алгоритма
- •3.3. Применение многослойных персептронов
- •3.3.1. Решение конкретных задач
- •3.3.2. Естественные координаты
- •3.3.3. Репликативные нейронные сети
- •3.3.4. Практическое использование репликативных нейронных сетей
- •Глава 4. Сети Кохонена
- •4.1. Основной принцип работы сети Кохонена
- •4.2. Сходимость алгоритма самообучения
- •Глава 5. Сети радиальных базисных функций
- •5.1. Архитектура сетей
- •5.2. Интерполяция при помощи центральных функций
- •5.3. Интерполяция с помощью центральных функций и полиномов
- •5.4. Аппроксимация с помощью центральных функций
- •5.5. Вариационное исчисление для решения проблемы аппроксимации с помощью rbf-сетей
- •5.6. Расширение на случай многих функций
- •5.7. Расширение линейной частью
- •5.9. Итеративное дополнительное обучение rbf- и hbf-сетей
- •5.10. Выбор центров и радиусов в rbf-сетях
- •5.10.1. Итеративный алгоритм кластеризации
- •5.10.2. Выбор параметра
- •5.10.3. Расчет выходной весовой матрицы c
- •Глава 6. Нейронные сети и генетические алгоритмы
- •6.1. Эволюция как способ оптимизации.
- •6.2 Генетические алгоритмы
- •6.3. Нейро-генетические способы
- •Глава 7. Система моделирования нейронных сетей Trajan 2.0
- •7.1. Создание сети и обучающей последовательности
- •7.1.1. Создание сети
- •7.1.2. Количество и размерность слоев в сети
- •7.1.3. Создание обучающей последовательности
- •7.1.4. Редактирование набора образцов
- •7.2. Обучение сети
- •7.2.1. Типы сетей
- •7.2.2. Создание обучающей и проверочной последовательностей образов
- •7.2.3. Создание сокращенной обучающей последовательности
- •7.2.4. Визуализация процесса обучения
- •7.2.5. Оптимизация процесса обучения
- •7.2.6. Обучение с перекрестной проверкой
- •7.3. Работа с сетью
- •7.3.1. Возможности сети по работе с образцами
- •7.3.2. Интерпретация классификации
- •7.3.3. Работа с сетью Кохонена.
- •7.4. Генетический алгоритм выбора входных атрибутов
- •7.5. Сохранение результатов работы
- •Глава 8. Экспериментальное исследование эффективности применения нейронных сетей
- •Глава 9. Методика представления, архивирования и обработки обучающей последовательности для алгоритмов обучения нейросетей
- •Глава 10. Возможности использования среды www для дистанционного обучения
- •Глава 11. Создание программ для среды www
- •Глава 12. Технико-экономический анализ и обоснование разработки адаптивного обучающего и контролирующего курсов по нейросетям
- •12.1. Обоснование выбора темы и области применения разработки
- •12.2. Оценка ожидаемой экономической целесообразности разработки, изготовления и использования проектируемой системы
- •12.2.1. Расчет затрат на разрабоку и изготовление предлагаемого курса
- •12.2.2. Расчет экономического эффекта от создания и использования обучающего курса
- •12.3. Выводы
- •Глава 13. Обучение контролирующей системы
- •Глава 14. Дистанционный обучающий и контролирующий курс
- •Содержание обучающего курса
- •Заключение
- •Литература
- •Приложение 1. Лабораторная работа «Кластеризация образов с помощью системы моделирования нейросетей Trajan 2.1»
- •1. Цель работы
- •2. Знания и умения, формируемые данной лабораторной работой
- •3. Постановка задачи
- •4. Принципиальные особенности сетей Кохонена.
- •5. Создание сети Кохонена
- •6. Обучение сети Кохонена
- •7. Работа с сетью Кохонена.
- •8. Задание
- •9. Контрольные вопросы
- •Приложение 2. Вопросы контролирующего курса.
- •Приложение 3. Обучающие последовательности для контролирующей системы
- •Приложение 4. Листинг контролирующей программы.
Глава 11. Создание программ для среды www
В настоящее время существуют две возможности для написания программ в Internet: программа может исполняться на сервере или же на клиентской машине (часто эти два способа комбинируются). Оба способа имеют свои достоинства и недостатки. Основным недостатком второго подхода является то, что результаты выполнения проверок невозможно регистрировать централизованно. В связи с этим программы обучения обязательно должны иметь серверную часть.
В случае необходимости можно добавить также программы, выполняемые на клиентской машине. Обычно эти программы разрабатываются с использованием языков Java, JavaScript или Visual Basic (ActiveX). Последняя технология поддерживается пока только продуктом Internet Explorer фирмы Microsoft. JavaScript в версии 1.2 на сегодня поддерживается программой Communicator фирмы Netscape (версия 1.1 поддерживается многими программами), а технология Java 1.1 хоть и претендует на стандарт, но фирмы-разработчики (в частности, Microsoft) стремятся расширить возможности языка, что может привести к несовместимости.
Из всего этого следует, что к написанию клиентских программ следует относиться с осторожностью – если программа работает в Вашей программе просмотра, не обязательно она будет работать и во всех остальных.
Серверные программы избавлены от несовместимости. Для нормального функционирования серверных программ часто необходима всего лишь поддержка клиентом стандарта HTML v.3, а эта возможность имеется в большинстве программ (включая и российские разработки, например, Ariadna).
Способ написания серверной программы зависит от платформы сервера. Например, на многих UNIX-платформах выбор ограничен программами CGI (Common Gateway Interface), которые пишутся обычно на языке C (или C++) или же на пакетных языках типа Perl. На многих рабочих станциях теперь функционирует также и язык Java.
В случае, когда используется сервер Netscape Fast Track возможна также поддержка NSAPI. Похожая технология применяется и в серверах Microsoft (IIS – Internet Information Server и персональный Web-сервер) – ISAPI. Смысл подобных расширений заключается в том, что код содержится в памяти в одном экземпляре (в виде динамически загружаемой библиотеки) в отличие от программ CGI, когда для каждого нового пользователя создается новая среда функционирования копии программы. Следует отметить, что программы CGI пишутся как консольные приложения, причем в режиме стандартного вывода они выводят содержимое гипертекстового файла.
В качестве примера программы, выполняемой на клиентской машине в проекте предлагается Java-апплет, иллюстрирующий работу самоорганизующихся карт Кохонена. Апплет позволяет изменять характеристики сети Кохонена и наблюдать за процессом автоматической классификации (кластеризации) образов. В данном случае сеть переводит 3-х мерное цветное RGB изображение на 2-х мерную сетку.
На рис. 1 изображено как выглядит окно броузера после входа на страницу с апплетом.
Рис. 1. Апплет, демонстрирующий работу самоорганизующихся карт Кохонена.
Здесь каждая ячейка сетки отображает один элемент (нейрон) нейронной сети. Круг отмечает нейроны-"победители". Цвет (состоящий из трех оттенков: красный, зеленый, синий) представляется в сети в виде числового вектора. При инициализации сети цвет ячеек выбирается случайным образом – эти значения и являются входным значением сети. Используя сигмоидальную функцию сеть Кохонена располагает похожие элементы рядом и подстраивает веса. Таким образом, апплет демострирует визуальное изображение топологической карты.
Алгоритм работы апплета аналогичен алгоритму Кохонена.
Нажатие на кнопку Start запускает процесс настройки карт. Остановить работу сети можно кнопкой Stop. Кнопка Reset предназначена для сброса всех характеристик сети и задания нового набора образов для работы сети (рис. 1).
Апплет позволяет менять различные характеристики сети и наблюдать происходящие изменения. Параметр Radius задает размер окрестности соседства и практически означает: сколько соседних элементов-клеток вокруг нейрона-"победителя" будут изменены (т. е. подстроены их веса). Изменение цвета ячеек сетки означает изменение значения "весов" элемента. Можно изменить окрестность соседства, выбрав определенный радиус в окне Radius, чем он больше тем больше будет подстраиваться. Также предоставляется возможность изменить скорость работы сети, при низкой скорости Slow можно пронаблюдать какие именно элементы изменяются, при высокой скорости Fast изменение сети и образование кластеров происходит более наглядно. Все эти настройки можно менять во время работы сети, не сбрасывая значения подстроенных весов. Для этого надо остановить работу сети, изменить ее характеристики и снова нажать кнопку Start.
Н
а
рис. 2 видно как сформировались кластеры
при различных значениях радиуса
окрестности.
Рис. 2. Сети Кохонена с сформированными кластерами.
Далее приведен текст апплета.
Листинг апплета sofm.java.
import java.awt.*;
import java.applet.*;
import java.util.*;
class synapse {
// this class models a weighted connection to a cell
double weight;
static double sharpness = 2.0; // higher values give sharper cutoff
cell c;
public static double sigmoid(double x) {
return 1.0 / (1.0 + Math.exp(-x));
}
public synapse(cell c, double dist) {
weight = 0.2 * sigmoid((sofm.limit - sharpness*dist)/sharpness);
// weight = 0.2 / (1.0 + dist); // use simple function
this.c = c;
}
public void update(double[] v, Graphics g) {
c.update(v, map.rate*weight, g);
}
}
class cell {
// has three basic properties: a grid position (gridv)
// an input space position (ipv)
// and a set of neighbours
double[] gridv;
double[] ipv;
int d;
static int neighboursEstimate = 30; // a rough estimate of number of neighbours - will grow automatically if needed to
Vector neighbours;
public cell(int d, int x, int y) {
// construct a cell with a d-dimensional randomly initialised vector at
// point x,y on the grid
ipv = new double[d];
gridv = new double[2];
gridv[0] = (double) x;
gridv[1] = (double) y;
this.d = d;
randCell();
neighbours = new Vector(neighboursEstimate);
}
public void randCell() {
for (int i=0; i<d; i++)
ipv[i] = Math.random();
}
public void addNeighbour(cell c) {
neighbours.addElement(new synapse(c, dist(gridv, c.gridv)));
}
public void removeNeighbours() {
neighbours.removeAllElements();
}
public void updateNeighbours(double[] v, Graphics g) {
// iterate over set of neighbours updating them
// in proportion to the connection weight
// now clearly identify the winner i.e. this cell
g.setColor(map.v2c(v));
g.fillOval((int)gridv[0]*map.size, (int)gridv[1]*map.size, map.size, map.size);
g.setColor(Color.black);
g.drawOval(1+(int)gridv[0]*map.size, 1+(int)gridv[1]*map.size, map.size-2, map.size-2);
try {Thread.sleep(100); }
catch (Exception e) {}
for (Enumeration e = neighbours.elements(); e.hasMoreElements(); )
((synapse) e.nextElement()).update(v, g);
}
public void update(double[] v, double w, Graphics g) {
// updates the vector of this cell using a weighted average
// of the current cell vector (ipv) and v
for (int i=0; i<d; i++) {
ipv[i] = (1.0 - w) * ipv[i] + w * v[i];
g.setColor(map.v2c(ipv));
g.fillRect((int)gridv[0]*map.size, (int)gridv[1]*map.size, map.size, map.size);
}
}
public static double sqr (double x) {
return x * x;
}
public static double dist(double[] x, double[] y) {
double dis = 0.0;
for (int i=0; i<x.length; i++)
dis += sqr(x[i] - y[i]);
return Math.sqrt(dis);
}
public double dist(double[] v) {
return dist(ipv, v);
}
}
class map {
// this class is to model the 2-d map with the underlying vectors
// can be set up to be a grid, each with a random neuron
// then each time, update it according to the chosen input vector
// this follows the cycle of pick winner, update neighbours
// (each cell includes itself in its set of neighbours)
int d; // the number of dimensions in input
int n; // the number of points on the grid
// cell[][] points;
static int size = 40; // number of pixels to use for each cell when drawing it
static double rate;
static double decayFac = 0.99; // no weight decay at present
Vector cells;
public map(int d, int n) {
this.n = n;
this.d = d;
cells = new Vector(n*n);
rate = 1.0;
makeMap();
setNeighbours();
}
public void makeMap() {
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
cells.addElement(new cell(d, i, j));
}
public void reset() {
rate = 1.0;
for (Enumeration e = cells.elements(); e.hasMoreElements();)
((cell) e.nextElement()).randCell();
}
public void setNeighbours() {
for (Enumeration e = cells.elements(); e.hasMoreElements();)
cellNeighbours((cell) e.nextElement());
}
public void cellNeighbours(cell c) {
c.removeNeighbours();
for (Enumeration e = cells.elements(); e.hasMoreElements();) {
cell cand = (cell) e.nextElement(); // cand is current candidate
if (cell.dist(c.gridv, cand.gridv) < sofm.limit)
c.addNeighbour(cand);
}
}
public cell getWinner(double[] v) {
double minDist = 100000.0; // choose this to be much bigger than a feasible distance
cell choice = null;
for (Enumeration e = cells.elements(); e.hasMoreElements();) {
cell cand = (cell) e.nextElement(); // cand is current candidate
double curDist = cand.dist(v);
if (curDist < minDist) {
choice = cand;
minDist = curDist;
}
}
return choice;
}
public void updateMap(Color c, Graphics g) {
update(c2v(c), g); // convert the colour to a vector
}
public void update(double[] v, Graphics g) {
cell winner = getWinner(v);
winner.updateNeighbours(v, g); // query this
rate *= decayFac;
}
public static double[] c2v(Color c) {
double[] v = new double[3];
v[0] = (double) c.getRed() / 255.0;
v[1] = (double) c.getGreen() / 255.0;
v[2] = (double) c.getBlue() / 255.0;
return v;
}
public static Color v2c(double[] v) {
return new Color((float) v[0], (float) v[1], (float) v[2]);
}
public void paint(Graphics g) {
for (Enumeration e = cells.elements(); e.hasMoreElements();) {
cell c = (cell) e.nextElement();
g.setColor(v2c(c.ipv));
g.fillRect((int)c.gridv[0]*size, (int)c.gridv[1]*size, size, size);
}
}
}
public class sofm extends Applet implements Runnable {
map sorg;
Thread animator;
int nCols = 8;
Color[] cols = new Color[8];
static double limit=5.0;
int sleepTime = 10;
Button start, stop, reset;
Choice neighbourhood, decay, speed; // decay not used
Panel buttons;
public void init() {
setControlPanel();
initColors();
sorg = new map(3,10);
animator = new Thread(this);
animator.start();
}
public void setControlPanel() {
setLayout(new BorderLayout());
buttons = new Panel();
start = new Button("start");
stop = new Button("stop");
reset = new Button("reset");
neighbourhood = new Choice();
neighbourhood.addItem("1.0");
neighbourhood.addItem("2.0");
neighbourhood.addItem("3.0");
neighbourhood.addItem("5.0");
neighbourhood.addItem("7.0");
neighbourhood.addItem("10.0");
neighbourhood.select("5.0");
speed = new Choice();
speed.addItem("fast");
speed.addItem("slow");
speed.select("fast");
buttons.add(new Label("Radius"));
buttons.add(neighbourhood);
buttons.add(start);
buttons.add(stop);
buttons.add(reset);
buttons.add(speed);
add("South", buttons);
}
public void initColors() {
cols[0] = Color.red;
cols[1] = Color.blue;
cols[2] = Color.green;
cols[3] = Color.white;
cols[4] = Color.black;
cols[5] = Color.magenta;
cols[6] = Color.pink;
cols[7] = Color.yellow;
}
public static int randInt(int range) {
return (int) (Math.random() * (double) range);
}
public void paint(Graphics g) {
validate();
sorg.paint(g);
}
public boolean handleEvent(Event event) {
// use 1.0 event model for maxmimum browser compatibilty
if (event.id == Event.ACTION_EVENT) {
if (event.target == start) {
// System.out.println("start");
animator.resume();
return true;
}
if (event.target == stop) {
animator.suspend();
return true;
}
if (event.target == reset) {
sorg.reset();
repaint();
return true;
}
if (event.target == speed) {
String s = speed.getSelectedItem();
if (s.equals("slow"))
sleepTime = 1000;
else
sleepTime = 10;
return true;
}
if (event.target == neighbourhood) {
limit = new Double(neighbourhood.getSelectedItem()).doubleValue();
// System.out.println(limit);
sorg.setNeighbours();
return true;
}
}
return super.handleEvent(event);
}
public void run() {
sorg.paint(getGraphics());
while(true) {
Color current = cols[randInt(nCols)];
Graphics g = getGraphics();
g.setColor(current);
g.fillRect(180, 410, 40, 30);
sorg.updateMap(current, g);
try { Thread.sleep(sleepTime); }
catch (Exception e) {
System.out.println(e);
}
}
}
}
В данном проекте для проведения контроля знаний применяется программа CGI созданная в среде Delphi, использующая обученную нейронную сеть для принятия решений.
В разделе описания обучающего и котролирующего курсов приведен интерфейс программы и результаты ее исполнения.
Ознакомиться с работой программы можно по адресу http:\\158.250.47.76\index.html.
Далее приведен алгоритм работы программы.
Рис. 3. Схема алгоритма работы контролирующей программы.