GetEntryName() 공개 메소드

public GetEntryName ( int id_entry ) : string
id_entry int
리턴 string
예제 #1
0
    public bool ProcessTrainingSample(SentenceData sample)
    {
        n_learn_samples++;

        for (int iword = 1; iword < sample.CountWords() - 1; ++iword)
        {
            WordData token    = sample.GetWord(iword);
            string   wordform = token.GetWord().ToLower();

            if (wordform.Contains("  "))
            {
                // кратные пробелы сокращаем до одинарных
                System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex("[ ]{2,}");
                wordform = rx.Replace(wordform, " ");
            }

            string lemma = gren.GetEntryName(token.GetEntryID());
            if (IsUnknownLexem(lemma) || IsNumword(lemma))
            {
                continue;
            }

            int POS_tag = tags.MatchTags(token, gren);

            table.Store(POS_tag, wordform, lemma);
            n_learn_wordforms++;
        }


        return(true);
    }
예제 #2
0
    public bool ProcessSample(SampleData sample)
    {
        n_learn_samples++;

        for (int iword = 1; iword < sample.morphology.Count - 1; ++iword)
        {
            SolarixGrammarEngineNET.SyntaxTreeNode token = sample.morphology[iword];

            string wordform = token.GetWord().ToLower();

            if (wordform.Contains("  "))
            {
                System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex("[ ]{2,}");
                wordform = rx.Replace(wordform, " ");
            }

            string lemma = gren.GetEntryName(token.GetEntryID());
            if (IsUnknownLexem(lemma) || IsNumword(lemma))
            {
                continue;
            }

            int POS_tag = tags.MatchTags(token, gren);

            table.Store(POS_tag, wordform, lemma);
            n_learn_wordforms++;
        }


        return(true);
    }
예제 #3
0
    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);
    }
예제 #4
0
    string GetTokenVersionLemma(int version_index, SolarixGrammarEngineNET.SyntaxTreeNode token)
    {
        string lemma = string.Empty;
        int    ekey  = token.GetVersionEntryID(version_index);
        string ename = gren.GetEntryName(ekey);

        if (IsUnknownLexem(ename))
        {
            lemma = token.GetWord().ToLower();
        }
        else
        {
            lemma = ename.ToLower();
        }

        return(lemma);
    }
예제 #5
0
    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);
    }
예제 #6
0
    private static string TermToString(SolarixGrammarEngineNET.GrammarEngine2 gren, SolarixGrammarEngineNET.SyntaxTreeNode term)
    {
        int id_entry = term.GetEntryID();

        if (gren.GetEntryName(id_entry) == "???")
        {
            return(term.GetWord());
        }

        string res_word = gren.RestoreCasing(id_entry, term.GetWord());

        return(res_word);
    }
    public string GetContextPoint(SolarixGrammarEngineNET.GrammarEngine2 gren)
    {
        System.Text.StringBuilder b = new StringBuilder();

        if (!string.IsNullOrEmpty(lexem))
        {
            b.AppendFormat("\"{0}\"", lexem);
        }
        else
        {
            if (id_class != -1)
            {
                b.AppendFormat("{0}:*", gren.GetClassName(id_class));
            }
            else
            {
                int pos = gren.GetEntryClass(id_entry);
                b.AppendFormat("{0}:{1}", gren.GetClassName(pos), gren.GetEntryName(id_entry));
            }

            b.Append("{");

            // выводим список координатных пар
            foreach (SolarixGrammarEngineNET.CoordPair p in pairs)
            {
                string CoordName = gren.GetCoordName(p.CoordID);
                if (gren.CountCoordStates(p.CoordID) == 0)
                {
                    if (p.StateID == 1)
                    {
                        b.AppendFormat(" {0}", CoordName);
                    }
                    else
                    {
                        b.AppendFormat(" ~{0}", CoordName);
                    }
                }
                else
                {
                    string StateName = gren.GetCoordStateName(p.CoordID, p.StateID);
                    b.AppendFormat(" {0}:{1}", CoordName, StateName);
                }
            }

            b.Append(" }");
        }

        return(b.ToString());
    }
