Wir begeben uns in die Welt der Sprachverarbeitung (Natural Language Processing, NLP).Im Vergleich zu unseren bisherigen Daten (z.B. Hauspreise oder Pixel von Bildern) handelt es sich bei Sprachdaten um sequentielle Daten. Wir arbeiten mit Wörtern und Sätzen unterschiedlicher Länge. Wir lernen zunächst, wie man Wörter und Sätze repräsentiert und welche Vorverarbeitungsschritte man unternehmen muss.
Bag of Words, Word Embeddings
Bislang hatten wir es mit hauptsächlich mit Bilddaten zu tun. Bei Bildern hat man eine feste Eingabegröße, z.B. ein Bild mit 28x28 Pixeln. Da liegt es nahe, für jedes Pixel ein Neuron in der Eingabeschicht zu einzurichten, also 784 Neuronen für 28x28 Pixel.
Bei Sprach- oder Textdaten hat man zunächst mal das Problem, ein Wort zu repräsentieren. Aber auch wenn man jedes Wort als einen Zahlenvektor mit fixer Länge $n$ repräsentieren kann, hat man das Problem, dass ein Satz keine feste Länge hat. Wie soll man einen Satz in ein Neuronales Netz einspeisen?
Solche Daten wie Sätze nennt man sequentielle Daten. Weitere Beispiele sind:
Allen Beispielen ist gemein, dass es sich um eine Sequenz von Einzeldaten handelt und diese Einzeldaten wiederum eine feste Größe haben: ein Ton, ein Audiosample, ein 2D-Bild. Wir könnten also einem Neuronalen Netz eine Sequenz von Daten nacheinander zuführen. Das erfordert allerdings, dass ein NN sich an die vorigen Elemente erinnert. Unsere bisherigen Netze waren Feedforward-Netze (auch die CNN), weil ein Neuron von Schicht $l$ nur auf ein Neuron in einer höheren Schicht $k$, also mit $k > l$, zeigen konnte. Wir lernen jetzt Netze kennen, wo Verbindungen aus in niedrigere Schichten, also "zurück" zeigen können. Damit ist das Netz kein DAG mehr (directed acyclic graph), da diese Rückwärtsverbindungen Zyklen einführen. Dieser Typ Netz nennt sich Rekurrentes Neuronales Netz oder RNN.
Obwohl RNNs sehr erfolgreich in der Sprachverarbeitung sind, kam mit der Transformer-Architektur 2017 eine tatsächlich noch erfolgreichere Technologie hervor, die ohne rückwärtsgerichtete Verbindungen funktioniert.
Wir wissen jetzt, was sequentielle Daten sind, aber welchen Einsatzzwecke hat das Neuronale Netz? Hier unterscheiden wir die folgenden Typen:
Wir gehen alle Typen durch.
In dem Artikel The magic of LSTM neural networks sind einige der Beispiel schön illustriert.
Many-to-One bedeutet: Eine Sequenz wird eingegeben und eine Kategorie wird ausgegeben. Es handelt sich also um ein typisches Klassifikationsproblem.
Im Bereich Sentiment Analysis geht es um die Aufgabe, einen Text nach seiner Bedeutung bzw. Aussage zu klassifizieren. Im einfachsten Fall ist das eine binäre Klassifikation, z.B. ob eine Filmrezension positiv oder negativ ist wie beim sogenannten IMDB Dataset.
Ganz allgemein beschäftigt man sich bei der Textklassfikation mit der automatischen Kategorisierung von Texten. Zum Beispiel, ob eine e-Mail SPAM oder kein SPAM ist, oder in welche Kategorie eine Supportanfrage gehört, damit die Nachricht automatisch in die richtige Abteilung geleitet wird.
Bei der Speaker recognition/identification geht es darum, anhand eines Audiosignals festzustellen, wer dies gesprochen hat. Jeder mögliche Sprecher ist also eine Kategorie. Die binäre Variante wäre dann Speaker verification/authentication, wo es nur darum geht, ob ein Audiosignal von einem bestimmten Sprecher produziert wurde oder nicht.
Im Bereich Activity recognition geht es darum, aufgrund von Videodaten relevante Aktivitäten zu entdecken. Im Bereich öffentliche Sicherheit können das verdächtige Aktivitäten sein, die auf Gewalt oder Gefahr hindeuten. Im Smart-Home kann das ein Gestenbefehl des Benutzers sein. Oder es geht darum, eine Kollektion von Filmschnipseln mit Aktivitäten zu annotieren, so dass man besser darin suchen kann.
Many-to-Many bedeutet: eine Sequenz wird eingegeben und eine Sequenz wird ausgegeben. Das typische Beispiel ist Machine Translation, wo z.B. ein englischer Satz eingegeben wird und ein deutscher Satz ausgegeben wird. In diesem Fall ist die Länge der Sequenzen unterschiedlich. Sobald die Ausgabe ein Text beliebiger Länge ist, spricht man auch von einem generativem System.
Ein weiteres Beispiel ist Question-Answering, wo eine Frage eingegeben wird und eine Antwort generiert wird. Auch die großen Sprachmodelle GPT-1 bis GPT-4 kann man in diese Kategorie einordnen.
Bei der Named Entity Recognition ist das Ziel, bei jedem Wort eine Aussage darüber zu treffen, ob es sich um einen Eigennamen handelt (z.B. um in einem Text Personen, Geschäfte oder Orte zu identifizieren). Das heißt, die Eingabesequenz ist ein Text und die Ausgabesequenz besteht aus Nullen und Einsen und beide Sequenzen sind gleich lang.
One-to-Many bedeutet: aufgrund einer Eingabe mit fester Größe (z.B. eine Zufallszahl oder eine feste Anzahl von Anfangsnoten) wird eine Sequenz generiert. Dies kommt etwa im Bereich Musik, aber auch zum Generieren von Texten vor. Bei der Musik kann die Eingabe ein Genre sein, entsprechend wird neue Musik in diesem Stil "komponiert". Bei Texten kann es ein Autor wie "Shakespeare" als Eingabe sein und es wird ein entsprechender Text generiert.
Ein weitere Anwendung ist das Image Captioning: Hier ist die Eingabe ein Bild mit fester Größe und die Aufgabe ist, eine möglichst gute Bildbeschreibung (engl. caption) als Text zu generieren.
Wie kann man einen Text variabler Länge, z.B. den Satz "the cat sat on the mat", einem neuronalen Netz zuführen? Der nächste Satz könnte weniger oder mehr Wörter enthalten. Bei einem Netz müssen wir aber entscheiden, wie viele Input-Neuronen es gibt.
Das führt zunächst zu der Frage, wie man ein einzelnes Wort wie "cat" oder "the" repräsentiert. Wir gehen von einem Vokabular $V$ von Strings mit fixer Größe $|V|$ aus, in dem jedes mögliche Wort mit einem eindeutigen Index (Zahl) gelistet ist (man spricht auch manchmal von einem Dictionary).
Die trivialste Möglichkeit ist, jedes Wort mit seinem Index im Vokabular $V$ zu repräsentieren, z.B. 5 für "the", 1 für "cat", 2 für "mat" usw. Dann wäre der Satz "The cat sat on the mat" eine Folge von Zahlen [5, 1, 4, 3, 5, 2].
Die Elemente von $V$ ("cat", "mat"...) nennt man auch Tokens.
Die Größe eines Vokabulars kann für kleine "Spielzeugsysteme" im Bereich 10000 oder 20000 liegen, für echte Systeme ist aber eher im Bereich 100000, 1 Million oder 100 Millionen realistisch.
Da die Größe von $V$ begrenzt ist, enthält $V$ in der Regel ein spezielles Token, das unbekannte Wörter repräsentiert. Dieses wird oft als <UNK> (für unknown) bezeichnet. Je nach Anwendung sind Tokens für Satzzeichen oder für das Satzende <EOS> enthalten, z.B. wenn man das Satzende vorhersagen möchte.
Das Problem mit dieser Repräsentation ist, dass Ähnlichkeit von Wörtern nicht einer numerischen Ähnlichkeit (Distanz bzw. Differenz) entspricht. Das Wort "cat" ist zum Beispiel rein zufällig sehr nah an "mat", obwohl es keine semantische Ähnlichkeit gibt. Wörter wie "dog" oder "tiger" sollten viel näher an "cat" sein. Diese Diskrepanz erschwert einem Neuronalen Netz die Arbeit und wird heutzutage im Bereich NN nicht verwendet.
Außerdem haben wir mit dieser Repräsentation noch nicht das Problem gelöst, einen Satz mit beliebiger Länge in ein Netz mit fixer Anzahl von Input-Neuronen einzuspeisen. Die "naive" Idee, einfach sehr viele Input-Neuronen zu definieren (z.B. 100 Neuronen) und die nicht benutzten Neuronen (bei 5 Wörtern wären das die restlichen 95 Neuronen) mit 0 zu belegen, erweist sich in der Praxis als nicht nutzbar.
Wir können unsere Wörter mit dem bekannten One-Hot-Encoding repräsentieren. Ein Wort $w$ mit Index $i$ wird als Vektor $v = (0, 0, \ldots, 0, 1, 0, \ldots, 0)$ der Länge $|V|$ repräsentiert. Vektor $v$ hat genau eine 1 an der Stelle $i$ und sonst Nullen. Man nennt solche Vektoren auch sparse.
Das Wort "cat" könnte so aussehen - bei einem sehr kleinen Vokabular mit $|V|=5$:
$$\left( \begin{array}{c} 1 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \end{array} \right)$$Schauen wir uns ein Beispiel für dieses kleine Vokabular an:
Wenn wir die Wörter einzeln einem Neuronalen Netz zuführen würden, hätten wir folgende Inputs für den Satz "the cat sat on the mat":
Wenn wir für den ganzen Satz einen einzigen Output generieren möchten - z.B. SPAM oder Nicht-SPAM - dann haben wir hier ein Problem, denn wir generieren ja fünf Outputs. Außerdem ist jeder Output unabhängig von den anderen Outputs, d.h. man kann Zusammenhänge zwischen den Wörtern nicht abbilden.
Wie kodieren wir also einen ganzen Satz als Input für ein Netz mit fixer Eingabegröße? Ein Satz kann schließlich unterschiedlich lang sein.
Ein häufiger Ansatz ist es, einfach alle Wortvektoren zu addieren, so dass man immer einen Summenvektor der Länge $|V|$ erhält. Diese Repräsentation nennt man Bag of Words (ein "Sack voll Wörter"). Im Grunde spiegelt dieser Vektor die Häufigkeitsverteilung aller Wörter, die in dem Satz vorkommen, wider:
$$ \mbox{the cat sat on the mat} \quad\Rightarrow\quad \left( \begin{array}{c} 1 \\ 1 \\ 1 \\ 1 \\ 1 \\ 2 \end{array} \right) $$(Dieser Bag-of-Words-Vektor ist in der Regel auch "sparse", d.h. es gibt z.B. 10000 Stellen, von denen nur einige wenige nicht gleich Null sind.)
Man beachte, dass die Information der Wortreihenfolge (wo steht welches Wort im Satz) verloren geht. Für viele einfache Anwendungen reicht es aber schon aus, nur das Vorkommen bestimmter Wörter zu verarbeiten, unabhängig davon, wie genau diese angeordnet sind. Man denke an SPAM-Detection oder eine einfache Kategorisierung von Textdokumenten. Man kann sich vorstellen, dass hier bestimmte Signalwörter eine größere Rolle spielen als die Reihenfolge (man spricht auch von Keyword Spotting). Umgekehrt gibt es natürlich viele Beispiele, wo die Reihenfolge der Wörter ausschlaggebend für die Bedeutung ist. Typische Beispiel sind Negationen, zum Beispiel "du, nicht ich" versus "nicht du, ich" (beide haben eine identische Bag-of-Words-Repräsentation).
Mittlerweile hat es sich zum Standard entwickelt, sogenannte Word Embeddings zu verwenden, um Wörter zu repräsentieren. Das ist sozusagen eine Zwischenlösung zwischen den beiden Möglichkeiten, die wir bislang betrachtet haben. Statt ein Wort als einzelne Zahl zu repräsentieren oder als One-Hot-Vektor, verwenden wir einen relativ "kurzen" Vektor, wo alle Komponenten (Features) tatsächlich mit Werten belegt sind.
Wir geben eine beliebige Anzahl von Features $m$ vor, z.B. $m=2$, und möchten für jedes Wort eine Repräsenation als Vektor der Länge 2 finden. Die Elemente dieses Feature-Vektors beschränken sich nicht auf 0 und 1, sondern können beliebige Dezimalzahlen sein. Wichtig ist, dass die Länge $m$ der Word-Embedding-Vektoren deutlich geringer ist als die Größe des Vokabulars $|V|$, zum Beispiel $m=30$ bei einem Vokabular von $|V| = 17000$.
Hier ein Beispiel:
Natürlich gilt auch hier das Argument von Option 2: die Bedeutungsnähe von Wörtern sollte eine Entsprechung in der numerischen Nähe der Vektoren haben.
Jetzt werden diese Repräsentation aber gelernt (s.u.) und die Ähnlichkeiten stellen sich tatsächlich im Laufe des Lernens ein. Am Ende des Lernprozesses hat man eine "Tabelle" wie oben, wo man für jedes Wort die 4-dimensionale Kodierung (Einbettung) als Feature-Vektor der Länge $m$ ablesen kann.
Jede Dimension in der Abbildung oben nennt man Feature und man kann sich das als einen semantischen Aspekt des Worts vorstellen, der mit einem Wert zwischen 0 und 1 (oder einer anderen Skalierung) belegt ist. Mögliche Aspekte sind "belebt-unbelebt". Es kann auch eine Formeigenschaft wie "kurz-lang" oder eine Bewegungseigenschaft wie "schnell-langsam" oder ein Persönlichkeitsmerkmal wie "introvertiert-extrovertiert" sein. Da die Embeddings gelernt werden, richtet sich die Repräsentation nach den Daten und dem Ziel der Klassifikationsaufgabe.
Beim Word Embedding unterscheidet man also zwischen Größe des Vokabulars $|V|$ und der Anzahl der Features $m$. In realen Anwendungen ist die Größe des Vokabulars z.B. 100000 und die Anzahl der Features im Bereich 100 oder 30.
Bengio et al. (2003) haben eine Methode vorgestellt, um Wort-Feature-Vektoren zu lernen. Man spricht auch von Neuronalen Sprachmodellen (Neural Language Model). Die Grundidee ist es, ein Zwei-Schichten-Netz auf die Aufgabe zu trainieren, das jeweils nächste Wort in einem Satz vorherzusagen auf Basis der letzten $n$ Wörter, wobei $n$ fix ist und z.B. 2 oder 3 beträgt.
Zur Erklärung der Aufgabe: Bei dem Satz
the cat sat on the mat
möchte man also, dass das Modell folgende Vorhersagen macht:
the cat -> sat
cat sat -> on
sat on -> the
on the -> mat
Im Beispiel haben wir $n=2$ angenommen. Dieses Problem löst man normalerweise mit Hilfe von Statistik, indem man einfach die Häufigkeit von Wortfolgen zählt und damit die bedingte Wahrscheinlichkeit $P(w_3 | w_1, w_2)$ schätzt.
Wir sehen diese Aufgabe aber nur als Mittel zum Zweck. Der Einfachheit halber reduzieren wir das Problem auf die Vorhersage des nächsten Worts auf Basis des vorangegangenen Worts, also für $n=1$. Jetzt betrachten wir ein Netz, das als erste Schicht ein Mapping von One-Hot-Vektoren (Länge $|V|$) auf einen Feature-Vektor, der die Länge $m$ hat. Beispielhafte Werte sind $|V| = 17000$ und $m=30$ (aus Bengio et al., 2003).
Das Mapping von One-Hot-Vektor zu Feature-Vektor kann man mit einer Matrix $E$ der Größe $m \times |V|$ darstellen. Bei Eingabe eines Worts $x_o$ in One-Hot-Enkodierung berechnet man durch Matrizenmultiplikation den Feature-Vektor $x_f$:
$$ x_f = E \, x_o $$Wir können uns jetzt ein Netz konstruieren mit $|V|$ Eingabeneuronen und $m$ Neuronen in der zweiten Schicht. Die dritte Schicht würde das nächste Wort vorhersagen, muss also $|V|$ Ausgabeneuronen mit Softmax-Aktivierung haben.
Man kann sich die Netzarchitektur so vorstellen:
Es zeigt sich, dass sich durch das Trainieren eines solchen Netzes sehr gute Embeddings in der Matrix $E$ ergeben. Nachteil ist die hohe Anzahl der Parameter.
Interessant an dem Ansatz ist auch, dass es bei dem beschriebenen Netz nicht um die eigentliche Aufgabe (nächstes Wort vorhersagen) geht, sondern um die Matrix $E$ als Word Embedding. Die Aufgabe der Wortvorhersage lässt sich mit anderen Mechanismen tatsächlich besser lösen.
Einem aktuelleren Ansatz namens Word2Vec (Mikolov et al. 2013), entwickelt von Google, liegt die Idee zugrunde, dass nicht aufeinander folgende Wörter betrachtet werden, sondern beliebige Wörter. In einem Satz wird also ein Wort zufällig herausgepickt, welches vorhergesagt werden soll (Target), und ein weiteres zufälliges Wort (oder mehrere) in dem Satz wird als "Hinweis" ausgewählt (Kontext). Dieses Verfahren ist nochmal effizienter als das von Bengio et al.
Wir haben hier die beiden Verfahren der Neuronalen Sprachmodelle und Word2Vec natürlich nur sehr grob skizziert. Wichtig ist, dass eine Embedding-Schicht eine One-Hot-Repräsentation eines Worts (z.B. ein Vektor der Länge 10000 bei einem Vokabular von 10000 Wörtern) in einen wesentlich kompakteren Feature-Vektor, z.B. mit Länge 32, umwandelt.
Bengio, Yoshua; Ducharme, Réjean; Vincent, Pascal & Janvin, Christian (2003) A Neural Probabilistic Language Model. In: Journal of Machine Learning Research, 3, pp. 1137–1155.
Cho, Kyunghyun; van Merriënboer, Bart; Bahdanau, Dzmitry; Bengio, Yoshua (2014) On the Properties of Neural Machine Translation: Encoder–Decoder Approaches. In: Proceedings of SSST-8, Eighth Workshop on Syntax, Semantics and Structure in Statistical Translation, pp. 103–111.
Joulin, Armand; Grave, Edouard; Bojanowski, Piotr; Mikolov, Tomas (2017) Bag of Tricks for Efficient Text Classification. In: Proceedings of the 15th Conference of the European Chapter of the Association for Computational Linguistics. arXiv