Создание Частотного Словаря На Основе Анализа Библиотеки Художественной Литературы.

Общий привет. Недавно для полировки морфологического словаря, способного (предположительно) образовывать все возможные формы слова из инфинитива, мне понадобился довольно большой частотный словарь русского языка.

Частотный словарь — очень простая вещь; слова в нем упорядочены по частоте их появления в анализируемом тексте.

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

Но для анализа такой громоздкой библиотеки, а площадь библиотеки, которую я использую, превышает 157 гектаров, ресурсов среднестатистического домашнего компьютера едва хватает. Если быть точнее, то библиотека хранится в пятидесяти zip-архивах по 0,5 – 2 ГБ, каждый из которых содержит 20–30 тысяч произведений в формате fb2. В сжатом виде весит 60 ГБ.

Проблема была решена на C#.

Результат должен быть получен в адекватное время, для которого я выбрал не более 8 часов, чтобы можно было запустить выполнение вечером и получить результат утром.



Поиск решения
Множество Самый очевидный способ решения того, что называется «в лоб», — это два массива, в первом — слова, во втором — числа.

Встретив новое слово, мы добавляем его в первый массив, если его там нет, или добавляем его в индекс во втором массиве, если мы нашли слово в первом.

Попробовав этот вариант, я сразу в нем разочаровался; через несколько часов программа со скрипом пролезла первую половину первого архива.

Любой профессиональный программист, наверное, уже смеется над таким подходом.

Однако, признаюсь, я даже не предполагал, что меня ждет подвох.

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

Узким местом оказался момент добавления нового слова.

Чтобы массив оставался упорядоченным, слово приходится вставлять где-то в середине, а иногда и в самом начале.

Для этого вам придется сдвинуть вправо каждый элемент массива, расположенный справа от выбранной позиции.

Когда речь идет о миллионах слов, эта задача становится очень утомительной для процессора и он мстит, откладывая завершение программы на недели вперед. Упорядоченный список Мне пришлось искать структуру данных, которая бы позволяла добавлять каждый элемент просто в конец структуры, но в то же время позволяла бы их упорядочивать.

Именно тогда я наткнулся на упорядоченные списки.

Ячейка упорядоченного списка хранит сам фрагмент данных и указатель на другую ячейку.

Все нормально, мы просто добавляем новое слово и меняем 2 индекса, индекс предыдущего слова, указывающий на данное, и индекс данного слова, указывающий на следующее.

Но, к несчастью, поиск в таком списке требует очень больших вычислительных ресурсов.

Если в упорядоченном массиве мы могли начать поиск с середины и за одну итерацию разделить его пополам, то в упорядоченном списке нам приходится лазить по указателям от одного к другому, как по нитке, пока не найдём нужное место во всей этой путанице.

Я не пробовал этот вариант; научившись предыдущей неудаче, я сразу учуял засаду.

Бинарное дерево поиска Я нашел следующую структуру данных только через несколько часов.

Я столкнулся с двоичными деревьями поиска.

Немного почитав о различных вариантах, я остановился на самобалансирующемся дереве АВЛ, созданном, кстати, советскими учеными Георгием Максимовичем Адельсоном-Вельским и Евгением Михайловичем Ландисом и унаследовавшим его название от их фамилий.

Структура двоичного дерева аналогична упорядоченному списку, но каждый элемент, за исключением нескольких листовых элементов (называемых листьями), относится к двум элементам.

Корневой элемент — это тот, который находится в середине упорядоченного массива.

Он относится к элементу меньшему (левому) и большему (правому), кроме того, гарантируется, что все элементы левой ветви будут меньше этого, а все элементы правой ветви будут больше.

Рассмотрев левый или правый элемент, к которому мы пришли, мы увидим одну и ту же иерархию, она также относится к двум элементам, левая ветвь тоже меньше, правая ветвь больше.

Чтобы понять, как сбалансировать такое дерево, лучше всего прочитать соответствующую статью, например здесь: Деревья АВЛ .

Важно отметить, что двоичное дерево поиска полностью удовлетворило мои требования.

Быстрый поиск и быстрое добавление нового элемента.



Результат
В итоге, потратив еще несколько часов на оптимизацию, я получил многопоточное приложение, которое распаковывает архив в оперативную память, считает частоту появления различных слов и обрабатывает полученные данные с помощью AVL-дерева.

Вот несколько строк результатов работы программы, слева слово, справа частота.

Это наиболее распространенные слова разной длины:

  • я 34361402
  • а 36192092
  • от 52479822
  • по номеру 126422246
  • и 158458227
  • от 23978868
  • он 32602346
  • тогда 42163693
  • на номер 83001625
  • не 97183097
  • все 19576264
  • это 21318968
  • это 27719894
  • лайк 30228770
  • что 63106338
  • даже 6789652
  • было 6832494
  • если 7750404
  • я 12381969
  • было 15450767
  • возможно 5455561
  • очень 5477013
  • время 6317279
  • когда 9788599
  • на номер 9987225
  • мизантропия 296
  • высококвалифицированный 350
  • Ваше Превосходительство 384
  • Ваши Превосходительства 489
  • Превосходительство 3739
  • человеконенавистнический 46
  • мизантропия 52
  • частное предприятие 60
  • Ваше Превосходительство 91
  • национал-социалистската 96
Всего было получено 9,5 млн слов, анализ длился 8482 секунды, средняя скорость обработки неупакованного текста составила 18,57 МБ/сек.

Теперь я могу использовать полученные данные для уточнения своего морфологического словаря, а получив словарь, можно будет улучшить «частотный анализатор», т.к.

появится возможность группировать слова с одним корнем.

Кроме того, требует доработки работа «анализатора частот» с различными кодировками и т.п.

Далее следует синтаксический анализ предложения.

В конечном итоге я хочу получить хоть сколько-нибудь адекватную семантическую сеть.

Несмотря на то, что мой «доклад» затрагивает и тему программирования, и лингвистики – прошу не упрекать меня в неточностях в написании (особенно в пунктуации) или не самом гладком решении задачи, а указать на эти ошибки или предложить более изящное решения, я буду рад. Спасибо всем.

Теги: #компьютерная лингвистика #структуры данных #оптимизация кода #Семантика

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.