예제 #8
0
    private void ProcessTree(SolarixGrammarEngineNET.SyntaxTreeNode node)
    {
        string word1 = node.GetWord().ToUpper();

        int e1 = node.GetEntryID();
        int c1 = gren.GetEntryClass(e1);

        if (
            c1 == SolarixGrammarEngineNET.GrammarEngineAPI.VERB_ru ||
            c1 == SolarixGrammarEngineNET.GrammarEngineAPI.INFINITIVE_ru ||
            c1 == SolarixGrammarEngineNET.GrammarEngineAPI.IMPERSONAL_VERB_ru
            )
        {
            string ename1 = gren.GetEntryName(e1);

            System.Text.StringBuilder b = new System.Text.StringBuilder();
            b.AppendFormat("{0}", ename1);

            if (node.leafs.Count > 0)
            {
                b.Append("(");

                for (int ileaf = 0; ileaf < node.leafs.Count; ++ileaf)
                {
                    SolarixGrammarEngineNET.SyntaxTreeNode leaf = node.leafs[ileaf];
                    string s = GetNodeNonterminal(leaf);

                    if (!string.IsNullOrEmpty(s))
                    {
                        b.AppendFormat(" {0}", s);
                    }
                }

                b.Append(" )");
            }

            string str = b.ToString();

            int f = 0;
            if (verb_pattern.TryGetValue(str, out f))
            {
                verb_pattern[str] = f + 1;
            }
            else
            {
                verb_pattern.Add(str, 1);
            }
        }

        for (int ileaf = 0; ileaf < node.leafs.Count; ++ileaf)
        {
            SolarixGrammarEngineNET.SyntaxTreeNode leaf = node.leafs[ileaf];

            int e2 = leaf.GetEntryID();
            int c2 = gren.GetEntryClass(e2);
            if (c2 != SolarixGrammarEngineNET.GrammarEngineAPI.PUNCTUATION_class)
            {
                string word2 = leaf.GetWord().ToUpper();

                string w2 = string.Format("{0}+{1}", word1, word2);
                int    f  = 0;
                if (biword.TryGetValue(w2, out f))
                {
                    biword[w2] = f + 1;
                }
                else
                {
                    biword.Add(w2, 1);
                }
            }

            ProcessTree(leaf);
        }

        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);
    }
예제 #10
0
    public void Store()
    {
        using (System.IO.StreamWriter wr = new System.IO.StreamWriter("edge_lens.txt"))
        {
            foreach (var x in edge_len2count.OrderBy(z => z.Key))
            {
                wr.WriteLine("{0};{1}", x.Key, x.Value);
            }
        }



        int n_assoc2 = 0;

        using (System.IO.StreamWriter wr = new System.IO.StreamWriter("distance2.sql"))
        {
            wr.WriteLine("DELETE FROM assoc2_corpus_stat;");

            foreach (var w2 in distance_matrix.OrderByDescending(z => z.Value.id_entry1).ThenByDescending(z => z.Value.N))
            {
                string word1 = gren.GetEntryName(w2.Key.id_entry1);
                string word2 = gren.GetEntryName(w2.Key.id_entry2);

                double M = ((double)w2.Key.sum_distance) / ((double)w2.Key.N);
                double D = ((double)w2.Key.sum_distance2) / ((double)w2.Key.N) - M * M;

                wr.WriteLine("INSERT INTO assoc2_corpus_stat( id_entry1, id_entry2, word1, word2, M, D, N ) VALUES ( {5}, {6}, '{0}', '{1}', {2}, {3}, {4} );", EscapeSQL(word1), EscapeSQL(word2), M.ToString("0.####").Replace(",", "."), System.Math.Sqrt(D).ToString("0.####").Replace(",", "."), w2.Key.N, w2.Key.id_entry1, w2.Key.id_entry2);
                n_assoc2++;

                if ((n_assoc2 % 100) == 0)
                {
                    wr.WriteLine("GO");
                }
            }
        }

        System.Console.WriteLine("Total number of biword associations: {0}", n_assoc2);

        using (System.IO.StreamWriter wr = new System.IO.StreamWriter("stat.sql"))
        {
            wr.WriteLine("DELETE FROM wordform_corpus_stat;");
            wr.WriteLine("DELETE FROM wordentry_corpus_stat;");

            foreach (var x in wordform_stat)
            {
                wr.WriteLine("INSERT INTO wordform_corpus_stat( id_entry, word, freq ) VALUES ( {0}, '{1}', {2} );", x.Key.id_entry, x.Key.wordform.Replace("'", "''"), x.Value);
            }

            foreach (var x in wordentry_stat)
            {
                wr.WriteLine("INSERT INTO wordentry_corpus_stat( id_entry, freq ) VALUES ( {0}, {1} );", x.Key, x.Value);
            }
        }


        using (System.IO.StreamWriter wr = new System.IO.StreamWriter("wordentry.stat.txt"))
        {
            foreach (var x in wordentry_stat.OrderByDescending(z => z.Value))
            {
                wr.WriteLine("{0};{1};{2}", x.Key, gren.GetEntryName(x.Key), x.Value);
            }
        }

        using (System.IO.StreamWriter wr = new System.IO.StreamWriter("wordentry.stat2.txt"))
        {
            foreach (var x in wordentry_stat.OrderByDescending(z => z.Value))
            {
                wr.WriteLine("[{0}]", gren.GetEntryName(x.Key));
            }
        }

        using (System.IO.StreamWriter wr = new System.IO.StreamWriter("lemma_sematags.txt"))
        {
            foreach (var x in wordentry_stat.Where(z => z.Value >= MIN_SEMATAG_FREQ).OrderByDescending(z => z.Value))
            {
                string lemma = gren.GetEntryName(x.Key);
                if (!char.IsPunctuation(lemma[0]) && lemma != "???" && lemma != "unknownentry" && lemma != "number_")
                {
                    wr.WriteLine("{0}\t{1}", lemma, x.Key);
                }
            }
        }


        using (System.IO.StreamWriter wr = new System.IO.StreamWriter("dublicated_samples.txt"))
        {
            foreach (var k in sample2count.Where(z => z.Value > 1))
            {
                wr.WriteLine("{0}", k.Key);
            }
        }

        return;
    }
