Автор работы: Пользователь скрыл имя, 12 Мая 2012 в 21:54, курсовая работа
В данном курсовом проекте была разработана программа-анализатор слов естественного языка с использованием нейросети.
В ходе выполнения данного курсового проекта была разработана библиотека, содержащая классы для лексического анализа слов естественного языка с использованием нейросети (для решения поставленной задачи была выбрана нейросеть обратного распространения ошибки), была написана тестирующая программа, подготовлены тесты. При тестировании, после соответствующей настройки, программа не допустила ни одной ошибки.
Введение
1. Анализ нейронных сетей
1.1 Выбор разновидности сети
1.2 Модель многослойного персептрона с обучением по методу обратного распространения ошибки
1.3 Постановка задачи
2. Проектирование библиотеки классов для реализации нейросети и тестовой программы
2.1 Программная реализация нейросети обратного распространения ошибки
2.2 Класс перевода текста в двоичный вид
2.3 Класс хеш-таблицы и методов работы с ней
2.4 Класс разбиения текста на лексемы и распознавания
2.5 Описание тестирующей программы
2.6 Результаты тестирования
3. Руководство программисту
Заключение
Список используемой литературы
Приложения
Полный алгоритм обучения НС с помощью процедуры обратного распространения строится так:
1. Инициализировать пороговые
значения и весовые
2. Подать
на входы сети один из
3. Вычислить
ошибки для выходного слоя (calculate_output_layer_
private void
calculate_output_layer_errors(
{ for (int j = 0; j < MAX_OUT; j++)
{ ol[j].E = (desired[j] - ol[j].a) * ol[j].a * (1 - ol[j].a); } }
Вычисление ошибки для скрытого и входного слоев производится методами calculate_input_layer_errors и calculate_hidden_layer_errors по формуле (8). Код соответствеющей функции для входного слоя предтсавлен ниже:
private void calculate_input_layer_errors()
{
double sum;
for (int i = 0; i < MAX_INP; i++)
{
sum = 0; // {Сумма ошибок скрытого слоя}
for (int j = 1; j < MAX_HID; j++)
{ sum = sum + hl[j].E * hl[j].w[i]; }
ipl[i].E = ipl[i].a * (1 - ipl[i].a) * sum;
}
}
Используя формулы (9), (10), (11) получим функцию, обучающую весовые коэффициенты и пороговые уровни:
private void weight_change()
{ //i обозначает нейрон скрытого слоя, j - выходного
for (int j = 0; j < MAX_OUT; j++) //выходной слой
{ for (int i = 0; i < MAX_HID; i++) //Подстройка}
{ ol[j].change[i] = BETA * ol[j].E * hl[i].a + M * ol[j].change[i];
ol[j].w[i] = ol[j].w[i] + ol[j].change[i]; }
//Подстройка значения порога
ol[j].t_change = BETA * ol[j].E * 1 + M * ol[j].t_change;
ol[j].threshold = ol[j].threshold + ol[j].t_change; // }
//Модифицируем веса между входным слоем и скрытым слоем
…
//Модифицируем веса между входами и входным слоем
… } }
Далее объединим вышеуказанные функции в одном методе back_propogate().
В общем виде функция обучения сети будет выглядеть следующим образом:
public void train_the_network()
{ blank_changes();//Очистка предыдущих значений changes}
for (int loop = 0; loop < num_cycles; loop++)
{ for (int pat = 0; pat < MAX_PAT; pat++)
{ for (int i = 0; i < MAX_INP; i++) //Копирование входного образа}
{ test_pat[i] = INP_PATTERNS[pat, i]; } /в массив 'test_pat'
for (int i = 0; i < MAX_OUT; i++) //Копирование выходного образа
{ desired[i] = OUT_PATTERNS[pat, i]; } //в массив'desired'
run_the_network();//
back_propagate(); } }
AddWeightsToFile(); }
Для очистки предыдущих значений используется функция blank_changes.
Для упрощения временной сложности работы сети полученные весовые коэффициенты будем записывать в отдельные файлы (метод AddWeightsToFile()), имена которым даются программой автоматически Для считывания сохраненных параметров будет применяться метод ExtractWeights().
2.2 Класс перевода текста в двоичный вид
Данный класс предназначен для бинаризации исходных данных (слов), т.е. перевода слов с естественного языка в набор единиц и нулей. Данная процедура является необходимой, т.к. нейронная сеть обратного распространения ошибки работает только с двоичными данными. UML диаграмма класса Binarization представлена на рисунке 7.
Класс Binarization |
Закрытые поля |
string[] sLetter; |
int iLengthPattern; |
Закрытые методы |
private string DecToBin(string value) |
Открытые методы |
public double[] GetBinarizeWord(string sWord) |
public double[,] GetBinarizeText(out double[,] OUT_PATTERNS, out int max_pat, out int iLengthPattern1) |
public Binarization(string[] sLetter1) |
Рисунок 7 –UML-диаграмма класса Binarization
Параметром конструктора является массив строк для перевода в двоичный вид.
Алгоритм работы методов GetBinarizeWord и GetBinarizeText данного класса в общем состоит из следующих этапов:
2.3 Класс хеш-таблицы и методов работы с ней
Некоторые слова невозможно четко классифицировать, т.к. они относятся либо к неизменяемым частям речи (наречия, деепричастия и.т.д), либо схожи по некоторым признакам со словами других частей речи. (существительное кровать оканчивается как глагол на ать). Слова определенных классов имеются в достаточно ограниченных количествах (союзы и.т.д) и создание для их распознавания нейросети является неоправданным. Для работы с такого рода словами и предназначен данный класс. UML диаграмма класса Hash представленна на рисунке 8.
Класс Hash |
Закрытые поля |
Dictionary<int, string> predlog = new Dictionary<int, string>(); |
Dictionary<int, string> narechie = new Dictionary<int, string>(); |
Dictionary<int, string> deepr = new Dictionary<int, string>(); |
Dictionary<int, string> soyuz = new Dictionary<int, string>(); |
Dictionary<int, string> mest = new Dictionary<int, string>(); |
Dictionary<int, string> iskl = new Dictionary<int, string>(); |
string[] sConstant = { "predlog", "narechie", "deepr", "soyuz", "mest", "iskl" }; |
Закрытые методы |
private int HashFunction(string sInfo) |
Открытые методы |
public bool CheckHash(string sInfo, string sHash_name) |
public void AddLetterInHashAndFile(string sLetter, string sClass,bool Flag) |
public void AddToHash(string sInfo, string sHash_name) |
public void ReadFileInHash(string sNamefile) |
public void WriteWordInFile(string sInfo, string sNamefile) |
public Hash() |
Рисунок 8 – UML диаграмма класса Hash
Полями данного класса являются хеш-таблицы – predlog (содержит предлоги), narechie (наречия), deepr (деепричастия), soyuz (союзы), mest (местоимения), iskl (существительные, глаголы, прилагательные сложные для распознавания).
Класс также содержит методы:
2.4 Класс разбиения текста на лексемы и распознавания
Данный класс является главным. Его задача – вычленение лексем из текста и их дальнейшее распознавание. В нем используются объекты всех вышеописанных классов. UML-диаграмма класса Analization представлена на рисунке 9.
Класс Analization |
Закрытые поля |
List<Results> results = new List<Results>(); |
bool flag_oy = false; |
bool flag_om = false; |
bool flag_im = false; |
bool flag_em = false; |
Bool flag_ie=false; |
bool flag_mi=false; |
Закрытые методы |
private void AddEtalonLetter() |
private string GetNeuroResult(string sLetter, string sFileName, int N_HID, double beta, double m, int Epoch, bool flag) |
private string Scaning(string sLetter, int N_HID, double beta, double m, int Epoch, bool flag) |
Открытые методы |
public static void AddToFile(string sLetter, string sFile) |
public string BigToSmall(string letter) |
public Analization(string sText, int N_HID, double beta, double m, int Epoch, bool flag) |
public List<Results> GetResult() |
Рисунок 9 – UML-диаграмма класса Analization
Параметрами конструктора являются:
Из всех вышеперечисленных методов наиболее важными являются: конструктор, Scaning и GetNeuroResult.
Анализируемый текст сначала подается в конструктор. Там он разбивается на отдельные лексемы, тип которых либо определяется сразу (если это знак препинания или имя собственное), либо посредством метода Scaning. Код данного метода представлен ниже:
private string Scaning(string sLetter, int N_HID, double beta, double m, int Epoch, bool flag)
{ Hash hash = new Hash();
string result = "существительное";//результат
string[] znaks = { "с", "п", "г" };
for (int i = 0; i < znaks.Length; i++)//поиск существительных, прилагательных и глаголов-исключений, сохраненных в хеш-таблице
{ if (hash.CheckHash(sLetter + znaks[i].ToString(), "iskl") == true)
{ switch (znaks[i])
{ case "с": result = "существительное";//если в конце слова буква с – возвращаем результат
return result;
case "п": result = "прилагательное";
return result;
case "г": result = "глагол";
return result; } } }
if (hash.CheckHash(sLetter, "predlog") == true)//проверяем, является ли слово предлогом (ищем в соответствующей хеш-таблице
{ result = "предлог";//если слово есть в хеш-таблице – возвращаем результат
return result; }
//Для местоимений, союзов, деепричастий и наречий аналогично
…
if (String.Compare(sLetter, "не") == 0 || String.Compare(sLetter, "бы") == 0)
{ result = "частица";
return result; }
if (sLetter.Length < 2)
{ return "предлог"; }
//----------------------------
string[] pril
= {"ий","ый","ая","яя","го","ую"
string[] glagol
= {"ит","ат","ят","ут","ют","ул"
string[] prich
= {"вший","шими","вшая","вшем","
string okonchanie= (sLetter[sLetter.Length - 2].ToString() + sLetter[sLetter.Length - 1].ToString());
if (Array.IndexOf(pril,
{string ok_i_suff = sLetter[sLetter.Length - 4].ToString() + sLetter[sLetter.Length - 3].ToString() + okonchanie;
if (Array.IndexOf(prich,ok_i_
{ return "причастие"; //если есть – результат причастие }
return "прилагательное"; //если нет - прилагательное }
else
…
if (String.Compare(okonchanie, "ом") == 0)//если окончание -ом
{ string res=
GetNeuroResult(sLetter,"-ом",
flag_om = true;//при повторном поступлении слова на –ом нейросеть повторно обкчаться не будет
return res; }
else
//Аналогично для –ем, -им, -ой, -ие, -ми.
….}
Метод Scaning логически можно разделить на 3 блока:
Во втором блоке подразумевается определение типа слова по окончанию (последние две буквы) при помощи условных операторов:
В третьем блоке в зависимости от окончания слова производится вызов функции private string GetNeuroResult(string sLetter, string sFileName, int N_HID, double beta, double m, int Epoch, bool flag) параметрами:
Информация о работе Распознавание слов естественного языка с использованием нейросетей