Skip to content

avidale/python-ruwordnet

Repository files navigation

python-ruwordnet

This is a Python wrapper for the RuWordNet thesaurus.

Это питонячья обёртка для тезауруса RuWordNet.

В настоящий момент поддержана версия 2021 года (RuWordNet 2.0): 59905 синсетов (смысловых групп), 154111 значений слов и словосочетаний.

Аналогичные и связанные проекты:

Что это такое

RuWordNet --- это один из немногих тезаурусов для русского языка.

Тезаурус --- это машиночитаемый словарь какого-то языка, составленный лингвистами и содержащий информацию о связях между словами.

RuWordNet разбит на синсеты --- наборы синонимичных слов и словосочетаний. Между синсетами установлены бинарные отношения, такие, как гипоним-гипероним, то есть "частное-общее". Например, "спаржа" является частным случаем "овощей". Такая разметка на синонимы и гиперонимы позволяет устанавливать отношения между словами с большей надёжностью (по крайней мере, в теории), чем при помощи word2vec и прочей дистрибутивной семантики.

Основными сущностями в тезаурусе являются Sense (смысл) - одно конкретное слово или словосочетание с конкретным же значением, а также Synset (синсет) - множество сущностей Sense с одинаковыми значениями и с одной частью речи. У многозначных слов существует по одной сущности Sense на каждое значение. Sense.synset - это синсет, к которому относится данное значение слова. Synset.senses - это список значений слов, включённых в данный синсет (то есть синонимичных друг другу).

Части речи поддержано три: существительное N, глагол V, и прилагательное A. Некоторые Sense состоят из нескольких слов, и часть речи им присваивается по главному слову.

В текущей версии тезауруса поддержаны следующие отношения между синсетами:

  • hyponyms / hypernyms : более частные и более общие понятия, например, "спаржа" / "овощи"
  • domains / domain_items: домены и их атрибуты, например, "спорт" / "мяч"
  • meronyms / holonyms: части и целые, например, "желудь" / "дуб"
  • classes / instances : классы и экземпляры, например, "Смоленск" / "областной центр"
  • premises / conclusions: предпосылки и возможные выводы из них, например, "прибежать" / "бегать" (поддержано только для глаголов)
  • causes / effects: причины и следствия, например, "толпиться" / "переснимать" (только для глаголов)
  • pos_synonyms: синонимы из других частей речи
  • antonyms: антонимы
  • related: прочие смысловые связи, например, "овощи" / "овощехранилище"
  • ili: interlingual index, то есть аналогичный синсет в другом языке (английском)

Кроме того, есть отношения между смыслами:

  • words / phrases - из каких слов состоит фраза, и в каких фразах участвует слово, например, "чувство" / "порыв чувств"
  • sources / derivations - от каких слов произошло данное, и какие произошли от него, например, "приятель" / "приятельский"

В данном пакете тезаурус обёрнут в ORM SQLAlchemy. Это значит, что вы можете скачать его содержимое в виде текстовой базы sqlite, либо переложить его в свою собственную базу данных.

Как запускать

Чтобы воспользоваться тезаурусом, выберите одну из двух опций:

  1. Либо клонируйте этот репозиторий;
  2. Либо установите пакет и скачайте файл с тезаурусом (около 80 мб):
pip install ruwordnet
ruwordnet download

В настоящий момент существует несколько версий тезауруса:

  • версия 2020 года содержится в файле ruwordnet/static/ruwordnet.db, и доступна в версии пакета ruwordnet>=0.0.2.
  • версия 2021 года (RuWordNet 2.0) содержится в файле ruwordnet/static/ruwordnet-2021.db, и доступна по умолчанию начиная с версии пакета ruwordnet>=0.0.4. В этой версии увеличился размер словаря и добавились свойства related (произвольная связь с другим синсетом) и ili (interlingual index, т.е. связь с английским WordNet) у синсетов.

Для применения пакета нужно создать объект RuWordNet:

from ruwordnet import RuWordNet
wn = RuWordNet()

Если вы не использовали команду ruwordnet download, вы можете самостоятельно указать путь до файла либо передать в конструктор открытую сессию SQLAlchemy:

from ruwordnet import RuWordNet
wn = RuWordNet(filename_or_session='ruwordnet/static/ruwordnet-2021.db')

После этого можно, например, искать синсеты, в которые входит слово

