Lemmatisering is het proces van het omzetten van een woord naar zijn basisvorm. Het verschil tussen afstammen en lemmatiseren is dat lemmatiseren rekening houdt met de context en het woord omzet in zijn betekenisvolle basisvorm, terwijl afstammen alleen de laatste paar tekens verwijdert, wat vaak leidt tot onjuiste betekenissen en spelfouten.
Lemmatiseringsbenaderingen in Python vergelijken. foto doorJasmijn Schreiber
Inhoud
1. Inleiding 2. Wordnet Lemmatizer 3. Wordnet Lemmatizer met passende POS-tag 4. spaCy Lemmatisering 5. TekstBlob Lemmatizer 6. TextBlob Lemmatizer met passende POS-tag 7. Patroon Lemmatizer 8. Stanford CoreNLP Lemmatisering 9. Gensim Lemmatize 10. Boomtagger 11. Vergelijking van NLTK, TextBlob, spaCy, Pattern en Stanford CoreNLP 12. Conclusie
1. Inleiding
Lemmatisering is het proces van het omzetten van een woord naar zijn basisvorm.
Het verschil tussen afstammen en lemmatiseren is dat lemmatiseren rekening houdt met de context en het woord omzet in zijn betekenisvolle basisvorm, terwijl afstammen alleen de laatste paar tekens verwijdert, wat vaak leidt tot onjuiste betekenissen en spelfouten.
Lemmatisering zou bijvoorbeeld de basisvorm van 'zorgzaam' in 'zorg' correct identificeren, terwijl stamelen het deel 'ing' zou afsnijden en omzetten in auto. ‘Zorg’ -> Lemmatisering -> ‘Zorg’ ‘Zorg’ -> Stemming -> ‘Auto’
Ook kan hetzelfde woord soms meerdere verschillende 'lemma's' hebben. Dus, op basis van de context waarin het wordt gebruikt, moet u de tag 'part-of-speech' (POS) voor het woord in die specifieke context identificeren en het juiste lemma extraheren.
Voorbeelden van het implementeren hiervan vindt u in de volgende paragrafen. Vandaag zullen we zien hoe we lemmatisatie kunnen implementeren met behulp van de volgende python-pakketten.
- Wordnet Lemmatizer
- Spacy Lemmatizer
- TekstBlob
- CLiPS-patroon
- Stanford CoreNLP
- Gensim Lemmatizer
- TreeTagger
2. Wordnet Lemmatizer met NLTK
Wordnetis een grote, vrij en openbaar beschikbare lexicale database voor de Engelse taal met als doel gestructureerde semantische relaties tussen woorden tot stand te brengen.
Het biedt ook lemmatiseringsmogelijkheden en is een van de vroegste en meest gebruikte lemmatizers.
NLTK biedt er een interface voor, maar u moet deze eerst downloaden om hem te kunnen gebruiken. Volg de onderstaande instructies om te installerennltk
en downloadenwordnet
.
# NLTK installeren en importeren# In terminal of prompt:# pip install nltk# # Download Wordnet via NLTK in python console:import nltknltk.download('wordnet')
Om te lemmatiseren, moet u een instantie van hetWordNetLemmatizer()
en bel delemmatiseren()
functie op een enkel woord.
import nltkfrom nltk.stem import WordNetLemmatizer # Init the Wordnet Lemmatizerlemmatizer = WordNetLemmatizer()# Lemmatize Single Wordprint(lemmatizer.lemmatize("bats"))#> batprint(lemmatizer.lemmatize("are"))#> areprint(lemmatizer.lemmatize ("voeten"))#> voet
Laten we een eenvoudige zin lemmatiseren. We symboliseren de zin eerst in woorden met behulp vannltk.word_tokenize
en dan bellen welemmatizer.lemmatize()
op elk woord. Dit kan gedaan worden in een lijstbegrip (de for-lus tussen vierkante haken om een lijst te maken).
# Definieer de te lemmatiseren zin = "De gestreepte vleermuizen hangen voor het beste aan hun voeten" # Tokenize: splits de zin op in woordenword_list = nltk.word_tokenize(sentence)print(word_list)#> ['The', 'striped', 'bats', 'are', 'hanging', 'on', 'their', 'feet', 'for', 'best']# Lemmatiseer woordenlijst en joinlemmatized_output = ' '.join([lemmatizer.lemmatize( w) for w in word_list])print(lemmatized_output)#> De gestreepte vleermuis hangt het beste aan zijn voet
De bovenstaande code is een eenvoudig voorbeeld van het gebruik van de wordnet lemmatizer op woorden en zinnen.
Merk op dat het niet goed werkte. Omdat 'zijn' niet wordt omgezet in 'zijn' en 'hangen' niet wordt omgezet in 'hangen' zoals verwacht.
Dit kan worden gecorrigeerd als we het juiste verstrekken'part-of-speech'-tag(POS-tag) als het tweede argument voorlemmatiseren()
.
Soms kan hetzelfde woord meerdere lemma's hebben op basis van de betekenis/context.
print(lemmatizer.lemmatize("strepen", 'v')) #> stripprint(lemmatizer.lemmatize("strepen", 'n')) #> streep
3. Wordnet Lemmatizer met passende POS-tag
Bij grote teksten is het misschien niet mogelijk om handmatig de juiste POS-tag voor elk woord op te geven.
Dus in plaats daarvan zullen we de juiste POS-tag voor elk woord vinden, deze toewijzen aan het juiste invoerteken dat de WordnetLemmatizer accepteert en deze doorgeven als het tweede argument aanlemmatiseren()
.
Dus hoe krijg je de POS-tag voor een bepaald woord?
In nltk is het beschikbaar via denltk.pos_tag()
methode. Het accepteert alleen een lijst (lijst met woorden), zelfs als het een enkel woord is.
print(nltk.pos_tag(['feet']))#> [('feet', 'NNS')]print(nltk.pos_tag(nltk.word_tokenize(zin)))#> [('The', 'DT '), ('gestreept', 'JJ'), ('vleermuizen', 'NNS'), ('zijn', 'VBP'), ('hangend', 'VBG'), ('aan', 'IN '), ('hun', 'PRP$'), ('voeten', 'NNS'), ('voor', 'IN'), ('beste', 'JJS')]
nltk.pos_tag()
retourneert een tuple met de POS-tag. De sleutel hier is om de POS-tags van NLTK toe te wijzen aan het formaat dat wordnet lemmatizer zou accepteren. Deget_wordnet_pos()
hieronder gedefinieerde functie doet deze toewijzingstaak.
# Lemmatize with POS Tag from nltk.corpus import wordnetdef get_wordnet_pos(word): """Wijs POS-tag toe aan eerste teken lemmatize() accepteert""" tag = nltk.pos_tag([word])[0][1][0] .upper() tag_dict = {"J": wordnet.ADJ, "N": wordnet.NOUN, "V": wordnet.VERB, "R": wordnet.ADV} return tag_dict.get(tag, wordnet.NOUN) # 1. Init Lemmatizerlemmatizer = WordNetLemmatizer()# 2. Lemmatiseer een enkel woord met het juiste POS-tagwoord = 'feet'print(lemmatizer.lemmatize(word, get_wordnet_pos(word)))# 3. Lemmatiseer een zin met de juiste POS-tagzin = "De gestreepte vleermuizen hangen het beste aan hun voeten"print([lemmatizer.lemmatize(w, get_wordnet_pos(w)) for w in nltk.word_tokenize(sentence)])#> ['The', 'strip', 'bat ', 'zijn', 'hangen', 'aan', 'hun', 'voet', 'voor', 'beste']
4. spaCy Lemmatisering
spaCy is relatief nieuw in de ruimte en wordt aangekondigd als een krachtige NLP-motor.
Het komt metvoorgebouwde modellendie tekst kan ontleden en verschillende NLP-gerelateerde functies kan berekenen via één enkele functieaanroep.
Natuurlijk geeft het ook het lemma van het woord. Laten we, voordat we beginnen, spaCy installeren en het 'en'-model downloaden.
# Installeer spaCy (uitvoeren in terminal/prompt)import sys!{sys.executable} -m pip install spacy# Download spaCy's 'en' Model!{sys.executable} -m spacy download nl
spaCy bepaalt standaard de part-of-speech-tag en wijst het bijbehorende lemma toe. Het wordt geleverd met een aantal vooraf gebouwde modellen waarbij de 'en' die we zojuist hierboven hebben gedownload een van de standaardmodellen voor het Engels is.
import spacy# Initialiseer het spacy 'en' model, behoud alleen de tagger-component die nodig is voor lemmatizationnlp = spacy.load('en', disable=['parser', 'ner'])sentence = "De gestreepte vleermuizen hangen een tijdje aan hun voeten best"# Parseer de zin met behulp van het geladen 'en'-modelobject `nlp`doc = nlp(sentence)# Extraheer het lemma voor elk token en voeg toe aan" ".join([token.lemma_ voor token in doc])#> ' de strip vleermuis worden hang op -PRON- voet voorgoed'
Het deed alle lemmatiseringen die de Wordnet Lemmatizer geleverd met de juiste POS-tag deed. Bovendien lemmatiseerde het ook 'beste' naar 'goed'. Leuk! Je zou het -PRON--teken zien verschijnen wanneer spacy een voornaamwoord detecteert.
5. TekstBlob Lemmatizer
TexxtBlob is ook een krachtig, snel en handig NLP-pakket. De ... gebruikenWoord
EnTekstBlob
objecten, is het vrij eenvoudig om respectievelijk woorden en zinnen te ontleden en te lemmatiseren.
# pip install textblobfrom textblob import TextBlob, Word# Lemmatiseer een woordwoord = 'strepen'w = Word(woord)w.lemmatize()#> stripe
Om een zin of paragraaf echter te lemmatiseren, ontleden we deze met behulp van TextBlob en noemen we delemmatiseren()
functie op de geparseerde woorden.
# Lemmatiseer een zinzin = "De gestreepte vleermuizen hangen het beste aan hun voeten"verzonden = TextBlob(zin)" ". join([w.lemmatize() voor w in verzonden.woorden])#> 'De gestreepte vleermuis hangt het beste aan hun voet'
In het begin werkte het niet geweldig, omdat TextBlob, net als NLTK, ook intern wordnet gebruikt. Laten we dus de juiste POS-tag doorgeven aan delemmatiseren()
methode.
6. TextBlob Lemmatizer met passende POS-tag
# Definieer functie om elk woord te lemmatiseren met zijn POS-tagdef lemmatize_with_postag(zin): verzonden = TextBlob(zin) tag_dict = {"J": 'a', "N": 'n', "V": 'v', " R": 'r'} woorden_en_tags = [(w, tag_dict.get(pos[0], 'n')) voor w, pos in verzonden.tags] lemmatized_list = [wd.lemmatize(tag) voor wd, tag in words_and_tags] return " ".join(lemmatized_list)# Lemmatizesentence = "De gestreepte vleermuizen hangen het beste aan hun voeten"lemmatize_with_postag(sentence)#> 'De gestreepte vleermuizen hangen het beste aan hun voeten'
7. Patroon Lemmatizer
Patroon door CLiPsis een veelzijdige module met veel handige NLP-mogelijkheden.
!pip installatiepatroon
Als je problemen tegenkomt tijdens het installeren van pattern, bekijk dan het bekendeproblemen op github. Ik ben zelf geconfronteerddeze kwestiebij installatie op een mac.
import patternfrom pattern.en import lemma, lexemesentence = "De gestreepte vleermuizen hingen aan hun voeten en aten de beste vissen"" ".join([lemma(wd) voor wd in zin.split()])#> 'de gestreepte vleermuis op hun voeten hangen en de beste vissen eten'
Ook kunt u per woord de mogelijke lexemen bekijken.
# Lexeme's voor elk woord [lexeme(wd) voor wd in zin.split()]#> [['the', 'thes', 'thing', 'thed'],#> ['stripe', 'stripes' , 'striping', 'striped'],#> ['bat', 'bats', 'batting', 'batted'],#> ['zijn', 'ben', 'zijn', 'is', ' zijn', 'was', 'waren', 'zijn', #> . 'ben niet', 'ben niet', 'is niet', 'was niet', 'weren niet'],#> ['hangen', 'hangen', 'hangen', 'hangen'], #> ['aan', 'ons', 'oning', 'oned'],#> ['hun', 'hun', 'hun', 'hun'],#> ['voeten', 'voeten' , 'feet', 'feeted'],#> ['and', 'ands', 'anding', 'anded'],#> ['eten', 'eet', 'eten', 'at', ' gegeten'],#> ['best', 'bests', 'besting', 'bested'],#> ['fishes', 'fishing', 'fished']]
U kunt het lemma ook verkrijgen door de tekst te ontleden.
from pattern.en import parseprint(parse('De gestreepte vleermuizen hingen aan hun voeten en aten de beste vissen', lemmata=True, tags=False, chunks=False))#> De/DT/de gestreepte/JJ/gestreepte vleermuizen /NNS/bat were/VBD/be hanging/VBG/hang on/IN/on their/PRP$/their #> feet/NNS/foot and/CC/and at/VBD/eat best/JJ/best fishes/NNS /vis
8. Stanford CoreNLP Lemmatisering
Standford CoreNLPis een populaire NLP-tool die oorspronkelijk is geïmplementeerd in Java. Er zijn veel pythonwikkels omheen geschreven. Degene die ik hieronder gebruik, is er een die best handig in gebruik is.
Maar daarvoor moet u Java en de Standford CoreNLP-software downloaden.
Zorg ervoor dat u aan de volgende vereisten voldoet voordat u naar de lemmatiseringscode gaat: Stap 1: Java 8 geïnstalleerd U kunt downloaden en installeren vanafJava-downloadpagina. Mac-gebruikers kunnen de Java-versie controleren door te typenjava -versie
op terminaal. Als het 1.8+ is, dan is het OK.
Volg anders de onderstaande stappen.
brew updatebrew install jenvbrew cask install java
Stap 2:Download de Standford CoreNLP-softwareen pak het uit.
Stap 3: Start de Stanford CoreNLP-server vanaf de terminal. Hoe?CD
naar de map die u zojuist hebt uitgepakt en voer het onderstaande commando in terminal uit:
cd stanford-corenlp-full-2018-02-27java -mx4g -cp "*" edu.stanford.nlp.pipeline.StanfordCoreNLPServer -annotators "tokenize,ssplit,pos,lemma,parse,sentiment" -port 9000 -timeout 30000
Hiermee wordt een StanfordCoreNLPServer gestart die luistert op poort 9000.
Nu zijn we klaar om de lemma's in python te extraheren. In destanfordcorenl
pakket, is het lemma ingebed in de uitvoer van hetannoteren()
methode van het StanfordCoreNLP-verbindingsobject (zie onderstaande code).
# Voer `pip install stanfordcorenlp` uit om het stanfordcorenlp-pakket te installeren van stanfordcorenlp import StanfordCoreNLPimport json# Maak verbinding met de CoreNLP-server die we net zijn gestartnlp = StanfordCoreNLP('http://localhost', port=9000, timeout=30000)# Definieer de eigenschappen die nodig zijn om lemmaprops te krijgen = {'annotators': 'pos,lemma', 'pipelineLanguage': 'en', 'outputFormat': 'json'}sentence = "De gestreepte vleermuizen hingen aan hun voeten en aten de beste vissen"parsed_str = nlp.annotate( zin, eigenschappen=props)parsed_dict = json.loads(parsed_str)parsed_dict#> {'sentences': [{'index': 0,#> 'tokens': [{'after': ' ',#> 'before' : '',#> 'characterOffsetBegin': 0,#> 'characterOffsetEnd': 3,#> 'index': 1,#> 'lemma': 'de', << ---------- - LEMMA#> 'originalText': 'The',#> 'pos': 'DT',#> 'word': 'The'},#> {'after': ' ',#> 'before': ' ',#> 'characterOffsetBegin': 4,#> 'characterOffsetEnd': 11,#> 'index': 2,#> 'lemma': 'gestreept', << ----------- LEMMA #> 'originalText': 'gestreept',#> 'pos': 'JJ',#> 'woord': 'gestreept'},#> {'na': ' ',#> 'voor': ' ', #> 'characterOffsetBegin': 12,#> 'characterOffsetEnd': 16,#> 'index': 3,#> 'lemma': 'bat', << ----------- LEMMA#> 'originalText': 'vleermuizen',#> 'pos': 'NNS',#> 'word': 'vleermuizen'}#> ...#> ...
De uitvoer vannlp.annotate()
werd omgebouwd tot eendict
gebruik makend vanjson.loads
.
Nu is het lemma dat we nodig hebben een paar lagen ingebed in deontleed_dict
.
Dus hier hebben we alleen de lemma-waarde van elk dictum nodig.
Ik gebruik onderstaande lijstbegrippen om de slag te slaan.
lemma_list = [v for d in parsed_dict['sentences'][0]['tokens'] for k,v in d.items() if k == 'lemma']" ".join(lemma_list)#> 'the gestreepte vleermuis hangen aan hun voet en eten de beste vis '
Laten we dit een leuke functie generaliseren om grotere paragrafen te behandelen.
from stanfordcorenlp import StanfordCoreNLPimport json, stringdef lemmatize_corenlp(conn_nlp, zin): props = { 'annotators': 'pos,lemma', 'pipelineLanguage': 'en', 'outputFormat': 'json' } # tokenize into words sents = conn_nlp .word_tokenize(sentence) # verwijder interpunctie uit getokeniseerde lijst sents_no_punct = [s for s in sends if s not in string.punctuation] # vorm zin zin2 = " ".join(sents_no_punct) # annotate to get lemma parsed_str = conn_nlp.annotate( zin2, eigenschappen=props) parsed_dict = json.loads(parsed_str) # extraheer het lemma voor elk woord lemma_list = [v voor d in parsed_dict['sentences'][0]['tokens'] voor k,v in d.items () if k == 'lemma'] # vorm een zin en retourneer deze " ".join(lemma_list)# maak de verbinding en roep `lemmatize_corenlp`nlp = StanfordCoreNLP('http://localhost', port=9000, timeout =30000)lemmatize_corenlp(conn_nlp=nlp, zin=zin)#> 'de gestreepte vleermuis hangt aan zijn voet en eet de beste vis'
9. Gensim Lemmatize
Gensim biedt lemmatiseringsfaciliteiten op basis van depatroon
pakket.
Het kan worden geïmplementeerd met behulp van delemmatiseren()
methode in degebruikt
moduul.
Standaardlemmatiseren()
staat alleen de tags 'JJ', 'VB', 'NN' en 'RB' toe.
from gensim.utils import lemmatizesentence = "De gestreepte vleermuizen hingen aan hun voeten en aten de beste vissen"lemmatized_out = [wd.decode('utf-8').split('/')[0] for wd in lemmatize(sentence )]#> ['gestreept', 'vleermuis', 'zijn', 'hangen', 'voet', 'eten', 'beste', 'vis']
10. Boomtagger
Treetagger is een Part-of-Speech tagger voor vele talen.
En het geeft ook het lemma van het woord.
U moet het downloaden en installerenTreeTagger-softwarezelf om het te gebruiken door de genoemde stappen te volgen.
# pip install treetaggerwrapperimporteer treetaggerwrapper als ttpwtagger = ttpw.TreeTagger(TAGLANG='en', TAGDIR='/Users/ecom-selva.p/Documents/MLPlus/11_Lemmatization/treetagger')tags = tagger.tag_text("De gestreepte vleermuizen waren hangend aan hun voeten en aten de beste vissen")lemma's = [t.split('\t')[-1] for t in tags]#> ['the', 'striped', 'bat', 'we', 'hangen', 'aan', 'hun', 'voet', 'en', 'eten', 'goed', 'vissen']
Treetagger doet inderdaad goed werk bij het converteren van 'beste' naar 'goed' en ook voor andere woorden. Voor meer informatie, zieTreeTaggerWrapper's documentatie.
11. Vergelijking van NLTK, TextBlob, spaCy, Pattern en Stanford CoreNLP
Laten we lemmatisering uitvoeren met behulp van de 5 implementaties op de volgende zin en de uitvoer vergelijken.
zin = """Na aanvallen van muizen marcheerden zorgzame boeren naar Delhi voor betere leefomstandigheden. De politie van Delhi vuurde dinsdag waterkanonnen en traangasgranaten af op protesterende boeren die barricades probeerden te doorbreken met hun auto's, auto's en tractoren.""" # NLTKfrom nltk.stem import WordNetLemmatizerlemmatizer = WordNetLemmatizer()pprint(" ".join([lemmatizer.lemmatize(w, get_wordnet_pos(w)) voor w in nltk.word_tokenize(zin) als w niet in string.interpunctie]))# ('Volgende muisaanval zorg boer marcheert naar Delhi voor goed leven'# 'staat Delhi politie op dinsdag vuurt waterkanon en traangasgranaat af op '#' protest boer a ze proberen de barricade te doorbreken met hun auto auto en '# 'tractor' )# Spacyimport spacynlp = spacy.load('en', disable=['parser', 'ner'])doc = nlp(zin)pprint(" ".join([token.lemma_ voor token in doc]))# ('volg muizenaanval, zorgboer be marcheert naar delhi voor goede levensomstandigheden'# '. Delhi-politie vuurt dinsdag waterkanon en traangasgranaat af bij protest'#'boer als -PRON- probeert barricade te doorbreken met -PRON- auto, auto en '#' tractor .')# TextBlobpprint(lemmatize_with_postag(sentence))# ('Na een muisaanval moet een zorgboer naar Delhi marcheren voor een goed leven' # 'conditie Delhi-politie op dinsdag vuurt waterkanon en traangasgranaat af op '# ' protest boer a ze proberen de barricade te doorbreken met hun auto auto en '# 'tractor')# Patternfrom pattern.en import lemmapprint(" ".join([lemma(wd) for wd in zin.split()]))# ( 'volg muizenaanvallen, zorgboer moet marcheren naar Delhi voor betere levensomstandigheden' # '. Politie van Delhi op dinsdag vuurt waterkanon en traangranaat af op '#' protestboer a ze proberen de barricade te doorbreken met hun auto's, auto's en '#' tractoren.')# Stanfordpprint(lemmatize_corenlp(conn_nlp=conn_nlp, zin=zin))# ('follow mouse attack care farmer be march to Delhi for better living' # 'staat De politie van Delhi vuurt dinsdag waterkanonnen en traangasgranaten af op '#' protestboer terwijl ze barricade proberen te doorbreken met hun auto, auto en '# 'tractor' )
12. Conclusie
Dit zijn dus de methoden die u kunt gebruiken in de tijd dat u een NLP-project start.
Ik zou graag willen weten of u via uw opmerkingen nieuwe benaderingen of suggesties heeft.
Veel leerplezier!