public void FinishLearning() { wrt_train.Close(); wrt_test.Close(); wrt_test2.Close(); using (System.IO.StreamWriter wrt = new System.IO.StreamWriter("rnnsharp_tags.txt")) { for (int i = 0; i < tags.Count(); ++i) { wrt.WriteLine("{1}", i, tags.GetIdByIndex(i)); } } string cmd = string.Format("{0}\\rnnsharp_train.cmd", System.IO.Directory.GetCurrentDirectory()); System.Diagnostics.Process p = new System.Diagnostics.Process(); p.StartInfo.Arguments = null; p.StartInfo.FileName = cmd; Console.WriteLine("Executing {0}", p.StartInfo.FileName); bool r = p.Start(); p.WaitForExit(); return; }
public void Check( string line, ref int total_word_count, ref int error_count_no_filter, ref int error_count_with_model ) { // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { List <List <int> > word2tags = new List <List <int> >(); List <int> selected_tags = new List <int>(); // Токенизация без использования синтаксических правил using (SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_TOKENIZE_ONLY /*| SolarixGrammarEngineNET.GrammarEngine.SOL_GREN_DISABLE_FILTERS*/)) { if (tokens.Count != projs.Count) { return; } // Преобразуем все проекции каждого слова в варианты распознавания тегов List <int> tag_set = new List <int>(); int start_tag = -1, end_tag = -1; //List<string> words = new List<string>(); bool unmatched_tag = false; List <int> suffices = new List <int>(); int last_word_index = tokens.Count - 1; for (int i = 0; i < tokens.Count; ++i) { SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i]; string word = token.GetWord().ToLower(); // words.Add(word); int suffix_id = GetTokenSuffix(i, last_word_index, token); suffices.Add(suffix_id); SolarixGrammarEngineNET.SyntaxTreeNode proj = projs[i]; List <int> wt = new List <int>(); for (int j = 0; j < proj.VersionCount(); ++j) { int id_tag = tags.GetIndexById(tags.MatchTags(proj, j, gren)); if (id_tag != -1) { if (!wt.Contains(id_tag)) { wt.Add(id_tag); } if (!tag_set.Contains(id_tag)) { tag_set.Add(id_tag); } } if (i == 0) { start_tag = id_tag; } else if (i == tokens.Count - 1) { end_tag = id_tag; } } if (wt.Count == 0) { // ни один тег не подошел, это ошибка кодовой книги. unmatched_tag = true; } word2tags.Add(wt); selected_tags.Add(wt[0]); } if (unmatched_tag) { return; } // ----------------------------------------- // Посчитаем ошибки до применения модели // ----------------------------------------- int n_err = 0; for (int iword = 1; iword < tokens.Count - 1; ++iword) { SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[iword]; int ekey1 = token.GetEntryID(); int id_class1 = gren.GetEntryClass(ekey1); int tag = selected_tags[iword]; if (tag != -1) { TagMatcher m = tags[tags.GetIdByIndex(tag)]; if (!m.MatchPartOfSpeech(id_class1)) { n_err++; } } } error_count_no_filter += n_err; total_word_count += (tokens.Count - 2); int Nword = tokens.Count; // кол-во последовательных шагов - число слов, включая левую и правую границы int Nstate = tag_set.Count; // Viterbi trellis // вероятности для состояний double[,] V = new double[Nword, Nstate]; for (int t = 0; t < Nword; ++t) { for (int s = 0; s < Nstate; ++s) { V[t, s] = 0.0; } } // backpointers для отслеживания лучшего пути int[,] BACKPOINTER = new int[Nword, Nstate]; for (int t = 0; t < Nword; ++t) { for (int s = 0; s < Nstate; ++s) { BACKPOINTER[t, s] = -1; // возможно, надо как-то инициализировать дефолтный путь на случай, если найти лучший не получится - то есть надо проставить от начального до конечного. } } V[0, tag_set.IndexOf(start_tag)] = 1.0; // начальное состояние - стартуем из этого состояния. for (int t = 1; t < Nword; ++t) { // проставляем вероятность получения состояний на шаге t, исходя из значений на предыдущем шаге. for (int s2 = 0; s2 < Nstate; ++s2) // состояния на шаге t { double max_v = 0.0; int best_prev_state = 0; int id_tag2 = tag_set[s2]; double b = 0.0; Dictionary <int, double> bx; if (PB.TryGetValue(id_tag2, out bx)) { bx.TryGetValue(suffices[t], out b); } for (int s1 = 0; s1 < Nstate; ++s1) // состояния на шаге t-1 { int id_tag1 = tag_set[s1]; double vt = V[t - 1, s1] * PA[id_tag1, id_tag2] * b; if (vt > max_v) { max_v = vt; best_prev_state = s1; } } V[t, s2] = max_v; BACKPOINTER[t, s2] = best_prev_state; } } // обратный ход по состояниям, указанным в BACKPOINTER. int best_state = tag_set.IndexOf(end_tag); for (int t = Nword - 1; t > 0; --t) { int best_prev_state = BACKPOINTER[t, best_state]; int selected_tag = tag_set[best_prev_state]; // Делаем вариант распознавания, давший этот токен, первым в списке. // ATT: грубые ошибки выбора тега не допускаем, то есть разрешаем только те теги, которые были // получены при распознавании слова. if (word2tags[t - 1].Contains(selected_tag)) { selected_tags[t - 1] = selected_tag; } else { // ... грубая ошибка выбора тега. } best_state = best_prev_state; } // Теперь проверяем количество ошибок в выборе частей речи. for (int iword = 1; iword < tokens.Count - 1; ++iword) { SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[iword]; int ekey1 = token.GetEntryID(); int id_class1 = gren.GetEntryClass(ekey1); int tag = selected_tags[iword]; if (tag != -1) { TagMatcher m = tags[tags.GetIdByIndex(tag)]; if (!m.MatchPartOfSpeech(id_class1)) { error_count_with_model++; } } } } } return; }