spaCy-pl

Devloping tools for Polish language processing in spaCy.

Our goal is to extend spaCy, a popular production-ready NLP library, to fully support Polish language.
We are dedicated to using state-of-the art techniques for Polish language processing, which are demonstrated on this website.

Development status

Feature Development status Details
Tokenization Version: Final
Status: Done
Release: Merged
Current version is available on the master branch of spaCy, our contribution included an improved list of stop words for Polish.
For implementation details see our pull request
Lexical attributes Version: Final
Status: Done
Release: Merged
Initial release of attributes was added to spaCy in the pull request with tokenizer
Lemmatization Version: Stable
Status: Done
Release: In progress
Lemmatizer pull request is currently under review and should be merged to spaCy soon.
Word vectors Version: Final
Status: Done
We started by training word2vec and GloVe embeddings on NKJP dataset, but eventually decided to use facebook's fasttext vectors for Polish.
POS Tagger Version: Stable
Status: Done
Release: Done
Current version of POS Tagger was trained on NKJP dataset, with labels reduced to match the UD POS tagset, using fasttext word vectors.
POS Tag Accuracy: 97.87%
To install pipeline (POS Tagger, Dependency Parser, NER):
pip install https://storage.googleapis.com/spacy-pl-public-models/pl_model-1.0.0.tar.gz
Dependency Parser Version: Stable
Status: Done
Release: Done
Trained on LFG dataset, using fasttext word vectors.
Validation metrics: UAS = 93.95%, LAS = 89.96%
To install pipeline (POS Tagger, Dependency Parser, NER):
pip install https://storage.googleapis.com/spacy-pl-public-models/pl_model-1.0.0.tar.gz
NER Version: Stable
Status: Done
Release: Done
NER is trained on Wrocław Dataset with reduced number of labels, using fasttext vectors. POC version is available in the recently released pipeline, and the new improved version is coming soon.
NER F-score: 60.2%
To install pipeline (POS Tagger, Dependency Parser, NER):
pip install https://storage.googleapis.com/spacy-pl-public-models/pl_model-1.0.0.tar.gz

Our team

Stanisław Giziński

Team Leader, NLP Specialist
LinkedIn GitHub

  • Existing NLP tools research & testing
  • Dataset analysis & selection
  • Data format integration
  • Data version control setup & management
  • Project planning
  • Parser training

Krzysztof Kowalczyk

Presentation & QA Specialist
LinkedIn GitHub Kaggle

  • Workflow coordination
  • Communication with spaCy maintainers
  • Improved training tools implementation
  • Code reviews & testing
  • Demo website design & implementation
  • Project presentations

Piotr Ksiązek

Developer & researcher

  • Statistical analysis of NKJP Corpus
  • Tokenizer research & implementation
  • Trie-based lemmatizer implementation
  • Tagset conversion implementation
  • Vocab data generation
  • NER training

Mateusz Olko

Developer & researcher
LinkedIn GitHub

  • Communication with project principal
  • Lemmatization rules research & selection
  • Tagset selection
  • Tagger training
  • Integration of fasttext vectors into all models
  • Model testing

Project principal

This project is a part of our BSc thesis at University of Warsaw, Faculty of Mathematics, Informatics and Mechanics (MIM UW) .

It was proposed by Sigmoidal LLC, a Machine Learning Consulting firm experienced in applying AI and Machine Learning to business problems.

Components: Tokenizer, Lemmatizer, Lexical Attributes

This notebook demonstrates the usage of Polish language class in spaCy.

At the moment of writing this, our last pull request was not yet accepted to spaCy master branch. You can install spaCy from our pull request branch to reproduce our results:

pip install https://github.com/spacy-pl/spaCy/archive/pl-release/lemmatizer-tagmap-and-tests.zip

and make sure to also install a model that contains Polish POS Tagger (necessary for lemmatization to work correctly):

pip install https://storage.googleapis.com/spacy-pl-public-models/pl_model-1.0.0.tar.gz

Loading language class

Because our models are not ready yet, we use a dummy tagger that always returns unknown tag. This hack is required for other language components to work correctly, but it soon won't be necessary - we will update the notebook as soon as we have the models trained and packaged

