/// <summary> /// Строит n-грамную модель. /// </summary> /// <param name="inputFile">Входной файл корпуса.</param> /// <param name="reader">Объект для чтения корпуса.</param> private void BuildNGrammModel(string inputFile, ICorporaReader reader) { reader.Open(inputFile); nGramm = new TagNGramm(); int nGrammSize = 3; foreach (var sentense in reader.ReadSentences(int.MaxValue)) { //предлоги в корпусе не имеют падежа, а союзы не имеют типа //чтобы добавить эту информацию, воспользуемся модифицированным словарём foreach (var lexem in sentense) { if (serviceTags.ContainsKey(lexem.Word.ToLower())) { lexem.Tag = serviceTags[lexem.Word]; } } if (sentense.Count > 0 && sentense.Count(a => a.Tag == Tag.NoWord || a.Tag == Tag.Unfixed) == 0) { foreach (var ngamm in sentense.BuildNGramms(nGrammSize)) { nGramm.AddNGramm(ngamm); } } } reader.Close(); }
/// <summary> /// Трунирует модель классов энтропии. /// </summary> /// <param name="inputFile">Входной файл словаря.</param> /// <param name="reader">Объект для чтения корпуса.</param> private void BuildEntropyClassModel(string inputFile, ICorporaReader reader) { entClass = new DawgEntropyClassModel(); reader.Open(inputFile); serviceTags = new Dictionary <string, Tag>(); foreach (WordForm lexem in reader.ReadDictionary(long.MaxValue)) { if ((lexem.Tag & (Tag.Conjunction | Tag.Particle | Tag.Preposition)) != 0) { Tag outTag = Tag.NoWord; serviceTags.TryGetValue(lexem.Word.ToLower(), out outTag); serviceTags[lexem.Word.ToLower()] = outTag | lexem.Tag; } entClass.AddLexem(lexem); } ((DawgEntropyClassModel)entClass).Build(); reader.Close(); }
/// <summary> /// Трунирует модель целиком. /// </summary> /// <param name="corporaFile">Файл корпуса.</param> /// <param name="reader">Объект для чтения корпуса.</param> /// <param name="sentCount">Количество предложений.</param> /// <param name="concurrent">Установить <c>true</c>, если необходимо выполнить параллельно. </param> private void TrainFull(string corporaFile, ICorporaReader reader, int sentCount, bool concurrent) { reader.Open(corporaFile); punctuation = new List <string>(); sentenceDelimiters = new List <string>(); reader.Open(corporaFile); //читаем заданное количество предложений foreach (var sentence in reader.ReadSentences(sentCount)) { //предлоги в корпусе не имеют падежа, а союзы не имеют типа //чтобы добавить эту информацию, воспользуемся модифицированным словарём foreach (var lexem in sentence) { if (serviceTags.ContainsKey(lexem.Word.ToLower())) { lexem.Tag = serviceTags[lexem.Word]; } } //запишем все знаки пунктуации, которые встретим foreach (var punc in sentence.Where(a => (a.Tag & Tag.Punctuation) != 0 && !a.Word.Any((c) => char.IsLetter(c)) && !punctuation.Contains(a.Word))) { punctuation.Add(punc.Word); } WordForm last = sentence.Last(); if ((last.Tag & Tag.Punctuation) != 0 && !sentenceDelimiters.Contains(last.Word)) { sentenceDelimiters.Add(last.Word); } if (sentence.Count(lexem => lexem.Tag == Tag.NoWord || lexem.Tag == Tag.Unfixed) == 0) { //строим все возможные окна длины 7 foreach (var window in Utils.BuildAllWindows(sentence, 7)) { Tag tag = window.Skip(3).First().Tag; //тэг разгадываемого слова foreach (var group in groups) //для каждой группы { group.AddVector(window.ToVector(nGramm, entClass), tag); } } } } if (concurrent) //обучаем параллельно { Parallel.ForEach(groups, (group) => { group.Train(true); }); } else { foreach (var group in groups) { group.Train(false); } } string pattern = @"(-?\d+(?:\.\d+)?|"; foreach (var sign in punctuation) { pattern += Regex.Escape(sign) + "+|"; } pattern = pattern + @"\s+)"; this.lexemPattern = new Regex(pattern); this.sentencePattern = new Regex(@"(\.+|!|\?)"); reader.Close(); }
/// <summary> /// Запускает процесс обучения модели. /// </summary> /// <param name="corporaFile">Исходный файл корпуса.</param> /// <param name="sentCount">Количество предложений, которые будут прочитаны.</param> /// <param name="concurrent"><c>true</c>, если обучение должно происходить /// параллельно (для такого варианта может понадобиться больше памяти, но /// процесс займёт меньше времени).</param> /// <remarks>Может занять очень много времени и использовать большое /// количество памяти.</remarks> public void Train(string corporaFile, ICorporaReader reader, int sentCount, bool concurrent) { punctuation = new List <string>(); sentenceDelimiters = new List <string>(); reader.Open(corporaFile); //читаем заданное количество предложений int i = 0; foreach (var sentence in reader.ReadSentences(sentCount)) { //запишем все знаки пунктуации, которые встретим foreach (var punc in sentence.Where(a => (a.Tag & Tag.Punctuation) != 0 && !punctuation.Contains(a.Word))) { punctuation.Add(punc.Word); } WordForm last = sentence.Last(); if ((last.Tag & Tag.Punctuation) != 0 && !sentenceDelimiters.Contains(last.Word)) { sentenceDelimiters.Add(last.Word); } if (sentence.Count(lexem => lexem.Tag == Tag.NoWord) == 0) { #if DEBUG i++; Console.Write(string.Format("\rПредложений прочитано: {0}", i)); #endif //строим все возможные окна длины 7 foreach (var window in Utils.BuildAllWindows(sentence, 7)) { Tag tag = window.Skip(3).First().Tag; //тэг разгадываемого слова foreach (var group in groups) //для каждой группы { group.AddVector(window.ToVector(nGramm, entClass), tag); } } } } if (concurrent) //обучаем параллельно { Parallel.ForEach <TagGroup>(groups, (group) => { group.Train(true); }); } else { //обучаем последовательно i = 0; foreach (var group in groups) { group.Train(false); #if DEBUG Console.WriteLine("Закончено обучение группы " + i); #endif i++; } } string pattern = @"(-?\d+(?:\.\d+)?|"; foreach (var sign in punctuation) { pattern += Regex.Escape(sign) + "+|"; } pattern = pattern + @"\s+)"; this.lexemPattern = new Regex(pattern); this.sentencePattern = new Regex(@"(\.+|!|\?)"); reader.Close(); }