예제 #11
0
    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;
    }
예제 #12
0
    public void Store()
    {
        using (System.IO.StreamWriter wr = new System.IO.StreamWriter("kb_verb_prepos.txt"))
        {
            string prev_word1 = string.Empty;
            foreach (var x in verb_prepos.OrderByDescending(z => z.Key.id_entry1).ThenByDescending(z => z.Value))
            {
                string word1 = gren.GetEntryName(x.Key.id_entry1);
                string word2 = gren.GetEntryName(x.Key.id_entry2);

                if (word1 != "???")
                {
                    if (prev_word1 != word1)
                    {
                        wr.WriteLine("\n\n");
                    }

                    prev_word1 = word1;
                    wr.WriteLine("{0} {1} = {2}", word1, word2, x.Value);
                }
            }
        }

        using (System.IO.StreamWriter wr = new System.IO.StreamWriter("kb_prepos_noun.txt"))
        {
            string prev_word1 = string.Empty;
            foreach (var x in prepos_noun.OrderByDescending(z => z.Key.id_entry1).ThenByDescending(z => z.Value))
            {
                string word1 = gren.GetEntryName(x.Key.id_entry1);
                string word2 = gren.GetEntryName(x.Key.id_entry2);

                if (word2 != "???")
                {
                    if (prev_word1 != word1)
                    {
                        wr.WriteLine("\n\n");
                    }

                    prev_word1 = word1;
                    wr.WriteLine("{0} {1} = {2}", word1, word2, x.Value);
                }
            }
        }

        using (System.IO.StreamWriter wr = new System.IO.StreamWriter("kb_adj_noun.txt"))
        {
            string prev_word1 = string.Empty;
            foreach (var x in adj_noun.OrderByDescending(z => z.Key.id_entry1).ThenByDescending(z => z.Value))
            {
                string word1 = gren.GetEntryName(x.Key.id_entry1);
                string word2 = gren.GetEntryName(x.Key.id_entry2);

                if (word1 != "???" && word2 != "???")
                {
                    if (prev_word1 != word1)
                    {
                        wr.WriteLine("\n\n");
                    }

                    prev_word1 = word1;
                    wr.WriteLine("{0} {1} = {2}", word1, word2, x.Value);
                }
            }
        }

        return;
    }
    public bool ProcessSample(string line)
    {
        n_learn_samples++;

        if (tokens_file == null)
        {
            tokens_file = new System.IO.StreamWriter(tokens_file_path);
        }

        // чтобы получить все возможные теги, надо для каждого слова получить все возможные распознавания.
        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 sfx1 = GetTokenSuffix(iword, last_word_index, lemma);
                    int    id1  = MatchSuffix(sfx1, true);

                    string sfx2 = GetTokenLemmaSuffix(iword, last_word_index, lemma);
                    int    id2  = MatchSuffix(sfx2, true);
                }
            }
        }


        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            test_samples.Add(line);
            test_sample_token_counts.Add(tokens.Count);

            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();

                if (iword > 0 && iword < tokens.Count - 1)
                {
                    tokens_file.Write("{0}", word);

                    // все допустимые варианты лемматизации
                    int nlemma = 0;
                    for (int j = 0; j < tokens[iword].VersionCount(); ++j)
                    {
                        int    id_entry = tokens[iword].GetVersionEntryID(j);
                        string ename2   = gren.GetEntryName(id_entry);

                        if (IsUnknownLexem(ename2)) // не будем учитывать ошибки лемматизации для не-словарных лексем.
                        {
                            continue;
                        }

                        tokens_file.Write("\t{0}", ename2);

                        nlemma++;
                    }

                    if (nlemma == 0)
                    {
                        tokens_file.Write("\t{0}", word);
                    }

                    tokens_file.WriteLine("");
                }

                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 = GetTokenLemmaSuffix(iword, last_word_index, lemma);
                sfx_lemma.Add(lemma_suffix);
                sfx_lemma_index.Add(MatchSuffix(lemma_suffix, true));
            }
            tokens_file.WriteLine("");

            for (int iword = 1; iword < tokens.Count - 1; ++iword)
            {
                string res = ResultLabel(sfx_lemma_index[iword]);

                //string tag0 = LemmaLabel( -1, sfx_lemma_index[iword - 1] ); // для Витерби в MEMM

                if (iword > 1 && iword < tokens.Count - 2)
                {
                    string tag1 = TagLabel(-2, sfx_index[iword - 2]);
                    string tag2 = TagLabel(-1, sfx_index[iword - 1]);
                    string tag3 = TagLabel(0, sfx_index[iword]);
                    string tag4 = TagLabel(1, sfx_index[iword + 1]);
                    string tag5 = TagLabel(2, sfx_index[iword + 2]);

                    WriteTrain(tag1, tag2, tag3, tag4, tag5, res);
                    WriteTest(tag1, tag2, tag3, tag4, tag5, res);
                }
                else
                {
                    string tag2 = TagLabel(-1, sfx_index[iword - 1]);
                    string tag3 = TagLabel(0, sfx_index[iword]);
                    string tag4 = TagLabel(1, sfx_index[iword + 1]);

                    WriteTrain(tag2, tag3, tag4, res);
                    WriteTest(tag2, tag3, tag4, res);
                }
            }

            WriteTestEOS();
        }

        return(true);
    }
