Skip to content

Latest commit

 

History

History
451 lines (297 loc) · 14.4 KB

chapter2.md

File metadata and controls

451 lines (297 loc) · 14.4 KB
title description prev next type id
Kapitel 2: Großangelegte Datenanalyse mit spaCy
In diesem Kapitel verwendest du deine neuen Skills, um konkrete Informationen aus großen Textmengen zu extrahieren. Du lernst außerdem, spaCys Datenstrukturen optimal zu nutzen sowie statistische und regelbasierte Strategien für Textanalyse effektiv zu kombinieren.
/chapter1
/chapter3
chapter
2

Teil 1

  • Schlage den String "Katze" in nlp.vocab.strings nach, um den Hash zu erhalten.
  • Schlage den Hash nach, um wieder den String zu erhalten.
  • Du kannst den String-Speicher in nlp.vocab.strings wie ein reguläres Python-Dictionary verwenden. nlp.vocab.strings["Einhorn"] zum Beispiel gibt den Hash zurück. Und das Nachschlagen des Hashes gibt wiederum den String zurück.

Teil 2

  • Schlage als String-Label "PER" (verwendet für Personen-Entitäten im deutschen Modell) in nlp.vocab.strings nach, um den Hash zu erhalten.
  • Schlage den Hash nach, um wieder den String zu erhalten.
  • Du kannst den String-Speicher in nlp.vocab.strings wie ein reguläres Python-Dictionary verwenden. nlp.vocab.strings["Einhorn"] zum Beispiel gibt den Hash zurück. Und das Nachschlagen des Hashes gibt wiederum den String zurück.

Warum führt dieser Code zu einer Fehlermeldung?

import spacy

# Erstelle ein englisches und deutsches nlp-Objekt
nlp = spacy.blank("en")
nlp_de = spacy.blank("de")

# Schlage die ID für den String "Bowie" nach
bowie_id = nlp.vocab.strings["Bowie"]
print(bowie_id)

# Schlage die ID für "Bowie" im Vokabular nach
print(nlp_de.vocab.strings[bowie_id])

Hashes können nicht umgekehrt werden. Um dieses Problem zu vermeiden, füge das Wort zum neuen Vokabular hinzu, zum Beispiel, indem du einen Text verarbeitest oder den String hinzufügst, oder benutze dasselbe Vokabular, um den Hash wieder in einen String umzuwandeln.

Jeder String kann in einen Hash umgewandelt werden.

Der Name der Variable nlp ist nur einen Konvention. Wenn der Code die Variable nlp statt nlp_de verwenden würde, würde dies das vorhandene nlp-Objekt überschreiben, und damit ebenfalls das Vokabular.

Lass uns ein paar Doc-Objekte manuell erstellen!

Teil 1

  • Importiere das Doc von spacy.tokens.
  • Erstelle ein Doc mit den words und spaces. Vergiss nicht, das gemeinsame Vokabular als Argument anzugeben.

Die Klasse Doc akzeptiert drei Argumente: das gemeinsame Vokabular, typischerweise nlp.vocab, eine Liste von words und eine Liste von spaces, boolesche Werte, die angeben, ob auf das Wort ein Leerzeichen folgt.

Teil 2

  • Importiere das Doc von spacy.tokens.
  • Erstelle ein Doc mit den words und spaces. Vergiss nicht, das gemeinsame Vokabular als Argument anzugeben.

Schau dir die einzelnen Wörter im erwarteten Text-Output an und siehe nach, ob auf das Wort ein Leerzeichen folgt. Wenn ja, sollte der Leerzeichen-Wert an dieser Stelle True sein. Wenn nicht, sollte er False sein.

Teil 3

  • Importiere das Doc von spacy.tokens.
  • Ergänze die words und spaces, um den gewünschten Text zu erzielen, und erstelle ein doc.

Beachte die einzelnen Tokens. Um zu sehen, wie spaCy diesen String typischerweise tokenisiert, kannst du es in Python ausprobieren und die einzelnen Tokens für nlp("Was, echt?!") drucken.