In [1]:
import spacy
from spacy.lang.pl import Polish
In [2]:
nlp = spacy.load('pl_model')
In [3]:
pan_tadeusz = """
Litwo! Ojczyzno moja! ty jesteś jak zdrowie:
Ile cię trzeba cenić, ten tylko się dowie,
Kto cię stracił. Dziś piękność twą w całej ozdobie
Widzę i opisuję, bo tęsknię po tobie.

    Panno święta, co Jasnej bronisz Częstochowy
I w Ostrej świecisz Bramie! Ty, co gród zamkowy
Nowogródzki ochraniasz z jego wiernym ludem!
Jak mnie dziecko do zdrowia powróciłaś cudem
(Gdy od płaczącej matki, pod Twoją opiekę
Ofiarowany, martwą podniosłem powiekę;
I zaraz mogłem pieszo, do Twych świątyń progu
Iść za wrócone życie podziękować Bogu),
Tak nas powrócisz cudem na Ojczyzny łono.
Tymczasem przenoś moją duszę utęsknioną
Do tych pagórków leśnych, do tych łąk zielonych,
Szeroko nad błękitnym Niemnem rozciągnionych;
Do tych pól malowanych zbożem rozmaitem,
Wyzłacanych pszenicą, posrebrzanych żytem;
Gdzie bursztynowy świerzop, gryka jak śnieg biała,
Gdzie panieńskim rumieńcem dzięcielina pała,
A wszystko przepasane jakby wstęgą, miedzą
Zieloną, na niej z rzadka ciche grusze siedzą.
"""

Parsing the data

Right now, the data processing takes very long (>1min for such a small document) due to our hack for getting a lemmatizer to work:

Because we don't have a loaded POS Tagger at the moment, we created a dummy tagger that always returns an unknown tag. This triggers lemmatizer to search all available rules instead of the ones for a specific POS tag.

In [4]:
doc = nlp(pan_tadeusz)
doc
Out[4]:

Litwo! Ojczyzno moja! ty jesteś jak zdrowie:
Ile cię trzeba cenić, ten tylko się dowie,
Kto cię stracił. Dziś piękność twą w całej ozdobie
Widzę i opisuję, bo tęsknię po tobie.

    Panno święta, co Jasnej bronisz Częstochowy
I w Ostrej świecisz Bramie! Ty, co gród zamkowy
Nowogródzki ochraniasz z jego wiernym ludem!
Jak mnie dziecko do zdrowia powróciłaś cudem
(Gdy od płaczącej matki, pod Twoją opiekę
Ofiarowany, martwą podniosłem powiekę;
I zaraz mogłem pieszo, do Twych świątyń progu
Iść za wrócone życie podziękować Bogu),
Tak nas powrócisz cudem na Ojczyzny łono.
Tymczasem przenoś moją duszę utęsknioną
Do tych pagórków leśnych, do tych łąk zielonych,
Szeroko nad błękitnym Niemnem rozciągnionych;
Do tych pól malowanych zbożem rozmaitem,
Wyzłacanych pszenicą, posrebrzanych żytem;
Gdzie bursztynowy świerzop, gryka jak śnieg biała,
Gdzie panieńskim rumieńcem dzięcielina pała,
A wszystko przepasane jakby wstęgą, miedzą
Zieloną, na niej z rzadka ciche grusze siedzą.

Feature demonstration

Iterating over tokens

We can easily inspect every token in the document by iterating over it. This way, we can examine how well our lemmatizer works:

In [5]:
for token in doc[:50]:
    if token.is_alpha and token.lemma_ != token.lower_:
        print(f"token: {token.text}; lemma: {token.lemma_}")
token: Litwo; lemma: litwa
token: Ojczyzno; lemma: ojczyzna
token: dowie; lemma: dować
token: stracił; lemma: stracić
token: całej; lemma: cały
token: ozdobie; lemma: ozdoba
token: Widzę; lemma: widzieć
token: opisuję; lemma: opisywać
token: tęsknię; lemma: tęsknić
token: Panno; lemma: panna
token: święta; lemma: święto
token: bronisz; lemma: bronić

Token attributes:

In [6]:
for token in doc[:10]:
    print(f"Token: {token} \n - alpha: {token.is_alpha}, \n - digit: {token.is_digit}, \n - stopword: {token.is_stop}")
Token: 
 
 - alpha: False, 
 - digit: False, 
 - stopword: False
Token: Litwo 
 - alpha: True, 
 - digit: False, 
 - stopword: False
Token: ! 
 - alpha: False, 
 - digit: False, 
 - stopword: False
Token: Ojczyzno 
 - alpha: True, 
 - digit: False, 
 - stopword: False
Token: moja 
 - alpha: True, 
 - digit: False, 
 - stopword: True
Token: ! 
 - alpha: False, 
 - digit: False, 
 - stopword: False
Token: ty 
 - alpha: True, 
 - digit: False, 
 - stopword: True
Token: jesteś 
 - alpha: True, 
 - digit: False, 
 - stopword: False
Token: jak 
 - alpha: True, 
 - digit: False, 
 - stopword: True
Token: zdrowie 
 - alpha: True, 
 - digit: False, 
 - stopword: False

Models: Vectors, POS Tagger, Dependency Parser, NER

This notebook demonstrates the usage of Polish models that we developed for spaCy.

At the moment of writing this, our last pull request was not yet accepted to spaCy master branch. You can install spaCy from our pull request branch to reproduce our results:

pip install https://github.com/spacy-pl/spaCy/archive/pl-release/lemmatizer-tagmap-and-tests.zip

and make sure to also install a model that contains Polish POS Tagger (necessary for lemmatization to work correctly):

pip install https://storage.googleapis.com/spacy-pl-public-models/pl_model-1.0.0.tar.gz
In [1]:
import spacy
In [2]:
nlp = spacy.load('pl_model')
In [3]:
doc = nlp("Polacy nie gęsi, iż swój język mają.")
# source: https://pl.wikiquote.org/wiki/A_niechaj_narodowie_w%C5%BCdy_postronni_znaj%C4%85

POS Tagger and Dependency Parser

Currently, POS Tagger and Dependency Parser perform at the level of accuracy similar to corresponding models for other languages in spaCy, and a few percent worse than the state-of-the-art models for Polish.

In [4]:
spacy.displacy.render(doc, style='dep', options={'compact': True, 'distance': 120})
Polacy NOUN nie PART gęsi, NOUN SCONJ swój ADJ język NOUN mają. VERB nsubj advmod mark det nsubj ccomp

Named Entity Recognition

As for the Named Entity Recognizer, there is a challenge of dataset selection for Polish language:

  • NKJP corpus has only 5 tags, and large portion of dataset is incorrectly labeled
  • PWr corpus is well-labeled using 58 tags, but is significantly smaller than NKJP

The NER shipped in pl_model==0.3.0 is trained on PWr with number of tags reduced to 19. While results are mostly correct, it's F-score of 39% is disappointing and there is still room for improvement. In particulat, we are planning to experiment more with tag merging vs dropping tags, to reduce number of tags even further.

