In den nächsten zwei Sitzungen geht es um NLP mit Python. Da hierbei auch die jeweiligen Konzepte aus der Linguistik eingeführt werden müssen, werden wir nur einige wenige Grundbegriffe ansprechen.
Sie werden dabei lernen, wie man mit zwei Bibliotheken diese Aufgaben erledigt, um dann in den Hausaufgaben mit weiteren Bibliotheken zu arbeiten.
In [2]:
text = """Als der Abend herbeikam und die Freunde in einer weitumherschauenden Laube saßen, trat eine ansehnliche Figur auf die Schwelle, welche unser Freund sogleich für den Barbier von heute früh erkannte. Auf einen tiefen, stummen Bückling des Mannes erwiderte Lenardo: Ihr kommt, wie immer, sehr gelegen und werdet nicht säumen, uns mit Eurem Talent zu erfreuen. — Ich kann Ihnen wohl, fuhr er zu Wilhelmen gewendet fort, Einiges von der Gesellschaft erzählen, deren Band zu sein ich mich rühmen darf. Niemand tritt in unsern Kreis, als wer gewisse Talente aufzuweisen hat, die zum Nutzen oder Vergnügen einer jeden Gesellschaft dienen würden. Dieser Mann ist ein derber Wundarzt, der in bedenklichen Fällen, wo Entschluß und körperliche Kraft gefordert wird, seinem Meister trefflich an der Seite zu stehen bereit ist. Was er als Bartkünstler leistet, davon können Sie ihm selbst ein Zeugniß geben. Hiedurch ist er uns eben so nöthig als willkommen. Da nun aber diese Beschäftigung gewöhnlich eine große und oft lästige Geschwätzigkeit mit sich führt, so hat er sich zu eigner Bildung eine Bedingung gefallen lassen, wie denn Jeder, der unter uns leben will, sich von einer gewissen Seite bedingen muß, wenn ihm nach anderen Seiten hin die größere Freiheit gewährt ist. Dieser also hat nun auf die Sprache Verzicht gethan, insofern etwas Gewöhnliches oder Zufälliges durch sie ausgedrückt wird; daraus aber hat sich ihm ein anderes Redetalent entwickelt, welches absichtlich, klug und erfreulich wirkt, die Gabe des Erzählens nämlich. Sein Leben ist reich an wunderlichen Erfahrungen, die er sonst zu ungelegener Zeit schwätzend zersplitterte, nun aber durch Schweigen genöthigt im stillen Sinne wiederholt und ordnet. Hiermit verbindet sich denn die Einbildungskraft und verleiht dem Geschehenen Leben und Bewegung. Mit besonderer Kunst und Geschicklichkeit weiß er wahrhafte Märchen und märchenhafte Geschichten zu erzählen, wodurch er oft zur schicklichen Stunde uns gar sehr ergötzt, wenn ihm die Zunge durch mich gelös't wird; wie ich denn gegenwärtig thue, und ihm zugleich das Lob ertheile, daß er sich in geraumer Zeit, seitdem ich ihn kenne, noch niemals wiederholt hat. Nun hoff' ich, daß er auch diesmal, unserm theuren Gast zu Lieb' und Ehren, sich besonders hervorthun werde.
Ueber das Gesicht des Rothmantels verbreitete sich eine geistreiche Heiterkeit, und er fing ungesäumt folgendermaßen zu sprechen an:
Hochverehrte Herren! da mir bekannt ist, daß Sie vorläufige Reden und Einleitungen nicht besonders lieben, so will ich ohne weiteres versichern, daß ich diesmal vorzüglich gut zu bestehen hoffe. Von mir sind zwar schon gar manche wahrhafte Geschichten zu hoher und allseitiger Zufriedenheit ausgegangen, heute aber darf ich sagen, daß ich eine zu erzählen habe, welche die bisherigen weit übertrifft, und die, wiewohl sie mir schon vor einigen Jahren begegnet ist, mich noch immer in der Erinnerung unruhig macht, ja sogar eine endliche Entwicklung hoffen läßt. Sie möchte schwerlich ihres Gleichen finden.
"""
Textblob installieren:
In [3]:
from textblob_de import TextBlobDE as TextBlob
from textblob_de import PatternParser
doc = TextBlob(text)
print("Number of sentences: ", len(doc.sentences))
print("Length of sentences in characters: ")
for s in doc.sentences:
print(len(s), end=" - ")
Achtung: Mit doc.sentences iterieren wir über die Sätze im Text. Aber der Satz ist kein String, sondern ein besonderes Objekt:
In [4]:
type(s)
Out[4]:
In [5]:
Das gilt auch schon für unser Dokument-Objekt doc:
In [6]:
type(doc)
Out[6]:
Das Gute daran, ist, dass wir - wie oben - über dieses Objekt iterieren können:
for s in doc.sentences
Aber genau genommen iterieren wir ja nicht über das 'doc'-Objekt, sondern über die Daten einer bestimmten Sicht, die wir mit dem Attribut 'sentences' aktivieren. Wir können auch andere Sichten aktivieren, z.B. Worte:
for w in doc.words
In [7]:
doc.words[:20]
Out[7]:
In [8]:
w = doc.words[0]
In [9]:
type(w)
Out[9]:
Vielleicht sollten wir erst einmal erläutern, warum es nicht ganz einfach ist, einen Text in Sätze zu zerlegen. Zuuerst könnte man denken, dass man das mit einigen sehr einfachen Regeln erledigen kann, aber wie ein Blick auf das nächste Beispiel zeigt, ist das nicht so einfach:
In [10]:
text_2 = """Johann Wolfgang Goethe wurde, glaube ich, am 28.8.1749 geboren. Es könnte auch am 20.8. sein. Ich muss zugeben: Genau weiß ich das nicht."""
text_3 = """Die heutige Agenda ist kurz. 1. Die Frage nach dem Anfang. 2. Ende. Viel Spaß!"""
In [11]:
doc = TextBlob(text_2)
list(doc.sentences)
Out[11]:
In [12]:
doc = TextBlob(text_3)
list(doc.sentences)
Out[12]:
In [13]:
blob = TextBlob("Das ist ein schönes Auto.", parser=PatternParser(pprint=True, lemmata=True))
blob.parse()
In [14]:
doc.sentences[0].words
Out[14]:
In [15]:
import spacy
nlp = spacy.load('de')
doc = nlp(text_2)
for s in doc.sents:
print(s)
In [16]:
doc = nlp(text_3)
for s in doc.sents:
print(s)
Im folgenden werden wir nur mit Spacy weiterarbeiten. Für Spacy spricht, dass es recht neu ist, eine ganze Reihe von Sprachen unterstützt, ein modernes Python-Interface mit einer wohlüberlegten API hat, vergleichsweise neue Aspekte der Sprachtechnologie, z.B. Word Embeddings, unterstützt und dass Deutsch zu den gut unterstützten Sprachen zählt. Gegen Spacy spricht, dass es von einer privaten Firma entwickelt wird, allerdings wird das dadurch gemildert, dass spacy selbst auf github unter einer sehr freizügigen MIT-Lizenz verfügbar ist.
In [17]:
print(spacy.__version__)
In [18]:
import spacy
doc = nlp(text_2)
for token in doc:
print(token.text, end="< | >")
In [19]:
doc = nlp(text_3)
a = [print(token.text, end="< | >") for token in doc]
In [20]:
doc = nlp(text_2)
print("{:<15}{:<15}{:<15}".format("TOKEN", "LEMMA", "POS-Tag"))
for token in doc:
print("{:15}{:15}{:15}".format(token.text, token.lemma_, token.pos_ ))
In [21]:
doc = nlp("Diese Auskünfte muss ich dir nicht geben.")
[token.lemma_ for token in doc]
Out[21]:
In [24]:
from spacy_iwnlp import spaCyIWNLP
iwnlp = spaCyIWNLP(lemmatizer_path=r'\mydata\Dropbox\uni\progrs\spacy-iwnlp\IWNLP.Lemmatizer_20170501.json')
nlp.add_pipe(iwnlp)
In [29]:
import spacy
from spacy_iwnlp import spaCyIWNLP
nlp = spacy.load('de')
iwnlp = spaCyIWNLP(lemmatizer_path=r'\mydata\Dropbox\uni\progrs\spacy-iwnlp\IWNLP.Lemmatizer_20170501.json')
nlp.add_pipe(iwnlp)
doc = nlp('Wir mögen Fußballspiele mit ausgedehnten Verlängerungen.')
for token in doc:
print('POS: {}\tIWNLP:{}'.format(token.pos_, token._.iwnlp_lemmas))
l
Out[29]:
In [28]:
doc = nlp('Wir mögen Fußballspiele mit ausgedehnten Verlängerungen.')
for token in doc:
print('POS: {}\tIWNLP:{}'.format(token.pos_, token._.iwnlp_lemmas))
In [ ]:
In [ ]:
In [90]:
from spacy import displacy
text_4 = "Am Anfang war das Wort, das aber bald durch blutige Taten ersetzt wurde."
doc = nlp(text_4)
displacy.render(doc, style='dep', jupyter=True)
In [ ]:
In [100]:
text_5 = """Früher hat man über Johann Wolfang von Goethe gesprochen, weil er den 'Faust' geschrieben hat, oder über Mozart,
weil der die Zauberflöte komponiert hat. Heute dagegen redet man über Samsung, weil das neue Samsung Note4 erschienen ist,
oder über den neuen BMW. Gut, über Steve Jobs hat man noch so geredet, als wäre er ein neuer Mozart der Technologie.
In den USA weiß man kaum noch wer Shakespeare ist, und in Berlin benimmt man sich schon so, also könnte man mit
1 Mio. € einen Goethe kaufen."""
#text_5 = text_5.replace("\n", "") #new lines irritate the parser
doc = nlp(text_5)
for ent in doc.ents:
print(ent.text, ent.start_char, ent.end_char, ent.label_)
In [ ]:
In [ ]: