Skip to content

gurgutan/NLDB.2

Repository files navigation

# NLDB

Система поиска текстовой информации по шаблону в больших текстовых файлах

Проект создается как библиотека классов для использования в проектах обработки текстовой информации.
Основной класс с функционалом системы:
Engine.
Основные модули:
NLDB - программа (в перспективе библиотека класов) с основным функционалом (классы Language, DataContainer, Word, Term, Grammar);
NLCLI - интерпретатор командной строки для создания, наполнения и управления хранилищем данных (классы Shell, Commands);
NLDBTests - тесты. Многие тесты быстро устаревают, опаздывая за изменением функционала, так что большинство пока закомментировано.
Платформа:
.NET Core 2.2, использется SQLite 1.0.109

Назначение системы

Эксперименты с алгоритмами обработки текста на естественноых и формальных языках

Функционал системы

Построение иерархической структуры текста для анализа.

Поиск нужного блока текста с использованием различных метрик схожести.

Поиск связанных блоков текста, где связь определяется различными отношениями: следования, предшествования, включения и т.п.

Описание и реализация задач в системе

  1. Построение иерархической многоуровневой структуры текста путем создания Словаря (метод Language.BuildLexicon), состоящего из ранжированных Слов (класс Word).
    1. Исходный текст является линейной последовательностью символов и подается на вход как текстовый файл (UTF-8) или строка System.String. При помощи простого лексического анализа текст разбивается на слова ранга n (свойство Word.rank), где n - это максимальный ранг слов, заданный в настройках системы.

      Пример. Предположим, текст является файлом с набором статей Wikipedia. Лексический анализ разбивает текст на статьи - Слова ранга 3, которые, в свою очередь разбиваются на Слова ранга 2 - предложения, которые разбиваются на Слова ранга 1 - Слова, которые состоят из букв - Слов ранга 0.

    2. На данный момент (8.10.2018) лексический анализатор (класс Parser) приводит текст весь текст к нижнему регистру, удаляет незначимые символы, разделяет текст на фрагменты в соответствии с символами-разделителями, заданными регулярными выражениями (метод Parser.Split).
    3. Каждое Слово ранга n имеет следующие представления:
      • Блок текста, ограниченный символами разделителями;
      • Дерево Слов. Высота дерева - n, потомки корня дерева - Слова ранга n-1;
    4. Словарь объединяет в себе слова различных рангов. Для достижения эффективности обработки данных возможно разбиение Словаря на несколько, содержащих Слова только одного ранга.
  2. Поиск блока текста (Слова) с использованием различных метрик схожести.
    1. Поиск Слова из Словаря по введенной строке (метод Language.Identify) производится как поиск Слова, для которого оценка уверенности (confidence) в похожести на введенный текст максимальна.
    2. По введенной строке строится Слово, начиная с составляющих минимального 0-го ранга (например, букв). Построенные Слова сравнивается со Словами из Словаря, для каждого из которых вычисляется оценка схожести. Ближайшим считается Слово с максимальной оценкой схожести.
    3. После определения дочерних Слов n-1 ранга определяется родительское Слово ранга n, с учетом вычисленных ранее оценок схожести дочерних слов.
    4. Математически операция вычисления родительского Слова, соответствующего дочерним Словам ранга n-1 выглядит как умножение вектора дочерних Слов w на матрицу принадлежности P размерности (n-1)xn. При этом матрица принадлежности бинарная, со строками - id слов ранга n-1, столбцами - id слов ранга n. Распознаваемое Слово - вектор-строка v, с элементами из интервала [0,1], - оценками схожести элементов с соответствующими Словами из Словаря. Вместо суммирования в этой векторно-матричной операции применяется операция max. Вместо произведения - вычисление функции схожести элемента w[i] и элемента P[i,k]. Слово-победитель (то, которому принадлежат дочерние Слова) выясняется через argmax(v). Т.о. полная формула вычисления слова по составляющим элементам выгляди как id_parent = argmax(w*P). Если речь идет об определении слова ранга n по потомкам ранга 0, то вычисления рекурсивно повторяется для всех рангов от 0 до n-1.
    5. Метрики для вычисления схожести могут различаться для разных рангов. На данный момент используются метрики: Confidence.Equality, Confidence.Cosine, Confidence.SoftInclusive (пояснения и формулы в тексте класса Confidence).
    6. Уверенность в схожести Слова определяется по формуле, аналогичной формуле полной вероятности , исходя из следующих предпосылок: Если Слово ранга n состоит из некоторых Слов ранга n-1, то полная апостериорная уверенность того что строка является Словом ранга n, является суммой произведений уверенностей в схожести соответстветствующих составляющих термов ранга n-1. Вместо суммы max
  3. Добавлен метод для поиска набора похожих на введенный текст Слов (метод Language.Similars). Алгоритм аналогичен описанному выше, только выбирается не одно Слово-родитель с максимальной оценкой, а несколько лучших.
  4. Добавлен метод для получения следующего за найденным "похожим" на введенный текст Словом (метод Language.Next). В методе используются описанные выше методы поиска родительских слов (контекст слова) и вычисляется предполагаемое продолжение с использованием взвешенного префиксного дерева Слов. Предполагается использование в диалоговых системах машинного интерфейса.
  5. Добавлен метод рекуррентной последовательности слов, следующих за "похожим" на введенный текст (метод Language.PredictRecurrent). Использует алгорим учитывающий частоты n-грамм слов. На данный момент (01.09.2018) закомментирован, так как выводит связный бред и не представляет интереса, кроме развлекательных целей
  6. Добавлен метод для выделения синтаксического ядра Слов высоких рангов (например, суть статьи в нескольких предложениях) (метод Language.GetCore). Алгоритм использует матрицу схожестви между Словами, минимаксные стратегии оптимизации и методы перечисленные выше. Требует напильника, а может и топора.