In [5]:
doc = nlp("""
Światowe Forum Ekonomiczne (ang. World Economic Forum, WEF) – szwajcarska fundacja non-profit znana z organizacji corocznej konferencji w Davos.

Konferencja w Davos jest spotkaniem prezesów najbogatszych światowych korporacji, przywódców politycznych (prezydentów, premierów i innych) oraz wybranych intelektualistów i dziennikarzy. Bierze w nim udział około 2000 osób. W roku 2013 konferencja odbyła się w dniach 23–27 stycznia[1].

Oprócz konferencji w Davos fundacja organizuje również spotkania regionalne oraz publikuje raporty.

WEF zostało założone w 1971 r. przez Klausa W. Schwaba, niemieckiego profesora biznesu.

Według zwolenników, WEF jest odpowiednim miejscem dla dialogu i debaty na temat głównych społecznych i ekonomicznych problemów planety, ponieważ wśród uczestników obecni są przedstawiciele największych ekonomicznych organizacji i najbardziej wpływowych organizacji politycznych, a także intelektualistów, co sprzyja odpowiedniej atmosferze do prowadzenia szerokiej i otwartej debaty.

Według krytyków WEF, jest to tylko forum biznesu, na którym najbogatsze przedsiębiorstwa mogą łatwo negocjować umowy między sobą, a także wywierać nacisk na najbardziej wpływowych polityków świata. Zdaniem krytyków, celem tych spotkań jest bardziej zysk niż rozwiązywanie ekonomicznych problemów, takich jak bieda. Uważa się, że WEF jest zdominowane przez korporacje i ma wpływ na globalne podejmowanie decyzji, więc jest postrzegany przez krytyków jako niewybierany, niedemokratyczny, elitarny, poufny światowy Senat. Do 2001 roku głównymi zarządami podejmującymi decyzje w WEF były Forum Zarządu Dyrektorów i Rada Zarządu Dyrektorów.

Z tych powodów, w trakcie spotkań WEF (szczególnie od czasu Corocznych Spotkań WEF w styczniu 2000) przeciwnicy regularnie organizują protesty. Akty ograniczania praw obywatelskich podczas protestów są odbierane przez krytyków jako dowód współpracy między władzami lokalnymi a WEF przeciwko prawom człowieka.
""")  # source: https://pl.wikipedia.org/wiki/%C5%9Awiatowe_Forum_Ekonomiczne
In [6]:
spacy.displacy.render(doc, style='ent')

Światowe Forum Ekonomiczne ORG (ang. World Economic Forum, WEF) – szwajcarska fundacja non-profit znana z organizacji corocznej konferencji w Davos GPE .

Konferencja w Davos GPE jest spotkaniem prezesów najbogatszych światowych korporacji, przywódców politycznych (prezydentów, premierów i innych) oraz wybranych intelektualistów i dziennikarzy. Bierze w nim udział około 2000 osób. W roku 2013 konferencja odbyła się w dniach 23–27 stycznia[1].

Oprócz konferencji w Davos GPE fundacja organizuje również spotkania regionalne oraz publikuje raporty.

WEF ORG zostało założone w 1971 r. przez Klausa W. Schwaba PERSON , niemieckiego profesora biznesu.

Według zwolenników, WEF ORG jest odpowiednim miejscem dla dialogu i debaty na temat głównych społecznych i ekonomicznych problemów planety, ponieważ wśród uczestników obecni są przedstawiciele największych ekonomicznych organizacji i najbardziej wpływowych organizacji politycznych, a także intelektualistów, co sprzyja odpowiedniej atmosferze do prowadzenia szerokiej i otwartej debaty.

Według krytyków WEF PRODUCT , jest to tylko forum biznesu, na którym najbogatsze przedsiębiorstwa mogą łatwo negocjować umowy między sobą, a także wywierać nacisk na najbardziej wpływowych polityków świata. Zdaniem krytyków, celem tych spotkań jest bardziej zysk niż rozwiązywanie ekonomicznych problemów, takich jak bieda. Uważa się, że WEF PRODUCT jest zdominowane przez korporacje i ma wpływ na globalne podejmowanie decyzji, więc jest postrzegany przez krytyków jako niewybierany, niedemokratyczny, elitarny, poufny światowy Senat ORG . Do 2001 roku głównymi zarządami podejmującymi decyzje w WEF ORG były Forum Zarządu Dyrektorów i Rada Zarządu Dyrektorów.

Z tych powodów, w trakcie spotkań WEF PRODUCT (szczególnie od czasu Corocznych Spotkań ORG WEF ORG w styczniu 2000) przeciwnicy regularnie organizują protesty. Akty ograniczania praw obywatelskich podczas protestów są odbierane przez krytyków jako dowód współpracy między władzami lokalnymi a WEF ORG przeciwko prawom człowieka.

Entity attribute search

Searching for adjectives that describe a given entity.

In this demo, we can use spaCy to identify named entities and find adjectives that are used to describe them in a set of polish newspaper articles.

Use the search panel below to select a named entity and display a wordcloud of adjectives that refer to that entity.