Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

ws1819:phasmid

Dies ist eine alte Version des Dokuments!


Phasmid - Der Prestige-Textgenerierungs Bot für Akademiker und Singles mit Niveau

Arda, Paul und Lucas

„America, A plague in England's shame. Poor greatness, save our nightingale! Romeo, forgive me into myself, So thou no more but furnight, English peace.“ -Phasmid

Idee:

Die Idee ist das Erstellen einer Selbstlernenden Künstlichen Intelligenz, welche gegebenes Textverhalten imitieren und selber Texte/Nachrichten verfassen kann. Hierfür muss eine Textquelle analysiert und ausgewertet werden können, Muster der Sprache erkannt und erlernt werden, sowie diese Anwendung im „unterrichten“ der KI finden.

Erstplanung:

Schritte:

  • Datenbeschaffung (Twitch-Chatlogs, Nachrichtentexte, Whatsapp, Discord, …)
  • Datenverarbeitung (Auslesen der nützlichen Daten und Sortierung der Selbigen)
  • Datenanalyse
  • Einarbeiten und Verstehen von Grundprinzipien des Machine Learnings
  • KI Grundstruktur
  • Trainieren der KI
  • Implementierung als Chatbot (Discord, Twitch, etc.)

Umsetzung

Die Umsetzung des Projektes stellte sich als deutlich weniger geradlinig heraus, als Anfangs angenommen. Hierfür waren mehrere Faktoren verantwortlich. Einerseits ist der Umfang des Bereichs des Maschinellen Lernens, für welchen wir uns entschieden hatten, ein sehr großer, in welchen der Einstieg schwer fällt. Dies liegt unter Anderem daran, dass sich die Konzepte auf komplexe stochastische Modelle zurückführen lassen, deren Anwendung das Programm durchführt (Wie das funktioniert, versuchen wir später genauer zu erklären). Außerdem stellten sich mehrere unserer Ansätze als mehr oder minder ungeeignet heraus, sodass große Teile der Arbeit der ersten Wochen für sich genommen zwar funktionierten, in das fertige Projekt jedoch kaum einflossen. Auch unsere erste Idee einen „Chatbot“ zu erstellen, haben wir nur teilweise zum Ende geführt. Zwar kann unser Programm wunderbare Texte generieren und nach Trainingsstil zwischen Donald Trump und Shakespeare variieren, es kann jedoch (noch) nicht in Echtzeit auf andere Nachrichten reagieren etc.

Wie funktioniert überhaupt "Maschinelles Lernen"?

Für das Verständnis des Projektes und des Projektcodes ist es wichtig einen kleinen Einblick in Maschinelles Lernen (ML) zu erhalten, welchen wir versuchen in aller Kürze hier zu vermitteln. Wie bereits erwähnt ist das Konzept des Maschinellen Lernens ein durchaus komplexes und nicht unbedingt intuitives, trotzdem wird es auch in den letzten Monaten und Jahren immer mehr zu einer Art Modewort innerhalb der Medien.

Lernende Computer? Ist die Terminator-Apokalypse nahe?

Keine Sorge so ist es (noch) nicht. Klar sollte erstmal werden, dass ein Computer nicht in derselben Weise lernen kann, wie es ein Mensch tut, weswegen man eventuell direkt den Term „Lernen“ als abstraktere Umschreibung sehen sollte. Vielmehr beschreibt dies die Fähigkeit eines Programmes gewisse Strukturen in Daten zu erkennen und anhand dieser stochastische Vorhersagen zu treffen. Die Genauigkeit dieser Vorhersagen wird meistens als Qualitätsmaß eines Machine Learning Programms gesehen. Anwendung findet diese Idee der Programmierung in immer vielfältigeren Bereichen, weswegen der „Medien-Hype“ vermutlich sogar gerechtfertigt ist, da so teilweise Lösungen zu Problemen gefunden werden können, bei denen wir überhaupt nicht wüssten, wie man eine explizite Aufgabenstellung an ein Programm stellen könnte. (Paradebeispiel hierfür ist die menschliche Sprache, da wir diese zwar verstehen und immer wieder benutzen, jedoch kaum Möglichkeiten haben dieses Konzept mit etwas Anderem als Sprache zu beschreiben.) Dies war ausschlaggebend, warum wir uns entschieden haben mit Machine Learning zu arbeiten.