In dieser Übung wirst du die Doc- und Span-Objekte von Hand erstellen und die Entitäten aktualisieren – genauso wie es spaCy hinter den Kulissen macht. Ein gemeinsames nlp-Objekt wurde bereits für dich erstellt.

  • Importiere die Klassen Doc und Span von spacy.tokens.
  • Verwende die Klasse Doc direkt, um ein doc auf Basis der Wörter und Leerzeichen zu erstellen.
  • Erstelle eine Span für "David Bowie", basierend auf dem doc, und weise ihm das Label "PER" ("Person") zu.
  • Überschreibe die doc.ents mit einer Liste einer Entität: die span "David Bowie".
  • Das Doc wird mit drei Argumenten initialisiert: das gemeinsame Vokabular, z.B. nlp.vocab, eine Liste von Wörtern und eine Liste von booleschen Werten, die angeben, ob auf ein Wort ein Leerzeichen folgt.
  • Die Klasse Span akzeptiert vier Argumente: das Referenz-Doc, den Start-Token-Index, den End-Token-Index und ein optionales Label.
  • Die doc.ents sind schreibbar, das heißt du kannst dem Attribut eine Liste bestehend aus Span-Objekten zuweisen.

Der Code in diesem Beispiel versucht, einen Text zu analysieren und alle Eigennamen (proper nouns) zu finden, auf die ein Verb folgt.

import spacy

nlp = spacy.load("de_core_news_sm")
doc = nlp("Berlin gefällt mir sehr gut")

# Finde alle Tokens und Wortarten
token_texts = [token.text for token in doc]
pos_tags = [token.pos_ for token in doc]

for index, pos in enumerate(pos_tags):
    # Teste, ob der aktuelle Token ein Eigenname ist
    if pos == "PROPN":
        # Teste, ob der nächste Token ein Verb ist
        if pos_tags[index + 1] == "VERB":
            result = token_texts[index]
            print("Eigenname vor Verb gefunden:", result)

Teil 1

Warum ist der Code schlecht geschrieben?

Es sollte nicht nötig sein, Strings wieder in Token-Objekte umzuwandeln. Versuche stattdessen zu vermeiden, Tokens in Strings umzuwandeln, wenn du nach wie vor auf ihre Attribute und Beziehungen zueinander zugreifen möchtest.

Wandle die Ergebnisse stets so spät wie möglich in Strings um, und versuche, eingebaute Token-Attribute zu verwenden, um den Code einheitlich zu halten.

Das Attribut .pos_ gibt die grobe Wortart zurück und "PROPN" ist der korrekte Tag für Eigennamen.

Teil 2

  • Schreibe den Code um und verwende die eingebauten Token-Attribute statt die String-Listen token_texts und pos_tags.
  • Iteriere über die tokens im doc und schaue dir das token.pos_-Attribut an.
  • Verwende doc[token.i + 1], um den nächsten Token und sein Attribut .pos_ zu erhalten.
  • Wenn ein Eigenname (proper noun) vor einem Verb gefunden wurde, drucke seinen token.text.
  • Lösche die Variablen token_texts und pos_tags – wir müssen keine Listen von Strings im Voraus erstellen!
  • Statt über die pos_tags, iteriere über die tokens im doc und verwende das token.pos_-Attribut.
  • Um zu testen, ob der nächste Token ein Verb ist, schaue dir doc[token.i + 1].pos_ an.

In dieser Übung wirst du eine größere englische Pipeline verwenden, die ca. 20.000 Wortvektoren enthält. Das Pipeline-Package ist bereits vorinstalliert.

  • Lade die mittelgroße Pipeline "en_core_web_md" mit Wortvektoren.
  • Drucke den Vektor für "bananas" mithilfe des Attributs token.vector.
  • Um eine Pipeline zu laden, rufe spacy.load mit dem String-Namen der Pipeline auf.
  • Um auf einen Token in einem Doc zuzugreifen, kannst du seinen Index verwenden, zum Beispiel doc[4].

In dieser Übung wirst du spaCy's similarity-Methoden verwenden, um Doc-, Token- und Span-Objekte zu vergleichen und Ähnlichkeitswerte zu erhalten.

Teil 1

  • Verwende die Methode doc.similarity, um doc1 mit doc2 zu vergleichen, und drucke das Ergebnis.

Die Methode doc.similarity erwartet ein Argument: das andere Objekt, mit dem das aktuelle Objekt verglichen werden soll.

