- перевод полученного десятичного числа в двоичный вид при помощи метода 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)