/razdel

Rule-based tokenizer, sentenizer for russian language

Primary LanguagePython

razdel Build Status

razdel — библиотека для разделения русскоязычного текста на токены и предложения. Система построена на правилах.

Использование

>>> from razdel import tokenize

>>> tokens = list(tokenize('Кружка-термос на 0.5л (50/64 см³, 516;...)'))
>>> tokens
[Substring(0, 13, 'Кружка-термос'),
 Substring(14, 16, 'на'),
 Substring(17, 20, '0.5'),
 Substring(20, 21, 'л'),
 Substring(22, 23, '(')
 ...]
 
>>> [_.text for _ in tokens]
['Кружка-термос', 'на', '0.5', 'л', '(', '50/64', 'см³', ',', '516', ';', '...', ')']
>>> from razdel import sentenize

>>> text = '''
... - "Так в чем же дело?" - "Не ра-ду-ют".
... И т. д. и т. п. В общем, вся газета
... '''

>>> list(sentenize(text))
[Substring(1, 23, '- "Так в чем же дело?"'),
 Substring(24, 40, '- "Не ра-ду-ют".'),
 Substring(41, 56, 'И т. д. и т. п.'),
 Substring(57, 76, 'В общем, вся газета')]

Установка

razdel поддерживает Python 2.7+, 3.4+ и PyPy 2, 3.

$ pip install razdel

Качество

Важно! К сожалению, в задаче разделения текста на предложения и токены нет одного правильного ответа. Как, например, разбить на предложения текст «Как же так?! Захар...» — воскликнут Пронин.? Можно считать, что это одно предложение, можно разбить на три «Как же так?!| |Захар...»| |— воскликнут Пронин., razdel разобьёт на два «Как же так?!| |Захар...» — воскликнут Пронин.. Как разделить на токены сокращение т.е.? Можно считать, что это один токен, можно рабить на т.|е., razdel разобъёт на т|.|е|..

razdel старается разбивать текст на предложения и токены так, как это сделано в 4 датасетах: SynTagRus, OpenCorpora, ГИКРЯ и РНК из репозитория morphoRuEval-2017. В основном это новостные тексты и литература. Правила razdel заточены под них. На текстах другой тематики (социальные сети, научные статьи) библиотека может работать хуже.

Мы считаем число ошибок, а не их долю, потому что в задаче токенизации очень много тривиальных тестов. Например, тест чуть-чуть?! нетривиальный, в нём токенизатор может ошибиться, дать ответ чуть|-|чуть|?|!, хотя эталон чуть-чуть|?!, таких тестов мало. Большинство фраз простые, например для словосочетания в 5 часов ..., правильный ответ даст даже str.split: в| |5| |часов| |.... Из-за тривиальных тестов качество всех систем получается высокое, тяжело оценить разницу между, например, 99.33% 99.12% 99.95% 99.88%, поэтому мы пишем абсолютное число ошибок.

errors — число ошибок, состоит из precision и recall-ошибок. Precision-ошибки считались так: возьмём все токены из разметки, например, что-то, проверим, что токенизатор не делит их на части. Recall-ошибки считались так: возьмём все биграммы токенов, например, что-то?, проверим, что разделение происходит между токенами, результат что|-|то|? не считается recall-ошибкой, то и ? разделены.

time — время выполнения.

Что такое, например, spacy_tokenize, spacy_tokenize2 написано в eval/zoo.py. Таблицы вычисляются в eval.ipynb

Токены

corpora syntag gicrya rnc
errors time errors time errors time errors time
re.findall(\w+|\d+|\p+) 1863 13.39 1613 14.74 1188 11.89 5005 12.64
nltk.word_tokenize 1666 141.41 1685 146.76 169 106.38 1987 116.64
spacy_tokenize 2846 73.26 2068 72.23 905 50.41 2706 51.05
spacy_tokenize2 2102 90.61 1272 89.12 226 63.28 1877 67.53
mystem 2577 73.33 2137 72.51 1156 55.75 1297 57.73
moses 1335 64.10 1405 65.34 808 49.13 1748 52.48
segtok.word_tokenize 414 52.69 584 54.60 830 40.70 1252 39.18
razdel.tokenize 348 27.99 460 28.36 151 21.22 1755 18.54

Предложения

corpora syntag gicrya rnc
errors time errors time errors time errors time
re.split([.?!…]) 8027 10.19 2188 6.59 4096 7.79 8191 10.37
moses 17131 73.15 8274 47.13 6698 55.79 21743 69.20
nltk.sent_tokenize 7752 57.96 1907 34.52 2212 39.40 11390 49.64
segtok.split_single 8981 79.18 1971 49.67 79135 13.92 86252 23.07
deepmipt 4529 38.37 579 23.20 3502 26.86 7487 26.18
razdel.sentenize 4323 26.75 369 16.09 5872 19.46 4903 19.56

Лицензия

MIT

Поддержка

Разработка

Тесты

pip install -e .
pip install -r requirements.txt
make test
make int  # 2000 integration tests

Пакет

make version
git push
git push --tags

make clean wheel upload

Алиас ctl

source alias.sh

Посмотреть ошибки mystem на syntag

cat data/syntag_tokens.txt | ctl sample 1000 | ctl gen | ctl diff --show moses_tokenize | less

Нетривиальные тесты для токенов

pv data/*_tokens.txt | ctl gen --recall | ctl diff space_tokenize > tests.txt
pv data/*_tokens.txt | ctl gen --precision | ctl diff re_tokenize >> tests.txt

Обновить интеграционные тесты

cd razdel/tests/data/
pv sents.txt | ctl up sentenize > t; mv t sents.txt

Посмотреть различия токенизации razdel и moses

cat data/*_tokens.txt | ctl sample 1000 | ctl gen | ctl up tokenize | ctl diff moses_tokenize | less

Измерить производительность razdel

cat data/*_tokens.txt | ctl sample 10000 | pv -l | ctl gen | ctl diff tokenize | wc -l