Doch was macht ein Computer wenn er "lernt"?

Die meisten Machine Learning Programme basieren auf sog. Neuronalen Netzwerken, auch dieses wieder eine abstrakte Umschreibung entsprungen aus den Anfängen des maschinellen Lernens. Die Grundidee damals war, das menschliche Gehirn zu imitieren mithilfe von Verknüpfungen, welche denen in unserem Gehirn ähneln sollten. Anschaulich ist dieses Bild tatsächlich immer noch bis zu einem gewissen Level anwendbar.

Das Prinzip funktioniert folgendermaßen: Das neuronale Netz erhält einen Input. Dieses sind meistens vektorisierte Daten, das heißt die Ursprungsinformationen werden in Vektoren oder Matrizen bestehend aus Zahlen verpackt, damit diese verwendbar für das Programm werden. Dieser Input kann aus beliebig vielen „Features“ bestehen, welche dann das Format des Eingangs bestimmen, jedes Feature wird sozusagen ein Neuron. Diese werden mit der nächsten Schicht aus Neuronen verknüpft, sodass jeder Eingang mit jedem Neuron verbunden ist. Die Anzahl der Neuronen ist hier arbiträr und kann größer oder kleiner gemacht werden, abhängig beispielsweise davon, wie komplex das Problem, welches man untersuchen will, ist. Nun rät zu Beginn das Programm eine gewisse Abhängigkeit, zwischen der Input und der nächsten Schicht und übergibt davon abhängig einen Wert an jedes einzelne Neuron. Heruntergebrochen könnte man sagen, verschiedene Neuronen werden aufgrund dieser (zu Beginn geratenen) Abhängigkeiten aktiviert oder deaktiviert. Nun könnte man noch noch beliebig viele dieser Schichten übereinander stapeln (Wieder um die Komplexität der Erfassung des Programms zu erhöhen), der Einfachheit halber bleiben wir aber für die Erklärung bei nur einer sog. Hidden Layer. Nun werden erneut Verknüpfungen von der Hidden Layer zu unserem Output erzeugt, welcher dann wieder aufgrund (zu Anfangs geratener) Gewichtungen in gewisser Weise angesteuert wird und anhand dessen eine Vorhersage trifft. Und erst jetzt beginnt das eigentliche Lernen: Die Vorhersage wird mit dem erwarteten Output verglichen. So könnten wir zum Beispiel ein Programm zur Erkennung von Handschrift geschrieben haben und ein geschriebenes „a“ übergeben haben, jedoch die Vorhersage: „z“ erhalten (alles natürlich dann im vektorisierten Format). Offensichtlich ist unser Programm noch nicht perfekt, es hat aber ja auch noch nicht gelernt. Der Weg wie wir nun die Vorhersagen für die Zukunft verbessern können ist, dass wir basierend auf dem Unterschied zwischen Vorhersage und erwartetem Output alle Gewichtungen innerhalb des Netzwerkes minimal verändern und anschließend das Programm erneut, aber mit diesen Gewichtungen und anderen Trainingsdaten, laufen lassen. Nach vielen Iterationen verbessert sich das Modell und die Gewichtungen der einzelnen Neuronen stellen bestenfalls eine erkannte Struktur dar, welche sichere Vorhersagen treffen kann. Wichtig ist: Dies war nur eine kurze und vage Zusammenfassung. In Wirklichkeit haben die meisten Netze mehrere Millionen solcher Neuronen oder Knoten und benötigen sehr viele Iterationen zum Lernen, weswegen das Ausführen der Programme teils Stunden in Anspruch nehmen kann.

Wer noch genauer verstehen möchte, wie diese Netze funktionieren und wie beispielsweise die Gewichtungen berechnet werden oder welche Probleme beim Lernen auftreten können, sei auf den Eintrag (…) verwiesen.

Das fertige Projekt

