Смекни!
smekni.com

Распознавание слов естественного языка с использованием нейросетей (стр. 4 из 7)

- перевод полученного десятичного числа в двоичный вид при помощи метода DecToBin;

- обработка полученных данных.

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 (существительные, глаголы, прилагательные сложные для распознавания).

Класс также содержит методы:

- HashFunction – значение хеш-функции для текущего слова;

- CheckHash – проверка наличия записи в хеш-таблице;

- AddLetterInHashAndFile – классификация и добавление нового слова в хеш-таблицу, а также запись в файл;

- AddToHash – добавление слова в хеш-таблицу;

- ReadFileInHash и WriteWordInHash – чтение слов из файла и запись слова в файл соответственно.

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

Параметрами конструктора являются:

- текст для анализа – sText;

- параметры нейросети N_HID, beta, m, Epoch;

- индикатор необходимости обучения нейросети – flag.

Из всех вышеперечисленных методов наиболее важными являются: конструктор, 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,okonchanie)!=-1)//если окончание слова содержится в массиве окончаний прилагательных переходим к проверке суффикса

{string ok_i_suff = sLetter[sLetter.Length - 4].ToString() + sLetter[sLetter.Length - 3].ToString() + okonchanie;

if (Array.IndexOf(prich,ok_i_suff)!= -1)//ищем в массиве суффиксов и окончаний причастий

{ return "причастие"; //если есть – результат причастие }

return "прилагательное"; //если нет - прилагательное }

else

if (String.Compare(okonchanie, "ом") == 0)//еслиокончание -ом

{ string res= GetNeuroResult(sLetter,"-ом",N_HID,beta,m,Epoch,flag_om);//распознаемсловонейросетью

flag_om = true;//при повторном поступлении слова на –ом нейросеть повторно обкчаться не будет

return res; }

else

//Аналогично для –ем, -им, -ой, -ие, -ми.

….}

Метод Scaning логически можно разделить на 3 блока:

- поиск слова в хеш-таблицах;

- идентификация слова по окончанию и определение его типа;

- идентификация слова по окончанию и проведение углубленного анализа с помощью нейронной сети.

Во втором блоке подразумевается определение типа слова по окончанию (последние две буквы) при помощи условных операторов:

- при помощи метода IndexOf класса Array определяется наличие в соответствующем массиве (массиве окончаний глаголов - glagol, прилагательных - pril) данного окончания;

- если это окончание прилагательного или -ся то критерий поиска изменяется до идентификации по паре суффикс-окончание: определяется наличие данной пары в массиве prich (причастие);

- после проведения вышеуказанных операций функция возвращает тип лексемы: глагол, прилагательное или причастие;

- в случае, если окончание не найдено ни в одном из массивов, то тип лексемы определяется как существительное;

- если слово оканчивается на -ие, -ми, -ем, -им, -ом то переходим к третьему блоку.

В третьем блоке в зависимости от окончания слова производится вызов функции private string GetNeuroResult(string sLetter, string sFileName, int N_HID, double beta, double m, int Epoch, bool flag) параметрами:

- sLetter – лексема,

- sFileName – имя файла с обучающей выборкой,

- N_HID – количество скрытых нейронов,

- beta – коэффициент обучения,

- m – момент,

- Epoch – количество эпох обучения,

- flag – логическая переменная, в значении «истина» означающая, что анализ будет производиться без обучения;

Код данной функции представлен ниже:

private string GetNeuroResult(string sLetter, string sFileName, int N_HID, double beta, double m, int Epoch, bool flag)

{ string[] techears = File.ReadAllLines(sFileName+".txt");

Binarization binar = new Binarization(techears);//проводимбинаризацию

double[,] inp = new double[1, 1], outp = new double[1, 1]; double[] test = new double[1]; //обучающаявыборка, выходы, тестоваявыборка

int max_inp, max_pat;//кол-во нейронов и выборок

inp = binar.GetBinarizeText(out outp, out max_pat, out max_inp);//получаем обучающую выборкув закодированном виде

test = binar.GetBinarizeWord(sLetter);//получаем тестовую выборку в закодированном виде

NeuroNetwork neuro = new NeuroNetwork(inp, outp, max_inp, N_HID, max_pat, beta, m, Epoch, sFileName, flag);//создаем объект нейросеть

if (flag == false)//если она не обучена

{ neuro.random_weights();//инициализируем весовые коэффициенты случайными числами

neuro.train_the_network(); //обучаемнейросеть}

string[] m_resultat = neuro.test_the_network(test);

string res1="",res2="";

switch (sFileName)

{ //в зависимости от имени файла с обучающей выборкой возможны определенные комбинации возвращаемых результатов

case "-ой":

res1 = "существительное";

res2 = "прилагательное";

break;

… }

//анализируем полученные значения нейросети и возвращаем результат

if (double.Parse(m_resultat[0]) < 0.5 && double.Parse(m_resultat[1]) < 0.5 && double.Parse(m_resultat[2]) < 0.5)

{ return res1; }

if (double.Parse(m_resultat[0]) < 0.5 && double.Parse(m_resultat[1]) < 0.5 && double.Parse(m_resultat[2]) > 0.5)

{ return res2; }

return "неизвестно"; }

Алгоритм данной функции можно разделить на следующие этапы:

- извлечение обучающей выборки из файла,

- ее бинаризация при помощи класса Binarization,

- если flag==false – обучение нейронной сети,

- получение результата,

- определение по полученному результату типа лексемы.

2.5 Описание тестирующей программы

Программа выполнена в виде Windows-приложения в среде Microsoft Visual Studio и имеет оконный интерфейс.

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

Приложение состоит из трех окон:

- окно ввода текста для анализа (рисунок 13);

- окно анализа текста (рисунок 14);

- окно добавления лексемы в хеш-таблицу или в обучающую выборку (рисунок 15).

Текст для анализа загружается из файла или вводится с клавиатуры в richTextBox. Результат анализа (лексема и класс) выводится в dataGridView (рисунок 10)