%global _empty_manifest_terminate_build 0
Name: python-slovnet
Version: 0.6.0
Release: 1
Summary: Deep-learning based NLP modeling for Russian language
License: MIT
URL: https://github.com/natasha/slovnet
Source0: https://mirrors.nju.edu.cn/pypi/web/packages/3e/d1/bba34dec46f1fcb85ca35815268be427ee89d09728c85ae4ab294dd9db09/slovnet-0.6.0.tar.gz
BuildArch: noarch
Requires: python3-numpy
Requires: python3-razdel
Requires: python3-navec
%description
![CI](https://github.com/natasha/slovnet/actions/workflows/test.yml/badge.svg)
SlovNet is a Python library for deep-learning based NLP modeling for Russian language. Library is integrated with other Natasha projects: Nerus — large automatically annotated corpus, Razdel — sentence segmenter, tokenizer and Navec — compact Russian embeddings. Slovnet provides high quality practical models for Russian NER, morphology and syntax, see evaluation section for more:
* NER is 1-2% worse than current BERT SOTA by DeepPavlov but 60 times smaller in size (~30 MB) and works fast on CPU (~25 news articles/sec).
* Morphology tagger and syntax parser have comparable accuracy on news dataset with large SOTA BERT models, take 50 times less space (~30 MB), work faster on CPU (~500 sentences/sec).
## Downloads
## Install
During inference Slovnet depends only on Numpy. Library supports Python 3.5+, PyPy 3.
```bash
$ pip install slovnet
```
## Usage
Download model weights and vocabs package, use links from downloads section and Navec download section. Optionally install Ipymarkup to visualize NER markup.
Slovnet annotator `map` method has list of items as input and same size iterator over markups as output. Internally items are processed in batches of size `batch_size`. Default size is 8, larger batch — more RAM, better CPU utilization. `__call__` method just calls `map` with a list of 1 item.
### NER
```python
>>> from navec import Navec
>>> from slovnet import NER
>>> from ipymarkup import show_span_ascii_markup as show_markup
>>> text = 'Европейский союз добавил в санкционный список девять политических деятелей из самопровозглашенных республик Донбасса — Донецкой народной республики (ДНР) и Луганской народной республики (ЛНР) — в связи с прошедшими там выборами. Об этом говорится в документе, опубликованном в официальном журнале Евросоюза. В новом списке фигурирует Леонид Пасечник, который по итогам выборов стал главой ЛНР. Помимо него там присутствуют Владимир Бидевка и Денис Мирошниченко, председатели законодательных органов ДНР и ЛНР, а также Ольга Позднякова и Елена Кравченко, председатели ЦИК обеих республик. Выборы прошли в непризнанных республиках Донбасса 11 ноября. На них удержали лидерство действующие руководители и партии — Денис Пушилин и «Донецкая республика» в ДНР и Леонид Пасечник с движением «Мир Луганщине» в ЛНР. Президент Франции Эмманюэль Макрон и канцлер ФРГ Ангела Меркель после встречи с украинским лидером Петром Порошенко осудили проведение выборов, заявив, что они нелегитимны и «подрывают территориальную целостность и суверенитет Украины». Позже к осуждению присоединились США с обещаниями новых санкций для России.'
>>> navec = Navec.load('navec_news_v1_1B_250K_300d_100q.tar')
>>> ner = NER.load('slovnet_ner_news_v1.tar')
>>> ner.navec(navec)
>>> markup = ner(text)
>>> show_markup(markup.text, markup.spans)
Европейский союз добавил в санкционный список девять политических
LOC─────────────
деятелей из самопровозглашенных республик Донбасса — Донецкой народной
LOC───── LOC──────────────
республики (ДНР) и Луганской народной республики (ЛНР) — в связи с
───────────────── LOC────────────────────────────────
прошедшими там выборами. Об этом говорится в документе, опубликованном
в официальном журнале Евросоюза. В новом списке фигурирует Леонид
LOC────── PER────
Пасечник, который по итогам выборов стал главой ЛНР. Помимо него там
──────── LOC
присутствуют Владимир Бидевка и Денис Мирошниченко, председатели
PER───────────── PER───────────────
законодательных органов ДНР и ЛНР, а также Ольга Позднякова и Елена
LOC LOC PER───────────── PER───
Кравченко, председатели ЦИК обеих республик. Выборы прошли в
───────── ORG
непризнанных республиках Донбасса 11 ноября. На них удержали лидерство
LOC─────
действующие руководители и партии — Денис Пушилин и «Донецкая
PER────────── ORG──────
республика» в ДНР и Леонид Пасечник с движением «Мир Луганщине» в ЛНР.
────────── LOC PER──────────── ORG────────── LOC
Президент Франции Эмманюэль Макрон и канцлер ФРГ Ангела Меркель после
LOC──── PER───────────── LOC PER───────────
встречи с украинским лидером Петром Порошенко осудили проведение
PER─────────────
выборов, заявив, что они нелегитимны и «подрывают территориальную
целостность и суверенитет Украины». Позже к осуждению присоединились
LOC────
США с обещаниями новых санкций для России.
LOC LOC───
```
### Morphology
Morphology annotator processes tokenized text. To split the input into sentencies and tokens use Razdel.
```python
>>> from razdel import sentenize, tokenize
>>> from navec import Navec
>>> from slovnet import Morph
>>> chunk = []
>>> for sent in sentenize(text):
>>> tokens = [_.text for _ in tokenize(sent.text)]
>>> chunk.append(tokens)
>>> chunk[:1]
[['Европейский', 'союз', 'добавил', 'в', 'санкционный', 'список', 'девять', 'политических', 'деятелей', 'из', 'самопровозглашенных', 'республик', 'Донбасса', '—', 'Донецкой', 'народной', 'республики', '(', 'ДНР', ')', 'и', 'Луганской', 'народной', 'республики', '(', 'ЛНР', ')', '—', 'в', 'связи', 'с', 'прошедшими', 'там', 'выборами', '.']]
>>> navec = Navec.load('navec_news_v1_1B_250K_300d_100q.tar')
>>> morph = Morph.load('slovnet_morph_news_v1.tar', batch_size=4)
>>> morph.navec(navec)
>>> markup = next(morph.map(chunk))
>>> for token in markup.tokens:
>>> print(f'{token.text:>20} {token.tag}')
Европейский ADJ|Case=Nom|Degree=Pos|Gender=Masc|Number=Sing
союз NOUN|Animacy=Inan|Case=Nom|Gender=Masc|Number=Sing
добавил VERB|Aspect=Perf|Gender=Masc|Mood=Ind|Number=Sing|Tense=Past|VerbForm=Fin|Voice=Act
в ADP
санкционный ADJ|Animacy=Inan|Case=Acc|Degree=Pos|Gender=Masc|Number=Sing
список NOUN|Animacy=Inan|Case=Acc|Gender=Masc|Number=Sing
девять NUM|Case=Nom
политических ADJ|Case=Gen|Degree=Pos|Number=Plur
деятелей NOUN|Animacy=Anim|Case=Gen|Gender=Masc|Number=Plur
из ADP
самопровозглашенных ADJ|Case=Gen|Degree=Pos|Number=Plur
республик NOUN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Plur
Донбасса PROPN|Animacy=Inan|Case=Gen|Gender=Masc|Number=Sing
— PUNCT
Донецкой ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
народной ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
республики NOUN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
( PUNCT
ДНР PROPN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
) PUNCT
и CCONJ
Луганской ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
народной ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
республики NOUN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
( PUNCT
ЛНР PROPN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
) PUNCT
— PUNCT
в ADP
связи NOUN|Animacy=Inan|Case=Loc|Gender=Fem|Number=Sing
с ADP
прошедшими VERB|Aspect=Perf|Case=Ins|Number=Plur|Tense=Past|VerbForm=Part|Voice=Act
там ADV|Degree=Pos
выборами NOUN|Animacy=Inan|Case=Ins|Gender=Masc|Number=Plur
. PUNCT
```
### Syntax
Syntax parser processes sentencies split into tokens. Use Razdel for segmentation.
```python
>>> from ipymarkup import show_dep_ascii_markup as show_markup
>>> from razdel import sentenize, tokenize
>>> from navec import Navec
>>> from slovnet import Syntax
>>> chunk = []
>>> for sent in sentenize(text):
>>> tokens = [_.text for _ in tokenize(sent.text)]
>>> chunk.append(tokens)
>>> chunk[:1]
[['Европейский', 'союз', 'добавил', 'в', 'санкционный', 'список', 'девять', 'политических', 'деятелей', 'из', 'самопровозглашенных', 'республик', 'Донбасса', '—', 'Донецкой', 'народной', 'республики', '(', 'ДНР', ')', 'и', 'Луганской', 'народной', 'республики', '(', 'ЛНР', ')', '—', 'в', 'связи', 'с', 'прошедшими', 'там', 'выборами', '.']]
>>> navec = Navec.load('navec_news_v1_1B_250K_300d_100q.tar')
>>> syntax = Syntax.load('slovnet_syntax_news_v1.tar')
>>> syntax.navec(navec)
>>> markup = next(syntax.map(chunk))
# Convert CoNLL-style format to source, target indices
>>> words, deps = [], []
>>> for token in markup.tokens:
>>> words.append(token.text)
>>> source = int(token.head_id) - 1
>>> target = int(token.id) - 1
>>> if source > 0 and source != target: # skip root, loops
>>> deps.append([source, target, token.rel])
>>> show_markup(words, deps)
┌► Европейский amod
┌►└─ союз nsubj
┌───────┌─┌─└─── добавил
│ │ │ ┌──► в case
│ │ │ │ ┌► санкционный amod
│ │ └►└─└─ список obl
│ │ ┌──► девять nummod:gov
│ │ │ ┌► политических amod
│ ┌─────└►┌─└─└─ деятелей obj
│ │ │ ┌──► из case
│ │ │ │ ┌► самопровозглашенных amod
│ │ └►└─└─ республик nmod
│ │ └──► Донбасса nmod
│ │ ┌──────────► — punct
│ │ │ ┌──► Донецкой amod
│ │ │ │ ┌► народной amod
│ │ │ ┌─┌─┌─└─└─ республики
│ │ │ │ │ │ ┌► ( punct
│ │ │ │ │ └►┌─└─ ДНР parataxis
│ │ │ │ │ └──► ) punct
│ │ │ │ │ ┌────► и cc
│ │ │ │ │ │ ┌──► Луганской amod
│ │ │ │ │ │ │ ┌► народной amod
│ │ └─│ └►└─└─└─ республики conj
│ │ │ ┌► ( punct
│ │ └────►┌─└─ ЛНР parataxis
│ │ └──► ) punct
│ │ ┌──────► — punct
│ │ │ ┌►┌─┌─ в case
│ │ │ │ │ └► связи fixed
│ │ │ │ └──► с fixed
│ │ │ │ ┌►┌─ прошедшими acl
│ │ │ │ │ └► там advmod
│ └────►└─└─└─── выборами nmod
└──────────────► . punct
```
## Documentation
Materials are in Russian:
* Article about distillation and quantization in Slovnet
* Slovnet section of Datafest 2020 talk
## Evaluation
In addition to quality metrics we measure speed and models size, parameters that are important in production:
* `init` — time between system launch and first response. It is convenient for testing and devops to have model that starts quickly.
* `disk` — file size of artefacts one needs to download before using the system: model weights, embeddings, binaries, vocabs. It is convenient to deploy compact models in production.
* `ram` — average CPU/GPU RAM usage.
* `speed` — number of input items processed per second: news articles, tokenized sentencies.
### NER
4 datasets are used for evaluation: factru
, gareev
, ne5
and bsnlp
. Slovnet is compared to deeppavlov
, deeppavlov_bert
, deeppavlov_slavic
, pullenti
, spacy
, stanza
, texterra
, tomita
, mitie
.
For every column top 3 results are highlighted:
|
factru |
gareev |
ne5 |
bsnlp |
f1 |
PER |
LOC |
ORG |
PER |
ORG |
PER |
LOC |
ORG |
PER |
LOC |
ORG |
slovnet |
0.959 |
0.915 |
0.825 |
0.977 |
0.899 |
0.984 |
0.973 |
0.951 |
0.944 |
0.834 |
0.718 |
slovnet_bert |
0.973 |
0.928 |
0.831 |
0.991 |
0.911 |
0.996 |
0.989 |
0.976 |
0.960 |
0.838 |
0.733 |
deeppavlov |
0.910 |
0.886 |
0.742 |
0.944 |
0.798 |
0.942 |
0.919 |
0.881 |
0.866 |
0.767 |
0.624 |
deeppavlov_bert |
0.971 |
0.928 |
0.825 |
0.980 |
0.916 |
0.997 |
0.990 |
0.976 |
0.954 |
0.840 |
0.741 |
deeppavlov_slavic |
0.956 |
0.884 |
0.714 |
0.976 |
0.776 |
0.984 |
0.817 |
0.761 |
0.965 |
0.925 |
0.831 |
pullenti |
0.905 |
0.814 |
0.686 |
0.939 |
0.639 |
0.952 |
0.862 |
0.683 |
0.900 |
0.769 |
0.566 |
spacy |
0.901 |
0.886 |
0.765 |
0.970 |
0.883 |
0.967 |
0.928 |
0.918 |
0.919 |
0.823 |
0.693 |
stanza |
0.943 |
0.865 |
0.687 |
0.953 |
0.827 |
0.923 |
0.753 |
0.734 |
0.938 |
0.838 |
0.724 |
texterra |
0.900 |
0.800 |
0.597 |
0.888 |
0.561 |
0.901 |
0.777 |
0.594 |
0.858 |
0.783 |
0.548 |
tomita |
0.929 |
|
|
0.921 |
|
0.945 |
|
|
0.881 |
|
|
mitie |
0.888 |
0.861 |
0.532 |
0.849 |
0.452 |
0.753 |
0.642 |
0.432 |
0.736 |
0.801 |
0.524 |
`it/s` — news articles per second, 1 article ≈ 1KB.
|
init, s |
disk, mb |
ram, mb |
speed, it/s |
slovnet |
1.0 |
27 |
205 |
25.3 |
slovnet_bert |
5.0 |
473 |
9500 |
40.0 (gpu) |
deeppavlov |
5.9 |
1024 |
3072 |
24.3 (gpu) |
deeppavlov_bert |
34.5 |
2048 |
6144 |
13.1 (gpu) |
deeppavlov_slavic |
35.0 |
2048 |
4096 |
8.0 (gpu) |
pullenti |
2.9 |
16 |
253 |
6.0 |
spacy |
8.0 |
140 |
625 |
8.0 |
stanza |
3.0 |
591 |
11264 |
3.0 (gpu) |
texterra |
47.6 |
193 |
3379 |
4.0 |
tomita |
2.0 |
64 |
63 |
29.8 |
mitie |
28.3 |
327 |
261 |
32.8 |
### Morphology
Datasets from GramEval2020 are used for evaluation:
* `news` — sample from Lenta.ru.
* `wiki` — UD GSD.
* `fiction` — SynTagRus + JZ.
* `social`, `poetry` — social, poetry subset of Taiga.
Slovnet is compated to a number of existing morphology taggers: deeppavlov
, deeppavlov_bert
, rupostagger
, rnnmorph
, maru
, udpipe
, spacy
, stanza
.
For every column top 3 results are highlighted. `slovnet` was trained only on news dataset:
|
news |
wiki |
fiction |
social |
poetry |
slovnet |
0.961 |
0.815 |
0.905 |
0.807 |
0.664 |
slovnet_bert |
0.982 |
0.884 |
0.990 |
0.890 |
0.856 |
deeppavlov |
0.940 |
0.841 |
0.944 |
0.870 |
0.857 |
deeppavlov_bert |
0.951 |
0.868 |
0.964 |
0.892 |
0.865 |
udpipe |
0.918 |
0.811 |
0.957 |
0.870 |
0.776 |
spacy |
0.964 |
0.849 |
0.942 |
0.857 |
0.784 |
stanza |
0.934 |
0.831 |
0.940 |
0.873 |
0.825 |
rnnmorph |
0.896 |
0.812 |
0.890 |
0.860 |
0.838 |
maru |
0.894 |
0.808 |
0.887 |
0.861 |
0.840 |
rupostagger |
0.673 |
0.645 |
0.661 |
0.641 |
0.636 |
`it/s` — sentences per second.
|
init, s |
disk, mb |
ram, mb |
speed, it/s |
slovnet |
1.0 |
27 |
115 |
532.0 |
slovnet_bert |
5.0 |
475 |
8087 |
285.0 (gpu) |
deeppavlov |
4.0 |
32 |
10240 |
90.0 (gpu) |
deeppavlov_bert |
20.0 |
1393 |
8704 |
85.0 (gpu) |
udpipe |
6.9 |
45 |
242 |
56.2 |
spacy |
8.0 |
140 |
579 |
50.0 |
stanza |
2.0 |
591 |
393 |
92.0 |
rnnmorph |
8.7 |
10 |
289 |
16.6 |
maru |
15.8 |
44 |
370 |
36.4 |
rupostagger |
4.8 |
3 |
118 |
48.0 |
### Syntax
Slovnet is compated to several existing syntax parsers: udpipe
, spacy
, deeppavlov
, stanza
.
|
news |
wiki |
fiction |
social |
poetry |
|
uas |
las |
uas |
las |
uas |
las |
uas |
las |
uas |
las |
slovnet |
0.907 |
0.880 |
0.775 |
0.718 |
0.806 |
0.776 |
0.726 |
0.656 |
0.542 |
0.469 |
slovnet_bert |
0.965 |
0.936 |
0.891 |
0.828 |
0.958 |
0.940 |
0.846 |
0.782 |
0.776 |
0.706 |
deeppavlov_bert |
0.962 |
0.910 |
0.882 |
0.786 |
0.963 |
0.929 |
0.844 |
0.761 |
0.784 |
0.691 |
udpipe |
0.873 |
0.823 |
0.622 |
0.531 |
0.910 |
0.876 |
0.700 |
0.624 |
0.625 |
0.534 |
spacy |
0.943 |
0.916 |
0.851 |
0.783 |
0.901 |
0.874 |
0.804 |
0.737 |
0.704 |
0.616 |
stanza |
0.940 |
0.886 |
0.815 |
0.716 |
0.936 |
0.895 |
0.802 |
0.714 |
0.713 |
0.613 |
`it/s` — sentences per second.
|
init, s |
disk, mb |
ram, mb |
speed, it/s |
slovnet |
1.0 |
27 |
125 |
450.0 |
slovnet_bert |
5.0 |
504 |
3427 |
200.0 (gpu) |
deeppavlov_bert |
34.0 |
1427 |
8704 |
75.0 (gpu) |
udpipe |
6.9 |
45 |
242 |
56.2 |
spacy |
9.0 |
140 |
579 |
41.0 |
stanza |
3.0 |
591 |
890 |
12.0 |
## Support
- Chat — https://telegram.me/natural_language_processing
- Issues — https://github.com/natasha/slovnet/issues
- Commercial support — https://lab.alexkuk.ru
## Development
Dev env
```bash
python -m venv ~/.venvs/natasha-slovnet
source ~/.venvs/natasha-slovnet/bin/activate
pip install -r requirements/dev.txt
pip install -e .
```
Test
```bash
make test
```
Rent GPU
```bash
yc compute instance create \
--name gpu \
--zone ru-central1-a \
--network-interface subnet-name=default,nat-ip-version=ipv4 \
--create-boot-disk image-folder-id=standard-images,image-family=ubuntu-1804-lts-ngc,type=network-ssd,size=20 \
--cores=8 \
--memory=96 \
--gpus=1 \
--ssh-key ~/.ssh/id_rsa.pub \
--folder-name default \
--platform-id gpu-standard-v1 \
--preemptible
yc compute instance delete --name gpu
```
Setup instance
```
sudo locale-gen ru_RU.UTF-8
sudo apt-get update
sudo apt-get install -y \
python3-pip
# grpcio long install ~10m, not using prebuilt wheel
# "it is not compatible with this Python"
sudo pip3 install -v \
jupyter \
tensorboard
mkdir runs
nohup tensorboard \
--logdir=runs \
--host=localhost \
--port=6006 \
--reload_interval=1 &
nohup jupyter notebook \
--no-browser \
--allow-root \
--ip=localhost \
--port=8888 \
--NotebookApp.token='' \
--NotebookApp.password='' &
ssh -Nf gpu -L 8888:localhost:8888 -L 6006:localhost:6006
scp ~/.slovnet.json gpu:~
rsync --exclude data -rv . gpu:~/slovnet
rsync -u --exclude data -rv 'gpu:~/slovnet/*' .
```
Intall dev
```bash
pip3 install -r slovnet/requirements/dev.txt -r slovnet/requirements/gpu.txt
pip3 install -e slovnet
```
Release
```bash
# Update setup.py version
git commit -am 'Up version'
git tag v0.6.0
git push
git push --tags
# Github Action builds dist and publishes to PyPi
```
%package -n python3-slovnet
Summary: Deep-learning based NLP modeling for Russian language
Provides: python-slovnet
BuildRequires: python3-devel
BuildRequires: python3-setuptools
BuildRequires: python3-pip
%description -n python3-slovnet
![CI](https://github.com/natasha/slovnet/actions/workflows/test.yml/badge.svg)
SlovNet is a Python library for deep-learning based NLP modeling for Russian language. Library is integrated with other Natasha projects: Nerus — large automatically annotated corpus, Razdel — sentence segmenter, tokenizer and Navec — compact Russian embeddings. Slovnet provides high quality practical models for Russian NER, morphology and syntax, see evaluation section for more:
* NER is 1-2% worse than current BERT SOTA by DeepPavlov but 60 times smaller in size (~30 MB) and works fast on CPU (~25 news articles/sec).
* Morphology tagger and syntax parser have comparable accuracy on news dataset with large SOTA BERT models, take 50 times less space (~30 MB), work faster on CPU (~500 sentences/sec).
## Downloads
## Install
During inference Slovnet depends only on Numpy. Library supports Python 3.5+, PyPy 3.
```bash
$ pip install slovnet
```
## Usage
Download model weights and vocabs package, use links from downloads section and Navec download section. Optionally install Ipymarkup to visualize NER markup.
Slovnet annotator `map` method has list of items as input and same size iterator over markups as output. Internally items are processed in batches of size `batch_size`. Default size is 8, larger batch — more RAM, better CPU utilization. `__call__` method just calls `map` with a list of 1 item.
### NER
```python
>>> from navec import Navec
>>> from slovnet import NER
>>> from ipymarkup import show_span_ascii_markup as show_markup
>>> text = 'Европейский союз добавил в санкционный список девять политических деятелей из самопровозглашенных республик Донбасса — Донецкой народной республики (ДНР) и Луганской народной республики (ЛНР) — в связи с прошедшими там выборами. Об этом говорится в документе, опубликованном в официальном журнале Евросоюза. В новом списке фигурирует Леонид Пасечник, который по итогам выборов стал главой ЛНР. Помимо него там присутствуют Владимир Бидевка и Денис Мирошниченко, председатели законодательных органов ДНР и ЛНР, а также Ольга Позднякова и Елена Кравченко, председатели ЦИК обеих республик. Выборы прошли в непризнанных республиках Донбасса 11 ноября. На них удержали лидерство действующие руководители и партии — Денис Пушилин и «Донецкая республика» в ДНР и Леонид Пасечник с движением «Мир Луганщине» в ЛНР. Президент Франции Эмманюэль Макрон и канцлер ФРГ Ангела Меркель после встречи с украинским лидером Петром Порошенко осудили проведение выборов, заявив, что они нелегитимны и «подрывают территориальную целостность и суверенитет Украины». Позже к осуждению присоединились США с обещаниями новых санкций для России.'
>>> navec = Navec.load('navec_news_v1_1B_250K_300d_100q.tar')
>>> ner = NER.load('slovnet_ner_news_v1.tar')
>>> ner.navec(navec)
>>> markup = ner(text)
>>> show_markup(markup.text, markup.spans)
Европейский союз добавил в санкционный список девять политических
LOC─────────────
деятелей из самопровозглашенных республик Донбасса — Донецкой народной
LOC───── LOC──────────────
республики (ДНР) и Луганской народной республики (ЛНР) — в связи с
───────────────── LOC────────────────────────────────
прошедшими там выборами. Об этом говорится в документе, опубликованном
в официальном журнале Евросоюза. В новом списке фигурирует Леонид
LOC────── PER────
Пасечник, который по итогам выборов стал главой ЛНР. Помимо него там
──────── LOC
присутствуют Владимир Бидевка и Денис Мирошниченко, председатели
PER───────────── PER───────────────
законодательных органов ДНР и ЛНР, а также Ольга Позднякова и Елена
LOC LOC PER───────────── PER───
Кравченко, председатели ЦИК обеих республик. Выборы прошли в
───────── ORG
непризнанных республиках Донбасса 11 ноября. На них удержали лидерство
LOC─────
действующие руководители и партии — Денис Пушилин и «Донецкая
PER────────── ORG──────
республика» в ДНР и Леонид Пасечник с движением «Мир Луганщине» в ЛНР.
────────── LOC PER──────────── ORG────────── LOC
Президент Франции Эмманюэль Макрон и канцлер ФРГ Ангела Меркель после
LOC──── PER───────────── LOC PER───────────
встречи с украинским лидером Петром Порошенко осудили проведение
PER─────────────
выборов, заявив, что они нелегитимны и «подрывают территориальную
целостность и суверенитет Украины». Позже к осуждению присоединились
LOC────
США с обещаниями новых санкций для России.
LOC LOC───
```
### Morphology
Morphology annotator processes tokenized text. To split the input into sentencies and tokens use Razdel.
```python
>>> from razdel import sentenize, tokenize
>>> from navec import Navec
>>> from slovnet import Morph
>>> chunk = []
>>> for sent in sentenize(text):
>>> tokens = [_.text for _ in tokenize(sent.text)]
>>> chunk.append(tokens)
>>> chunk[:1]
[['Европейский', 'союз', 'добавил', 'в', 'санкционный', 'список', 'девять', 'политических', 'деятелей', 'из', 'самопровозглашенных', 'республик', 'Донбасса', '—', 'Донецкой', 'народной', 'республики', '(', 'ДНР', ')', 'и', 'Луганской', 'народной', 'республики', '(', 'ЛНР', ')', '—', 'в', 'связи', 'с', 'прошедшими', 'там', 'выборами', '.']]
>>> navec = Navec.load('navec_news_v1_1B_250K_300d_100q.tar')
>>> morph = Morph.load('slovnet_morph_news_v1.tar', batch_size=4)
>>> morph.navec(navec)
>>> markup = next(morph.map(chunk))
>>> for token in markup.tokens:
>>> print(f'{token.text:>20} {token.tag}')
Европейский ADJ|Case=Nom|Degree=Pos|Gender=Masc|Number=Sing
союз NOUN|Animacy=Inan|Case=Nom|Gender=Masc|Number=Sing
добавил VERB|Aspect=Perf|Gender=Masc|Mood=Ind|Number=Sing|Tense=Past|VerbForm=Fin|Voice=Act
в ADP
санкционный ADJ|Animacy=Inan|Case=Acc|Degree=Pos|Gender=Masc|Number=Sing
список NOUN|Animacy=Inan|Case=Acc|Gender=Masc|Number=Sing
девять NUM|Case=Nom
политических ADJ|Case=Gen|Degree=Pos|Number=Plur
деятелей NOUN|Animacy=Anim|Case=Gen|Gender=Masc|Number=Plur
из ADP
самопровозглашенных ADJ|Case=Gen|Degree=Pos|Number=Plur
республик NOUN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Plur
Донбасса PROPN|Animacy=Inan|Case=Gen|Gender=Masc|Number=Sing
— PUNCT
Донецкой ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
народной ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
республики NOUN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
( PUNCT
ДНР PROPN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
) PUNCT
и CCONJ
Луганской ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
народной ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
республики NOUN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
( PUNCT
ЛНР PROPN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
) PUNCT
— PUNCT
в ADP
связи NOUN|Animacy=Inan|Case=Loc|Gender=Fem|Number=Sing
с ADP
прошедшими VERB|Aspect=Perf|Case=Ins|Number=Plur|Tense=Past|VerbForm=Part|Voice=Act
там ADV|Degree=Pos
выборами NOUN|Animacy=Inan|Case=Ins|Gender=Masc|Number=Plur
. PUNCT
```
### Syntax
Syntax parser processes sentencies split into tokens. Use Razdel for segmentation.
```python
>>> from ipymarkup import show_dep_ascii_markup as show_markup
>>> from razdel import sentenize, tokenize
>>> from navec import Navec
>>> from slovnet import Syntax
>>> chunk = []
>>> for sent in sentenize(text):
>>> tokens = [_.text for _ in tokenize(sent.text)]
>>> chunk.append(tokens)
>>> chunk[:1]
[['Европейский', 'союз', 'добавил', 'в', 'санкционный', 'список', 'девять', 'политических', 'деятелей', 'из', 'самопровозглашенных', 'республик', 'Донбасса', '—', 'Донецкой', 'народной', 'республики', '(', 'ДНР', ')', 'и', 'Луганской', 'народной', 'республики', '(', 'ЛНР', ')', '—', 'в', 'связи', 'с', 'прошедшими', 'там', 'выборами', '.']]
>>> navec = Navec.load('navec_news_v1_1B_250K_300d_100q.tar')
>>> syntax = Syntax.load('slovnet_syntax_news_v1.tar')
>>> syntax.navec(navec)
>>> markup = next(syntax.map(chunk))
# Convert CoNLL-style format to source, target indices
>>> words, deps = [], []
>>> for token in markup.tokens:
>>> words.append(token.text)
>>> source = int(token.head_id) - 1
>>> target = int(token.id) - 1
>>> if source > 0 and source != target: # skip root, loops
>>> deps.append([source, target, token.rel])
>>> show_markup(words, deps)
┌► Европейский amod
┌►└─ союз nsubj
┌───────┌─┌─└─── добавил
│ │ │ ┌──► в case
│ │ │ │ ┌► санкционный amod
│ │ └►└─└─ список obl
│ │ ┌──► девять nummod:gov
│ │ │ ┌► политических amod
│ ┌─────└►┌─└─└─ деятелей obj
│ │ │ ┌──► из case
│ │ │ │ ┌► самопровозглашенных amod
│ │ └►└─└─ республик nmod
│ │ └──► Донбасса nmod
│ │ ┌──────────► — punct
│ │ │ ┌──► Донецкой amod
│ │ │ │ ┌► народной amod
│ │ │ ┌─┌─┌─└─└─ республики
│ │ │ │ │ │ ┌► ( punct
│ │ │ │ │ └►┌─└─ ДНР parataxis
│ │ │ │ │ └──► ) punct
│ │ │ │ │ ┌────► и cc
│ │ │ │ │ │ ┌──► Луганской amod
│ │ │ │ │ │ │ ┌► народной amod
│ │ └─│ └►└─└─└─ республики conj
│ │ │ ┌► ( punct
│ │ └────►┌─└─ ЛНР parataxis
│ │ └──► ) punct
│ │ ┌──────► — punct
│ │ │ ┌►┌─┌─ в case
│ │ │ │ │ └► связи fixed
│ │ │ │ └──► с fixed
│ │ │ │ ┌►┌─ прошедшими acl
│ │ │ │ │ └► там advmod
│ └────►└─└─└─── выборами nmod
└──────────────► . punct
```
## Documentation
Materials are in Russian:
* Article about distillation and quantization in Slovnet
* Slovnet section of Datafest 2020 talk
## Evaluation
In addition to quality metrics we measure speed and models size, parameters that are important in production:
* `init` — time between system launch and first response. It is convenient for testing and devops to have model that starts quickly.
* `disk` — file size of artefacts one needs to download before using the system: model weights, embeddings, binaries, vocabs. It is convenient to deploy compact models in production.
* `ram` — average CPU/GPU RAM usage.
* `speed` — number of input items processed per second: news articles, tokenized sentencies.
### NER
4 datasets are used for evaluation: factru
, gareev
, ne5
and bsnlp
. Slovnet is compared to deeppavlov
, deeppavlov_bert
, deeppavlov_slavic
, pullenti
, spacy
, stanza
, texterra
, tomita
, mitie
.
For every column top 3 results are highlighted:
|
factru |
gareev |
ne5 |
bsnlp |
f1 |
PER |
LOC |
ORG |
PER |
ORG |
PER |
LOC |
ORG |
PER |
LOC |
ORG |
slovnet |
0.959 |
0.915 |
0.825 |
0.977 |
0.899 |
0.984 |
0.973 |
0.951 |
0.944 |
0.834 |
0.718 |
slovnet_bert |
0.973 |
0.928 |
0.831 |
0.991 |
0.911 |
0.996 |
0.989 |
0.976 |
0.960 |
0.838 |
0.733 |
deeppavlov |
0.910 |
0.886 |
0.742 |
0.944 |
0.798 |
0.942 |
0.919 |
0.881 |
0.866 |
0.767 |
0.624 |
deeppavlov_bert |
0.971 |
0.928 |
0.825 |
0.980 |
0.916 |
0.997 |
0.990 |
0.976 |
0.954 |
0.840 |
0.741 |
deeppavlov_slavic |
0.956 |
0.884 |
0.714 |
0.976 |
0.776 |
0.984 |
0.817 |
0.761 |
0.965 |
0.925 |
0.831 |
pullenti |
0.905 |
0.814 |
0.686 |
0.939 |
0.639 |
0.952 |
0.862 |
0.683 |
0.900 |
0.769 |
0.566 |
spacy |
0.901 |
0.886 |
0.765 |
0.970 |
0.883 |
0.967 |
0.928 |
0.918 |
0.919 |
0.823 |
0.693 |
stanza |
0.943 |
0.865 |
0.687 |
0.953 |
0.827 |
0.923 |
0.753 |
0.734 |
0.938 |
0.838 |
0.724 |
texterra |
0.900 |
0.800 |
0.597 |
0.888 |
0.561 |
0.901 |
0.777 |
0.594 |
0.858 |
0.783 |
0.548 |
tomita |
0.929 |
|
|
0.921 |
|
0.945 |
|
|
0.881 |
|
|
mitie |
0.888 |
0.861 |
0.532 |
0.849 |
0.452 |
0.753 |
0.642 |
0.432 |
0.736 |
0.801 |
0.524 |
`it/s` — news articles per second, 1 article ≈ 1KB.
|
init, s |
disk, mb |
ram, mb |
speed, it/s |
slovnet |
1.0 |
27 |
205 |
25.3 |
slovnet_bert |
5.0 |
473 |
9500 |
40.0 (gpu) |
deeppavlov |
5.9 |
1024 |
3072 |
24.3 (gpu) |
deeppavlov_bert |
34.5 |
2048 |
6144 |
13.1 (gpu) |
deeppavlov_slavic |
35.0 |
2048 |
4096 |
8.0 (gpu) |
pullenti |
2.9 |
16 |
253 |
6.0 |
spacy |
8.0 |
140 |
625 |
8.0 |
stanza |
3.0 |
591 |
11264 |
3.0 (gpu) |
texterra |
47.6 |
193 |
3379 |
4.0 |
tomita |
2.0 |
64 |
63 |
29.8 |
mitie |
28.3 |
327 |
261 |
32.8 |
### Morphology
Datasets from GramEval2020 are used for evaluation:
* `news` — sample from Lenta.ru.
* `wiki` — UD GSD.
* `fiction` — SynTagRus + JZ.
* `social`, `poetry` — social, poetry subset of Taiga.
Slovnet is compated to a number of existing morphology taggers: deeppavlov
, deeppavlov_bert
, rupostagger
, rnnmorph
, maru
, udpipe
, spacy
, stanza
.
For every column top 3 results are highlighted. `slovnet` was trained only on news dataset:
|
news |
wiki |
fiction |
social |
poetry |
slovnet |
0.961 |
0.815 |
0.905 |
0.807 |
0.664 |
slovnet_bert |
0.982 |
0.884 |
0.990 |
0.890 |
0.856 |
deeppavlov |
0.940 |
0.841 |
0.944 |
0.870 |
0.857 |
deeppavlov_bert |
0.951 |
0.868 |
0.964 |
0.892 |
0.865 |
udpipe |
0.918 |
0.811 |
0.957 |
0.870 |
0.776 |
spacy |
0.964 |
0.849 |
0.942 |
0.857 |
0.784 |
stanza |
0.934 |
0.831 |
0.940 |
0.873 |
0.825 |
rnnmorph |
0.896 |
0.812 |
0.890 |
0.860 |
0.838 |
maru |
0.894 |
0.808 |
0.887 |
0.861 |
0.840 |
rupostagger |
0.673 |
0.645 |
0.661 |
0.641 |
0.636 |
`it/s` — sentences per second.
|
init, s |
disk, mb |
ram, mb |
speed, it/s |
slovnet |
1.0 |
27 |
115 |
532.0 |
slovnet_bert |
5.0 |
475 |
8087 |
285.0 (gpu) |
deeppavlov |
4.0 |
32 |
10240 |
90.0 (gpu) |
deeppavlov_bert |
20.0 |
1393 |
8704 |
85.0 (gpu) |
udpipe |
6.9 |
45 |
242 |
56.2 |
spacy |
8.0 |
140 |
579 |
50.0 |
stanza |
2.0 |
591 |
393 |
92.0 |
rnnmorph |
8.7 |
10 |
289 |
16.6 |
maru |
15.8 |
44 |
370 |
36.4 |
rupostagger |
4.8 |
3 |
118 |
48.0 |
### Syntax
Slovnet is compated to several existing syntax parsers: udpipe
, spacy
, deeppavlov
, stanza
.
|
news |
wiki |
fiction |
social |
poetry |
|
uas |
las |
uas |
las |
uas |
las |
uas |
las |
uas |
las |
slovnet |
0.907 |
0.880 |
0.775 |
0.718 |
0.806 |
0.776 |
0.726 |
0.656 |
0.542 |
0.469 |
slovnet_bert |
0.965 |
0.936 |
0.891 |
0.828 |
0.958 |
0.940 |
0.846 |
0.782 |
0.776 |
0.706 |
deeppavlov_bert |
0.962 |
0.910 |
0.882 |
0.786 |
0.963 |
0.929 |
0.844 |
0.761 |
0.784 |
0.691 |
udpipe |
0.873 |
0.823 |
0.622 |
0.531 |
0.910 |
0.876 |
0.700 |
0.624 |
0.625 |
0.534 |
spacy |
0.943 |
0.916 |
0.851 |
0.783 |
0.901 |
0.874 |
0.804 |
0.737 |
0.704 |
0.616 |
stanza |
0.940 |
0.886 |
0.815 |
0.716 |
0.936 |
0.895 |
0.802 |
0.714 |
0.713 |
0.613 |
`it/s` — sentences per second.
|
init, s |
disk, mb |
ram, mb |
speed, it/s |
slovnet |
1.0 |
27 |
125 |
450.0 |
slovnet_bert |
5.0 |
504 |
3427 |
200.0 (gpu) |
deeppavlov_bert |
34.0 |
1427 |
8704 |
75.0 (gpu) |
udpipe |
6.9 |
45 |
242 |
56.2 |
spacy |
9.0 |
140 |
579 |
41.0 |
stanza |
3.0 |
591 |
890 |
12.0 |
## Support
- Chat — https://telegram.me/natural_language_processing
- Issues — https://github.com/natasha/slovnet/issues
- Commercial support — https://lab.alexkuk.ru
## Development
Dev env
```bash
python -m venv ~/.venvs/natasha-slovnet
source ~/.venvs/natasha-slovnet/bin/activate
pip install -r requirements/dev.txt
pip install -e .
```
Test
```bash
make test
```
Rent GPU
```bash
yc compute instance create \
--name gpu \
--zone ru-central1-a \
--network-interface subnet-name=default,nat-ip-version=ipv4 \
--create-boot-disk image-folder-id=standard-images,image-family=ubuntu-1804-lts-ngc,type=network-ssd,size=20 \
--cores=8 \
--memory=96 \
--gpus=1 \
--ssh-key ~/.ssh/id_rsa.pub \
--folder-name default \
--platform-id gpu-standard-v1 \
--preemptible
yc compute instance delete --name gpu
```
Setup instance
```
sudo locale-gen ru_RU.UTF-8
sudo apt-get update
sudo apt-get install -y \
python3-pip
# grpcio long install ~10m, not using prebuilt wheel
# "it is not compatible with this Python"
sudo pip3 install -v \
jupyter \
tensorboard
mkdir runs
nohup tensorboard \
--logdir=runs \
--host=localhost \
--port=6006 \
--reload_interval=1 &
nohup jupyter notebook \
--no-browser \
--allow-root \
--ip=localhost \
--port=8888 \
--NotebookApp.token='' \
--NotebookApp.password='' &
ssh -Nf gpu -L 8888:localhost:8888 -L 6006:localhost:6006
scp ~/.slovnet.json gpu:~
rsync --exclude data -rv . gpu:~/slovnet
rsync -u --exclude data -rv 'gpu:~/slovnet/*' .
```
Intall dev
```bash
pip3 install -r slovnet/requirements/dev.txt -r slovnet/requirements/gpu.txt
pip3 install -e slovnet
```
Release
```bash
# Update setup.py version
git commit -am 'Up version'
git tag v0.6.0
git push
git push --tags
# Github Action builds dist and publishes to PyPi
```
%package help
Summary: Development documents and examples for slovnet
Provides: python3-slovnet-doc
%description help
![CI](https://github.com/natasha/slovnet/actions/workflows/test.yml/badge.svg)
SlovNet is a Python library for deep-learning based NLP modeling for Russian language. Library is integrated with other Natasha projects: Nerus — large automatically annotated corpus, Razdel — sentence segmenter, tokenizer and Navec — compact Russian embeddings. Slovnet provides high quality practical models for Russian NER, morphology and syntax, see evaluation section for more:
* NER is 1-2% worse than current BERT SOTA by DeepPavlov but 60 times smaller in size (~30 MB) and works fast on CPU (~25 news articles/sec).
* Morphology tagger and syntax parser have comparable accuracy on news dataset with large SOTA BERT models, take 50 times less space (~30 MB), work faster on CPU (~500 sentences/sec).
## Downloads
## Install
During inference Slovnet depends only on Numpy. Library supports Python 3.5+, PyPy 3.
```bash
$ pip install slovnet
```
## Usage
Download model weights and vocabs package, use links from downloads section and Navec download section. Optionally install Ipymarkup to visualize NER markup.
Slovnet annotator `map` method has list of items as input and same size iterator over markups as output. Internally items are processed in batches of size `batch_size`. Default size is 8, larger batch — more RAM, better CPU utilization. `__call__` method just calls `map` with a list of 1 item.
### NER
```python
>>> from navec import Navec
>>> from slovnet import NER
>>> from ipymarkup import show_span_ascii_markup as show_markup
>>> text = 'Европейский союз добавил в санкционный список девять политических деятелей из самопровозглашенных республик Донбасса — Донецкой народной республики (ДНР) и Луганской народной республики (ЛНР) — в связи с прошедшими там выборами. Об этом говорится в документе, опубликованном в официальном журнале Евросоюза. В новом списке фигурирует Леонид Пасечник, который по итогам выборов стал главой ЛНР. Помимо него там присутствуют Владимир Бидевка и Денис Мирошниченко, председатели законодательных органов ДНР и ЛНР, а также Ольга Позднякова и Елена Кравченко, председатели ЦИК обеих республик. Выборы прошли в непризнанных республиках Донбасса 11 ноября. На них удержали лидерство действующие руководители и партии — Денис Пушилин и «Донецкая республика» в ДНР и Леонид Пасечник с движением «Мир Луганщине» в ЛНР. Президент Франции Эмманюэль Макрон и канцлер ФРГ Ангела Меркель после встречи с украинским лидером Петром Порошенко осудили проведение выборов, заявив, что они нелегитимны и «подрывают территориальную целостность и суверенитет Украины». Позже к осуждению присоединились США с обещаниями новых санкций для России.'
>>> navec = Navec.load('navec_news_v1_1B_250K_300d_100q.tar')
>>> ner = NER.load('slovnet_ner_news_v1.tar')
>>> ner.navec(navec)
>>> markup = ner(text)
>>> show_markup(markup.text, markup.spans)
Европейский союз добавил в санкционный список девять политических
LOC─────────────
деятелей из самопровозглашенных республик Донбасса — Донецкой народной
LOC───── LOC──────────────
республики (ДНР) и Луганской народной республики (ЛНР) — в связи с
───────────────── LOC────────────────────────────────
прошедшими там выборами. Об этом говорится в документе, опубликованном
в официальном журнале Евросоюза. В новом списке фигурирует Леонид
LOC────── PER────
Пасечник, который по итогам выборов стал главой ЛНР. Помимо него там
──────── LOC
присутствуют Владимир Бидевка и Денис Мирошниченко, председатели
PER───────────── PER───────────────
законодательных органов ДНР и ЛНР, а также Ольга Позднякова и Елена
LOC LOC PER───────────── PER───
Кравченко, председатели ЦИК обеих республик. Выборы прошли в
───────── ORG
непризнанных республиках Донбасса 11 ноября. На них удержали лидерство
LOC─────
действующие руководители и партии — Денис Пушилин и «Донецкая
PER────────── ORG──────
республика» в ДНР и Леонид Пасечник с движением «Мир Луганщине» в ЛНР.
────────── LOC PER──────────── ORG────────── LOC
Президент Франции Эмманюэль Макрон и канцлер ФРГ Ангела Меркель после
LOC──── PER───────────── LOC PER───────────
встречи с украинским лидером Петром Порошенко осудили проведение
PER─────────────
выборов, заявив, что они нелегитимны и «подрывают территориальную
целостность и суверенитет Украины». Позже к осуждению присоединились
LOC────
США с обещаниями новых санкций для России.
LOC LOC───
```
### Morphology
Morphology annotator processes tokenized text. To split the input into sentencies and tokens use Razdel.
```python
>>> from razdel import sentenize, tokenize
>>> from navec import Navec
>>> from slovnet import Morph
>>> chunk = []
>>> for sent in sentenize(text):
>>> tokens = [_.text for _ in tokenize(sent.text)]
>>> chunk.append(tokens)
>>> chunk[:1]
[['Европейский', 'союз', 'добавил', 'в', 'санкционный', 'список', 'девять', 'политических', 'деятелей', 'из', 'самопровозглашенных', 'республик', 'Донбасса', '—', 'Донецкой', 'народной', 'республики', '(', 'ДНР', ')', 'и', 'Луганской', 'народной', 'республики', '(', 'ЛНР', ')', '—', 'в', 'связи', 'с', 'прошедшими', 'там', 'выборами', '.']]
>>> navec = Navec.load('navec_news_v1_1B_250K_300d_100q.tar')
>>> morph = Morph.load('slovnet_morph_news_v1.tar', batch_size=4)
>>> morph.navec(navec)
>>> markup = next(morph.map(chunk))
>>> for token in markup.tokens:
>>> print(f'{token.text:>20} {token.tag}')
Европейский ADJ|Case=Nom|Degree=Pos|Gender=Masc|Number=Sing
союз NOUN|Animacy=Inan|Case=Nom|Gender=Masc|Number=Sing
добавил VERB|Aspect=Perf|Gender=Masc|Mood=Ind|Number=Sing|Tense=Past|VerbForm=Fin|Voice=Act
в ADP
санкционный ADJ|Animacy=Inan|Case=Acc|Degree=Pos|Gender=Masc|Number=Sing
список NOUN|Animacy=Inan|Case=Acc|Gender=Masc|Number=Sing
девять NUM|Case=Nom
политических ADJ|Case=Gen|Degree=Pos|Number=Plur
деятелей NOUN|Animacy=Anim|Case=Gen|Gender=Masc|Number=Plur
из ADP
самопровозглашенных ADJ|Case=Gen|Degree=Pos|Number=Plur
республик NOUN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Plur
Донбасса PROPN|Animacy=Inan|Case=Gen|Gender=Masc|Number=Sing
— PUNCT
Донецкой ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
народной ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
республики NOUN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
( PUNCT
ДНР PROPN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
) PUNCT
и CCONJ
Луганской ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
народной ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
республики NOUN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
( PUNCT
ЛНР PROPN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
) PUNCT
— PUNCT
в ADP
связи NOUN|Animacy=Inan|Case=Loc|Gender=Fem|Number=Sing
с ADP
прошедшими VERB|Aspect=Perf|Case=Ins|Number=Plur|Tense=Past|VerbForm=Part|Voice=Act
там ADV|Degree=Pos
выборами NOUN|Animacy=Inan|Case=Ins|Gender=Masc|Number=Plur
. PUNCT
```
### Syntax
Syntax parser processes sentencies split into tokens. Use Razdel for segmentation.
```python
>>> from ipymarkup import show_dep_ascii_markup as show_markup
>>> from razdel import sentenize, tokenize
>>> from navec import Navec
>>> from slovnet import Syntax
>>> chunk = []
>>> for sent in sentenize(text):
>>> tokens = [_.text for _ in tokenize(sent.text)]
>>> chunk.append(tokens)
>>> chunk[:1]
[['Европейский', 'союз', 'добавил', 'в', 'санкционный', 'список', 'девять', 'политических', 'деятелей', 'из', 'самопровозглашенных', 'республик', 'Донбасса', '—', 'Донецкой', 'народной', 'республики', '(', 'ДНР', ')', 'и', 'Луганской', 'народной', 'республики', '(', 'ЛНР', ')', '—', 'в', 'связи', 'с', 'прошедшими', 'там', 'выборами', '.']]
>>> navec = Navec.load('navec_news_v1_1B_250K_300d_100q.tar')
>>> syntax = Syntax.load('slovnet_syntax_news_v1.tar')
>>> syntax.navec(navec)
>>> markup = next(syntax.map(chunk))
# Convert CoNLL-style format to source, target indices
>>> words, deps = [], []
>>> for token in markup.tokens:
>>> words.append(token.text)
>>> source = int(token.head_id) - 1
>>> target = int(token.id) - 1
>>> if source > 0 and source != target: # skip root, loops
>>> deps.append([source, target, token.rel])
>>> show_markup(words, deps)
┌► Европейский amod
┌►└─ союз nsubj
┌───────┌─┌─└─── добавил
│ │ │ ┌──► в case
│ │ │ │ ┌► санкционный amod
│ │ └►└─└─ список obl
│ │ ┌──► девять nummod:gov
│ │ │ ┌► политических amod
│ ┌─────└►┌─└─└─ деятелей obj
│ │ │ ┌──► из case
│ │ │ │ ┌► самопровозглашенных amod
│ │ └►└─└─ республик nmod
│ │ └──► Донбасса nmod
│ │ ┌──────────► — punct
│ │ │ ┌──► Донецкой amod
│ │ │ │ ┌► народной amod
│ │ │ ┌─┌─┌─└─└─ республики
│ │ │ │ │ │ ┌► ( punct
│ │ │ │ │ └►┌─└─ ДНР parataxis
│ │ │ │ │ └──► ) punct
│ │ │ │ │ ┌────► и cc
│ │ │ │ │ │ ┌──► Луганской amod
│ │ │ │ │ │ │ ┌► народной amod
│ │ └─│ └►└─└─└─ республики conj
│ │ │ ┌► ( punct
│ │ └────►┌─└─ ЛНР parataxis
│ │ └──► ) punct
│ │ ┌──────► — punct
│ │ │ ┌►┌─┌─ в case
│ │ │ │ │ └► связи fixed
│ │ │ │ └──► с fixed
│ │ │ │ ┌►┌─ прошедшими acl
│ │ │ │ │ └► там advmod
│ └────►└─└─└─── выборами nmod
└──────────────► . punct
```
## Documentation
Materials are in Russian:
* Article about distillation and quantization in Slovnet
* Slovnet section of Datafest 2020 talk
## Evaluation
In addition to quality metrics we measure speed and models size, parameters that are important in production:
* `init` — time between system launch and first response. It is convenient for testing and devops to have model that starts quickly.
* `disk` — file size of artefacts one needs to download before using the system: model weights, embeddings, binaries, vocabs. It is convenient to deploy compact models in production.
* `ram` — average CPU/GPU RAM usage.
* `speed` — number of input items processed per second: news articles, tokenized sentencies.
### NER
4 datasets are used for evaluation: factru
, gareev
, ne5
and bsnlp
. Slovnet is compared to deeppavlov
, deeppavlov_bert
, deeppavlov_slavic
, pullenti
, spacy
, stanza
, texterra
, tomita
, mitie
.
For every column top 3 results are highlighted:
|
factru |
gareev |
ne5 |
bsnlp |
f1 |
PER |
LOC |
ORG |
PER |
ORG |
PER |
LOC |
ORG |
PER |
LOC |
ORG |
slovnet |
0.959 |
0.915 |
0.825 |
0.977 |
0.899 |
0.984 |
0.973 |
0.951 |
0.944 |
0.834 |
0.718 |
slovnet_bert |
0.973 |
0.928 |
0.831 |
0.991 |
0.911 |
0.996 |
0.989 |
0.976 |
0.960 |
0.838 |
0.733 |
deeppavlov |
0.910 |
0.886 |
0.742 |
0.944 |
0.798 |
0.942 |
0.919 |
0.881 |
0.866 |
0.767 |
0.624 |
deeppavlov_bert |
0.971 |
0.928 |
0.825 |
0.980 |
0.916 |
0.997 |
0.990 |
0.976 |
0.954 |
0.840 |
0.741 |
deeppavlov_slavic |
0.956 |
0.884 |
0.714 |
0.976 |
0.776 |
0.984 |
0.817 |
0.761 |
0.965 |
0.925 |
0.831 |
pullenti |
0.905 |
0.814 |
0.686 |
0.939 |
0.639 |
0.952 |
0.862 |
0.683 |
0.900 |
0.769 |
0.566 |
spacy |
0.901 |
0.886 |
0.765 |
0.970 |
0.883 |
0.967 |
0.928 |
0.918 |
0.919 |
0.823 |
0.693 |
stanza |
0.943 |
0.865 |
0.687 |
0.953 |
0.827 |
0.923 |
0.753 |
0.734 |
0.938 |
0.838 |
0.724 |
texterra |
0.900 |
0.800 |
0.597 |
0.888 |
0.561 |
0.901 |
0.777 |
0.594 |
0.858 |
0.783 |
0.548 |
tomita |
0.929 |
|
|
0.921 |
|
0.945 |
|
|
0.881 |
|
|
mitie |
0.888 |
0.861 |
0.532 |
0.849 |
0.452 |
0.753 |
0.642 |
0.432 |
0.736 |
0.801 |
0.524 |
`it/s` — news articles per second, 1 article ≈ 1KB.
|
init, s |
disk, mb |
ram, mb |
speed, it/s |
slovnet |
1.0 |
27 |
205 |
25.3 |
slovnet_bert |
5.0 |
473 |
9500 |
40.0 (gpu) |
deeppavlov |
5.9 |
1024 |
3072 |
24.3 (gpu) |
deeppavlov_bert |
34.5 |
2048 |
6144 |
13.1 (gpu) |
deeppavlov_slavic |
35.0 |
2048 |
4096 |
8.0 (gpu) |
pullenti |
2.9 |
16 |
253 |
6.0 |
spacy |
8.0 |
140 |
625 |
8.0 |
stanza |
3.0 |
591 |
11264 |
3.0 (gpu) |
texterra |
47.6 |
193 |
3379 |
4.0 |
tomita |
2.0 |
64 |
63 |
29.8 |
mitie |
28.3 |
327 |
261 |
32.8 |
### Morphology
Datasets from GramEval2020 are used for evaluation:
* `news` — sample from Lenta.ru.
* `wiki` — UD GSD.
* `fiction` — SynTagRus + JZ.
* `social`, `poetry` — social, poetry subset of Taiga.
Slovnet is compated to a number of existing morphology taggers: deeppavlov
, deeppavlov_bert
, rupostagger
, rnnmorph
, maru
, udpipe
, spacy
, stanza
.
For every column top 3 results are highlighted. `slovnet` was trained only on news dataset:
|
news |
wiki |
fiction |
social |
poetry |
slovnet |
0.961 |
0.815 |
0.905 |
0.807 |
0.664 |
slovnet_bert |
0.982 |
0.884 |
0.990 |
0.890 |
0.856 |
deeppavlov |
0.940 |
0.841 |
0.944 |
0.870 |
0.857 |
deeppavlov_bert |
0.951 |
0.868 |
0.964 |
0.892 |
0.865 |
udpipe |
0.918 |
0.811 |
0.957 |
0.870 |
0.776 |
spacy |
0.964 |
0.849 |
0.942 |
0.857 |
0.784 |
stanza |
0.934 |
0.831 |
0.940 |
0.873 |
0.825 |
rnnmorph |
0.896 |
0.812 |
0.890 |
0.860 |
0.838 |
maru |
0.894 |
0.808 |
0.887 |
0.861 |
0.840 |
rupostagger |
0.673 |
0.645 |
0.661 |
0.641 |
0.636 |
`it/s` — sentences per second.
|
init, s |
disk, mb |
ram, mb |
speed, it/s |
slovnet |
1.0 |
27 |
115 |
532.0 |
slovnet_bert |
5.0 |
475 |
8087 |
285.0 (gpu) |
deeppavlov |
4.0 |
32 |
10240 |
90.0 (gpu) |
deeppavlov_bert |
20.0 |
1393 |
8704 |
85.0 (gpu) |
udpipe |
6.9 |
45 |
242 |
56.2 |
spacy |
8.0 |
140 |
579 |
50.0 |
stanza |
2.0 |
591 |
393 |
92.0 |
rnnmorph |
8.7 |
10 |
289 |
16.6 |
maru |
15.8 |
44 |
370 |
36.4 |
rupostagger |
4.8 |
3 |
118 |
48.0 |
### Syntax
Slovnet is compated to several existing syntax parsers: udpipe
, spacy
, deeppavlov
, stanza
.
|
news |
wiki |
fiction |
social |
poetry |
|
uas |
las |
uas |
las |
uas |
las |
uas |
las |
uas |
las |
slovnet |
0.907 |
0.880 |
0.775 |
0.718 |
0.806 |
0.776 |
0.726 |
0.656 |
0.542 |
0.469 |
slovnet_bert |
0.965 |
0.936 |
0.891 |
0.828 |
0.958 |
0.940 |
0.846 |
0.782 |
0.776 |
0.706 |
deeppavlov_bert |
0.962 |
0.910 |
0.882 |
0.786 |
0.963 |
0.929 |
0.844 |
0.761 |
0.784 |
0.691 |
udpipe |
0.873 |
0.823 |
0.622 |
0.531 |
0.910 |
0.876 |
0.700 |
0.624 |
0.625 |
0.534 |
spacy |
0.943 |
0.916 |
0.851 |
0.783 |
0.901 |
0.874 |
0.804 |
0.737 |
0.704 |
0.616 |
stanza |
0.940 |
0.886 |
0.815 |
0.716 |
0.936 |
0.895 |
0.802 |
0.714 |
0.713 |
0.613 |
`it/s` — sentences per second.
|
init, s |
disk, mb |
ram, mb |
speed, it/s |
slovnet |
1.0 |
27 |
125 |
450.0 |
slovnet_bert |
5.0 |
504 |
3427 |
200.0 (gpu) |
deeppavlov_bert |
34.0 |
1427 |
8704 |
75.0 (gpu) |
udpipe |
6.9 |
45 |
242 |
56.2 |
spacy |
9.0 |
140 |
579 |
41.0 |
stanza |
3.0 |
591 |
890 |
12.0 |
## Support
- Chat — https://telegram.me/natural_language_processing
- Issues — https://github.com/natasha/slovnet/issues
- Commercial support — https://lab.alexkuk.ru
## Development
Dev env
```bash
python -m venv ~/.venvs/natasha-slovnet
source ~/.venvs/natasha-slovnet/bin/activate
pip install -r requirements/dev.txt
pip install -e .
```
Test
```bash
make test
```
Rent GPU
```bash
yc compute instance create \
--name gpu \
--zone ru-central1-a \
--network-interface subnet-name=default,nat-ip-version=ipv4 \
--create-boot-disk image-folder-id=standard-images,image-family=ubuntu-1804-lts-ngc,type=network-ssd,size=20 \
--cores=8 \
--memory=96 \
--gpus=1 \
--ssh-key ~/.ssh/id_rsa.pub \
--folder-name default \
--platform-id gpu-standard-v1 \
--preemptible
yc compute instance delete --name gpu
```
Setup instance
```
sudo locale-gen ru_RU.UTF-8
sudo apt-get update
sudo apt-get install -y \
python3-pip
# grpcio long install ~10m, not using prebuilt wheel
# "it is not compatible with this Python"
sudo pip3 install -v \
jupyter \
tensorboard
mkdir runs
nohup tensorboard \
--logdir=runs \
--host=localhost \
--port=6006 \
--reload_interval=1 &
nohup jupyter notebook \
--no-browser \
--allow-root \
--ip=localhost \
--port=8888 \
--NotebookApp.token='' \
--NotebookApp.password='' &
ssh -Nf gpu -L 8888:localhost:8888 -L 6006:localhost:6006
scp ~/.slovnet.json gpu:~
rsync --exclude data -rv . gpu:~/slovnet
rsync -u --exclude data -rv 'gpu:~/slovnet/*' .
```
Intall dev
```bash
pip3 install -r slovnet/requirements/dev.txt -r slovnet/requirements/gpu.txt
pip3 install -e slovnet
```
Release
```bash
# Update setup.py version
git commit -am 'Up version'
git tag v0.6.0
git push
git push --tags
# Github Action builds dist and publishes to PyPi
```
%prep
%autosetup -n slovnet-0.6.0
%build
%py3_build
%install
%py3_install
install -d -m755 %{buildroot}/%{_pkgdocdir}
if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
pushd %{buildroot}
if [ -d usr/lib ]; then
find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
fi
if [ -d usr/lib64 ]; then
find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
fi
if [ -d usr/bin ]; then
find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
fi
if [ -d usr/sbin ]; then
find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
fi
touch doclist.lst
if [ -d usr/share/man ]; then
find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
fi
popd
mv %{buildroot}/filelist.lst .
mv %{buildroot}/doclist.lst .
%files -n python3-slovnet -f filelist.lst
%dir %{python3_sitelib}/*
%files help -f doclist.lst
%{_docdir}/*
%changelog
* Wed May 10 2023 Python_Bot - 0.6.0-1
- Package Spec generated