Teil 2

  • Verwende die Methode token.similarity, um token1 mit token2 zu vergleichen, und drucke das Ergebnis.

Die Methode token.similarity erwartet ein Argument: das andere Objekt, mit dem das aktuelle Objekt verglichen werden soll.

Teil 3

  • Erstelle Spans für "great restaurant" und "really nice bar".
  • Verwende die Methode span.similarity, um die Spans zu vergleichen, und drucke das Ergebnis.

Die Methode span.similarity erwartet ein Argument: das andere Objekt, mit dem das aktuelle Objekt verglichen werden soll.

Warum findet dieses Pattern die Tokens "Silicon Valley" nicht im doc?

pattern = [{"LOWER": "silicon"}, {"TEXT": " "}, {"LOWER": "valley"}]
doc = nlp("Im Silicon Valley herrscht nach wie vor eine männerdominierte Kultur.")

Das Attribut "LOWER" im Pattern beschreibt Tokens, deren kleingeschriebene Form einem entsprechenden Wert gleicht. Das heißt, {"LOWER": "valley"} findet Tokens wie "Valley", "VALLEY", "valley" usw.

Der Tokenizer sorgt bereits dafür, dass Leerzeichen abgespalten werden, und jedes Dictionary im Pattern beschreibt einen Token.

Standardmäßig werden alle Tokens, die von einem Pattern beschrieben werden, genau einmal gefunden. Operatoren sind nur notwending, wenn dieses Verhalten geändert werden soll – zum Beispiel, um einen Token 0 Mal oder öfter zu finden.

In dieser Übung geht es zur Abwechslung um einen englischen Text. Beide Patterns enthalten Fehler und finden Tokens nicht wie erwartet. Kannst du sie korrigieren? Falls du nicht weiter weißt, drucke die Tokens im doc, um zu sehen, wie der Text aufgeteilt wurde, und justiere das Pattern entsprechend, sodass jedes Dictionary einen Token repräsentiert.

  • Ändere pattern1, sodass es korrekt alle Erwähnungen von "Amazon" (Groß- und Kleinschreibung), plus einen Eigennamen (proper noun) beginnend mit einem Großbuchstaben findet.
  • Ändere pattern2, sodass es korrekt alle Erwähnungen von "ad-free" (Groß- und Kleinschreibung), plus das folgende Nomen findet.
  • Versuche mal, die Strings, die gefunden werden sollen, mit dem nlp-Objekt zu verarbeiten – zum Beispiel, [token.text for token in nlp("ad-free viewing")].
  • Inspiziere die Tokens und achte darauf, dass jedes Dictionary korrekt einen einzelnen Token beschreibt.

Manchmal ist es effizienter, exakte Strings zu suchen, anstatt Patterns für einzelne Tokens zu schreiben. Dies ist vor allem der Fall, wenn es eine begrenzte Anzahl an Dingen gibt, die gefunden werden sollen – wie zum Beispiel alle Länder der Welt. Es gibt bereits eine Liste aller Länder, die wir als Basis für unser Skript zum Extrahieren von Informationen verwenden können. Eine Liste von String-Namen ist verfügbar als Variable COUNTRIES.

  • Importiere den PhraseMatcher und initialisiere ihn mit dem gemeinsamen vocab als Variable matcher.
  • Füge die patterns hinzu und wende den Matcher auf das doc an.

Das gemeinsame vocab ist verfügbar unter nlp.vocab.

In der vorherigen Übung hast du ein Skript geschrieben, das spaCys PhraseMatcher verwendet, um Ländernamen im Text zu finden. Lass uns nun diesen Länder-Matcher mit einem längeren Text verwenden, den Satzbau analysieren und die Entitäten des aktuellen Dokuments mit den gefundenen Ländern aktualisieren.

  • Iteriere über die Resultate und erstelle eine Span mit dem label "LOC" (Location).
  • Überschreibe die Entitäten in doc.ents und füge die gefundene Span hinzu.
  • Wähle den Kopf-Token (head) des Root-Tokens der Span aus.
  • Drucke den Text des Kopf-Tokens und der Span.
  • Denke daran, dass der Text in der Variable text verfügbar ist.
  • Der Root-Token ist verfügbar als span.root. Der Kopf-Token eines Tokens ist verfügbar als das Attribut token.head.