close

Вход

Забыли?

вход по аккаунту

?

ИТиПЗ (ДД)

код для вставкиСкачать
Министерство образования и науки РФ
Федеральное государственное бюджетное образовательное учреждение
высшего профессионального образования
«Ижевский государственный технический университет
имени М. Т. Калашникова»
Кафедра «Мехатронные системы»
Отчет по курсовой работе
Дисциплина: «Интеллектуальные технологии
и представление знаний»
Тема: «Разработка искусственной нейронной сети для
прогнозирования курса доллара»
Выполнил: студент гр. 7-05-3
Шкляев Р.М.
Проверил: ст. преподаватель
Синицын А.Н.
Ижевск 2012
Содержание
Задание
3
Введение
3
1. Реализация нейронной сети и ее обучение
4
2. Разработка алгоритма
7
3. Разработка программы
10
4. Вычислительный эксперимент
11
Заключение
13
Список литературы
13
Приложение А. Текст программы
14
Приложение Б. Руководство пользователя
32
Приложение В. Руководство программиста
33
2
ЗАДАНИЕ
Разработать алгоритм и программу для прогнозирования курса доллара
с использованием нейронной сети.
ВВЕДЕНИЕ
Данная курсовая работа состоит из четырёх разделов и трёх
приложений, на 33 страницах. В ней приведены:
– схемы алгоритмов программы;
–текст программы;
–вычислительные эксперименты.
Разработанная программа для прогнозирования курса доллара
реализовывается на универсальной ЭВМ. Для корректной работы этой
программы необходимо иметь операционную систему Windows XP (SP 23)/Vista (SP 1)/ Windows 7. Программа разработана в среде разработки
программного обеспечения Microsoft Visual Studio 2010.
Целью данной работы является разработка искусственной нейронной
сети.
Искусственные нейронные сети (НС) — совокупность моделей
биологических нейронных сетей. Представляют собой сеть элементов —
искусственных нейронов — связанных между собой синоптическими
соединениями. Сеть обрабатывает входную информацию и в процессе
изменения своего состояния во времени формирует совокупность выходных
сигналов.
Большинство моделей НС требуют обучения. В общем случае,
обучение — такой выбор параметров сети, при котором сеть лучше всего
справляется с поставленной проблемой.
3
1 РЕАЛИЗАЦИЯ НЕЙРОННОЙ СЕТИ И ЕЕ ОБУЧЕНИЕ
Каждый нейрон в сети состоит из взвешенного сумматора и
нелинейного элемента (рисунок 1).
Рисунок 1 – Формальный нейрон
Функционирование нейрона определяется формулами:
(1)
(2)
где — входные сигналы, совокупность всех входных сигналов нейрона
образует вектор x;
— весовые коэффициенты, совокупность весовых коэффициентов образует
вектор весов w;
— взвешенная сумма входных сигналов, значение NET передается на
нелинейный элемент;
— пороговый уровень данного нейрона;
— нелинейная функция, называемая функцией активации.
Нейрон имеет несколько входных сигналов x и один выходной сигнал
OUT. Параметрами нейрона, определяющими его работу, являются: вектор
весов w, пороговый уровень θ и вид функции активации F.
Среди различных структур нейронных сетей (НС) одной из наиболее
известных является многослойная структура, в которой каждый нейрон
произвольного слоя связан со всеми аксонами нейронов предыдущего слоя
или, в случае первого слоя, со всеми входами НС. Такие НС называются
полносвязными. В многослойных же сетях оптимальные выходные значения
нейронов всех слоев, кроме последнего, как правило, не известны, и двух или
более слойный перцептрон уже невозможно обучить, руководствуясь только
величинами ошибок на выходах НС. Один из вариантов решения этой
проблемы –распространение сигналов ошибки от выходов НС к ее входам, в
направлении, обратном прямому распространению сигналов в обычном
режиме работы. Этот алгоритм обучения НС получил название процедуры
обратного распространения.
Согласно методу наименьших квадратов, минимизируемой целевой
функцией ошибки НС является величина:
E ( w) 1
( y (j ,Np) d j , p ) 2
2 j,p
(3)
где y (j ,Np) – реальное выходное состояние нейрона j выходного слоя N
нейронной сети при подаче на ее входы p-го образа; djp – идеальное
(желаемое) выходное состояние этого нейрона.
4
Суммирование ведется по всем нейронам выходного слоя и по всем
обрабатываемым сетью образам. Минимизация ведется методом
градиентного спуска, что означает подстройку весовых коэффициентов
следующим образом:
wij( n ) E
wij
(4)
Здесь wij – весовой коэффициент синаптической связи, соединяющей iый нейрон слоя n-1 с j-ым нейроном слоя n, – коэффициент скорости
обучения, 0<<1.
Как показано в [4],
E
E dy j s j
wij y j ds j wij
(5)
Здесь под yj, как и раньше, подразумевается выход нейрона j, а под sj –
взвешенная сумма его входных сигналов, то есть аргумент активационной
функции. Так как множитель dyj/dsj является производной этой функции по
ее аргументу, из этого следует, что производная активационной функция
должна быть определена на всей оси абсцисс. В случае сигмоиды
dy
s (1 s)
ds
(6)
E
E dyk sk
E dyk ( n1)
w jk
y j
dsk y j k yk dsk
k y k
(7)
Третий множитель sj/wij, очевидно, равен выходу нейрона
предыдущего слоя yi(n-1).
Что касается первого множителя в (5), он легко раскладывается
следующим образом:
Здесь суммирование по k выполняется среди нейронов слоя n+1.
Введя новую переменную
(jn ) E dy j
y j ds j
(8)
мы получим рекурсивную формулу для расчетов величин j(n) слоя n из
величин k(n+1) более старшего слоя n+1.
dy
(jn) (kn1) w(jkn1) j
ds
k
(9)
j
Для выходного же слоя
(l N ) ( yl( N ) d l ) dyl
dsl
(10)
Теперь мы можем записать (4) в раскрытом виде:
wij( n) (jn) yi( n1)
(11)
5
Иногда для придания процессу коррекции весов некоторой
инерционности, сглаживающей резкие скачки при перемещении по
поверхности целевой функции, (11) дополняется значением изменения веса
на предыдущей итерации
(12)
wij( n) (t ) ( wij( n) (t 1) (1 ) (jn) yi( n1) )
где – коэффициент инерционности, t – номер текущей итерации.
Таким образом, полный алгоритм обучения НС с помощью процедуры
обратного распространения строится так:
1. Подать на входы сети один из возможных образов и в режиме
обычного функционирования НС, когда сигналы распространяются от входов
к выходам, рассчитать значения последних. Напомним, что
M
s(j n ) yi( n1) wij( n )
(13)
i0
где M – число нейронов в слое n-1 с учетом нейрона с постоянным
выходным состоянием +1, задающего смещение; yi(n-1)=xij(n) – i-ый вход
нейрона j слоя n.
yj(n) = f(sj(n)), где f() – сигмоид
(14)
(0)
yq =Iq,
(15)
где Iq – q-ая компонента вектора входного образа.
2. Рассчитать (N) для выходного слоя по формуле (8).
Рассчитать по формуле (11) или (12) изменения весов w(N) слоя N.
3. Рассчитать по формулам (9) и (11) (или (9) и (12)) соответственно (n)
и w(n) для всех остальных слоев, n=N-1,...1.
4. Скорректировать все веса в НС
(16)
wij( n) (t ) wij( n) (t 1) wij( n) (t )
5. Если ошибка сети существенна, перейти на шаг 1. В противном случае
– конец.
Из выражения (11) следует, что когда выходное значение yi(n-1) стремится
к нулю, эффективность обучения заметно снижается.
6
2 РАЗРАБОТКА АЛГОРИТМА
В данном разделе приведены общая схема алгоритма прогнозирования
курса доллара с использованием искусственной нейронной сети и алгоритм
обучения нейронной сети.
Общая схема алгоритма представлена на рисунке 2.
Начало
Ввод данных
Обучение ИНС
Прогнозирование
Конец
Рисунок 2 – Схема алгоритма программы прогнозирования курса доллара
7
На рисунке 3 представлена схема алгоритма обучения ИНС
Начало
Ввод
тренировочных
данных
Ввод случайных
малых весовых
коэффициентов
Нахождение суммы и
решение функции
активации каждого
нейрона
Нахождение ошибки δ для
каждого нейрона
Вычисление новых
весовых коэффициентов с
учетом δ
Да
Нажата кнопка
«обучить сеть»?
Нет
Конец
Рисунок 3 – Схема алгоритма обучения ИНС
8
На рисунке 4 представлена схема алгоритма прогнозирования курса
доллара
Начало
Ввод
Экзаменационных
данных
Вычисление
активационной функции
Вычисление прогноза
Конец
Рисунок 4 – Схема алгоритма прогнозирования курса доллара ИНС
9
3 РАЗРАБОТКА ПРОГРАММЫ
В соответствии со схемой алгоритма программы написана программа,
которая прогнозирует курс доллара.
Программа написана на языке программирования C#, с помощью среды
разработки Microsoft Visual Studio 2010.
C# относится к семье языков с C-подобным синтаксисом, из них его
синтаксис наиболее близок к C++ и Java. Язык имеет строгую статическую
типизацию, поддерживает полиморфизм, перегрузку операторов, указатели
на функции-члены классов, атрибуты, события, свойства, исключения,
комментарии в формате XML. Переняв многое от своих предшественников
— языков C++, Delphi, Modula и Smalltalk — С#, опираясь на практику их
использования, исключает некоторые модели, зарекомендовавшие себя как
проблематичные при разработке программных систем: так, C# не
поддерживает множественное наследование классов (в отличие от C++).
Текст программы прогнозирования курса доллара приведен в
приложении А.
10
4 ВЫЧИСЛИТЕЛЬНЫЙ ЭКСПЕРИМЕНТ
Для выполнения вычислительного эксперимента запускаем
скомпилированный EXE файл или запускаем программу в среде разработки
Microsoft Visual Studio 2010.
1. Загружаются обучающие данные. Каждая строка в документе – одна
обучающая выборка. Значения в первой выборке - данные курса доллара в 2004
году в период 1.12-25.12. Последующие выборки с теми же датами, но каждая
следующая на год больше.
2. Вводится количество нейронов в слоях (через пробел), количество
чисел в поле равно количеству слоев в сети.
3. Обучаем сеть.
4. Загружаются данные для непосредственного прогнозирования. Данные
курса доллара за 2012 год в период 01.12-24.12.
5. Получение прогноза на 25.12.2012.
Результаты работы программы изображены на рисунках 5,6.
Рисунок 5 – Тестирование программы. Загрузка данных обучения и создание
сети.
11
Рисунок 6 – Тестирование программы. Обучение, загрузка экзаменационной
выборки, получение прогноза.
Значение прогноза (выхода сети) получилось равное 0,431. Это близко
к 0, следовательно, скорее всего курс доллара 25.12.2012 понизится,
относительно 24.12.2012. В случае, когда прогноз получается близкий к 1,
курс доллара, скорее всего, повысится.
12
ЗАКЛЮЧЕНИЕ
Разработанная программа распознавания возраста по фотографии
реализовывается на универсальной ЭВМ. Для корректной работы этой
программы необходимо иметь операционную систему Windows XP (SP 23)/Vista (SP 1)/ Windows 7. Программа разработана в среде разработки
программного обеспечения Microsoft Visual Studio 2010.
При выполнении курсовой работы были разработаны:
общая схема алгоритма программы;
схема алгоритма обучения;
схема алгоритма прогнозирования;
текст программы.
Разработанная программа работает правильно, что подтверждается
результатами вычислительных экспериментов.
СПИСОК ЛИТЕРАТУРЫ
1. Хайкин С. Нейронные сети: полный курс.– Изд.: Вильямс, 2006 –
1104с.
2. В.В.Круглов, В.В.Борисов. Искусственные нейронные сети. Теория и
практика – Изд.: Горячая Линия - Телеком, 2001 г. – 386с.
13
ПРИЛОЖЕНИЕ А. ТЕКСТ ПРОГРАММЫ
В данном приложении представлена программа прогнозирования курса
доллара.
На рисунке ПА.1 представлено содержание файла Form1.cs.
using
using
using
using
using
using
using
using
using
using
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Text;
System.Windows.Forms;
System.IO;
System.Runtime.Serialization;
System.Runtime.Serialization.Formatters.Binary;
namespace NeuralNetPropagation
{
public partial class Form2 : Form
{
// глобальная константа для заголовков окна и сообщений
public static string FormCaption = "Прогнозирование курса доллара";
// экземпляр класса, выполняющего чтение данных в файл
private TextDataEngine textDataEngine;
// Переменные для хранения числа обучающих выборок, чисел нейронов в слоях, числа данных
для экз. выборки
private int nLearnCount, nDataCount, nExamDataCount;
private int[] nNeuroCount;
// массив загрузки обучающих данных
private short[,] pressureArray;
// массив загрузки экзам. данных
private short[] pressureExamArray;
// Переменная для хранения скорости обучения
private double dLearnSpeed;
// Счетчик текущей итерации обучения
private int learns=0;
// была ли создана сеть для сохранения
bool canSave = false;
// Объект нейросети
private NeuralNet NN;
public Form2()
{
InitializeComponent();
this.Text = FormCaption;
// Создание экземпляров классов работы с данными внешних файлов
textDataEngine = new TextDataEngine();
// Задание параметров окна выбора чтения/сохранения параметров сети
openFileNetDialog.Filter = saveFileNetDialog.Filter = "Файлы хранения
состояния сети (*.net)|*.net";
openFileNetDialog.DefaultExt = saveFileNetDialog.DefaultExt = "net";
Рисунок ПА.1 – Содержание файла Form1.cs
14
// Если в системе доступен MS Excel, сделать возможность выбора файлов .xls
{
openFileDialog.Filter = "Текстовые файлы (разделители - точка
с запятой)(*.txt)|*.txt|";
}
// иначе только текстовые файлы с разделителями .csv
{
openFileDialog.Filter = "Текстовые файлы (разделители - точка
с запятой)(*.txt)|*.txt";
}
// По умолчанию - csv
openFileDialog.DefaultExt = "txt";
}
// Кнопка выбора файла данных для обучения
private void srcFileDlgBtn_MouseClick(object sender, MouseEventArgs e)
{
DialogResult res = openFileDialog.ShowDialog();
if (res == DialogResult.OK)
{
// Если указано имя файла то подразумеваем новые данные и очищаем поля на форме
learnCount.Text = dataLineCount.Text = "";
dataCount.Text = "";
logBox.Clear();
currentIteration.Text = "";
// получаем имя файла из диалога выбора имени файла
srcFilePath.Text = openFileDialog.FileName;
}
}
// Кнопка Загрузить данные
private void btnDataLoad_MouseClick(object sender, MouseEventArgs e)
{
// проверка на указание имени исходного файла
if (srcFilePath.Text == "")
{
MessageBox.Show("Не указан файл с исходными данными!",
FormCaption);
return;
}
try
{
// попытка прочитать введенные размеры массива обучающих данных
if (dataLineCount.Text == "")
nLearnCount = 0;
else
nLearnCount = int.Parse(dataLineCount.Text);
if (dataCount.Text == "")
nDataCount = 0;
else
nDataCount = int.Parse(dataCount.Text);
}
Рисунок ПА.1 – Продолжение
15
catch (System.FormatException)
{
MessageBox.Show("Неверно указаны параметры загрузки данных",
FormCaption);
return;
}
this.Cursor = Cursors.WaitCursor;
// выбор, из какого типа файлов грузятся данные
textDataEngine.srcFileName = srcFilePath.Text;
// передаем параметры загрузки данных
textDataEngine.nDataLineCount = nLearnCount;
textDataEngine.nDataCount = nDataCount;
// делаем попытку загрузить данные
if (!textDataEngine.LoadData())
{
this.Cursor = Cursors.Default;
return;
}
// получаем количество обучающих выборок, количество данных в выборке, данные выборок
nLearnCount = textDataEngine.nDataLineCount;
nDataCount = textDataEngine.nDataCount;
pressureArray = textDataEngine.pressureArray;
}
this.Cursor = Cursors.Default;
// отображаем на форме число загруженных выборок и количество данных в выборках
learnCount.Text = dataLineCount.Text = nLearnCount.ToString();
dataCount.Text = nDataCount.ToString();
MessageBox.Show("Данные загружены", FormCaption);
}
// Кнопка Создать сеть
private void button5_MouseClick(object sender, MouseEventArgs e)
{
logBox.Clear();
currentIteration.Text = "";
learns = 0;
try
{
// для создания сети должен быть хотя бы один вход и один выход
if ( nDataCount < 2 )
{
MessageBox.Show("Недостаточно входных данных для
создания сети", FormCaption);
return;
}
// попытка прочитать число слоев и нейронов в них
string[] strValues = neuroCount.Text.Split(' ');
nNeuroCount = new int[strValues.Length];
for (int i = 0; i < strValues.Length; i++)
{
nNeuroCount[i] = int.Parse(strValues[i]);
if (nNeuroCount[i] == 0)
throw new System.FormatException();
}
Рисунок ПА.1 – Продолжение
16
// Создать сеть с sizeX входами и двумя слоями
int sizeX = nDataCount-1;
NN = new NeuralNet(sizeX, nNeuroCount);
}
catch (System.FormatException)
{
MessageBox.Show("Неверно указаны параметры создания сети",
FormCaption);
return;
}
string strNNCreated = "Создана сеть:" + Environment.NewLine+
"Количество входов - " +
NN.GetX.ToString() + Environment.NewLine+
"Количество слоев - " +
nNeuroCount.Length.ToString() + Environment.NewLine +
"Количество нейронов в слоях
- " + neuroCount.Text + Environment.NewLine +
"Количество выходов - " +
NN.GetY.ToString();
MessageBox.Show(strNNCreated, FormCaption);
// установить флаг возможности сохранения данных сети
canSave = true;
}
// Кнопка Обучить сеть
private void button1_MouseClick(object sender, MouseEventArgs e)
{
try
{
// попытка прочитать коэффициент скорости обучения
dLearnSpeed = Double.Parse(learnSpeed.Text);
if (dLearnSpeed == 0)
throw new System.FormatException();
}
catch (System.FormatException)
{
MessageBox.Show("Неверно указаны параметры обучения сети",
FormCaption);
return;
}
this.Cursor = Cursors.WaitCursor;
if (learns == nLearnCount)
learns = 0;
// очищаем поле протокола обучения
if (learns == 0)
{
logBox.Clear();
currentIteration.Text = "";
}
// цикл по количеству обучающих выборок
for (; learns < nLearnCount;)
{
// счетчик итераций на форме
currentIteration.Text = (learns+1).ToString();
currentIteration.Update();
Рисунок ПА.1 – Продолжение
17
// определяем вектора входов и выходов нейросети
double[] X = new double[NN.GetX];
double[] Y = new double[NN.GetY];
// счетчик данных в загруженном массиве
int arrayIndex = 0;
// предыдущее значение для вычисления приращения
short prevValue = 0;
// считываем из загруженного массива элементы входного вектора
for (int i=0; i < X.Length; i++)
{
// если текущее значение в массиве больше предыдущего (курс растет),
// то вход сети получает значение 1, иначе 0
if (pressureArray[learns, arrayIndex] > prevValue)
X[i] = 1;
else
X[i] = 0;
// значение текущего элемента массива на следующей итерации будет предыдущим
prevValue = pressureArray[learns, arrayIndex];
arrayIndex++;
}
// после считывания данных для входов определяем значение для выхода сети
if (pressureArray[learns, arrayIndex] > prevValue)
Y[0] = 1;
else
Y[0] = 0;
// запуск поцедуры обучения сети на данной итерации
// на выходе outErr - получаем значение ошибки для обучающей пары
double outErr = Math.Round(NN.LearnNet(X, Y, dLearnSpeed),5);
// добавляем строку в поле протокола
logBox.AppendText(outErr.ToString()+ Environment.NewLine );
learns++;
if ( stopIteration.Checked == true )
break;
}
this.Cursor = Cursors.Default;
}
// Кнопка выбора файла данных для прогноза
private void button4_MouseClick(object sender, MouseEventArgs e)
{
DialogResult res = openFileDialog.ShowDialog();
if (res == DialogResult.OK)
{
srcExamFilePath.Text = openFileDialog.FileName;
}
}
// Кнопка Загрузить данные для прогноза
private void button3_MouseClick(object sender, MouseEventArgs e)
{
Рисунок ПА.1 – Продолжение
18
// проверка на указание имени исходного файла
if (srcExamFilePath.Text == "")
{
MessageBox.Show("Не указан файл с данными", FormCaption);
return;
}
try
{
if (examNetX.Text == "")
nExamDataCount = 0;
else
nExamDataCount = int.Parse(examNetX.Text);
}
catch (System.FormatException)
{
MessageBox.Show("Неверно указаны параметры загрузки данных",
FormCaption);
return;
}
this.Cursor = Cursors.WaitCursor;
// выбор, из какого типа файлов грузятся данные
// передаем имя файла с данными в объект работы с данными
textDataEngine.srcFileName = srcExamFilePath.Text;
// передаем параметры загрузки данных
textDataEngine.nDataCount = nExamDataCount;
// делаем попытку загрузить данные
if (!textDataEngine.LoadPropagationData())
{
this.Cursor = Cursors.Default;
return;
}
// получаем количество загруженных данных и массив с данными
nExamDataCount = textDataEngine.nDataCount;
pressureExamArray = textDataEngine.pressureExamArray;
this.Cursor = Cursors.Default;
// отображаем на форме число загруженных данных
examNetX.Text = nExamDataCount.ToString();
MessageBox.Show("Данные загружены", FormCaption);
}
// отображение окна справки
private void Form2_HelpButtonClicked(object sender, CancelEventArgs e)
{
new HelpForm().ShowDialog();
e.Cancel = true;
}
// кнопка Загрузить параметры сети
private void btnLoadNet_MouseClick(object sender, MouseEventArgs e)
{
string netDataOpenFile;
DialogResult res = openFileNetDialog.ShowDialog();
if (res == DialogResult.OK)
{
Рисунок ПА.1 – Продолжение
19
// Получить имя файла с данными
netDataOpenFile = openFileNetDialog.FileName;
}
else
return;
this.Cursor = Cursors.WaitCursor;
// открыть поток чтения файла, получить данные сети
Stream stream;
stream = File.Open(netDataOpenFile, FileMode.Open);
BinaryFormatter formatter = new BinaryFormatter();
// создать сеть из загруженных данных
NN = (NeuralNet)formatter.Deserialize(stream);
stream.Close();
// отобразить параметры загруженной сети
neuroCount.Text = "";
for (int i = 0; i < NN.CountLayers; i++)
{
if (i > 0)
neuroCount.AppendText(" ");
neuroCount.AppendText(NN.Layers[i].countY.ToString());
}
this.Cursor = Cursors.Default;
MessageBox.Show("Чтение завершено");
// Показать состояние загруженной сети
ShowNetStatus();
}
// кнопка Сохранить параметры сети
private void btnSaveNet_MouseClick(object sender, MouseEventArgs e)
{
string netDataSaveFile;
// проверить возможность сохранения данных
if (!canSave)
{
MessageBox.Show("Сеть не была создана, невозможно сохранить",
FormCaption);
return;
}
// Показать состояние сохраняемой сети
ShowNetStatus();
this.Cursor = Cursors.WaitCursor;
DialogResult res = saveFileNetDialog.ShowDialog();
if (res == DialogResult.OK)
{
// Получить имя файла для сохранения данных
netDataSaveFile = saveFileNetDialog.FileName;
}
else
return;
// открыть поток файла сохранения данных
Stream stream = File.Open(netDataSaveFile, FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
Рисунок ПА.1 – Продолжение
20
// выгрузить сеть
formatter.Serialize(stream, NN);
stream.Close();
this.Cursor = Cursors.Default;
MessageBox.Show("Запись завершена");
}
// Получение прогноза
private void button2_MouseClick(object sender, MouseEventArgs e)
{
this.Cursor = Cursors.WaitCursor;
examNetY.Text="";
// вектор входов с экзаменационными данными
double[] X = new double[nExamDataCount];
// вектор, который будет получать данные из сети
double[] Y;
short prevValue = 0;
// считываем из загруженного массива элементы входного вектора
for (int i = 0; i < nExamDataCount; i++)
{
// если текущее значение в массиве больше предыдущего (давление растет),
// то вход сети получает значение 1, иначе 0
if (pressureExamArray[i] > prevValue)
X[i] = 1;
else
X[i] = 0;
// значение текущего элемента массива на следующей итерации будет предыдущим
prevValue = pressureExamArray[i];
}
// вычислить значения выходов сети на основании имеющихся загруженных или обученных
данных
NN.NetOUT(X, out Y);
// отобразить данные в поле на форме
for (int i = 0; i < Y.Length; i++)
{
// Если на выходе сети более одного элемента, и элемент не первый,
// то вставить пробел перед значением выхода
if (i > 0)
examNetY.AppendText(" ");
// для краткости округлить значения до целого числа
double d = Math.Round(Y[i], 3);
// добавить в поле непосредственно само значение
examNetY.AppendText( d.ToString() );
}
this.Cursor = Cursors.Default;
}
Рисунок ПА.1 – Продолжение
21
private void ShowNetStatus()
{
string strNetLayers="";
for (int i = 0; i < NN.CountLayers; i++)
{
if (i > 0)
strNetLayers += " ";
strNetLayers += NN.Layers[i].countY;
}
string strNNStatus = "Состояние сети:" + Environment.NewLine +
"Количество входов - " +
NN.GetX.ToString() + Environment.NewLine +
"Количество слоев - " +
NN.CountLayers.ToString() + Environment.NewLine +
"Количество нейронов в слоях
- " + strNetLayers + Environment.NewLine +
"Количество выходов - " +
NN.GetY.ToString();
MessageBox.Show(strNNStatus, FormCaption);
}
private void srcFilePath_TextChanged(object sender, EventArgs e)
{
}
private void Form2_Load(object sender, EventArgs e)
{
}
}
}
Рисунок ПА.1 – Продолжение
22
На рисунке ПА.2 представлено содержание файла NeuroNet.cs.
using System;
using System.IO;
//using System.Runtime.InteropServices;
namespace NeuralNetPropagation
{
// Класс - слой нейросети
[Serializable()]
public class LayerNW
{
// Массив весов
double[,] Weights;
// число входов и выходов слоя
int cX, cY;
// Заполняем веса случайными числами
public void GenerateWeights()
{
Random rnd = new Random();
for (int i = 0; i < cX; i++)
{
for (int j = 0; j < cY; j++)
{
Weights[i, j] = rnd.NextDouble() - 0.5;
}
}
}
// Конструктор
public
{
cX
cY
с параметрами. передается количество входных и выходных нейронов
LayerNW(int countX, int countY)
= countX;
= countY;
// создать массив весов
Weights = new double[cX, cY];
}
// свойство, возвращает число входов слоя
public int countX
{
get { return cX; }
}
// свойство, возвращает число выходов слоя
public int countY
{
get { return cY; }
}
// свойство, возвращает или устанавливает вес связи
public double this[int row, int col]
{
get { return Weights[row, col]; }
set { Weights[row, col] = value; }
}
}
Рисунок ПА.2 – Cодержание файла NeuroNet.cs
23
// Класс - нейронная сеть
[Serializable()]
public class NeuralNet
{
// Слои НС
public LayerNW[] Layers;
// Число слоев, входов и выходов сети
int countLayers = 0, countX, countY;
// Массив выходов для каждого слоя
double[][] LayerOUT; // LayerOUT[countLayers+1][]
// Дельта - коэффициент изменения весов
double[][] DELTA;
// LayerOUT[countLayers][]
// Конструкторы
/*
* Создает полносвязанную сеть из 1 слоя.
sizeX - размерность вектора входных параметров
sizeY - размерность вектора выходных параметров
*/
public NeuralNet(int sizeX, int sizeY)
{
countLayers = 1;
Layers = new LayerNW[countLayers];
Layers[0] = new LayerNW(sizeX, sizeY);
Layers[0].GenerateWeights();
}
/*
Создает полносвязанную сеть из n слоев.
sizeX - размерность вектора входных параметров
layers - массив слоев. Значение элементов массива - количество нейронов в слое
*/
public NeuralNet(int sizeX, params int[] layers)
{
// число слоев определяется кол-вом элементов массива
countLayers = layers.Length;
// число входов сети
countX = sizeX;
// число выходов сети равно числу нейронов последнего слоя
countY = layers[layers.Length - 1];
// Размерность выходов нейронов и Дельты
LayerOUT = new double[countLayers + 1][];
LayerOUT[0] = new double[sizeX];
DELTA = new double[countLayers][];
// Создаем слои
this.Layers = new LayerNW[countLayers];
int countY1, countX1 = sizeX;
// Устанавливаем размерность слоям и заполняем слоя случайными числами
for (int i = 0; i < countLayers; i++)
{
countY1 = layers[i];
LayerOUT[i + 1] = new double[countY1];
DELTA[i] = new double[countY1];
this.Layers[i] = new LayerNW(countX1, countY1);
this.Layers[i].GenerateWeights();
countX1 = countY1;
}
}
Рисунок ПА.2 – Продолжение
24
// Возвращает значение j-го слоя НС
public void NetOUT(double[] inX, out double[] outY, int jLayer)
{
GetOUT(inX, jLayer);
int N = LayerOUT[jLayer].Length;
outY = new double[N];
for (int i = 0; i < N; i++)
{
outY[i] = LayerOUT[jLayer][i];
}
}
// Возвращает значение НС
public void NetOUT(double[] inX, out double[] outY)
{
int j = countLayers;
NetOUT(inX, out outY, j);
}
// Возвращает ошибку (метод наименьших квадратов)
public double CalcError(double[] X, double[] Y)
{
double kErr = 0;
for (int i = 0; i < Y.Length; i++)
{
kErr += Math.Pow(Y[i] - LayerOUT[countLayers][i], 2);
}
return 0.5 * kErr;
}
/*
* Обучает сеть, изменяя ее весовые коэффициэнты.
X, Y - обучающая пара. kLearn - скорость обучаемости
В качестве результата метод возвращает ошибку 0.5(Y-outY)^2
*/
public double LearnNet(double[] X, double[] Y, double kLearn)
{
double O; // Вход нейрона
double s;
// Вычисляем выход сети
GetOUT(X);
// Заполняем дельта последнего слоя
for (int j = 0; j < Layers[countLayers - 1].countY; j++)
{
O = LayerOUT[countLayers][j];
DELTA[countLayers - 1][j] = (Y[j] - O) * O * (1 - O);
}
Рисунок ПА.2 – Продолжение
25
// Перебираем все слои начиная с последнего
// изменяя веса и вычисляя дельта для скрытого слоя
for (int k = countLayers - 1; k >= 0; k--)
{
// Изменяем веса выходного слоя
for (int j = 0; j < Layers[k].countY; j++)
{
for (int i = 0; i < Layers[k].countX; i++)
{
Layers[k][i, j] += kLearn * DELTA[k][j] *
LayerOUT[k][i];
}
}
if (k > 0)
{
// Вычисляем дельта слоя к-1
for (int j = 0; j < Layers[k - 1].countY; j++)
{
s = 0;
for (int i = 0; i < Layers[k].countY; i++)
{
s += Layers[k][j, i] * DELTA[k][i];
}
DELTA[k - 1][j] = LayerOUT[k][j] * (1 LayerOUT[k][j]) * s;
}
}
}
return CalcError(X, Y);
}
/* Вспомогательные закрытые функции */
// Возвращает все значения нейронов до lastLayer слоя
void GetOUT(double[] inX, int lastLayer)
{
double s;
// Инициализируем выходы "скрытого входного" слоя начальными значениями входов сети
for (int j = 0; j < Layers[0].countX; j++)
LayerOUT[0][j] = inX[j];
for (int i = 0; i < lastLayer; i++)
{
// вычисляем выходы слоев сети
for (int j = 0; j < Layers[i].countY; j++)
{
s = 0;
// суммируем веса связей нейрона текущего слоя с выходами предыдущего слоя
for (int k = 0; k < Layers[i].countX; k++)
{
s += Layers[i][k, j] * LayerOUT[i][k];
}
// Вычисляем значение активационной функции нейрона
s = 1.0 / (1 + Math.Exp(-s/*Коэффициент alpha здесь
равен 1*/));
LayerOUT[i + 1][j] = 0.998 * s + 0.001;
}
}
}
Рисунок ПА.2 – Продолжение
26
// Возвращает все значения нейронов всех слоев
void GetOUT(double[] inX)
{
GetOUT(inX, countLayers);
}
// Свойства.
// Возвращает число входов сети
public int GetX
{
get { return countX; }
}
// Возвращает число выходов сети
public int GetY
{
get { return countY; }
}
// Возвращает число слоев сети
public int CountLayers
{
get { return countLayers; }
}
}
}
Рисунок ПА.2 – Продолжение
27
На рисунке ПА.3 представлено содержание файла TextDataEngine.cs.
using
using
using
using
using
using
System;
System.Collections.Generic;
System.Text;
System.IO;
System.Globalization;
System.Windows.Forms;
namespace NeuralNetPropagation
{
class TextDataEngine
{
// класс, отвечающий за чтение данных из внешнего файла и сохранение данных в файл
// Переменная для хранения имени файла с исходными данными
public string srcFileName = "";
// массив для хранения обучающих данных
public short[,] pressureArray;
// массив для хранения экзаменационных данных
public short[] pressureExamArray;
// Количество загружаемых из файла строк данных и количество значений в строке
public int nDataLineCount;
public int nDataCount;
// конструктор
public TextDataEngine()
{
}
// процедура чтения данных жд обучения из текстового файла
public bool LoadData()
{
// класс .Net, осущестляющий чтение данных из текстового файла
StreamReader sr;
try
{
sr = new StreamReader(srcFileName);
// переменная для сохранения считанной строки
string strData;
if (nDataLineCount == 0 || nDataCount == 0)
{
// счетчики считанных данных
nDataLineCount = nDataCount = 0;
// посчитать сколько данных для обучающих выборок в файле
strData = sr.ReadLine();
while (strData != null)
{
strData = strData.Trim();
// пропускаем пустые строки
if (strData != "")
{
nDataLineCount++;
if (nDataCount == 0)
{
Рисунок ПА.3 – Cодержание файла TextDataEngine.cs
28
// получаем из считанной строки элементы, разделенные запятой или точкой с запятой
string[] strValues =
strData.Split(new Char[] { ',', ';' });
nDataCount = strValues.Length;
}
}
strData = sr.ReadLine();
}
sr.Close();
// если данных не нашлось, выйти с ошибкой
if (nDataLineCount == 0 || nDataCount == 0)
throw new Exception();
// переоткрыть поток
sr = new StreamReader(srcFileName);
}
// создать массив для обучающих выборок
pressureArray = new short[nDataLineCount, nDataCount];
int i=0, j=0;
// чтение очередной строки из исходного файла
strData = sr.ReadLine();
// цикл по строкам исходного файла, пока не будет достигнут конец файла
while (strData != null && i < nDataLineCount )
{
// удаляются пробелы
strData = strData.Trim();
// пропускаем пустые строки
if (strData != "")
{
// получаем из считанной строки элементы, разделенные запятой или точкой с запятой
string[] strValues = strData.Split(new Char[] {
',', ';' });
// цикл по элементам строки
for (j = 0; j < nDataCount; j++)
{
// если количество считанных элементов из строки меньше числа данных в первой строке
(эталон),
// оставшиеся числа будут равны 0
short s;
try
{
// попытка считать из элемента строки число
s = short.Parse(strValues[j]);
}
catch (Exception)
{
// если попытка считать неудачна, то число инициализируется 0-м
s = 0;
}
// запись значения в конкретный элемент массива
pressureArray[i,j]=s;
}
i++;
}
// чтение следующей строки
strData = sr.ReadLine();
}
sr.Close();
Рисунок ПА.3 – Продолжение
29
// в случае успешной обработки возвратить 'true'
return true;
}
catch (Exception)
{
// при возникновении ошибки при обработке файла выдать сообщение и возвратить 'false'
MessageBox.Show("Ошибка при обработке входных данных",
Form2.FormCaption);
return false;
}
}
// процедура чтения экзаменационных данных из текстового файла
public bool LoadPropagationData()
{
// класс .Net, осущестляющий чтение данных из текстового файла
StreamReader sr;
try
{
sr = new StreamReader(srcFileName);
// переменная для сохранения считанной строки
string strData;
if (nDataCount == 0)
{
// посчитать сколько данных в файле
strData = sr.ReadLine();
if (strData != null)
{
strData = strData.Trim();
if (strData != "")
{
// получаем из считанной строки элементы, разделенные запятой или точкой с запятой
string[] strValues = strData.Split(new
Char[] { ',', ';' });
nDataCount = strValues.Length;
}
}
sr.Close();
// если данных не нашлось, выйти с ошибкой
if (nDataCount == 0)
throw new Exception();
}
// переоткрыть поток
sr = new StreamReader(srcFileName);
// создать массив
pressureExamArray = new short[nDataCount];
int j = 0;
// чтение очередной строки из исходного файла
strData = sr.ReadLine();
// цикл по строкам исходного файла, пока не будет достигнут конец файла
if (strData != null)
{
// удаляются пробелы
strData = strData.Trim();
if (strData != "")
{
Рисунок ПА.3 – Продолжение
30
// получаем из считанной строки элементы, разделенные запятой или точкой с запятой
string[] strValues = strData.Split(new Char[] {
',', ';' });
// цикл по элементам строки
for (j = 0; j < nDataCount; j++)
{
// если количество считанных элементов из строки меньше числа данных в первой строке
(эталон),
// оставшиеся числа будут равны 0
short s;
try
{
// попытка считать из элемента строки число
s = short.Parse(strValues[j]);
}
catch (Exception)
{
// если попытка считать неудачна, то число инициализируется 0-м
s = 0;
}
// запись значения в конкретный элемент массива
pressureExamArray[j] = s;
}
}
}
sr.Close();
// в случае успешной обработки возвратить 'true'
return true;
}
catch (Exception)
{
// при возникновении ошибки при обработке файла выдать сообщение и возвратить 'false'
MessageBox.Show("Ошибка при обработке входных данных",
Form2.FormCaption);
return false;
}
}
}
}
Рисунок ПА.3 – Продолжение
31
Приложение Б. Руководство пользователя
Программа представляет собой приложение, позволяющее
прогнозировать курс доллара на основе статистических данных. При
запуске программы вы наблюдаете диалоговое окно. Окна
представлены на рисунках 5,6.
1) Для запуска программы нужно запустить файл $.exe.
2) необходимо произвести загрузку данных для обучения,
затем создать сеть, указав количество нейронов на слоях, через
пробел.
3) Обучить ИНС вручную, автоматически или загрузить уже
обученную ИНС.
4) Для получения прогноза, необходимо загрузить данные за
последний период и нажать кнопку «Получить прогноз».
5) Рядом в текстовом поле появится результат
прогнозирования.
6) Для завершения работы следует нажать кнопку «Закрыть».
32
Приложение В. Руководство программиста
Программа разработана в Microsoft Visual Studio 2010. Был разработан класс
Neuron – класс нейрона.
PressureArray – массив входных сигналов
Weights – массив весовых коэффициентов
Delta – изменение весов
countX, countY – количество сигналов
kLearn – скорость обучения
Weights = new double[cX, cY] - инициализация весовых коэффициентов
S - функция активации
Layers()- изменение весовых коэффициентов
NN.NetOUT()-вычисление значений выходов
kErr – вычисление ошибок
LearnNet() – обучение
33
Документ
Категория
Рефераты
Просмотров
51
Размер файла
590 Кб
Теги
итипз
1/--страниц
Пожаловаться на содержимое документа