예제 #14
0
    static void Execute( 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;
    }
예제 #15
0
    public FootPrintToken(SolarixGrammarEngineNET.GrammarEngine2 gren, SolarixGrammarEngineNET.SyntaxTreeNode root)
    {
        Contract.Ensures(!string.IsNullOrEmpty(this.word));
        Contract.Ensures(this.node != null);
        Contract.Ensures(this.tags != null);

        this.word = root.GetWord();
        this.tags = new List <string>();
        this.node = root;

        this.tags.Add(root.GetWord().ToLower());

        if (root.GetWord().Equals("не", StringComparison.OrdinalIgnoreCase))
        {
            this.tags.Add("neg");
        }


        int part_of_speech = gren.GetEntryClass(root.GetEntryID());

        switch (part_of_speech)
        {
        case SolarixGrammarEngineNET.GrammarEngineAPI.NUM_WORD_CLASS: this.tags.Add("num"); break;  // числительное цифрами

        case SolarixGrammarEngineNET.GrammarEngineAPI.NUMBER_CLASS_ru: this.tags.Add("num"); break; // числительное словом

        case SolarixGrammarEngineNET.GrammarEngineAPI.CONJ_ru: this.tags.Add("conj"); break;        // союз

        case SolarixGrammarEngineNET.GrammarEngineAPI.PRONOUN_ru: this.tags.Add("pr"); break;       // местоимение Я

        case SolarixGrammarEngineNET.GrammarEngineAPI.NOUN_ru: this.tags.Add("n"); break;

        case SolarixGrammarEngineNET.GrammarEngineAPI.ADJ_ru: this.tags.Add("adj"); break;

        case SolarixGrammarEngineNET.GrammarEngineAPI.VERB_ru: this.tags.Add("v"); break;

        case SolarixGrammarEngineNET.GrammarEngineAPI.INFINITIVE_ru: this.tags.Add("v"); this.tags.Add("inf"); break;

        case SolarixGrammarEngineNET.GrammarEngineAPI.GERUND_2_ru: this.tags.AddRange("adv adv_v".Split(' ')); break;

        case SolarixGrammarEngineNET.GrammarEngineAPI.ADVERB_ru:
        {
            this.tags.Add("adv");
            if (StringExtender.InCI(word, "очень крайне наиболее наименее чрезвычайно почти".Split()))         // модификаторы наречий и прилагательных
            {
                this.tags.Add("a_modif");
            }

            string adv_cat = AdverbCategory.GetQuestionWordForAdverb(word);
            if (!string.IsNullOrEmpty(adv_cat))
            {
                this.tags.Add("adv_" + adv_cat);
            }

            break;
        }

        case SolarixGrammarEngineNET.GrammarEngineAPI.PREPOS_ru: this.tags.Add("p"); break;

        case SolarixGrammarEngineNET.GrammarEngineAPI.PRONOUN2_ru: this.tags.Add("pr"); break;

        default: this.tags.Add("x"); break;
        }

        foreach (var p in root.GetPairs())
        {
            if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.CASE_ru)
            {
                switch (p.StateID)
                {
                case SolarixGrammarEngineNET.GrammarEngineAPI.NOMINATIVE_CASE_ru: this.tags.Add("nom"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.GENITIVE_CASE_ru: this.tags.Add("gen"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.ACCUSATIVE_CASE_ru: this.tags.Add("acc"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.DATIVE_CASE_ru: this.tags.Add("dat"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.PREPOSITIVE_CASE_ru: this.tags.Add("prep"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.PARTITIVE_CASE_ru: this.tags.Add("part"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.LOCATIVE_CASE_ru: this.tags.Add("loc"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.INSTRUMENTAL_CASE_ru: this.tags.Add("instr"); break;
                }
            }

            if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.NUMBER_ru)
            {
                switch (p.StateID)
                {
                case SolarixGrammarEngineNET.GrammarEngineAPI.SINGULAR_NUMBER_ru: this.tags.Add("sing"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.PLURAL_NUMBER_ru: this.tags.Add("pl"); break;
                }
            }

            if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.TENSE_ru)
            {
                switch (p.StateID)
                {
                case SolarixGrammarEngineNET.GrammarEngineAPI.PAST_ru: this.tags.Add("past"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.PRESENT_ru: this.tags.Add("pres"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.FUTURE_ru: this.tags.Add("future"); break;
                }
            }

            if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.FORM_ru)
            {
                switch (p.StateID)
                {
                case SolarixGrammarEngineNET.GrammarEngineAPI.ANIMATIVE_FORM_ru: this.tags.Add("anim"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.INANIMATIVE_FORM_ru: this.tags.Add("inanim"); break;
                }
            }

            if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.GENDER_ru)
            {
                switch (p.StateID)
                {
                case SolarixGrammarEngineNET.GrammarEngineAPI.MASCULINE_GENDER_ru: this.tags.Add("masc"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.FEMININE_GENDER_ru: this.tags.Add("fem"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.NEUTRAL_GENDER_ru: this.tags.Add("neut"); break;
                }
            }


            if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.PERSON_ru)
            {
                switch (p.StateID)
                {
                case SolarixGrammarEngineNET.GrammarEngineAPI.PERSON_1_ru: this.tags.Add("1"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.PERSON_2_ru: this.tags.Add("2"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.PERSON_3_ru: this.tags.Add("3"); break;
                }
            }


            if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.VERB_FORM_ru)
            {
                switch (p.StateID)
                {
                case SolarixGrammarEngineNET.GrammarEngineAPI.VB_INF_ru: this.tags.Add("vf1"); break;

                case SolarixGrammarEngineNET.GrammarEngineAPI.VB_ORDER_ru: this.tags.Add("imper"); break;
                }
            }

            if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.MODAL_ru)
            {
                switch (p.StateID)
                {
                case 1: this.tags.Add("mod"); break;
                }
            }
        }

        // Пометим связочные глаголы
        string lemma = gren.GetEntryName(root.GetEntryID());

        if (copula_verbs.Contains(lemma))
        {
            this.tags.Add("copula");
        }
    }