Пример использования методов класса

private static void Main(string[] args)
{
    //Имя Словаря(а также базы данных). При отсутствии класс Language его создаст автоматически.
    string dbname = "wikiru5mb.db";
    //Укажем файл с текстом, который будем использовать для обучения. Должен присутствовать по указанному пути
    string trainfile = @"D:\Data\Wiki\ru\5mb.txt";
    //Массив разделителей текста на Слова. Разделители задаются регулярными выражениями, 
    //применяемыми к нормализованному тексту.
    string[] splitters = new string[]
    {
        "",                 //0-й ранг - символы, поэтому используется пустая строка
        @"[^а-яё\d\{\}]+",  //1-ранг - любой символ не являющийся буквой русского алфавита или цифрой разделяет слова
        @"[\n\r]+",         //2-й ранг - символы перевода строки разделяет предложения
        @"\[\[{число}\]\]"  //3-й ранг - текст вида [[343467]] разделяет статьи
	};
    //Создаем Словарь
    Language l = new Language(dbname, splitters);
    //После создания объекта создаем хранилище. Это нужно так как к созданному ранее хранилищу можно сразу подключиться
    l.Create();
    //Подключимся к хранилищу
    l.Connect();
    Console.WriteLine($"Начало обучения на файле {trainfile}");
    //Запускаем процесс построения структуры текста
    l.BuildLexicon(trainfile);
    //Теперь будем использовать полученные данные
    Console.Write($"\n\nВведите фразу:");
    string line = Console.ReadLine();
    //Найдем 8 лучших совпадений с текстом line. rank=2 означает, что нас интересуют совпадения предложений
    List similars = l.Similars(text: line, rank: 2, count: 8);
    Console.WriteLine("\n\nПохожие предложения:\n" + similars.Aggregate("", (c, n) => c + $"\n" + n.ToString()));
    //Получим предположение о предложении, следующем за line
    List next = l.Next(text: line, rank: 2);
    Console.WriteLine("\n\nОтветные предложения (продолжение):\n" + next.Aggregate("", (c, n) => c + $"\n" + n.ToString()));
    //Получим предоположение о сути статьи, в котором есть предложение, наиболее похожее на line
    IEnumerable core = l.GetCore(text: line, rank: 2);
    Console.WriteLine("\n\nЯдро текста статьи:\n" + core.Aggregate("", (c, n) => c + $"\n" + n.ToString()));
	Console.ReadKey();
    //Отключаемся от хранилища
    l.Disconnect();
}

About

Natural Language Data Base

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published