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
- Чат — https://telegram.me/natural_language_processing
- Тикеты — https://github.com/natasha/razdel/issues
Тесты
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