Лабораторная работа - Обучение однослойного персептрона по дельта-правилу Розенблатта - файл n1.doc

Лабораторная работа - Обучение однослойного персептрона по дельта-правилу Розенблатта
Скачать все файлы (97 kb.)

Доступные файлы (1):
n1.doc97kb.01.02.2014 21:47скачать

n1.doc

Арзамасский Политехнический Институт (филиал) Нижегородского Государственного Технического Университета

Практическое занятие №
«Обучение однослойного персептрона по
дельта-правилу Розенблатта»


Арзамас 2009

Постановка задачи

Написать программу, реализующую обучение однослойного персептрона. В качестве примера выбрана следующая задача - нейронной сети предъявляется вектор, состоящий из 10 компонент, каждая из которых может быть нулем или единицей. Сеть должна научиться определять, чего больше - нулей или единиц.

Описание программы:

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

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

Обучение сети проводится по дельта-правилу Розенблатта . По завершении обучения программа выдает число выполненных итераций и значение достигнутой ошибки обучения.
Дельта-правило
Обучение сводится к следующему алгоритму:

  1. Проинициализировать элементы весовой матрицы (обычно небольшими случайными значениями)

  2. Подать на входы один из входных векторов, которые сеть должна научиться различать и вычислить ее выход

  3. Если выход правильный перейти на шаг 4.

Иначе вычислить разницу между идеальным и полученным значением выхода :

. (3.2.1)

Модифицировать веса в соответствии с формулой

, (3.2.2)

где и - номера текущей и следующей итерации,

- коэффициент скорости обучения (),

- номер входа,

- номер нейрона в слое.

Очевидно, что если , то весовые коэффициенты будут увеличены и, тем самым, уменьшат ошибку. В противном случае они будут уменьшены, и тоже уменьшится, приближаясь к .

  1. Цикл с шага 2, пока сеть не перестанет ошибаться.

На втором шаге на разных итерациях поочередно в случайном порядке предъявляются всевозможные входные вектора. Заранее нельзя определить число итераций, которое потребуется выполнить, а в некоторых случаях и гарантировать полный успех.

Блок-схема программы






Текст программы:
#include "stdafx.h"

#include

#include

#include

#include

#include

#include
const int CMaxInp=20; //Максимальное число входов

const int CMaxOut=10; //Максимальное число выходов

const int CMaxImages=200; //Максимальное число образов

const double CEta=0.75; //Темп обучения

const double CError=5.0e-4; //Граница требуемой ошибки

const int CCounter=1000; //Максимальное число итераций

const double CInitWeight=5.0; //Максимальное начальное значение случайных синаптических весов

const double CBiasNeuron=1.0; //Активность нейрона-порога


typedef double TMatrix[CMaxInp][CMaxOut+1];

//Нулевой столбец содержит значения порогов

typedef double TInpVector[CMaxInp];

typedef double TOutVector[CMaxOut];


//Структура сети

struct TPerceptron

{

int NInp; //Число входов

int NOut; //Число выходов

TInpVector Inp; //Текущий вектор входов

TOutVector Out; //Текущий вектор выходов

TMatrix W; //Матрица связей

};


//Запись в базе данных - обучающей выборке

struct TBaseRecord

{

TInpVector X;

TOutVector Y;

} ;


//Структура базы данных

struct TBase

{

int NImages; //Число обучающих образов

TBaseRecord Images[CMaxImages];

};
TPerceptron VNet;

TBase VBase;

bool VOK;

double VError, VTemp, VDelta;

int VCounter, Vi, Vj, Vk;

FILE *VFile;

double Sigmoid(double Z)

{

return (1.0/(1.0+exp(-Z)));

}
// Инициализация нейронной сети с 10 входами и одним выходом,

// задание начальных случайных значений матрицы связей

void InitAll()
{

srand( (unsigned)time( NULL ) );
int Li, Lj, Lk ;

VNet.NInp=10;

VNet.NOut=1;

for(Li=0;Li<=VNet.NInp;Li++)

{

for(Lj=1;Lj<=VNet.NOut;Lj++)

{

VNet.W[Li][Lj]=CInitWeight*((double)rand()/RAND_MAX-0.5);

}

}

VOK=true;

}
void GetDataBase()

// Генерация обучающей выборки из 200 случайных образов.

// При определении правильного числа единиц используется прямой

// подстчет *)