Doch nun endlich zum konkreten Projekt. Für unser Programm haben wir uns für ein GRU (Gated Recurrent Unit) Model entschieden. Dieses ist besonders nützlich für Daten, die mit Text zusammenhängen, da das GRU ein gewisses Gedächtnis besitzt und somit Umgebungen von beispielsweise Wörtern oder Buchstaben erkennen kann. Dies funktioniert indem der Output eines Zeitschrittes sowohl ausgegeben wird, als auch an den nächsten Zeitschritt weitergegeben werden kann. In unserem Model versuchen wir anhand von Buchstaben und deren Umgebung nachfolgende Buchstaben vorherzusagen und somit die Semantik und teilweise die Bedeutung des Ursprungstextes zu erfassen und diese in einem frisch generierten Text zu imitieren. Für den Input benötigen wir zuerst einen Ursprungstext, auf dessen Basis wir unser Model trainieren können. Wichtig für jegliche Form von maschinellem Lernen sind große Datenmengen, weswegen die einzige Bedingung an den Text eine nicht allzu geringe Zeichenmenge ist. Für das Testen des Modells haben wir beispielsweise die gesammelten Werke von Shakespeare oder einige Speeches von Donald Trump verwendet.

Um jedoch die Daten verarbeiten zu können teilen wir zuerst den Text in Sequenzen ein (z.B. 100 Zeichen lang). Die Trainingsdaten werden dann diese 100 Zeichen sein und der erwartete Output sind die gleichen Zeichen jedoch um ein Zeichen verschoben. Somit hat jedes Zeichen das Ziel, das darauf folgende Zeichen vorherzusagen. Um die Zeichen in unser Modell speisen zu können benötigen wir zuerst eine eindeutige vektorisierte Darstellung für jedes Zeichen, weswegen wir jedem individuellen Zeichen eine Zahl zwischen 0 und „Anzahl der unterschiedlichen Zeichen - 1“ zuweisen und anschließend unsere einzelnen Sequenzen in ein Array aus Zahlen umwandeln. Der erste Teil unseres Modells ist dann ein sog. Embedding. Dieses soll eine verbesserte vektorisierte Darstellung unser Eingabe erlernen und weitergeben, welche nicht nur die zugewiesene Zahl zu jedem Zeichen versteht sondern anhand der Umgebung der Zeichen eine verbesserte Darstellung der Sequenzen innerhalb unseres Modells erstellt. Die Ausgabe unseres Embeddings wird nun in das oben angesprochene GRU gegeben. Im obigen Bild zur GRU ist also, die Eingabe \(x_t\) (t = 0, 1, …, Länge der Sequenz) das t-te Zeichen der Sequenz und versucht das (t+1)-te Glied vorherzusagen (als Output \(o_x\)) und dies für alle Glieder der Sequenz. Ermittelt wird der Output anhand des Inputs von außen und dem Output des vorherigen GRUs, mithilfe einer Vergessens- und einer Updatefunktion. Die Vergessensfunktion sorgt dafür, dass alte Information von früheren Zeitschritten nicht zu stark gewichtet wird, wohingegen die Updatefunktion für das implementieren des neuen Inputs sorgt. Diese sind mathematisch wie folgt beschrieben: \[ \text{Update: } z_t = \sigma (W^{(z)}x_t+U^{(z)}h_{t-1}), \quad \text{Vergessen: } r_t = \sigma (W^{(r)}x_t+U^{(r)}h_{t-1}) \] wobei \(W\) für die Gewichtung des Inputs \( x_t \) steht und \(U\) für die Gewichtung des Inputs des vorherigen GRU Gates \( h_{t-1} \). Die \(\sigma\)-Funktion, sorgt hierbei dafür, dass das Ergebnis in einem einheitlichen Bereich liegt (zwischen 0 und 1). Hieraus wird dann die Ausgabe erzeugt, welche außerdem an die nächste GRU Zelle weitergegeben wird. Aus allen GRU Ausgaben erhalten wir dann mithilfe einer letzten Layer unsere endgültige Vorhersage als Vektor. Nachdem man dieses Modell dann lange genug trainiert hat und somit die Gewichtungen optimiert, können wir hiermit die Generierung eines Textes vornehmen. Hierbei beginnen wir mit einem sog. Seed, also einem Start-Text, auf welchem wir dann den Text aufbauen. Dieser wird dem Modell übergeben, welches hierauf basierend eine Ausgabe für den nächsten Buchstaben vorhersagt. Diese Vorhersage wird dann für den nächsten Buchstaben wieder dem Modell übergeben und dies wiederholen wir so oft, wie unsere Ausgabe lang sein soll.

