static string GetFeatures(SolarixGrammarEngineNET.GrammarEngine2 gren, SolarixGrammarEngineNET.AnalysisResults words, int focus_index) { List <string> features = new List <string>(); for (int offset = -window; offset <= window; ++offset) { int word_index = focus_index + offset; if (word_index >= 1 && word_index < words.Count - 1) { features.AddRange(GetWordFeatures(gren, words[word_index], offset.ToString())); if (word_index == 1) { features.Add($"start[{offset}]"); } if (word_index == words.Count - 2) { features.Add($"end[{offset}]"); } } } return(string.Join("\t", features)); }
public int Match(SolarixGrammarEngineNET.AnalysisResults tokens, int left_i, SolarixGrammarEngineNET.GrammarEngine2 gren) { // Проверяем, что не-омонимичные термы сопоставляются. bool m = true; for (int iterm = 0; iterm < points.Count; ++iterm) { if (points[iterm] != null) { SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[left_i + iterm]; if (!points[iterm].Match(token, gren)) { m = false; break; } } } if (m) { // Осталось проверить, правильно ли снята омонимия. SolarixGrammarEngineNET.SyntaxTreeNode omonym_token = tokens[left_i + omonym_point.GetPosition()]; return(omonym_point.Match(omonym_token) ? 1 : 0); } return(-1); }
public bool ProcessSample(string line) { // синтаксический разбор в дерево SolarixGrammarEngineNET.AnalysisResults trees = gren.AnalyzeSyntax(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY, SolarixGrammarEngineNET.GrammarEngine.SyntaxFlags.SOL_GREN_REORDER_TREE); Collect(trees); return(true); }
public void Collect(SolarixGrammarEngineNET.AnalysisResults trees) { for (int iroot = 1; iroot < trees.Count - 1; ++iroot) { ProcessTree(trees[iroot]); } return; }
private void AssembleEdges(SolarixGrammarEngineNET.AnalysisResults syntax_tree, List <Edge4Stat> edges, Dictionary <string, NodeLeafCount> leaves) { for (int iroot = 1; iroot < syntax_tree.Count - 1; ++iroot) { AssembleEdges(syntax_tree[iroot], edges, leaves); } return; }
private void Assemble3Grams(SolarixGrammarEngineNET.AnalysisResults syntax_tree, List <Rule3Gram> ngrams) { for (int iroot = 1; iroot < syntax_tree.Count - 1; ++iroot) { Assemble3Grams(syntax_tree[iroot], ngrams); } return; }
public bool ProcessSample(string line) { n_learn_samples++; // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { List <string> sfx = new List <string>(); List <int> sfx_index = new List <int>(); List <string> sfx_lemma = new List <string>(); List <int> sfx_lemma_index = new List <int>(); int last_word_index = tokens.Count - 1; for (int iword = 0; iword < tokens.Count; ++iword) { string word = tokens[iword].GetWord().ToLower(); string suffix = GetTokenSuffix(iword, last_word_index, tokens[iword]); sfx.Add(suffix); int index = MatchSuffix(suffix, true); sfx_index.Add(index); int ekey = tokens[iword].GetEntryID(); string ename = gren.GetEntryName(ekey); string lemma; if (IsUnknownLexem(ename)) { lemma = word; } else { lemma = ename.ToLower(); } sfx_lemma.Add(GetSuffix(lemma)); sfx_lemma_index.Add(MatchSuffix(GetSuffix(lemma), true)); } for (int iword = 1; iword < tokens.Count - 1; ++iword) { string tag1 = TagLabel(-1, sfx_index[iword - 1]); string tag2 = TagLabel(0, sfx_index[iword]); string tag3 = TagLabel(1, sfx_index[iword + 1]); string res = ResultLabel(sfx_lemma_index[iword]); WriteTrain(tag1, tag2, tag3, res); } } return(true); }
static void FindChunks(SolarixGrammarEngineNET.AnalysisResults root, Dictionary <int /*word_index*/, int /*chunk_index*/> labels) { var root_node = root[1]; labels[root_node.GetWordPosition()] = root_node.GetWordPosition(); for (int i = 0; i < root_node.leafs.Count; ++i) { var child_node = root_node.leafs[i]; int chunk_index = child_node.GetWordPosition(); GetChunkNodes(child_node, chunk_index, labels); } }
public OmonymContextEnumerator(SolarixGrammarEngineNET.AnalysisResults tokens, int _omonym_position, int _left_i, int _len, SolarixGrammarEngineNET.GrammarEngine2 _gren) { gren = _gren; left_i = _left_i; len = _len; omonym_position = _omonym_position; recognizers = new List <ContextRecognizer>(); // Для каждого токена, кроме омонимичной формы, генерируем список вариантов. // ... пока только код для контекстов длины=2 if (len == 2) { SolarixGrammarEngineNET.SyntaxTreeNode omonym_token = tokens[left_i + omonym_position]; OmonymTokenRecognizer omonym_point = new OmonymTokenRecognizer(omonym_position, omonym_token); if (omonym_position == 0) { TokenTagsEnumerator tte = new TokenTagsEnumerator(IsBoundaryToken(tokens, left_i + 1), tokens[left_i + 1], gren); int n = tte.Count; for (int i = 0; i < n; ++i) { List <TokenRecognizer> points = new List <TokenRecognizer>(); points.Add(null); // это омонимичная форма points.Add(tte[i]); ContextRecognizer ctx_recognizer = new ContextRecognizer(points, omonym_point, gren); recognizers.Add(ctx_recognizer); } } else { TokenTagsEnumerator tte = new TokenTagsEnumerator(IsBoundaryToken(tokens, left_i), tokens[left_i], gren); int n = tte.Count; for (int i = 0; i < n; ++i) { List <TokenRecognizer> points = new List <TokenRecognizer>(); points.Add(tte[i]); points.Add(null); // это омонимичная форма ContextRecognizer ctx_recognizer = new ContextRecognizer(points, omonym_point, gren); recognizers.Add(ctx_recognizer); } } } }
public void ProcessSample(string line, SolarixGrammarEngineNET.AnalysisResults tokens, int LanguageID, SolarixGrammarEngineNET.GrammarEngine2 gren) { int sample_len = tokens.Count; for (int i = 0; i < sample_len; ++i) { if (tokens[i].GetWord().Equals(word, StringComparison.CurrentCultureIgnoreCase)) { int position = i; // Омоним распознан однозначно? SolarixGrammarEngineNET.SyntaxTreeNode omonym_token = tokens[position]; // Создаем все возможные контексты с омонимом - разной длины, с разным местоположением. int MIN_CONTEXT_LEN = 2, MAX_CONTEXT_LEN = 2; for (int left_i = position - MAX_CONTEXT_LEN + 1; left_i <= position; ++left_i) { if (left_i >= 0) { int min_len = Math.Max(position - left_i + 1, MIN_CONTEXT_LEN); for (int ctx_len = min_len; ctx_len <= MAX_CONTEXT_LEN; ++ctx_len) { OmonymContext ctx; ctx.len = ctx_len; ctx.position = position - left_i; if (rules.ContainsKey(ctx)) { rules[ctx].ProcessSample(line, tokens, left_i, gren); } else { OmonymRule rule = new OmonymRule(ctx); rules.Add(ctx, rule); rule.ProcessSample(line, tokens, left_i, gren); } } } } } } return; }
public void ProcessSample(string line) { if (samples.Contains(line)) { return; } samples.Add(line); bool complete = false; using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeSyntax(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY, 0)) { if (tokens.Count == 3) { complete = true; TraverseNode(tokens[1]); } } if (!complete) { // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { for (int iword = 1; iword < tokens.Count - 2; ++iword) { SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[iword]; SolarixGrammarEngineNET.SyntaxTreeNode token2 = tokens[iword + 1]; if (IsPreposition(token) && IsNoun(token2)) { Store_Prepos_Noun(token, token2); } else if (IsVerb(token) && IsPreposition(token2)) { Store_Verb_Prepos(token, token2); } } } } return; }
public bool ProcessSample(string line) { // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { int last_word_index = tokens.Count - 1; for (int i = 0; i < tokens.Count; ++i) { SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i]; int suffix_id1 = GetTokenSuffix(i, last_word_index, token); int nver = token.VersionCount(); for (int j = 0; j < nver; ++j) { int ver_ekey = token.GetVersionEntryID(j); string ename = gren.GetEntryName(ver_ekey); int suffix_id2 = GetFormSuffix(i, last_word_index, ename); } } } using (SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_TOKENIZE_ONLY)) { int last_word_index = projs.Count - 1; for (int i = 0; i < projs.Count; ++i) { SolarixGrammarEngineNET.SyntaxTreeNode token = projs[i]; int suffix_id1 = GetTokenSuffix(i, last_word_index, token); int nver = token.VersionCount(); for (int j = 0; j < nver; ++j) { int ver_ekey = token.GetVersionEntryID(j); string ename = gren.GetEntryName(ver_ekey); int suffix_id2 = GetFormSuffix(i, last_word_index, ename); } } } return(true); }
public MatchedContextInfo(string _sample, SolarixGrammarEngineNET.AnalysisResults tokens, int left_i, int len) { sample = _sample; System.Text.StringBuilder b = new StringBuilder(); for (int i = 0; i < len; ++i) { string word = tokens[left_i + i].GetWord(); if (i == 0) { b.AppendFormat("{0}", word); } else { b.AppendFormat(" {0}", word); } } context = b.ToString(); return; }
public bool ProcessSample(string line) { n_learn_samples++; // чтобы получить все возможные теги, надо для каждого слова получить все возможные распознавания. using (SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_TOKENIZE_ONLY)) { int last_word_index = projs.Count - 1; for (int iword = 0; iword < projs.Count; ++iword) { for (int iproj = 0; iproj < projs[iword].VersionCount(); ++iproj) { string lemma = string.Empty; int ekey = projs[iword].GetVersionEntryID(iproj); string ename = gren.GetEntryName(ekey); if (IsUnknownLexem(ename)) { lemma = projs[iword].GetWord().ToLower(); } else { lemma = ename.ToLower(); } string sfx = GetTokenSuffix(iword, last_word_index, lemma); int id_lemma = MatchSuffix(sfx, true); } } } // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { List <string> sfx = new List <string>(); List <int> sfx_index = new List <int>(); List <string> sfx_lemma = new List <string>(); List <int> sfx_lemma_index = new List <int>(); int last_word_index = tokens.Count - 1; for (int iword = 0; iword < tokens.Count; ++iword) { string word = tokens[iword].GetWord().ToLower(); string suffix = GetTokenSuffix(iword, last_word_index, tokens[iword]); sfx.Add(suffix); int index = MatchSuffix(suffix, true); sfx_index.Add(index); int ekey = tokens[iword].GetEntryID(); string ename = gren.GetEntryName(ekey); string lemma; if (IsUnknownLexem(ename)) { lemma = word; } else { lemma = ename.ToLower(); } string lemma_suffix = GetTokenSuffix(iword, last_word_index, lemma); sfx_lemma.Add(lemma_suffix); sfx_lemma_index.Add(MatchSuffix(lemma_suffix, true)); } for (int iword = 1; iword < tokens.Count - 1; ++iword) { string tag1 = LemmaLabel(-1, sfx_lemma_index[iword - 1]); // для Витерби // features как контекст +/-1 слово вокруг текущего string tag2 = TagLabel(-1, sfx_index[iword - 1]); string tag3 = TagLabel(0, sfx_index[iword]); string tag4 = TagLabel(1, sfx_index[iword + 1]); string res = ResultLabel(sfx_lemma_index[iword]); WriteTrain(tag1, tag2, tag3, tag4, res); } } return(true); }
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; }
public bool ProcessSample(string line) { // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { List <int> token2tags = new List <int>(); List <int> suffices = new List <int>(); int last_word_index = tokens.Count - 1; bool all_hit = true; for (int i = 0; i < tokens.Count; ++i) { SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i]; string word = token.GetWord().ToLower(); int suffix_id = GetTokenSuffix(i, last_word_index, token); suffices.Add(suffix_id); int tt = tags.MatchTags(token, gren); if (tt == -1) { all_hit = false; break; } token2tags.Add(tags.GetIndexById(tt)); } if (all_hit) { for (int i = 0; i < tokens.Count; ++i) { int tt1 = token2tags[i]; T_counts[tt1]++; //SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i]; //string word = token.GetWord().ToLower(); int suffix_id = suffices[i]; Dictionary <int, int> word_freq; if (B_counts.TryGetValue(tt1, out word_freq)) { int freq0; if (word_freq.TryGetValue(suffix_id, out freq0)) { word_freq[suffix_id] = freq0 + 1; } else { word_freq.Add(suffix_id, 1); } } else { word_freq = new Dictionary <int, int>(); word_freq.Add(suffix_id, 1); B_counts.Add(tt1, word_freq); } if (i > 0) { int tt0 = token2tags[i - 1]; A_counts[tt0, tt1]++; } } } } return(true); }
static void Main(string[] args) { string dictionary_path = @"e:\MVoice\lem\bin-windows\dictionary.xml"; // путь к словарной базе string samples_path = @"E:\MVoice\lem\Слова\rus\SENT5.plain.txt"; // путь к файлу со списком предложений (одно предложение на одной строке) int NSAMPLE = 20000; // сколько предложений максимум обработать int START_INDEX = 0; // порядковый номер первого обрабатываемого предложений в исходном файле int MAXARGS = 20; // beam size bool append_result = false; // если леммы надо добавлять к существующему файлу, а не формировать файл с нуля string save_path = null; // путь к файлу, куда будут записаны леммы int source_format = 0; // 0 - token per line, 1 - sentence per line bool output_lemmas = true; // в результат записывать леммы с приведением к нижнему регистру bool output_suffix = false; bool output_words = false; // в результат записывать исходные слова с приведением к нижнему регистру int suffix_len = 0; int min_sentence_length = 0; // фильтр по минимальной длине предложений int max_sentence_length = int.MaxValue; // фильтр по максимальной длине предложений bool reject_unknown = false; // отбрасывать предложения с несловарными токенами bool emit_eol = false; // добавлять в выходной файл токены <EOL> для маркировки конца предложения int eol_count = 0; // кол-во вставляемых <EOL>, гарантированно перекрывающее размер окна в word2vec List <System.Text.RegularExpressions.Regex> rx_stop = new List <System.Text.RegularExpressions.Regex>(); for (int i = 0; i < args.Length; ++i) { if (args[i] == "-dict") { ++i; dictionary_path = args[i]; } else if (args[i] == "-samples") { ++i; samples_path = args[i]; } else if (args[i] == "-source_format") { ++i; source_format = int.Parse(args[i]); } else if (args[i] == "-append") { // Добавлять в конец существующего файла append_result = true; } else if (args[i] == "-emit_eol") { ++i; eol_count = int.Parse(args[i]); if (eol_count > 0) { emit_eol = true; } } else if (args[i] == "-result") { // Способ обработки токенов: // lemma => лемматизация // suffix => усечение до псевдосуффикса длиной -suffix_len // raw => исходные слова ++i; output_lemmas = false; output_suffix = false; output_words = false; if (args[i] == "suffix") { output_suffix = true; } else if (args[i] == "lemma") { output_lemmas = true; } else if (args[i] == "raw") { output_words = true; } else { throw new ApplicationException(string.Format("Unknown result format: {0}", args[i])); } } else if (args[i] == "-save") { // Путь к файлу, куда будут записываться результаты обработки ++i; save_path = args[i]; } else if (args[i] == "-nsample") { // кол-во обрабатываемых предложений, начиная с -start_index ++i; NSAMPLE = int.Parse(args[i]); } else if (args[i] == "-min_sent_len") { // Обрабатывать только предложения, содержащие не менее NNN токенов ++i; min_sentence_length = int.Parse(args[i]); } else if (args[i] == "-max_sent_len") { // Обрабатывать только предложения, содержащие не более NNN токенов ++i; max_sentence_length = int.Parse(args[i]); } else if (args[i] == "-suffix_len") { ++i; suffix_len = int.Parse(args[i]); } else if (args[i] == "-start_index") { // Начинать обработку с предложения с указанным индексом ++i; START_INDEX = int.Parse(args[i]); } else if (args[i] == "-reject_unknown") { reject_unknown = true; } else if (args[i] == "-rx_stop") { ++i; using (System.IO.StreamReader rdr = new System.IO.StreamReader(args[i])) { while (!rdr.EndOfStream) { string line = rdr.ReadLine(); if (line == null) { break; } line = line.Trim(); if (line.Length > 0) { rx_stop.Add(new System.Text.RegularExpressions.Regex(line)); } } } } else { throw new ApplicationException(string.Format("Unknown option {0}", args[i])); } } Samples sources = null; if (source_format == 1) { sources = new Samples1(samples_path); } else { sources = new Samples2(samples_path); } sources.SetMinSentenceLen(min_sentence_length); sources.SetMaxSentenceLen(max_sentence_length); if (output_suffix || output_words) { sources.SetTokenDelimiter('|'); } SolarixGrammarEngineNET.GrammarEngine2 gren = null; gren = new SolarixGrammarEngineNET.GrammarEngine2(); if (output_lemmas) { gren.Load(dictionary_path, true); } int counter = -1; int n_processed = 1; int MAX_COUNT = NSAMPLE; int LanguageID = SolarixGrammarEngineNET.GrammarEngineAPI.RUSSIAN_LANGUAGE; int Constraints = 120000 | (MAXARGS << 22); // 2 мин и 20 альтернатив SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags Flags = SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_MODEL_ONLY | SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_MODEL; // сколько всего предложений Console.WriteLine("Counting lines in source file {0}...", samples_path); int n_total_lines = sources.TotalCount(); Console.WriteLine("Total number of lines={0}", n_total_lines.ToString("N0", new System.Globalization.CultureInfo("en-US"))); System.IO.StreamWriter wrt = new System.IO.StreamWriter(save_path, append_result, new UTF8Encoding(false)); sources.Start(); while (true) { string sample = sources.Next(); if (sample == null) { break; } sample = sample.Trim(); counter++; if (counter < START_INDEX) { continue; } if (n_processed >= MAX_COUNT) { break; } bool contains_insane_chars = false; foreach (char c in sample) { if (c < 32) { contains_insane_chars = true; break; } } if (contains_insane_chars) { System.Text.StringBuilder b = new StringBuilder(sample.Length); foreach (char c in sample) { if (c >= 32) { b.Append(c); } } sample = b.ToString(); } n_processed++; if (sample.Length == 0) { continue; } if (rx_stop.Count > 0) { bool reject_this_sample = false; foreach (var rx in rx_stop) { if (rx.Match(sample).Success) { reject_this_sample = true; break; } } if (reject_this_sample) { continue; } } if (output_lemmas) { using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(sample, LanguageID, Flags, Constraints)) { for (int i = 1; i < tokens.Count - 1; ++i) { if (char.IsPunctuation(tokens[i].GetWord()[0])) { continue; } int id_entry = tokens[i].GetEntryID(); string lemma = gren.GetEntryName(id_entry); if (lemma == "???" || lemma.Equals("UNKNOWNENTRY", StringComparison.InvariantCultureIgnoreCase) || lemma.Equals("number_", StringComparison.InvariantCultureIgnoreCase)) { lemma = tokens[i].GetWord(); } lemma = lemma.ToLower(); wrt.Write(" {0}", lemma); } } } else if (output_words) { string[] tokens = sample.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); foreach (string token in tokens) { if (token.Length >= 1 && char.IsPunctuation(token[0])) { continue; } string norma = token.ToLower(); wrt.Write(" {0}", norma); } } else if (output_suffix) { string[] tokens = sample.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); foreach (string token in tokens) { if (token.Length == 0 || (token.Length == 1 && char.IsPunctuation(token[0]))) { continue; } string suffix = token; int num; if (int.TryParse(token, out num)) { suffix = token.Substring(token.Length - 1); } else if (token.Length > suffix_len + 1) { suffix = "~" + token.Substring(token.Length - suffix_len); } wrt.Write(" {0}", suffix.ToLower()); } } if (emit_eol) { for (int k = 0; k < eol_count; ++k) { wrt.Write(" <EOL>"); } } Console.WriteLine("[{1}/{2}] {0}", sample, counter, n_total_lines); wrt.Flush(); } wrt.Close(); return; }
/* * public void Check( string line ) * { * // Морфологический разбор * using( SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology( line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.SOL_GREN_COMPLETE_ONLY ) ) * { * // Токенизация без использования синтаксических правил * using( SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology( line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.SOL_GREN_TOKENIZE_ONLY ) ) * { * List<List<int>> word2tags = new List<List<int>>(); * * if( projs.Count != tokens.Count ) * return; * * total_word_count += projs.Count - 2; * * // Для каждого слова получим списки альтернативных лемматизаций. * List<List<string>> word2lemmas = new List<List<string>>(); * * List<string> lemmas = new List<string>(); * * int last_word_index = projs.Count - 1; * * for( int iword = 0; iword < projs.Count; ++iword ) * { * if( iword == 0 || iword == last_word_index ) * { * List<string> w2l = new List<string>(); * w2l.Add( string.Empty ); * word2lemmas.Add( w2l ); * } * else * { * List<string> word_lemmas = new List<string>(); * for( int iproj = 0; iproj < projs[iword].VersionCount(); ++iproj ) * { * string lemma = string.Empty; * int ekey = projs[iword].GetVersionEntryID( iproj ); * string ename = gren.GetEntryName( ekey ); * if( IsUnknownLexem( ename ) ) * lemma = projs[iword].GetWord().ToLower(); * else * lemma = ename.ToLower(); * * if( !word_lemmas.Contains( lemma ) ) * word_lemmas.Add( lemma ); * } * * word2lemmas.Add( word_lemmas ); * } * * lemmas.Add( word2lemmas[iword][0] ); * } * * * for( int iword = 1; iword < projs.Count - 1; ++iword ) * { * string suffix1 = GetTokenSuffix( iword - 1, last_word_index, projs[iword - 1] ); * int id_suffix1 = MatchSuffix( suffix1, false ); * if( id_suffix1 == -1 ) * continue; * * string suffix2 = GetTokenSuffix( iword, last_word_index, projs[iword] ); * int id_suffix2 = MatchSuffix( suffix2, false ); * if( id_suffix2 == -1 ) * continue; * * string suffix3 = GetTokenSuffix( iword + 1, last_word_index, projs[iword + 1] ); * int id_suffix3 = MatchSuffix( suffix3, false ); * if( id_suffix3 == -1 ) * continue; * * string label1 = TagLabel( -1, id_suffix1 ); * string label2 = TagLabel( 0, id_suffix2 ); * string label3 = TagLabel( 1, id_suffix3 ); * * * System.Collections.ArrayList context = new System.Collections.ArrayList(); * context.Add( label1 ); * context.Add( label2 ); * context.Add( label3 ); * * double[] probabilities = mModel.Evaluate( (string[])context.ToArray( typeof( string ) ) ); * * // теперь надо выбрать самый достоверный вариант. * double best_score = 0; * * // теперь перебираем проекции и смотрим, которая из них имеет в нормальной форме выбранный суффикс. * for( int iproj = 0; iproj < word2lemmas[iword].Count; ++iproj ) * { * string ename = word2lemmas[iword][iproj]; * string proj_suffix = GetSuffix( ename.ToLower() ); * int id_suffix = MatchSuffix( proj_suffix, false ); * if( id_suffix == -1 ) * continue; * * string res_label = ResultLabel( id_suffix ); * * if( !result_label2id.ContainsKey( res_label ) ) * continue; * * int res_label_index = result_label2id[res_label]; * * double p = probabilities[res_label_index]; * * if( p > best_score ) * { * best_score = p; * lemmas[iword] = ename.ToLower(); * } * } * } * * * // Теперь сравниваем леммы c правильными значениями. * for( int iword = 1; iword < tokens.Count - 1; ++iword ) * { * string mustbe = string.Empty; * * int ekey = tokens[iword].GetEntryID(); * string ename = gren.GetEntryName( ekey ); * * if( IsUnknownLexem( ename ) ) // не будем учитывать ошибки лемматизации для не-словарных лексем. * continue; * * mustbe = ename.ToLower(); * * if( mustbe != lemmas[iword] ) * error_count_with_ngram++; * * string lemma0 = string.Empty; * int ekey0 = projs[iword].GetEntryID(); * string ename0 = gren.GetEntryName( ekey0 ); * if( IsUnknownLexem( ename0 ) ) * continue; * * lemma0 = ename0.ToLower(); * * if( mustbe != lemma0 ) * error_count_no_filter++; * } * } * } * * return; * } */ public void Check(string line) { // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { total_word_count += tokens.Count - 2; System.Text.StringBuilder b = new System.Text.StringBuilder(); b.Capacity = 100; // Для каждого слова получим списки альтернативных лемматизаций. List <List <string> > word2lemmas = new List <List <string> >(); List <string> lemmas = new List <string>(); List <int> model_lemma_id = new List <int>(); int last_word_index = tokens.Count - 1; for (int iword = 0; iword < tokens.Count; ++iword) { if (iword == 0 || iword == last_word_index) { List <string> w2l = new List <string>(); w2l.Add(string.Empty); word2lemmas.Add(w2l); } else { List <string> word_lemmas = new List <string>(); string word = tokens[iword].GetWord(); System.IntPtr hLemmas = SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_GetLemmasW(lemm_engine, word); if (hLemmas == System.IntPtr.Zero) { throw new System.ApplicationException(); } int nlemma = SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_CountLemmas(hLemmas); for (int i = 0; i < nlemma; ++i) { b.Length = 0; SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_GetLemmaStringW(hLemmas, i, b, b.Capacity); string lemma = b.ToString().ToLower(); if (!word_lemmas.Contains(lemma)) { word_lemmas.Add(lemma); } } SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_DeleteLemmas(hLemmas); word2lemmas.Add(word_lemmas); } lemmas.Add(word2lemmas[iword][0]); model_lemma_id.Add(0); } for (int iword = 1; iword < tokens.Count - 1; ++iword) { string suffix1 = GetTokenSuffix(iword - 1, last_word_index, tokens[iword - 1]); int id_suffix1 = MatchSuffix(suffix1, false); if (id_suffix1 == -1) { continue; } string suffix2 = GetTokenSuffix(iword, last_word_index, tokens[iword]); int id_suffix2 = MatchSuffix(suffix2, false); if (id_suffix2 == -1) { continue; } string suffix3 = GetTokenSuffix(iword + 1, last_word_index, tokens[iword + 1]); int id_suffix3 = MatchSuffix(suffix3, false); if (id_suffix3 == -1) { continue; } string label1 = TagLabel(-1, id_suffix1); string label2 = TagLabel(0, id_suffix2); string label3 = TagLabel(1, id_suffix3); System.Collections.ArrayList context = new System.Collections.ArrayList(); context.Add(label1); context.Add(label2); context.Add(label3); double[] probabilities = mModel.Evaluate((string[])context.ToArray(typeof(string))); // теперь надо выбрать самый достоверный вариант. double best_score = 0; // теперь перебираем проекции и смотрим, которая из них имеет в нормальной форме выбранный суффикс. for (int iproj = 0; iproj < word2lemmas[iword].Count; ++iproj) { string ename = word2lemmas[iword][iproj]; string proj_suffix = GetSuffix(ename.ToLower()); int id_suffix = MatchSuffix(proj_suffix, false); if (id_suffix == -1) { continue; } string res_label = ResultLabel(id_suffix); if (!result_label2id.ContainsKey(res_label)) { continue; } int res_label_index = result_label2id[res_label]; double p = probabilities[res_label_index]; if (p > best_score) { best_score = p; model_lemma_id[iword] = id_suffix; lemmas[iword] = ename.ToLower(); } } } // Теперь сравниваем леммы c правильными значениями. for (int iword = 1; iword < tokens.Count - 1; ++iword) { string mustbe = string.Empty; int ekey = tokens[iword].GetEntryID(); string ename = gren.GetEntryName(ekey); if (IsUnknownLexem(ename)) // не будем учитывать ошибки лемматизации для не-словарных лексем. { continue; } mustbe = ename.ToLower(); // отдельно считаем все ошибки модели, так как часть из них могут быть // скрыты при выборе леммы в случаях, когда есть только один правильный вариант леммы, и он не совпадает с выбором модели. string mustbe_suffix = GetSuffix(mustbe); int mustbe_id_suffix = MatchSuffix(mustbe_suffix, false); if (mustbe_id_suffix != model_lemma_id[iword]) { raw_model_error_count++; } if (mustbe != lemmas[iword]) { error_count_with_ngram++; } string lemma0 = word2lemmas[iword][0].ToLower(); if (mustbe != lemma0) { error_count_no_filter++; } } } return; }
public string NormalizePhrase(AnalysisResults linkages) { return(SolarixGrammarEngineNET.GrammarEngine.NormalizePhraseFX(_hEngine, linkages.GetHandle())); }
public AnalysisResults AnalyzeMorphology( string phrase, int id_language ) { IntPtr hPack = GrammarEngine.sol_MorphologyAnalysis( _hEngine, phrase, 0, 0, 0, id_language ); AnalysisResults res = new AnalysisResults( this, hPack ); return res; }
public AnalysisResults AnalyzeSyntax( string _phrase, int id_language ) { IntPtr hPack = GrammarEngine.sol_SyntaxAnalysis( _hEngine, _phrase, 0, 0, 60000, id_language ); AnalysisResults res = new AnalysisResults( this, hPack ); return res; }
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)) { // Токенизация без использования синтаксических правил 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; } int last_word_index = projs.Count - 1; // ----------------------------------------- // Посчитаем ошибки до применения модели // ----------------------------------------- int n_err = 0; for (int iword = 1; iword < last_word_index; ++iword) { SolarixGrammarEngineNET.SyntaxTreeNode proj = projs[iword]; int ekey0 = proj.GetEntryID(); int id_class0 = gren.GetEntryClass(ekey0); // Совпадает с точным значением? SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[iword]; int ekey1 = token.GetEntryID(); int id_class1 = gren.GetEntryClass(ekey1); if (id_class0 != id_class1) { n_err++; } } error_count_no_filter += n_err; total_word_count += (tokens.Count - 2); List <int> n_pos = new List <int>(); // кол-во разных частей речи для каждого токена List <int> word2tags = new List <int>(); // Преобразуем все проекции каждого слова в варианты распознавания тегов for (int i = 0; i < tokens.Count; ++i) { SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i]; int index = GetTokenSuffix(i, last_word_index, token); word2tags.Add(index); // На сколько разных частей речи проецируется данное слово List <int> pos_list = new List <int>(); for (int k = 0; k < projs[i].VersionCount(); ++k) { int ekey0 = projs[i].GetVersionEntryID(k); int id_class0 = gren.GetEntryClass(ekey0); if (!pos_list.Contains(id_class0)) { pos_list.Add(id_class0); } } n_pos.Add(pos_list.Count); } List <Dictionary <int, int> > pos_score = new List <Dictionary <int, int> >(); List <int> pos_score_order = new List <int>(); // Инициализируем вектор частей речи значениями, которые соответствуют // чамым частотным словоформам. for (int iword = 0; iword < tokens.Count - 1; ++iword) { SolarixGrammarEngineNET.SyntaxTreeNode proj = projs[iword]; Dictionary <int, int> p = new Dictionary <int, int>(); for (int iproj = 0; iproj < proj.VersionCount(); ++iproj) { int ekey = proj.GetVersionEntryID(iproj); int id_class = gren.GetEntryClass(ekey); if (!p.ContainsKey(id_class)) { if (iproj == 0) { p.Add(id_class, 1); } else { p.Add(id_class, 0); } } } pos_score.Add(p); pos_score_order.Add(1); } // --------------------------------- // теперь применим модель // --------------------------------- bool use_4grams = true; bool use_3grams = true; bool use_2grams = true; for (int iword = 1; iword < tokens.Count - 1; ++iword) { string word = tokens[iword].GetWord(); bool applied = false; // ============== // ТЕТРАГРАММЫ // ============== if (use_4grams && !applied && iword > 2) { if (n_pos[iword] > 1) // Выбираем POS для iword на основе iword-3,iword-2,iword-1 { int tag0 = word2tags[iword - 3]; int tag1 = word2tags[iword - 2]; int tag2 = word2tags[iword - 1]; List <NGram4> n4_list; Int3 k = new Int3(tag0, tag1, tag2); if (tag0_2_ngram4.TryGetValue(k, out n4_list)) { // Перебираем варианты, которые вытекают из наличия тегов tag0,tag1,tag2 и прибавляем очки соответствующим частям речи. foreach (NGram4 n4_probe in n4_list) { int tag3 = n4_probe.tags3; TagMatcher m = selectors[tag3]; List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >(); Dictionary <int, int> pos2score = pos_score[iword]; foreach (KeyValuePair <int, int> p in pos2score) { if (m.MatchPartOfSpeech(p.Key)) { int m_freq = ngrams4[n4_probe]; changes.Add(new KeyValuePair <int, int>(p.Key, m_freq)); applied = true; } } foreach (var kv in changes) { pos2score[kv.Key] = pos2score[kv.Key] + kv.Value; } pos_score_order[iword] = 4; } } } else if (n_pos[iword - 1] > 1 && pos_score_order[iword - 1] < 4) // Выбираем POS для iword-1 на основе iword-3,iword-2,iword { int tag0 = word2tags[iword - 3]; int tag1 = word2tags[iword - 2]; int tag3 = word2tags[iword]; List <NGram4> n4_list; Int3 k = new Int3(tag0, tag1, tag3); if (tag1_2_ngram4.TryGetValue(k, out n4_list)) { // Перебираем варианты, которые вытекают из наличия тегов tag0,tag1,tag2 и прибавляем очки соответствующим частям речи. foreach (NGram4 n4_probe in n4_list) { int tag2 = n4_probe.tags2; TagMatcher m = selectors[tag2]; List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >(); Dictionary <int, int> pos2score = pos_score[iword]; foreach (KeyValuePair <int, int> p in pos2score) { if (m.MatchPartOfSpeech(p.Key)) { int m_freq = ngrams4_1[n4_probe]; changes.Add(new KeyValuePair <int, int>(p.Key, m_freq)); applied = true; } } foreach (var kv in changes) { pos2score[kv.Key] = pos2score[kv.Key] + kv.Value; } pos_score_order[iword - 1] = 4; } } } } // ============== // ТРИГРАММЫ // ============== if (use_3grams && !applied && iword > 1) { if (n_pos[iword] > 1) // Выбираем POS для iword на основе iword-2,iword-1 { { int tag0 = word2tags[iword - 2]; int tag1 = word2tags[iword - 1]; List <NGram3> n3_list; Int2 k = new Int2(tag0, tag1); if (tag0_2_ngram3.TryGetValue(k, out n3_list)) { // Перебираем варианты, которые вытекают из наличия тегов tag0,tag1, и прибавляем очки соответствующим частям речи. foreach (NGram3 n3_probe in n3_list) { int tag2 = n3_probe.tags2; TagMatcher m = selectors[tag2]; List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >(); Dictionary <int, int> pos2score = pos_score[iword]; foreach (KeyValuePair <int, int> p in pos2score) { if (m.MatchPartOfSpeech(p.Key)) { int m_freq = ngrams3[n3_probe]; changes.Add(new KeyValuePair <int, int>(p.Key, m_freq)); applied = true; } } foreach (var kv in changes) { pos2score[kv.Key] = pos2score[kv.Key] + kv.Value; } } } } if (iword < last_word_index) { // iword-1 --> iword <-- iword+1 int tag0 = word2tags[iword - 1]; int tag2 = word2tags[iword + 1]; List <NGram3> n3_list; Int2 k = new Int2(tag0, tag2); if (tag1_2_ngram3.TryGetValue(k, out n3_list)) { // Перебираем варианты, которые вытекают из наличия тегов tag0,tag2, и прибавляем очки соответствующим частям речи. foreach (NGram3 n3_probe in n3_list) { int tag1 = n3_probe.tags1; TagMatcher m = selectors[tag1]; List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >(); Dictionary <int, int> pos2score = pos_score[iword]; foreach (KeyValuePair <int, int> p in pos2score) { if (m.MatchPartOfSpeech(p.Key)) { int m_freq = ngrams3_1[n3_probe]; changes.Add(new KeyValuePair <int, int>(p.Key, m_freq)); applied = true; } } foreach (var kv in changes) { pos2score[kv.Key] = pos2score[kv.Key] + kv.Value; } pos_score_order[iword] = 3; } } } } else if (n_pos[iword - 1] > 1 && pos_score_order[iword - 1] < 3) // Выбираем POS для iword-1 на основе iword-2,iword { int tag0 = word2tags[iword - 2]; int tag2 = word2tags[iword]; List <NGram3> n3_list; Int2 k = new Int2(tag0, tag2); if (tag1_2_ngram3.TryGetValue(k, out n3_list)) { // Перебираем варианты, которые вытекают из наличия тегов tag0,tag2, и прибавляем очки соответствующим частям речи. foreach (NGram3 n3_probe in n3_list) { int tag1 = n3_probe.tags1; TagMatcher m = selectors[tag1]; List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >(); Dictionary <int, int> pos2score = pos_score[iword]; foreach (KeyValuePair <int, int> p in pos2score) { if (m.MatchPartOfSpeech(p.Key)) { int m_freq = ngrams3_1[n3_probe]; changes.Add(new KeyValuePair <int, int>(p.Key, m_freq)); applied = true; } } foreach (var kv in changes) { pos2score[kv.Key] = pos2score[kv.Key] + kv.Value; } pos_score_order[iword] = 3; } } } } // ============== // ДИГРАММЫ // ============== if (use_2grams && !applied && iword > 1) { if (n_pos[iword] > 1) // Выбираем POS для iword на основе iword-1 { { int tag0 = word2tags[iword - 1]; List <NGram2> n2_list; if (tag0_2_ngram2.TryGetValue(tag0, out n2_list)) { // Перебираем варианты, которые вытекают из наличия тега tag0, и прибавляем очки соответствующим частям речи. foreach (NGram2 n2_probe in n2_list) { int tag1 = n2_probe.tags1; TagMatcher m = selectors[tag1]; List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >(); Dictionary <int, int> pos2score = pos_score[iword]; foreach (KeyValuePair <int, int> p in pos2score) { if (m.MatchPartOfSpeech(p.Key)) { int m_freq = ngrams2[n2_probe]; changes.Add(new KeyValuePair <int, int>(p.Key, m_freq)); applied = true; } } foreach (var kv in changes) { pos2score[kv.Key] = pos2score[kv.Key] + kv.Value; } pos_score_order[iword] = 2; } } } if (iword < last_word_index) { // iword <-- iword+1 int tag1 = word2tags[iword + 1]; List <NGram2> n2_list; if (tag1_2_ngram2.TryGetValue(tag1, out n2_list)) { // Перебираем варианты, которые вытекают из наличия тега tag1, и прибавляем очки соответствующим частям речи. foreach (NGram2 n2_probe in n2_list) { int tag0 = n2_probe.tags0; TagMatcher m = selectors[tag0]; List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >(); Dictionary <int, int> pos2score = pos_score[iword]; foreach (KeyValuePair <int, int> p in pos2score) { if (m.MatchPartOfSpeech(p.Key)) { int m_freq = ngrams2_1[n2_probe]; changes.Add(new KeyValuePair <int, int>(p.Key, m_freq)); applied = true; } } foreach (var kv in changes) { pos2score[kv.Key] = pos2score[kv.Key] + kv.Value; } pos_score_order[iword] = 2; } } } } else if (n_pos[iword - 1] > 1 && pos_score_order[iword - 1] == 1) // Выбираем POS для iword-1 на основе iword { int tag1 = word2tags[iword]; List <NGram2> n2_list; if (tag1_2_ngram2.TryGetValue(tag1, out n2_list)) { // Перебираем варианты, которые вытекают из наличия тега tag1, и прибавляем очки соответствующим частям речи. foreach (NGram2 n2_probe in n2_list) { int tag0 = n2_probe.tags0; TagMatcher m = selectors[tag0]; List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >(); Dictionary <int, int> pos2score = pos_score[iword - 1]; foreach (KeyValuePair <int, int> p in pos2score) { if (m.MatchPartOfSpeech(p.Key)) { int m_freq = ngrams2_1[n2_probe]; changes.Add(new KeyValuePair <int, int>(p.Key, m_freq)); applied = true; } } foreach (var kv in changes) { pos2score[kv.Key] = pos2score[kv.Key] + kv.Value; } pos_score_order[iword - 1] = 2; } } } } } // Все вероятности перехода учтены. // Совпадает ли selected_id_class с требуемыми значениями? for (int iword = 1; iword < projs.Count - 1; ++iword) { Dictionary <int, int> word_pos_scores = pos_score[iword]; int best_score = 0; int best_pos = -1; foreach (KeyValuePair <int, int> k in word_pos_scores) { if (k.Value > best_score) { best_score = k.Value; best_pos = k.Key; } } SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[iword]; int ekey1 = token.GetEntryID(); int id_class1 = gren.GetEntryClass(ekey1); if (best_pos != id_class1) { error_count_with_model++; } } } } return; }
public void Collect(SolarixGrammarEngineNET.AnalysisResults tokens, SolarixGrammarEngineNET.AnalysisResults trees, SolarixGrammarEngineNET.GrammarEngine2 gren) { if (trees.Count == 3) { SolarixGrammarEngineNET.SyntaxTreeNode root = trees[1]; int p_ekey = root.GetEntryID(); int id_class = gren.GetEntryClass(p_ekey); if ( id_class == SolarixGrammarEngineNET.GrammarEngineAPI.IMPERSONAL_VERB_ru || id_class == SolarixGrammarEngineNET.GrammarEngineAPI.VERB_ru || id_class == SolarixGrammarEngineNET.GrammarEngineAPI.INFINITIVE_ru ) { ok = true; } } if (ok) { int N = tokens.Count; labels = new List <List <string> >(); for (int iroot = 0; iroot < N; ++iroot) { List <string> x = new List <string>(); x.Add("O"); labels.Add(x); } for (int iroot = 1; iroot < trees.Count - 1; ++iroot) { ProcessTree(trees[iroot], gren); } // ----------------------------------------------- // Уточняем разметку для групп существительных // ----------------------------------------------- for (int i = 1; i < N - 1; ++i) { List <string> l = labels[i]; if (l[0].StartsWith("NP")) { string NP = l[0]; // меняем метку у первого токена на B-NP l.RemoveAt(0); l.Insert(0, "B-NP"); // идем вправо до появления другой NP-метки. for (int k = i + 1; k < N; ++k) { if (labels[k][0] == NP) { labels[k].RemoveAt(0); labels[k].Insert(0, "I-NP"); } else { // Удалим все появления NP-метки далее вправо. for (int q = k; q < N; ++q) { labels[q].Remove(NP); } break; } } } } // Уточняем разметку для глагольных групп. for (int i = 1; i < N - 1; ++i) { List <string> l = labels[i]; if (l[0].StartsWith("VX")) { // Корневой глагол в сказуемом. // Цепочка токенов в группе может быть разорвана из-за того, что наречный оборот, привязанный к сказуемому, // стоит справа от глагольного дополнения. Поэтому проверим наличие таких разрывов. l.RemoveAt(0); // под VX лежит VP, который мы сейчас поднимем string VP = l[0]; int vp_begin = i; // ищем разрыв слева for (int k = i - 1; k >= 0; --k) { if (labels[k][0] != VP) { // слева - конец цепочки токенов для этого сказуемого. Удалим все более левые упоминания этого VP. for ( ; k >= 0; --k) { labels[k].Remove(VP); } break; } else { vp_begin = k; } } int vp_end = i; // ищем разрыв справа for (int k = i + 1; k < N; ++k) { if (labels[k][0] != VP) { // справа - конец цепочки токенов для этого сказуемого. Удалим все более правые упоминания этого VP. for ( ; k < N; ++k) { labels[k].Remove(VP); } break; } else { vp_end = k; } } // поставим отметку на первый VP-токен labels[vp_begin].RemoveAt(0); labels[vp_begin].Insert(0, "B-VP"); // а остальные пометим как I-VP for (int j = vp_begin + 1; j <= vp_end; ++j) { labels[j].Remove(VP); labels[j].Insert(0, "I-VP"); } } } for (int i = 0; i < labels.Count; ++i) { string l = labels[i][0]; string[] t = l.Split(':'); labels[i].Clear(); labels[i].Add(t[0]); } } return; }
private bool IsBoundaryToken(SolarixGrammarEngineNET.AnalysisResults tokens, int index) { return(index == 0 || index == tokens.Count - 1); }
public bool ProcessSample2(string line) { // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { List <int> token2tags = new List <int>(); List <int> suffices = new List <int>(); int last_word_index = tokens.Count - 1; bool all_hit = true; for (int i = 0; i < tokens.Count; ++i) { SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i]; string word = token.GetWord().ToLower(); int suffix_id = GetTokenSuffix(i, last_word_index, token); suffices.Add(suffix_id); int lemma_suffix_id = GetLemmaSuffix(i, last_word_index, token); token2tags.Add(lemma_suffix_id); } if (all_hit) { for (int i = 0; i < tokens.Count; ++i) { int tt1 = token2tags[i]; T_counts[tt1]++; //SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i]; //string word = token.GetWord().ToLower(); int suffix_id = suffices[i]; // обновляем матрицу со счетчиками эмиссии. Dictionary <int, int> word_freq; if (B_counts.TryGetValue(tt1, out word_freq)) { int freq0; if (word_freq.TryGetValue(suffix_id, out freq0)) { word_freq[suffix_id] = freq0 + 1; } else { word_freq.Add(suffix_id, 1); } } else { word_freq = new Dictionary <int, int>(); word_freq.Add(suffix_id, 1); B_counts.Add(tt1, word_freq); } if (i > 0) { // обновляем счетчики переходов между суффиксами лемм. int tt0 = token2tags[i - 1]; A_counts[tt0, tt1]++; } } } } return(true); }
public bool ProcessSample(string line) { int occurence_count = 0; // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { for (int i = 1; i < tokens.Count - 1; ++i) { SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i]; string word = token.GetWord().ToLower(); if (retrieve_omonyms_from_samples) { if (omonyms.Contains(word)) { occurence_count++; omonym_processors[word].ProcessSample(line, tokens, LanguageID, gren); } else if (!not_omonyms.Contains(word) && omonyms.Count < MaxOmonymPerSession) { bool is_omonym = false; if (!ignore_omonyms.Contains(word)) { // сделаем проекцию слова int id_class0 = -1; using (SolarixGrammarEngineNET.WordProjections projs = gren.FindWordForm(word)) { for (int j = 0; j < projs.Count; ++j) { int id_entry = projs.GetEntryKey(j); int id_class = gren.GetEntryClass(id_entry); if (id_class0 == -1) { id_class0 = id_class; } else if (id_class0 != id_class) { is_omonym = true; break; } } } if (is_omonym) { omonyms.Add(word); OmonymProcessor processor = new OmonymProcessor(word); omonym_processors.Add(word, processor); occurence_count++; omonym_processors[word].ProcessSample(line, tokens, LanguageID, gren); } else { not_omonyms.Add(word); } } } } else if (omonyms.Contains(word)) { occurence_count++; omonym_processors[word].ProcessSample(line, tokens, LanguageID, gren); } } } return(occurence_count > 0); }
public string NormalizePhrase( AnalysisResults linkages ) { return SolarixGrammarEngineNET.GrammarEngine.NormalizePhraseFX( _hEngine, linkages.GetHandle() ); }
public void Check(string line) { // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { // Токенизация без использования синтаксических правил using (SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_TOKENIZE_ONLY)) { List <List <int> > word2tags = new List <List <int> >(); if (projs.Count != tokens.Count) { return; } total_word_count += projs.Count - 2; // Для каждого слова получим списки альтернативных лемматизаций. List <List <string> > word2lemmas = new List <List <string> >(); List <List <int> > word2lemma_index = new List <List <int> >(); List <string> lemmas = new List <string>(); int last_word_index = projs.Count - 1; List <string> word_suffix = new List <string>(); for (int iword = 0; iword < projs.Count; ++iword) { string suffix = GetTokenSuffix(iword, last_word_index, tokens[iword]); word_suffix.Add(suffix); } for (int iword = 0; iword < projs.Count; ++iword) { if (iword == 0 || iword == last_word_index) { List <string> w2l = new List <string>(); w2l.Add(string.Empty); word2lemmas.Add(w2l); List <int> w2i = new List <int>(); w2i.Add(-1); word2lemma_index.Add(w2i); } else { List <string> word_lemmas = new List <string>(); List <int> word_results = new List <int>(); for (int iproj = 0; iproj < projs[iword].VersionCount(); ++iproj) { string lemma = string.Empty; int ekey = projs[iword].GetVersionEntryID(iproj); string ename = gren.GetEntryName(ekey); if (IsUnknownLexem(ename)) { lemma = projs[iword].GetWord().ToLower(); } else { lemma = ename.ToLower(); } if (!word_lemmas.Contains(lemma)) { word_lemmas.Add(lemma); int result = MatchSuffix(GetSuffix(lemma), false); word_results.Add(result); } } word2lemmas.Add(word_lemmas); word2lemma_index.Add(word_results); } lemmas.Add(word2lemmas[iword][0]); } for (int iword = 1; iword < projs.Count - 1; ++iword) { List <double> P_lemma = new List <double>(); for (int k = 0; k < word2lemma_index[iword].Count; ++k) { if (k == 0) { P_lemma.Add(1.0); } else { P_lemma.Add(1.0); } } // текущее слово string word0 = projs[iword].GetWord().ToLower(); string suffix0 = word_suffix[iword]; int id_suffix0 = MatchSuffix(suffix0, false); if (id_suffix0 == -1) { continue; } string tag0 = TagLabel(0, id_suffix0); int N_TOTAL0 = GetFeatureCount(tag0); for (int k = 0; k < word2lemma_index[iword].Count; ++k) { int lemma_index = word2lemma_index[iword][k]; int N_LEMMA0 = GetFeature2ResultCount(tag0, lemma_index); if (N_TOTAL0 > 0 && N_LEMMA0 > 0) { double p = ((double)N_LEMMA0) / ((double)N_TOTAL0); P_lemma[k] *= p; } } // предыдущее слово if (iword > 0) { string word1 = projs[iword - 1].GetWord().ToLower(); string suffix1 = word_suffix[iword - 1]; int id_suffix1 = MatchSuffix(suffix1, false); if (id_suffix1 == -1) { continue; } string tag1 = TagLabel(-1, id_suffix1); int N_TOTAL1 = GetFeatureCount(tag1); for (int k = 0; k < word2lemma_index[iword].Count; ++k) { int lemma_index = word2lemma_index[iword][k]; int N_LEMMA1 = GetFeature2ResultCount(tag1, lemma_index); if (N_TOTAL1 > 0 && N_LEMMA1 > 0) { double p = ((double)N_LEMMA1) / ((double)N_TOTAL1); P_lemma[k] *= p; } } } // следующее слово if (iword < projs.Count - 1) { string word2 = projs[iword + 1].GetWord().ToLower(); string suffix2 = word_suffix[iword + 1]; int id_suffix2 = MatchSuffix(suffix2, false); if (id_suffix2 == -1) { continue; } string tag2 = TagLabel(1, id_suffix2); int N_TOTAL2 = GetFeatureCount(tag2); for (int k = 0; k < word2lemma_index[iword].Count; ++k) { int lemma_index = word2lemma_index[iword][k]; int N_LEMMA2 = GetFeature2ResultCount(tag2, lemma_index); if (N_TOTAL2 > 0 && N_LEMMA2 > 0) { double p = ((double)N_LEMMA2) / ((double)N_TOTAL2); P_lemma[k] *= p; } } } // теперь надо выбрать самый достоверный вариант. double best_P = 0; for (int iproj = 0; iproj < word2lemmas[iword].Count; ++iproj) { double p = P_lemma[iproj]; if (p > best_P) { best_P = p; lemmas[iword] = word2lemmas[iword][iproj]; } } } // Теперь сравниваем леммы c правильными значениями. for (int iword = 1; iword < tokens.Count - 1; ++iword) { string mustbe = string.Empty; int ekey = tokens[iword].GetEntryID(); string ename = gren.GetEntryName(ekey); if (IsUnknownLexem(ename)) // не будем учитывать ошибки лемматизации для не-словарных лексем. { continue; } mustbe = ename.ToLower(); if (mustbe != lemmas[iword]) { error_count_with_ngram++; } string lemma0 = string.Empty; int ekey0 = projs[iword].GetEntryID(); string ename0 = gren.GetEntryName(ekey0); if (IsUnknownLexem(ename0)) { continue; } lemma0 = ename0.ToLower(); if (mustbe != lemma0) { error_count_no_filter++; } } } } return; }
public void Check(string line) { // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { // Токенизация без использования синтаксических правил using (SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_TOKENIZE_ONLY)) { List <List <int> > word2tags = new List <List <int> >(); if (projs.Count != tokens.Count) { return; } total_word_count += projs.Count - 2; // Для каждого слова получим списки альтернативных лемматизаций. List <List <string> > word2lemmas = new List <List <string> >(); List <List <int> > word2lemma_id = new List <List <int> >(); List <string> lemmas = new List <string>(); int last_word_index = projs.Count - 1; List <List <double> > viterbi_P = new List <List <double> >(); List <List <int> > viterbi_backpointer = new List <List <int> >(); for (int iword = 0; iword < projs.Count; ++iword) { if (iword == 0 || iword == last_word_index) { List <string> w2l = new List <string>(); w2l.Add(string.Empty); word2lemmas.Add(w2l); List <int> w2li = new List <int>(); w2li.Add(MatchSuffix(GetTokenSuffix(0, last_word_index, projs[iword]), false)); word2lemma_id.Add(w2li); } else { List <string> word_lemmas = new List <string>(); List <int> word_lemma_ids = new List <int>(); for (int iproj = 0; iproj < projs[iword].VersionCount(); ++iproj) { string lemma = string.Empty; int ekey = projs[iword].GetVersionEntryID(iproj); string ename = gren.GetEntryName(ekey); if (IsUnknownLexem(ename)) { lemma = projs[iword].GetWord().ToLower(); } else { lemma = ename.ToLower(); } if (!word_lemmas.Contains(lemma)) { word_lemmas.Add(lemma); int id_lemma = MatchSuffix(GetSuffix(lemma), false); if (id_lemma == -1) { throw new System.ApplicationException(); } word_lemma_ids.Add(id_lemma); } } word2lemmas.Add(word_lemmas); word2lemma_id.Add(word_lemma_ids); } lemmas.Add(word2lemmas[iword][0]); List <double> px = new List <double>(); List <int> bx = new List <int>(); for (int i = 0; i < word2lemmas[iword].Count; ++i) { if (iword == 0) { px.Add(1.0); // состояние START } else { px.Add(0.0); // для остальных столбцов пока не знаем } bx.Add(-1); } viterbi_P.Add(px); viterbi_backpointer.Add(bx); } // Для каждого слова получим id_suffix List <int> word_suffices = new List <int>(); for (int iword = 0; iword < projs.Count; ++iword) { string word = projs[iword].GetWord().ToLower(); string suffix = GetTokenSuffix(iword, last_word_index, projs[iword]); int id_suffix = MatchSuffix(suffix, false); if (id_suffix == -1) { continue; } word_suffices.Add(id_suffix); } // расчет по решетке for (int iword = 1; iword < projs.Count - 1; ++iword) { // в этом столбце столько разных состояний int n_states = word2lemmas[iword].Count; // сразу получим теги для контекста int id_suffix1 = word_suffices[iword - 1]; int id_suffix2 = word_suffices[iword]; int id_suffix3 = word_suffices[iword + 1]; string label1 = TagLabel(-1, id_suffix1); string label2 = TagLabel(0, id_suffix2); string label3 = TagLabel(1, id_suffix3); for (int istate = 0; istate < n_states; ++istate) { // для состояния istate получим целевую метку для леммы int id_result_lemma = word2lemma_id[iword][istate]; string result_label = ResultLabel(id_result_lemma); if (!result_label2id.ContainsKey(result_label)) { // переходов в такое состояние не было вообще, будет нулевая верояность continue; } int res_label_index = result_label2id[result_label]; // просматриваем переходы из состояний предыдущего шага int n_prev_states = word2lemmas[iword - 1].Count; double best_p = -1.0; int best_prev_state_index = -1; for (int i_prev_state = 0; i_prev_state < n_prev_states; ++i_prev_state) { int id_prev_lemma = word2lemma_id[iword - 1][i_prev_state]; string prev_lemma_label = LemmaLabel(-1, id_prev_lemma); double P_prev = viterbi_P[iword - 1][i_prev_state]; // запускаем модель для получения достоверности нового состояния System.Collections.ArrayList context = new System.Collections.ArrayList(); context.Add(prev_lemma_label); context.Add(label1); context.Add(label2); context.Add(label3); try { double[] probabilities = mModel.Evaluate((string[])context.ToArray(typeof(string))); double p = probabilities[res_label_index]; double P12 = p * P_prev; // вероятность данного перехода if (P12 > best_p) { best_p = P12; best_prev_state_index = i_prev_state; } } catch (System.Exception ex) { // ... обычно это означает, что встретился ключ, которые не был включен в обучающий набор. // будем считать, что у таких переходов нулевая вероятность.s } } if (n_states == 1) { // если на данном шаге всего 1 состояние, то можем принудительно присвоить ему накопленную достоверность=1 и таким образом // улучшить поведение модели при появлении неизвестных слов, приводящих к обнулению вероятностей. viterbi_P[iword][istate] = 1.0; } else { viterbi_P[iword][istate] = best_p; } viterbi_backpointer[iword][istate] = best_prev_state_index; } } // Для последнего состояния END просто найдем самое достоверное на пред. шаге double best_P1 = 0; int best_state1 = 0; for (int i = 0; i < word2lemmas[last_word_index - 1].Count; ++i) { double p = viterbi_P[last_word_index - 1][i]; if (p > best_P1) { best_P1 = p; best_state1 = i; } } viterbi_P[last_word_index][0] = best_P1; viterbi_backpointer[last_word_index][0] = best_state1; // теперь обратный проход по решетке, через записи в backpointer'ах восстанавливаем самую достоверную цепочку лемм // для последнего шага - всего одно состояние END. int cur_backpointer = viterbi_backpointer[projs.Count - 1][0]; int j = projs.Count - 2; List <string> best_lemmas = new List <string>(); for (int k = 0; k < projs.Count; ++k) { best_lemmas.Add(string.Empty); } while (j > 0) { // для этого шага - такая лучшая лемма string best_lemma = word2lemmas[j][cur_backpointer]; best_lemmas[j] = best_lemma; // определяем лучшее состояние для предыдущего шага int prev_backpointer = viterbi_backpointer[j][cur_backpointer]; cur_backpointer = prev_backpointer; j--; } // Теперь сравниваем леммы c правильными значениями. for (int iword = 1; iword < tokens.Count - 1; ++iword) { string mustbe = string.Empty; int ekey = tokens[iword].GetEntryID(); string ename = gren.GetEntryName(ekey); if (IsUnknownLexem(ename)) // не будем учитывать ошибки лемматизации для не-словарных лексем. { continue; } mustbe = ename.ToLower(); if (mustbe != best_lemmas[iword]) { error_count_with_ngram++; } string lemma0 = string.Empty; int ekey0 = projs[iword].GetEntryID(); string ename0 = gren.GetEntryName(ekey0); if (IsUnknownLexem(ename0)) { continue; } lemma0 = ename0.ToLower(); if (mustbe != lemma0) { error_count_no_filter++; } } } } return; }
public AnalysisResults AnalyzeSyntax( string phrase, int id_language, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags morph_flags, SolarixGrammarEngineNET.GrammarEngine.SyntaxFlags syntax_flags, int constraints ) { IntPtr hPack = GrammarEngine.sol_SyntaxAnalysis( _hEngine, phrase, morph_flags, syntax_flags, constraints, id_language ); AnalysisResults res = new AnalysisResults( this, hPack ); return res; }
static void ProcessSentence2(string phrase, SolarixGrammarEngineNET.GrammarEngine2 gren, int max_len) { nb_processed += 1; if (nb_skip != 0 && nb_processed < nb_skip) { return; } if (phrase.Length > 2) { bool used = false; string terminator = ""; if (IsSentenceTerminator(phrase.Last())) { terminator = new string(phrase.Last(), 1); // Удалим финальные символы типа . или ! int finalizers = 1; for (int i = phrase.Length - 2; i > 0; --i) { if (IsSentenceTerminator(phrase[i])) { finalizers++; } } phrase = phrase.Substring(0, phrase.Length - finalizers); } if (!processed_phrases.Contains(phrase)) { processed_phrases.Add(phrase); string phrase2 = Preprocess(phrase, gren); // Выполним оценку синтаксического качества предложения, чтобы отсеять мусор. int id_language = SolarixGrammarEngineNET.GrammarEngineAPI.RUSSIAN_LANGUAGE; SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags morph_flags = SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY | SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_MODEL; SolarixGrammarEngineNET.GrammarEngine.SyntaxFlags syntax_flags = SolarixGrammarEngineNET.GrammarEngine.SyntaxFlags.DEFAULT; int MaxAlt = 40; int constraints = 600000 | (MaxAlt << 22); using (SolarixGrammarEngineNET.AnalysisResults linkages = gren.AnalyzeSyntax(phrase2, id_language, morph_flags, syntax_flags, constraints)) { if (linkages.Count == 3) { SolarixGrammarEngineNET.SyntaxTreeNode root = linkages[1]; List <SolarixGrammarEngineNET.SyntaxTreeNode> terms = GetTerms(root).OrderBy(z => z.GetWordPosition()).ToList(); int score = linkages.Score; bool good = false; if (score >= -4) { good = true; if (!syntax_checker.IsEmpty()) { FootPrint footprint = new FootPrint(gren, terms); // Проверим синтаксическую структуру фразы, чтобы отсеять разговорную некондицию. good = syntax_checker.IsGoodSyntax(footprint); } } if (good) { used = true; WriteSample(phrase + terminator); wrt_samples.Flush(); } else { SkippedSample(phrase); } } } } } Console.Write("{0} processed, {1} stored\r", nb_processed, nb_stored); return; }
public AnalysisResults AnalyzeMorphology( string phrase, int id_language, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags flags, int constraints ) { IntPtr hPack = GrammarEngine.sol_MorphologyAnalysis( _hEngine, phrase, flags, 0, constraints, id_language ); AnalysisResults res = new AnalysisResults( this, hPack ); return res; }
/* * public void Check( string line, List<int> model_lemma_ids ) * { * // Морфологический разбор * using( SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology( line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.SOL_GREN_COMPLETE_ONLY ) ) * { * // Токенизация без использования синтаксических правил * using( SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology( line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.SOL_GREN_TOKENIZE_ONLY ) ) * { * List<List<int>> word2tags = new List<List<int>>(); * * if( projs.Count != tokens.Count ) * return; * * total_word_count += projs.Count - 2; * * // Для каждого слова получим списки альтернативных лемматизаций. * List<List<string>> word2lemmas = new List<List<string>>(); * * List<string> lemmas = new List<string>(); * * int last_word_index = projs.Count - 1; * * for( int iword = 0; iword < projs.Count; ++iword ) * { * if( iword == 0 || iword == last_word_index ) * { * List<string> w2l = new List<string>(); * w2l.Add( string.Empty ); * word2lemmas.Add( w2l ); * } * else * { * List<string> word_lemmas = new List<string>(); * for( int iproj = 0; iproj < projs[iword].VersionCount(); ++iproj ) * { * string lemma = string.Empty; * int ekey = projs[iword].GetVersionEntryID( iproj ); * string ename = gren.GetEntryName( ekey ); * if( IsUnknownLexem( ename ) ) * lemma = projs[iword].GetWord().ToLower(); * else * lemma = ename.ToLower(); * * if( !word_lemmas.Contains( lemma ) ) * word_lemmas.Add( lemma ); * } * * word2lemmas.Add( word_lemmas ); * } * * lemmas.Add( word2lemmas[iword][0] ); * } * * // model_lemma_ids - это те леммы, которые выбраны моделью. * for( int iword = 1; iword < projs.Count - 1; ++iword ) * { * // теперь перебираем проекции и смотрим, которая из них имеет в нормальной форме выбранный суффикс. * for( int iproj = 0; iproj < word2lemmas[iword].Count; ++iproj ) * { * string ename = word2lemmas[iword][iproj]; * string proj_suffix = GetSuffix( ename.ToLower() ); * int id_suffix = MatchSuffix( proj_suffix, false ); * if( id_suffix == -1 ) * continue; * * if( id_suffix == model_lemma_ids[iword] ) * { * lemmas[iword] = ename.ToLower(); * } * } * } * * // Теперь сравниваем леммы c правильными значениями. * for( int iword = 1; iword < tokens.Count - 1; ++iword ) * { * string mustbe = string.Empty; * * int ekey = tokens[iword].GetEntryID(); * string ename = gren.GetEntryName( ekey ); * * if( IsUnknownLexem( ename ) ) // не будем учитывать ошибки лемматизации для не-словарных лексем. * continue; * * mustbe = ename.ToLower(); * * if( mustbe != lemmas[iword] ) * error_count_with_ngram++; * * string lemma0 = string.Empty; * int ekey0 = projs[iword].GetEntryID(); * string ename0 = gren.GetEntryName( ekey0 ); * if( IsUnknownLexem( ename0 ) ) * continue; * * lemma0 = ename0.ToLower(); * * if( mustbe != lemma0 ) * error_count_no_filter++; * } * } * } * * return; * } */ public void Check(string line, List <int> model_lemma_ids) { // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { total_word_count += tokens.Count - 2; System.Text.StringBuilder b = new System.Text.StringBuilder(); b.Capacity = 100; int last_word_index = tokens.Count - 1; for (int iword = 1; iword < tokens.Count - 1; ++iword) { string word = tokens[iword].GetWord(); bool hit = false; System.IntPtr hLemmas = SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_GetLemmasW(lemm_engine, word); if (hLemmas == System.IntPtr.Zero) { throw new System.ApplicationException(); } int nlemma = SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_CountLemmas(hLemmas); for (int i = 0; i < nlemma; ++i) { b.Length = 0; SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_GetLemmaStringW(hLemmas, i, b, b.Capacity); string lemma = b.ToString().ToLower(); int id_lemma = MatchSuffix(GetLemmaSuffix(lemma), false); if (id_lemma == -1) { continue; } if (model_lemma_ids[iword] == id_lemma) { // модель выбрала эту лемму. сравним с вариантами точных лемм. bool found_lemma = false; for (int j = 0; j < tokens[iword].VersionCount(); ++j) { string version_lemma = GetTokenVersionLemma(j, tokens[iword]); string version_suffix = GetLemmaSuffix(version_lemma); int version_id = MatchSuffix(version_suffix, true); if (version_id == id_lemma) { found_lemma = true; break; } } hit = found_lemma; break; } } if (!hit) { error_count_with_ngram++; } SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_DeleteLemmas(hLemmas); } } return; }
public bool Sentence2Features(string line) { // синтаксический разбор в дерево using (SolarixGrammarEngineNET.AnalysisResults trees = gren.AnalyzeSyntax(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY, 0)) { // Морфологический разбор using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY)) { TreeLookup syntax = new TreeLookup(); syntax.Collect(tokens, trees, gren); if (!syntax.ok) { return(false); } int N = tokens.Count; List <WordTags> tag_index = new List <WordTags>(); List <string> words = new List <string>(); List <string> labels = new List <string>(); WordTags start_t = new WordTags(); start_t.common = START_id; tag_index.Add(start_t); words.Add("<START>"); labels.Add("O"); for (int iword = 1; iword < tokens.Count - 1; ++iword) { SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[iword]; string word = token.GetWord().ToLower(); SolarixGrammarEngineNET.SyntaxTreeNode token_prev = tokens[iword - 1]; WordTags t = new WordTags(); t.common = tags.MatchTags(tokens[iword], gren); t.modality = tags_modality.MatchTags(tokens[iword], gren); t.valency = tags_valency.MatchTags(tokens[iword], gren); tag_index.Add(t); string crf_word = word.Replace(" ", "_"); words.Add(crf_word); labels.Add(syntax.GetTokenLabel(iword)); } WordTags end_t = new WordTags(); end_t.common = END_id; tag_index.Add(end_t); words.Add("<END>"); labels.Add("O"); System.Text.StringBuilder b = new System.Text.StringBuilder(); int last_word_index = tokens.Count - 1; for (int iword = 0; iword < tokens.Count; ++iword) { b.Length = 0; string output_label = labels[iword]; string word = words[iword]; // PullFeatures1( b, tag_index, iword, -3 ); PullFeatures1(b, tag_index, iword, -2); PullFeatures1(b, tag_index, iword, -1); PullFeatures1(b, tag_index, iword, 0); PullFeatures1(b, tag_index, iword, 1); PullFeatures1(b, tag_index, iword, 2); // PullFeatures1( b, tag_index, iword, 3 ); // PullFeatures2( b, tag_index, iword, -3, -2 ); PullFeatures2(b, tag_index, iword, -2, -1); PullFeatures2(b, tag_index, iword, -1, 0); PullFeatures2(b, tag_index, iword, 0, 1); PullFeatures2(b, tag_index, iword, 1, 2); // PullFeatures2( b, tag_index, iword, 3, 4 ); // PullFeatures3( b, tag_index, iword, -3, -2, -1 ); PullFeatures3(b, tag_index, iword, -2, -1, 0); PullFeatures3(b, tag_index, iword, -1, 0, 1); PullFeatures3(b, tag_index, iword, 0, 1, 2); // PullFeatures3( b, tag_index, iword, 1, 2, 3 ); crf_file.WriteLine("{0}{1}", output_label, b.ToString()); visual_file.WriteLine("{0}\t{1}\t{2}", word, output_label, tag_index[iword]); } crf_file.WriteLine(""); visual_file.WriteLine(""); } } return(true); }
public void ProcessSample(string line, SolarixGrammarEngineNET.AnalysisResults tokens, int left_i, SolarixGrammarEngineNET.GrammarEngine2 gren) { // В контекст входят слова от left_i по left_i+ctx.len. /* * // ---- DEBUG * System.Text.StringBuilder b = new StringBuilder(); * for( int i=0; i<ctx.len; ++i ) * if( i>0 ) * b.AppendFormat( " {0}", tokens[left_i+i].GetWord() ); * else * b.AppendFormat( "{0}", tokens[left_i+i].GetWord() ); * * string context_str = b.ToString(); * // --- END DEBUG */ // ... todo проверяем, не сопоставляются ли слова с уже имеющимися контекстами. for (int i = 0; i < recognizers.Count; ++i) { ContextRecognizer recognizer = recognizers[i]; int match = recognizer.Match(tokens, left_i, gren); if (match == 1) { // правило правильно распознало контекст и сняло омонимию. recognizer.Success(new MatchedContextInfo(line, tokens, left_i, ctx.len)); } else if (match == 0) { // правило распознало контекст, но неправильно сняло омонимию. recognizer.Fail(new MatchedContextInfo(line, tokens, left_i, ctx.len)); } } // Используем сэмпл для генерации правил только в том случае, если омонимичный токен дал 1 вариант словарной статьи. bool generate_rule = true; int omonym_ekey = -1; SolarixGrammarEngineNET.SyntaxTreeNode omonym_token = tokens[left_i + ctx.position]; int omonym_versions = omonym_token.VersionCount(); for (int iver = 0; iver < omonym_versions; ++iver) { int ekey = omonym_token.GetVersionEntryID(iver); if (omonym_ekey == -1) { omonym_ekey = ekey; } else if (omonym_ekey != ekey) { // омонимичный токен распознан как несколько разных лемм, поэтому не будет генерировать для него правила. generate_rule = false; break; } } if (generate_rule) { // Генерируем варианты распознавания контекста, начиная от самого конкретного - через лексемы не-мононимичных слов, для самых // общих - частей речи для них же. OmonymContextEnumerator ctx_generator = new OmonymContextEnumerator(tokens, ctx.position, left_i, ctx.len, gren); for (int i = 0; i < ctx_generator.Count; ++i) { ContextRecognizer recognizer = ctx_generator[i]; // проверим, что такого распознавателя еще нет. bool is_unique = true; foreach (ContextRecognizer r in recognizers) { if (r.EqualTokens(recognizer)) { is_unique = false; break; } } if (is_unique) { recognizer.Success(new MatchedContextInfo(line, tokens, left_i, ctx.len)); recognizers.Add(recognizer); } } } return; }