{

srand( (unsigned)time( NULL ) );

int Li, Lj, Lk;
VOK=true;

VBase.NImages=200;

for(Li=1;Li<=VBase.NImages;Li++)

{ Lk=0;

for(Lj=1;Lj<=VNet.NInp;Lj++)

{

// Случайно 0 или 1 *)

VBase.Images[Li].X[Lj]=rand()>RAND_MAX/2?1:0;

//cout<<" "<
// Подсчет единиц *)

if(VBase.Images[Li].X[Lj]>0)Lk=Lk+1;

}

// Выход равен единице, если в данном входном векторе

// число единиц больше числа нулей *)

if(Lk>(VNet.NInp-Lk)) VBase.Images[Li].Y[1]=1;

else VBase.Images[Li].Y[1]=0;

//cout<<" "<
}

}
void main()

{ double VCorrect;

cout<<"-----------------------------------------";

VOK = true;
// Инициализация с контролем ошибки

srand( (unsigned)time( NULL ) );
InitAll();
if (!VOK)

{ cout<<"\n Ошибка инициализации"; }


// Генерация базы данных

VOK = true;

GetDataBase();
if (!VOK)

{cout<<"\n Ошибка при генерации базы данных"; }
// Цикл обучения

VOK=true;

VCounter=0;
do

{

VError=0.0;

//Цикл по обучающей выборке

for (int Vi=1;Vi<=VBase.NImages;Vi++)

{

//Подача очередного образа на входы сети

for (int Vj=1;Vj<=VNet.NInp;Vj++)

{VNet.Inp[Vj]=VBase.Images[Vi].X[Vj];}
//Цикл по нейронам. При аппаратной реализации

// будет выполняться параллельно !!!
for(int Vk=1;Vk<=VNet.NOut;Vk++)

{ //Состояние очередного нейрона

VTemp=CBiasNeuron*VNet.W[0][Vk];

for (int Vj=1;Vj<=VNet.NInp;Vj++)

{VTemp=VTemp+VNet.Inp[Vj]*VNet.W[Vj][Vk];}
VNet.Out[Vk]=Sigmoid( VTemp );
//Накопление ошибки

VDelta= VBase.Images[Vi].Y[Vk]-VNet.Out[Vk];

VError= VError + 0.5*VDelta*VDelta;
//Обучение по дельта-правилу Розенблатта

VNet.W[0][Vk]= VNet.W[0][Vk]+CEta*CBiasNeuron*VDelta;
for ( Vj=1;Vj<=VNet.NInp;Vj++)

{VNet.W[Vj][Vk]=VNet.W[Vj][Vk] + CEta*VNet.Inp[Vj]*VDelta;}
}

}
VCounter = VCounter + 1;

}
while ( (VCounter < CCounter) && (VError > CError));

// }
// Цикл завершен при достижении максимального числа

// итераций или минимально достаточной ошибки
printf("\nIter =%d ", VCounter);

printf("\nError=%lf\n ", VError) ;
printf("P E R C E P T R O N>> (Test)\n");

printf("-----------------------------------------------\n");

printf(" Question Answer Correct answer \n");

printf("-----------------------------------------------\n");

for (Vi=1;Vi<=CMaxImages/5;Vi++)

{

// Подача на вход случайного образа /

Vk=0;

for (Vj=1;Vj<=VNet.NInp;Vj++)

{

// Случайно 0 или 1

VNet.Inp[Vj]=rand()>RAND_MAX/2?1:0;

// Подсчет единиц /

if (VNet.Inp[Vj]>0)

Vk=Vk+1;

}

// Правильный ответ известен !

if (Vk>(VNet.NInp-Vk))

VCorrect=1.0;

else VCorrect=0.0;

// Ответ выдает нейросеть

for (Vk=1;Vk<=VNet.NOut;Vk++)

{

VTemp=CBiasNeuron*VNet.W[0][Vk];

for (Vj=1;Vj<=VNet.NInp;Vj++)

{

VTemp=VTemp+VNet.Inp[Vj]*VNet.W[Vj][Vk];

}

VNet.Out[Vk]=Sigmoid(VTemp);

}

// Выдача результатов

for (Vj=1;Vj<=VNet.NInp;Vj++)

printf(" %d",(int)VNet.Inp[Vj]);

printf("%6.2lf %d\n",VNet.Out[1],(int)VCorrect);

}
cout<<"-------------------------------------------------";


}

Результат выполнения программы:

Учебный текст
© perviydoc.ru
При копировании укажите ссылку.
обратиться к администрации