Natural Language Processing (NLP) ist eine Kombination aus Linguistik, Computerwissenschaft und Künstlicher Intelligenz. Dabei geht es um die maschinelle Verarbeitung von natürlicher Sprache, um sie in eine Form zu bringen, die von einem Computer verarbeitet werden kann und zugleich auch deren Inhalt und Bedeutung beschreibt.
Für NLP gibt es eine Vielzahl verschiedener Anwendungsmöglichkeiten. Dies beinhaltet beispielsweise:
Somit spielt Natural Language Processing eine wichtige Rolle für generelle linguistische Textanalysen, Sprachassistenten, Chatbots, Übersetzer oder Suchmaschinen.
spaCy ist eine freie open-source Python Bibliothek von Explosion AI, die einen einfachen Einstieg in die Disziplin des Natural Language Processing ermöglicht und zugleich auch fortgeschrittene Methoden zur Analyse von Texten bietet. Dafür stehen umfangreiche Features, wie Tokenization, POS-Tagging, Lemmatization oder NER, zur Verfügung.
spaCy stellt bereits statistische Modelle für verschiedene Sprachen zur Verfügung (darunter Englisch, Deutsch, Französisch, Chinesisch, Japanisch, etc.). Diese sind notwendig um einen Text mit linguistischen Annotationen auszustatten, z.B. ob ein Wort ein Substantiv oder ein Verb ist.
spaCy ist kompatibel mit 64-bit CPython 2.7 / 3.5+ und ist für Unix/Linux, macOS/OS X und Windows verfügbar. Es steht über pip oder conda zur Verfügung. Im Folgenden wird die Installation auf einem Windows Rechner unter der Verwendung von pip betrachtet. Grundsätzlich empfiehlt es sich eine Virtual Environment zu verwenden. Weitere Informationen zum Anlegen einer Virtual Environment und zusätzlichen Tipps zur Verwendung von pip lassen sich hier finden: Installing packages using pip and virtual environments.
Die Installation von spaCy erfolgt mit folgendem Befehl:
$ pip install -U spacy
Wie zuvor schon erwähnt bietet spaCy verschieden statistische Modelle für die unterschiedlichen Sprachen. Das Standardmodell ist en_core_web_sm
(Englisch). Da der Fokus in diesem Überblick auf deutschen Texten liegt, wird ein Modell für die deutsche Sprache (de_core_news_sm
) benötigt. spaCy bietet für Deutsch auch noch zwei weitere Modelle an, die sich hauptsächlich in der Größe von dem bereits genannten unterscheiden. de_core_news_sm
reicht für einen ersten Einblick jedoch aus. Das Modell wird mit dem folgenden Befehl in der console heruntergeladen:
$ python -m spacy download de_core_news_sm
Wenn spaCy erfolgreich installiert und das Sprachmodell heruntergeladen wurde, kann man auch schon starten.
Um nun einen ersten einfachen Text zu Analysieren muss zunächst das Sprachmodell geladen werden:
import spacy
nlp = spacy.load('de_core_news_sm')
nlp
repräsentiert nun das deutsche Sprachmodell, womit aus einem Text ein spaCy Doc Objekt erstellt wird.
doc = nlp('Alex spielt mit seinen Freunden Fußball.')
print([token.text for token in doc])
['Alex', 'spielt', 'mit', 'seinen', 'Freunden', 'Fußball', '.']
Wie hierbei erkennbar ist, enthält ein solches Doc
Objekt eine Reihe von Tokens, in die das Sprachmodell den Text aufgeteilt hat. Ein Token ist z.B. ein Wort oder ein Satzzeichen. Die Aufteilung eines Textes in diese einzelnen Bestandteile wird auch als Tokenization bezeichnet. Ein Token enthält neben dem eigentlichen Text noch weitere Informationen. Nachfolgend werden ein paar davon ausgegeben.
import pandas as pd
pd.DataFrame({"Token": [token.text for token in doc],
"Lemma": [token.lemma_ for token in doc],
"POS": [token.pos_ for token in doc],
"Tag": [token.tag_ for token in doc],
"Dep": [token.dep_ for token in doc]})
Token | Lemma | POS | Tag | Dep | |
---|---|---|---|---|---|
0 | Alex | Alex | PROPN | NE | sb |
1 | spielt | spielen | VERB | VVFIN | ROOT |
2 | mit | mit | ADP | APPR | mo |
3 | seinen | seinen | DET | PPOSAT | nk |
4 | Freunden | Freund | NOUN | NN | nk |
5 | Fußball | Fußball | NOUN | NN | nk |
6 | . | . | PUNCT | $. | punct |
Jetzt lassen sich neben der Tokenization auch noch weitere Features erkennen, die spaCy mit sich bringt. Hier wurden nur ein paar der Eigenschaften eines Tokens ausgewählt, die jeweils durch ein Feature zustande kommen:
spacy.displacy.render(doc)
Alle weiteren Eigenschaften, die ein Token beinhaltet, können hier eingesehen werden.
Um längere Texte handhabbar zu machen, können diese über das Doc
Object in ihre einzelnen Sätze zerlegt werden. Um dies zu zeigen, wird wiederum ein Doc
Object erstellt, diesmal jedoch für einen etwas längeren Text der mehrere Sätze umfasst.
text = '''Alex arbeitet seit einem Jahr bei trinnovative. Er interessiert sich für Themen wie z.B. KI und NLP. Heute schreibt er einen Artikel.'''
doc = nlp(text)
sents = doc.sents
for sent in sents:
print(list(sent))
[Alex, arbeitet, seit, einem, Jahr, bei, trinnovative, .]
[Er, interessiert, sich, für, Themen, wie, z.B., KI, und, NLP, .]
[Heute, schreibt, er, einen, Artikel, .]
Wie in diesem Beispiel zu sehen ist, hat spaCy die drei Sätze korrekt extrahiert. Ein Satz (hier sent
) besteht wieder jeweils aus einzelnen Tokens, auf die dann wiederum wie zuvor zugegriffen werden kann.
Die häufigsten Wörter eines Textes sind bei dessen Verarbeitung meist eine wichtige Kenngröße, die einen ersten Endruck vom Inhalt liefert. Deshalb wird Anhand des Wikipediaeintrags über Computerlinguistk (Definition + Geschichte) demonstriert wie diese Worthäufigkeiten mit spaCy wiedergegeben werden. Zunächst werden jedoch ein paar, für NLP typische, Vorverarbeitungsschritte durchgeführt (Preprocessing). Diese sind:
Hier stellt sich die Fragen, was Stoppwörtern (stop words) eigentlich sind und warum sie herausgefiltert werden sollten. Stoppwörter sind für gewöhnlich die häufigsten Wörter einer Sprache, die gleichzeitig wenig bis keine Relevanz für das Erfassen des Textinhaltes haben. Diese werden in einer sogenannten Stoppwortliste geführt, welche wie eine Blacklist behandelt wird. Wörter die also in dieser Liste aufgeführt sind, werden einfach herausgefiltert. Es gibt keine standardisierte Stoppwortliste für jede Sprache und sie kann bei verschiedenen Anwendungen variieren, das Prinzip bleibt jedoch gleich. Ein paar Beispiele für typische deutsche Stoppwörter sind: ich, du, er, der, die, und, in, sein. Würde man solche Wörter nicht herausfiltern, so wären die häufigsten Wörter eines Textes nicht sehr aufschlussreich, was dessen Inhalt betrifft.
Wie bei den Stoppwörtern gilt auch das Gleiche für die Satzzeichen. Sie sind nicht relevant für das Erfassen des Textinhaltes und würden die Liste der häufigsten Wörter nur verfälschen.
Bei der Lemmatisierung wird, wie oben schon kurz angesprochen, ein Wort wieder in seine Grundform zurückgeführt (“untersucht” -> “untersuchen”). Dieser Schritt wird vorgenommen, um die Vielzahl an Wortformen eines Wortes auf einen einzelnen Begriff zu reduzieren. Wenn, wie in diesem Fall, die häufigsten Wörter eines Textes ausgegeben werden sollen und die Tokens nicht lemmatisiert werden, dann würden z.B. “untersucht” und “untersuchen” als zwei verschiedene Wörter gelten, was ein unerwünschtes Ergebnis liefern würde. Aus demselben Grund werden auch alle Wörter in Kleinbuchstaben umgewandelt um z.B. der Großschreibung am Anfang eines Satzes entgegenzuwirken.
Je nach Anwendung können diese Preprocessing-Schritte natürlich variieren. Ein Token von spaCy beinhaltet eine Vielzahl an weiteren Eigenschaften, nach denen gefiltert werden kann. Ein paar Beispiele sind: is_digit
, is_currency
, like_email
, like_url
.
Im Folgenden wird nun das Erklärte umgesetzt:
from collections import Counter
doc = nlp(long_text)
# Alle vier Schritte des Preprocessing + filtern von tokens die nur Leerzeichen enthalt
words = [token.lemma_.lower() for token in doc if not token.is_stop and not token.is_punct and not token.is_space]
# Häufigkeit für jedes Wort berechnen
word_freq = Counter(words)
# 10 häufigste Wörter auswählen
most_freq_words = word_freq.most_common(10)
for word in most_freq_words:
print(word)
('computerlinguistik', 6)
('begriff', 3)
('untersuchen', 2)
('sprache', 2)
('informatik', 2)
('chomsky', 2)
('cl', 1)
('linguistischen', 1)
('datenverarbeitung', 1)
('ldv', 1)
Das Ergebnis liefert jetzt einen einfachen ersten Überblick über den Inhalt des Textes. “Computerlinguistik” tritt sechs mal auf und ist somit das häufigste Wort. Weiterhin scheinen auch “Sprache”, “Informatik” und “Chomsky” ein Rolle in dem Text zu spielen. Dies trifft auf den wirklichen Inhalt des Textes zu. Möchte man nur die häufigsten Substantive aus dem Text extrahieren, so kann man jetzt auf das zuvor angesprochene Part-of-speech Tag eines Tokens zugreifen.
# Alle vier Schritte des Preprocessing + filtern von tokens die nur Leerzeichen enthalt + nur Substantive
nouns = [token.lemma_.lower() for token in doc if not token.is_stop and
not token.is_punct and
not token.is_space and
(token.pos_ == "NOUN" or
token.pos_ == "PROPN")]
# Häufigkeit für jedes Substantiv berechnen
noun_freq = Counter(nouns)
# 10 häufigste Substantive auswählen
most_freq_nouns = noun_freq.most_common(10)
for noun in most_freq_nouns:
print(noun)
('computerlinguistik', 6)
('begriff', 3)
('sprache', 2)
('informatik', 2)
('chomsky', 2)
('cl', 1)
('datenverarbeitung', 1)
('ldv', 1)
('form', 1)
('sprachdaten', 1)
Bei der Named Entity Recognition werden automatisch Eigennamen identifiziert und in bestimmte Kategorien klassifiziert (z.B. Personen, Orte, Organisationen). spaCy nutzt wiederum ein statistisches Modell, um diese Klassifizierung vorzunehmen. Beim hier genutzten deutschen Modell ist eine Einteilung in die Kategorien Person (Einzelperson oder Familie), Ort/Location (Städte, Länder, Berge, etc.), Organisation (Firmen, Regierungseinrichtungen, etc.) oder Verschiedenes/Miscellaneous (z.B. Ereignisse, Nationalitäten, Kunstgegenstände). Die englischen Modelle bieten eine noch detailliertere Einteilung.
Über die Methode .ents
eines Doc
Objekts kann auf die gefundenen Entitäten zugegriffen werden. Da eine Entität eine Sammlung von Tokens ist, kann wiederum auf deren Methoden zugegriffen werden. Als Beispiel werden zwei kurze Sätze über die trinnovative GmbH betrachtet.
doc = nlp("Die trinnovative GmbH hat ihren Sitz in Regensburg. Die Geschäftsführer sind Andreas Beer, Johann Schenkl und Sebastian Erdenreich.")
for ent in doc.ents:
print('{0: <25} {1}'.format(ent.text, ent.label_))
trinnovative GmbH ORG
Regensburg LOC
Andreas Beer PER
Johann Schenkl PER
Sebastian Erdenreich PER
Wie leicht zu sehen ist wurde “trinnovative GmbH” als Organisation, “Regensburg” als Ort und die Namen der Geschäftsführer als Personen erkannt. Wie auch beim Dependency Parse bietet spaCy die Möglichkeit erkannte Entitäten direkt in einem Text zu visualisieren. Dies geschieht wiederum über den displaCy Visualizer.
spacy.displacy.render(doc, style='ent')
Mehr Details zur Named Entity Recognition mit spaCy können können in der Dokumentation nachgelesen werden.
In dieser kurzen Einführung zu Natural Language Processing mit spaCy wurden folgende Punkte behandelt:
Doc
ObjektsAuch wenn hier ein Einblick in einige wichtige Funktionen von spaCy und Konzepte des Natural Language Processing geliefert wurden, ist dies nur ein kleiner Teil von dem, was mit spaCy möglich ist. Weitere Features, die hier nicht behandelt wurden, sind zum Beispiel Rule-based Matching, Text Classification oder das Trainieren eines kompletten Modells für eine Sprache. spaCy ermöglicht also einen einfachen Einstieg in das Thema des Natural Language Processing und ist zugleich äußerst umfangreich und anpassbar um individuelle und komplexe Aufgabenstellungen zu bearbeiten.
Für weitere Informationen ist spaCy’s Dokumentation sehr zu empfehlen.