Fazit

Prozessschnipsel

komplette Twitch-Chatlogs unter: https://overrustlelogs.net

Protokoll

29.11.2018

Wir haben zu Allererst ein Programm verfasst, mit welchem wir, via Web-Scraping, Chatlogs verschiedenster Streamer herunterladen können und somit benutzen. Schwierigkeiten traten primär auf beim formatieren des Programms und Kennenlernen des Pakets „BeautifulSoup4“. Zum Ende hin hat dies aber funktioniert und der nächste Schritt wird sein, diese Daten ordentlich zu sortieren und speichern zu können.

06.12.2018

Zum Beginn dieser Woche haben wir uns zuerst kurz theoretisch mit dem Thema der Text Analyse befasst, mit welchem sich Lucas auf Basis des Buches „Applied Text Analysis with Python“ weiter befassen wird. Außerdem haben wir einen Termin für ein gemeinsames Lernen über Machine Learning vereinbart. Ansonsten haben Arda und Paul an einer Datenstruktur für die vorher gescrapten Daten gearbeitet und einem Weg diese abzuspeichern und effektiv benutzbar zu machen. Dies ist uns zum Ende hin mit dem Paket „pickles“ gelungen, welches eine Liste mit allen Chatlogs eines Streamers über den gesamten auf der Webseite hochgeladenen Zeitraum erstellt. Ziel für die nächste Woche ist nun, mit der Textverarbeitung zu beginnen und auch die Textanalyse zu planen und gestalten.

13.12.2018

Diese Woche haben wir uns das erste mal mit Stefan getroffen um die Grundlagen des Machine Learning zu lernen um Sie später in unserem Projekt einzubauen. Zudem haben wir zuhause und zum beginn des Donnerstags die komplette Textverarbeitung fertiggestellt und in Log Dateien gepickeled. Während Lucas sich weiter mit „Applied Text Analysis with Python“ beschäftigt hat und sich über das Konzept des „bag-of-word“ aufgeklärt hat. Haben Paul und Arda den Text bereinigt von allen Sonderzeichen etc. und diese gespeichert. Einen absoluten Wortzähler eingebaut (wie häufig ist jedes wort). Danach hat Paul sich mit n grammen auseinandergesetzt. Wir haben zum schluss trigramme von seagulls chat erstellt und deren häufigkeit ausgegeben. Wobei das häufigste trigramm „seagH seagH seagH“ 105409 mal vorkam. Jedoch hat das unpickle unserer Daten relativ lange gebraucht.

20.12.2018

Nach der letzten Woche hat Paul direkt begonnen die Datenstruktur zu verbessern indem er nur noch die Nachrichten selber ohne die Timestamps und Nutzernamen speichert. Dies hat die Geschwindigkeit des Erstellens von Trigrammen und anderen Anwendungen drastisch verbessert. Danach hat Paul zudem ein Text-Generator mittels des Trigram Modells erstellt welcher zwar größtenteils Semantiklose jedoch bereits ganze Sätze ausgibt. Am Dienstag trafen wir uns zum zweiten mal für das Maschinelle Lernen und lernten diesmal Regression, Regularisierung und Klassifikation. Zudem führte uns Stefan verschiedene Modelle des Machine Lerning vor, wie das „Dropout Regularisierung Modell“ und „convolutional layers“ welche jedoch zu kompliziert sind um diese hier zu erklären. Wir haben noch die Chatlogs von Nightblue3 heruntergeladen und uns den Rest des Donnerstags mit word2vec beschäftigt. Dafür mussten wir zunächst ein Programm schreiben welches unsere existierenden Chatlogs in ein anderes Dateiformat wandelt, wie auch später erklärt. Word2Vec ist teil von gensim (ein Machine Learning Algorithmus) und wurde von Google entwickelt. Das Programm schaut sich an welche Wörter im gleichen Kontext benutzt werden. Dafür benötigt man eine Liste von Sätzen wo die Sätze als Liste von Wörtern dargestellt werden (daher auch das umwandeln unserer bereits existierenden Liste von Sätzen, wo ein Satz ein String ist, in die richtige Struktur.). Zurückgegeben wird ein Modell welches die Beziehungen der Wörter untereinander darstellen kann und auch die Darstellung mittels Vektoren zwischen Wörtern zurückgeben kann. Dieses konnten wir vollständig ausführen und planen nun nach den Ferien uns vollständig mit Machine Learning zu beschäftigen.

