- BrainTools - https://www.braintools.ru -
Введение [1]
Попытка 1. Создание словаря на основе названий статей Викисловаря [3]
Попытка 2. Создание словаря на основе полного дампа содержимого русского Викисловаря [4]
Вывод [9]
Ссылка на GitHub [10]
Другие ссылки [11]
В задачах обработки естественного языка (NLP) часто требуется список слов русского языка. Такой список может использоваться как базовый фильтр для выявления неизвестных и потенциально некорректных слов.
Одним из распространённых инструментов для работы с русским текстом является библиотека pymorphy (pymorphy2 / pymorphy3), основанная на корпусе русского языка OpenCorpora. Она предназначена для морфологического анализа текстов и, в том числе, позволяет проверять, известно ли слово встроенному словарю библиотеки.
Однако словарь pymorphy ориентирован на нормативную лексику и морфологию. В нём отсутствует значительная часть имён собственных, топонимов, заимствований, разговорной и современной лексики. Поэтому при использовании pymorphy для фильтрации текста возникают ложные срабатывания, много редких и нестандартных слов определяются как неизвестные (что мы увидим ниже в разделе сравнения словарей).
Для повышения полноты выявления неизвестных слов я решил собрать свой максимально широкий список слов русского языка для задач NLP.
Такой список слов можно получить на основе данных сайта Wiktionary (Викисловарь). Wiktionary – это открытый многоязычный словарь, в котором каждая словарная единица представлена в виде отдельной статьи. Викисловарь содержит информацию о словах различных языков, включая русский, а также сведения об их морфологических и синтаксических свойствах.
Далее в статье термины «словарь» и «список слов» используются как синонимы. Под словарём понимается именно список слов, а не полноценный лингвистический словарь с определениями и разметкой.
Также термины «слово» и «словоформа» используются как равнозначные. Для обозначения нормальной формы слова используется термин «лемма».
Существуют готовые инструменты для парсинга данных с вики-сайтов, например wiktextract [1]. Wiktextract обрабатывает внутренние конструкции сайта и формирует структурированные данные. В результате получается полноценная лексическая база. Wiktextract решает широкий круг задач и является предпочтительным решением для задач, где требуется извлечение морфологии, значений и других лингвистических характеристик. Однако для задачи получения простого списка слов такой уровень обработки является избыточным и усложняет процесс без практической необходимости. К тому же wiktextract ориентирован под англоязычный раздел Wiktionary (enwiktionary).
Поэтому для решения своей задачи я выбрал более простой метод: взял данные русскоязычного раздела Wiktionary (ruwiktionary) и применил собственную логику [12] фильтрации. Такой подход даёт полный контроль над процессом формирования словаря и достаточен, если требуется получить список слов для практических задач. При этом ruwiktionary в разы меньше enwiktionary, что также ускоряет обработку.
Идея создания словаря такая:
В Wiktionary слова и устойчивые выражения имеют собственную страницу, а названия страниц совпадают с этими словами (выражениями). Поэтому, собрав все заголовки ruwiktionary, мы получим большой список слов русского языка для задач NLP.
Я скачал дамп ruwiktionary-latest-all-titles-in-ns0.gz [13][2]
Дамп содержит список заголовков всех статей из основного пространства имён русского раздела Wiktionary.
Был собран список заголовков. Для фильтрации заголовков использовалось следующее правило:
ru_pattern = re.compile(r"^[А-Яа-яЁё]+(?:[-'][А-Яа-яЁё]+)*$")
Оно оставляет только строки, состоящие из кириллицы, а также допускает дефисы и апострофы. Такая фильтрация пропускает максимально широкое количество слов, включая имена собственные, заимствованные и транслитерированные слова, междометия и много другое, что требуется для моей задачи.
После фильтрации все слова были приведены к нижнему регистру, удалены дубликаты и отсортированы.
В результате получился словарь с количеством слов: 1 542 954.
Вот первые 10 слов полученного списка:
|
|
word |
|
0 |
а |
|
1 |
а’асх |
|
2 |
а’атчевматальын |
|
3 |
а’атчегматальын |
|
4 |
а’к’алтывагыргын |
|
5 |
а-а |
|
6 |
а-а-а |
|
7 |
а-а-а-а |
|
8 |
а-ах |
|
9 |
а-во |
Видно, что в словаре представлены не только русские слова, но и слова других языков на кириллице (к примеру, слово “а’атчевматальын” – это слово из чукотского языка).
Для повышения качества словаря требуется дополнительная фильтрация слов.
Для формирования словаря был скачан более полный дамп ruwiktionary-latest-pages-articles-multistream.xml.bz2 [14] [3]
Дамп содержит тексты всех статей русского раздела Wiktionary. Это позволяет выполнить фильтрацию не только по языку, но и по содержимому.
Дамп был распакован. Из XML извлечены статьи.
Для каждой статьи извлечен заголовок (слово), проверено наличие русского раздела ({{-ru-}}) и выполнена фильтрация по ru_pattern, как и в прошлом примере. Дополнительно были удалены односимвольные слова, кроме а, в, и, к, о, с, у, я. Также удалены шумы, крики, припевки типа а-а-а.
re.compile(r"^(?![авикосуя]$)[а-яё]$")
re.compile(r"^(а|о|у|э|и|ы|е|я|ё|ю)(-1)+$")
В результате сформирован список заголовков статей (слов), написанных на кириллице и имеющих русскоязычный раздел. Количество слов в полученном словаре: 444 148.
Вот первые 10 и случайные 10 слов из словаря:
|
|
word |
|
word |
|
0 |
а |
163564 |
лемго |
|
1 |
а-во |
231463 |
орзали |
|
2 |
а-дато |
23402 |
бацкино |
|
3 |
а-каприччио |
400904 |
укиха |
|
4 |
а-конто |
235468 |
ответчица |
|
5 |
а-ля |
238978 |
отнимавши |
|
6 |
а-ля-карт |
206539 |
неоязычество |
|
7 |
а-мольный |
439786 |
энрике |
|
8 |
а-форфе |
377324 |
сторновав |
|
9 |
аа |
233787 |
остекление |
Составим таблицу со значениями выбранных слов.
|
Слово |
Значение |
Ссылка |
|
а |
союз: противопоставление, сопоставление |
|
|
а-во |
сокращение от агентство |
|
|
а-дато |
финансовый термин: число, от которого дан тот или иной документ |
|
|
а-каприччио |
музыкальный термин: произвольно, не подчиняясь установившимся формам |
|
|
а-конто |
финансовый термин: вид предварительного расчёта, представляющий собой авансовую оплату счетов экспортёра импортёром за проданные товары |
|
|
а-ля |
подобно, наподобие, словно, по образцу |
|
|
а-ля-карт |
по меню, по карте |
|
|
а-мольный |
написанный в тональности ля минор |
|
|
а-форфе |
заранее произведённая налоговыми органами оценка прибыли предприятия, на котором не ведётся точный бухгалтерский учёт |
|
|
аа |
междометие (эмоциональный звук) |
|
|
лемго |
город в Германии |
|
|
орзали |
мужское имя |
|
|
бацкино |
село в России |
|
|
укиха |
город в Японии |
|
|
ответчица |
женск. к ответчик |
|
|
отнимавши |
дееприч. от отнимать |
|
|
неоязычество |
новое язычество; движение, связанное с возрождением доавраамических верований |
|
|
энрике |
мужское имя |
|
|
сторновав |
дееприч. от сторновать |
|
|
остекление |
действие по значению гл. остеклить |
Представленные слова действительно имеют значение и могут употребляться в русскоязычных текстах. В словаре встречаются междометия, которые не несут большого смыслового значения, но тем не менее употребляются в речи. В словаре есть топонимы, имена и фамилии, много редко используемых, устаревших или узкоспециализированных слов, что естественно ввиду большого размера словаря.
Наличие русского раздела и фильтрация по кириллице не гарантируют, что слово русское. В словаре присутствуют редкие, заимствованные, транслитерированные и специфичные слова, имена собственные (в том числе топонимы, имена и фамилии).
Словарь не лемматизирован и включает как леммы, так и различные словоформы (например, причастия и деепричастия). Лемматизация не использовалась, потому что она может некорректно обрабатывать редкие и неизвестные слова, искажая их форму.
Такой подход позволяет охватить максимально широкий перечень словоформ. Это снижает количество ложных срабатываний и уменьшает объём ручной проверки, так как после сравнения со словарем в тексте остаются в основном:
шумовые токены (например, вокализации типа “ля-ля-ля”);
опечатки;
несуществующие или выдуманные слова;
вкрапления других языков.
Для оценки полученного словаря было выполнено сравнение со встроенным словарём библиотеки pymorphy3.
Результаты представлены в таблице:
|
Метрика |
Словарь pymorphy |
Словарь из Wiktionary |
|
Размер словаря, словоформ |
3 063 823 |
444 148 |
|
Взаимное перекрытие словарей |
249 155 словоформ |
|
|
8,1% покрывается Wiktionary |
56,1% покрывается pymorphy |
|
|
Количество относительно уникальных словоформ |
2 814 668 |
194 993 |
|
Доля относительно уникальных словоформ |
91.9% |
43.9% |
Словарь pymorphy во много раз больше словаря, созданного из данных Wiktionary. Однако 43.9% полученного словаря состоит из уникальных слов, которых нет в словаре pymorphy, что может быть полезным при анализе текстов.
Для оценки того, насколько вновь созданный словарь поможет в фильтрации неизвестных слов был проведён анализ двух текстов:
“Евгений Онегин” Александра Сергеевича Пушкина;
Все тексты песен Ивана Александровича Алексеева (Noize MC).
Результаты анализа приведены в таблице ниже:
|
Метрика |
А.С. Пушкин «Евгений Онегин» |
Тексты песен И.А. Алексеева (Noize MC) |
|
До лемматизации через pymorphy3 |
||
|
Количество уникальных словоформ |
9333 |
23365 |
|
Известны pymorphy |
9038 |
21566 |
|
После лемматизации через pymorphy3 (лемматизировали только известные pymorphy3 слова) |
||
|
Уникальных лемм и неизвестных словоформ |
5519 |
13481 |
|
Известны pymorphy |
5224 |
11682 |
|
Неизвестны pymorphy |
295 |
1799 |
|
Доля неизвестных словоформ для словаря pymorphy |
5.3% |
13.3% |
|
Из неизвестных pymorphy словоформ покрыты словарем из Wiktionary |
43 |
449 |
|
Словарь из Wiktionary дополнительно покрыл неизвестных словоформ |
14.6% |
25.0% |
|
Осталось неизвестных словоформ после двух словарей |
252 |
1350 |
|
4.6% |
10.0% |
|
В “Евгении Онегине” словарь из Wiktionary дополнительно покрыл 14.6% уникальных словоформ текста, которые отсутствуют в pymorphy.
Примеры таких слов:
вертер, дельвиг, митридат, морфей, осьмнадцать, дале, заране.
Это в основном имена собственные, архаизмы и устаревшие формы слов.
Для современных текстов (Noize MC) эффект значительно выше. Wiktionary дополнительно распознал 25.0% неизвестных словоформ.
Примеры:
сленг: кайфовый, движ, тусить, ништяк;
заимствования: баттл, дисс, флоу, лайв;
интернет-лексика: видос, гифка, комментить;
обсценная лексика: п**дос, до**я, х**та;
составные слова: бабл-гам, фитнес-тренер.
Словарь pymorphy отлично покрывает классические тексты и хорошо современные, поэтому является предпочтительным для морфологического анализа.
Однако словарь на основе Wiktionary неплохо дополняет его за счёт:
имён собственных;
топонимов;
заимствований;
обсценной лексики;
современной разговорной и интернет-лексики;
редких и устаревших слов.
Значительная часть оставшихся после двух словарей словоформ это:
повторяющиеся слоги и вокализации: “ла-ла-ла”, “е-е-е”;
словоформы с дефисом: “час-другой”, “моралисты-псевдожурналисты”;
опечатки или специально искаженные написания слов: “канатоходець”, “узбагойзя”;
слова других языков: “катацумури”, “пробач”.
Видно, что два словаря максимально отфильтровали из текста известные и допустимые словоформы, оставив в остатке преимущественно шумовые, заимствованные, выдуманные и неправильные слова.
В результате получился практический список словоформ русского языка состоящий из 444 тыс. слов.
В сравнении, словарь pymorphy значительно больше. Он содержит миллионы словоформ и хорошо покрывает нормативную лексику. Это делает его удобным и предпочтительным для морфологического анализа.
Словарь на основе Wiktionary меньше по размеру, но в нём присутствуют имена собственные, топонимы, заимствования, сленг и редкая лексика, которые часто отсутствуют в pymorphy.
На реальных текстах это даёт практический эффект:
Для классической литературы (Пушкин) pymorphy покрывает 94.7% текста.
Словарь из Wiktionary дополнительно покрывает 14.6% неизвестных слов.
Для современных текстов (Noize MC) pymorphy покрывает 86.7% текста.
Словарь из Wiktionary дополнительно покрывает 25.0% неизвестных слов.
Конечно, это не тот результат, которого я ожидал, начиная проект, однако даже такие значения повышают полноту определения неизвестных слов и уменьшают ручной труд при обработке текстов.
Предложенный подход показывает, что списки слов можно собирать самостоятельно на основе данных Wiktionary. При этом процесс формирования словаря относительно простой, быстрый и полностью контролируется. Можно выбирать дамп, настроить правила фильтрации и адаптировать результат под конкретные задачи.
Также данный подход можно применять для создания словарей других языков. Достаточно скачать нужный дамп Wiktionary и изменить правила фильтрации под особенности языка.
Таким образом, словарь созданный на основе данных Wiktionary хорошо дополняет словарь pymorphy и может использоваться в задачах NLP.
Список слов русского языка на основе данных Wiktionary в форматах CSV и TXT;
Список слов, которые есть в словаре из Wiktionary, но отсутствуют в pymorphy в форматах CSV и TXT;
Файл с проектом ipynb
доступны в репозитории: https://github.com/EgorTatarnikov/rus_dict_wiktionary [35]
https://github.com/tatuylonen/wiktextract [36] – парсер Wiktionary.
https://dumps.wikimedia.org/ruwiktionary/latest/ruwiktionary-latest-all-titles-in-ns0.gz [13] – список заголовков всех статей ruwiktionary.
https://dumps.wikimedia.org/ruwiktionary/latest/ruwiktionary-latest-pages-articles-multistream.xml.bz2 [14] – полный XML-дамп со всеми статьями ruwiktionary.
* Признан минюстом РФ иностранным агентом
Автор: TatarnikovEgor
Источник [37]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/29628
URLs in this post:
[1] Введение: #01
[2] Процесс создания словаря : #02
[3] Попытка 1. Создание словаря на основе названий статей Викисловаря: #03
[4] Попытка 2. Создание словаря на основе полного дампа содержимого русского Викисловаря: #04
[5] Выборочная проверка слов: #05
[6] Особенности словаря: #06
[7] Сравнение с pymorphy3: #07
[8] Проверка на текстах Пушкина и Noize MC: #08
[9] Вывод: #09
[10] Ссылка на GitHub: #10
[11] Другие ссылки: #11
[12] логику: http://www.braintools.ru/article/7640
[13] ruwiktionary-latest-all-titles-in-ns0.gz : https://dumps.wikimedia.org/ruwiktionary/latest/ruwiktionary-latest-all-titles-in-ns0.gz
[14] ruwiktionary-latest-pages-articles-multistream.xml.bz2: https://dumps.wikimedia.org/ruwiktionary/latest/ruwiktionary-latest-pages-articles-multistream.xml.bz2
[15] https://ru.wiktionary.org/wiki/а: https://ru.wiktionary.org/wiki/%D0%B0
[16] https://ru.wiktionary.org/wiki/а-во: https://ru.wiktionary.org/wiki/%D0%B0-%D0%B2%D0%BE
[17] https://ru.wiktionary.org/wiki/а-дато: https://ru.wiktionary.org/wiki/%D0%B0-%D0%B4%D0%B0%D1%82%D0%BE
[18] https://ru.wiktionary.org/wiki/а-каприччио: https://ru.wiktionary.org/wiki/%D0%B0-%D0%BA%D0%B0%D0%BF%D1%80%D0%B8%D1%87%D1%87%D0%B8%D0%BE
[19] https://ru.wiktionary.org/wiki/а-конто: https://ru.wiktionary.org/wiki/%D0%B0-%D0%BA%D0%BE%D0%BD%D1%82%D0%BE
[20] https://ru.wiktionary.org/wiki/а-ля: https://ru.wiktionary.org/wiki/%D0%B0-%D0%BB%D1%8F
[21] https://ru.wiktionary.org/wiki/а-ля-карт: https://ru.wiktionary.org/wiki/%D0%B0-%D0%BB%D1%8F-%D0%BA%D0%B0%D1%80%D1%82
[22] https://ru.wiktionary.org/wiki/а-мольный: https://ru.wiktionary.org/wiki/%D0%B0-%D0%BC%D0%BE%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9
[23] https://ru.wiktionary.org/wiki/а-форфе: https://ru.wiktionary.org/wiki/%D0%B0-%D1%84%D0%BE%D1%80%D1%84%D0%B5
[24] https://ru.wiktionary.org/wiki/аа: https://ru.wiktionary.org/wiki/%D0%B0%D0%B0
[25] https://ru.wiktionary.org/wiki/Лемго: https://ru.wiktionary.org/wiki/%D0%9B%D0%B5%D0%BC%D0%B3%D0%BE
[26] https://ru.wiktionary.org/wiki/Орзали: https://ru.wiktionary.org/wiki/%D0%9E%D1%80%D0%B7%D0%B0%D0%BB%D0%B8
[27] https://ru.wiktionary.org/wiki/Бацкино: https://ru.wiktionary.org/wiki/%D0%91%D0%B0%D1%86%D0%BA%D0%B8%D0%BD%D0%BE
[28] https://ru.wiktionary.org/wiki/Укиха: https://ru.wiktionary.org/wiki/%D0%A3%D0%BA%D0%B8%D1%85%D0%B0
[29] https://ru.wiktionary.org/wiki/ответчица: https://ru.wiktionary.org/wiki/%D0%BE%D1%82%D0%B2%D0%B5%D1%82%D1%87%D0%B8%D1%86%D0%B0
[30] https://ru.wiktionary.org/wiki/отнимавши: https://ru.wiktionary.org/wiki/%D0%BE%D1%82%D0%BD%D0%B8%D0%BC%D0%B0%D0%B2%D1%88%D0%B8
[31] https://ru.wiktionary.org/wiki/неоязычество: https://ru.wiktionary.org/wiki/%D0%BD%D0%B5%D0%BE%D1%8F%D0%B7%D1%8B%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE
[32] https://ru.wiktionary.org/wiki/Энрике: https://ru.wiktionary.org/wiki/%D0%AD%D0%BD%D1%80%D0%B8%D0%BA%D0%B5
[33] https://ru.wiktionary.org/wiki/сторновав: https://ru.wiktionary.org/wiki/%D1%81%D1%82%D0%BE%D1%80%D0%BD%D0%BE%D0%B2%D0%B0%D0%B2
[34] https://ru.wiktionary.org/wiki/остекление: https://ru.wiktionary.org/wiki/%D0%BE%D1%81%D1%82%D0%B5%D0%BA%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5
[35] https://github.com/EgorTatarnikov/rus_dict_wiktionary: https://github.com/EgorTatarnikov/rus_dict_wiktionary
[36] https://github.com/tatuylonen/wiktextract: https://github.com/tatuylonen/wiktextract
[37] Источник: https://habr.com/ru/articles/1027992/?utm_campaign=1027992&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.