for sense in wn.get_senses('замок'):
    print(sense.synset)
# Synset(id="126228-N", title="СРЕДНЕВЕКОВЫЙ ЗАМОК")
# Synset(id="114707-N", title="ЗАМОК ДЛЯ ЗАПИРАНИЯ")

Для каждого синсета можно глядеть на гиперонимы...

wn.get_senses('спаржа')[0].synset.hypernyms
# [Synset(id="348-N", title="ОВОЩИ"),
#  Synset(id="4789-N", title="ТРАВЯНИСТОЕ РАСТЕНИЕ"),
#  Synset(id="6878-N", title="ОВОЩНАЯ КУЛЬТУРА")]

... или, наоборот, на гипонимы

vegetables = wn.get_senses('спаржа')[0].synset.hypernyms[0]
vegetables.hyponyms
# [Synset(id="107993-N", title="АРТИШОК"),
# Synset(id="108482-N", title="СПАРЖА"),
# Synset(id="118660-N", title="ЗЕЛЕНЫЙ ГОРОШЕК"),
# ...

Чтобы найти синонимы для слова, нужно пройти по всем элементам его синсета:

for sense in wn.get_senses('собака'):
    print(sense.synset, [synonym.name for synonym in sense.synset.senses])
# Synset(id="4454-N", title="СОБАКА") ['СОБАКА', 'ПЕС', 'СОБАЧКА', 'СОБАЧОНКА', 'ПСИНА', 'ЧЕТВЕРОНОГИЙ ДРУГ', 'ПЕСИК']

Если у слова много значений, для каждого из них будет извлечена своя группа синонимов:

for sense in wn.get_senses('зеленый'):
    print(sense.synset, [synonym.name for synonym in sense.synset.senses])
# Synset(id="109478-A", title="ЗЕЛЕНЫЙ ЦВЕТ") ['ЗЕЛЕНЫЙ', 'ЗЕЛЕНОВАТЫЙ', 'ЗЕЛЕНЕНЬКИЙ']
# Synset(id="119627-A", title="НЕЗРЕЛЫЙ, НЕСПЕЛЫЙ") ['ЗЕЛЕНЫЙ', 'НЕДОЗРЕЛЫЙ', 'НЕЗРЕЛЫЙ', 'НЕСОЗРЕВШИЙ', 'НЕСПЕЛЫЙ']
# Synset(id="119626-A", title="ЗЕЛЕНЫЙ (БЛЕДНЫЙ)") ['ЗЕЛЕНЫЙ']
# Synset(id="120626-A", title="НЕОПЫТНЫЙ") ['ЗЕЛЕНЫЙ', 'НЕОПЫТНЫЙ', 'ЖЕЛТОРОТЫЙ', 'МАЛООПЫТНЫЙ', 'НЕИСКУШЕННЫЙ']

Поиск в тезаурусе

Обращаясь к объекту RuWordNet с помощью квадратных скобок, можно извлекать русские и английские синсеты (по id) и смыслу (по id или тексту).

wn['134045-N']
# Synset(id="134045-N", title="ПОТЕНЦИАЛ (ФИЗИЧЕСКАЯ ВЕЛИЧИНА)")
wn['11493827-n']
# WNSynset(id="11493827-n", definition="the difference in electrical charge between two points in a circuit expressed in volts")
wn['134045-N-189287']
# Sense(id="134045-N-189287", name="ПОТЕНЦИАЛ")
wn['electric_potential%1:19:00::']
# WNSense(key="electric_potential%1:19:00::", name="electric_potential")
wn['потенциал']
# [Sense(id="134045-N-189287", name="ПОТЕНЦИАЛ"), Sense(id="134046-N-189287", name="ПОТЕНЦИАЛ")]
wn['potential']
# [WNSense(key="potential%1:19:00::", name="potential"), WNSense(key="potential%3:00:00::", name="potential"), WNSense(key="potential%1:26:00::", name="potential")]

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

wn.get_synset_by_id("134045-N")
wn.get_en_synset_by_id("11493827-n")
wn.get_senses('потенциал')
wn.get_synsets('потенциал')
wn.get_en_senses('potential')
wn.get_en_synsets('potential')

Предупреждение: для английского WordNet представлены не все элементы, а только связанные с RuWordNet.

Больше примеров использования есть в .ipynb файлах в данном репозитории.