10.01.2019

In dieser Woche haben wir mit Stefan bei dem Machine Learning Treffen das erste mal ein Neuronales Netz gebaut und gelernt wie wir es trainieren. Deshalb haben wir heute angefangen unser Neuronales Netz zu planen. Insgesamt soll unser Neuronales Netz eine bestimmte Menge an buchstaben (zunächst 50), die den Anfang einer Nachricht bilden, übergeben bekommen und den darauf folgenden Buchstaben generieren. Dafür teilen wir zunächst unsere Nachrichten in einen Trainings-(X) sowie einen Testteil(Y) auf. Hierbei wird die Menge der X-Daten für das Trainieren des Netzwerkes diesem übergeben und die Y-Daten werden benutzt um die Vorhersagen des Modells zu testen und zu validieren. Die gesamte Umwandlung der Nachrichten in den X und Y Teil haben wir heute geschafft. Zudem hat Lucas angefangen unsere Dateien zu sortieren und hat dafür eine neue Unterstruktur innerhalb unseres Git-Verzeichnis erschaffen.

17.01.2019

Seit des letzten Eintrags hat Paul bei sich zuhause bereits unser erstes Neuronales Netz erseltt und es an einem viertel der verfügbaren Trainingsdaten trainiert. Jedoch spuckt dieses nach Programmieren eines Programms welches das Netzt anwendet nur Ausgaben wie „h o o o o o o o o o o o“ aus. Deshalb hat Paul den Rest der Zeit heute genutzt um das Neuronale Netz zu verbessern. Lucas hat heute weiter versucht den mastercleaned branch (der aufgeräumte Teil unseres Git-Verzeichnisses) aufzubauen, wobei mehrere Probleme aufgetaucht sind, wie beispielsweise Programme aus anderen Verzeichnisses zu importieren und zu verwenden, wobei alle Lösungen hierfür entweder aufwendig oder unsauber erscheinen. Zum Beispiel könnte man mit Verknüpfungen arbeiten oder oder gewisse Dateien vervielfältigen. Sicher ist jedoch, dass man für viele dieser Lösungen die Programme umschreiben müsste, was einige Geduld braucht.

24.01.2019

Diesen Dienstag haben wir mit Stefan das „Rekurente Neuronale Netzwerk“ (RNN) kennengelernt und wie man es umsetzt. Dies ist eine spezielle Art eines neuronalen Netzwerkes, welches lose gesprochen ein „Gedächtnis“ besitzt und somit besonders gut zeitliche Zusammenhänge in beispielsweise Sprache erfassen und Lernen kann. Dazu haben wir zudem eine Hausaufgabe bekommen, welche die Effizienz dieser RNNs zeigen soll. Ferner hat sich Lucas am Donnerstag mit der Organisation der Datenstruktur beschäftigt und diese zum größten Teil fertig gestellt bekommen. Außerdem haben wir die Hausaufgabe bearbeitet, welche uns auch für unser Projekt helfen kann und soll. Hierfür mussten wir zuerst Daten für einen Benchmark generieren und diese dann im Anschluss mithilfe eines Machine Learning Algorithmus testen, welcher ein besonderes Muster innerhalb der Daten erkennen und erlernen soll. Leider war die Umsetzung bisher noch nicht so erfolgreich und es wird noch einiges Fine-Tuning benötigt um ein erfolgreiches Ergebnis zu erzielen.

ws1819/phasmid.1551802168.txt.gz · Zuletzt geändert: 2019/03/05 17:09 von erchinger