Skip to content
Snippets Groups Projects
Commit 1fe6473a authored by Silas Dohm's avatar Silas Dohm
Browse files

spelling

parent 6098f658
Branches
No related tags found
No related merge requests found
\subsection{Analyse des Datensatzes}
Ein wichtiger Schritt in jeder Aufgabe im Bereich des maschinellen Lernens ist es die Datenbasis zu analysieren und zu verstehen.
Ein wichtiger Schritt in jeder Aufgabe im Bereich des maschinellen Lernens ist es, die Datenbasis zu analysieren und zu verstehen.
Der Yelp-Datensatz besteht aus einer Ansammlung von json Dateien. Darunter jeweils eine Datei für businesses, reviews, user, checkins, sowie tips - quasi short-reviews - und photos, welche als Cross-Referenz für andere Datensätze fungiert. Für dieses Projekt interessiert jedoch nur die review Datei.
Der Yelp-Datensatz besteht aus einer Ansammlung von json Dateien.
Darunter befindet sich jeweils eine Datei für
businesses, reviews, user, checkins, sowie tips - quasi short-reviews - und photos,
welche als Cross-Referenz für andere Datensätze fungiert.
für dieses Projekt ist jedoch nur die review Datei interessant.
Die Yelp-Reviews befinden sich in einer 6GB großen json Datei. Diese Datei könnte mit einem leistungsstarken Computer vollständig in den Arbeitsspeicher geladen werden. Jedoch wird im Rahmen
Die Yelp-Reviews befinden sich in einer 6\,GB großen json Datei. Diese Datei könnte mit einem leistungsstarken Computer vollständig in den Arbeitsspeicher geladen werden. Jedoch wird im Rahmen
dieser Arbeit die Datei zeilenweise verarbeitet.
Das zeilenweise Verarbeiten der Datei ermöglicht es, die Systemanforderungen
......@@ -26,7 +30,7 @@ In Zeile 0 wird der Pfad des Datensatzes definiert.
Danach wird in Zeile 2 mit einer for-Schleife über jede Zeile des Datensatzes iteriert,
wobei die Funktion \lstinline{open} die Datei öffnet und ein iterierbares Objekt zurück liefert.
Durch das Benutzen der Funktion \lstinline{enumerate} erhalten wir den
Durch das Benutzen der Funktion \lstinline{enumerate} erhält man den
aktuellen Index, sodass in der Variable \lstinline{index} die aktuelle
Zeilennummer gespeichert ist und in der Variable \lstinline{line} die aktuelle Zeile selbst.
......@@ -34,7 +38,7 @@ Die if-Abfrage in Zeile 3 sorgt dafür, dass die for-Schleife vorzeitig abgebroc
In Zeile 5 wird der Text der aktuellen Zeile ausgegeben.
Das Ausführen des Quellcodes im Listing \ref{list:four} führt zu folgender Ausgabe:
Das Ausführen des Quellcodes in Listing \ref{list:four} führt zu folgender Ausgabe:
\begin{lstlisting}[numbers=none]
{"review_id":"xQY8N_XvtGbearJ5X4QryQ",
"user_id":"OwjRMXRC0KyPrIlcjaXeFQ",
......@@ -57,7 +61,9 @@ Das Ausführen des Quellcodes im Listing \ref{list:four} führt zu folgender Aus
\end{lstlisting}
Hier ist zu erkennen, dass jede Zeile der review.json eine Rezension mit den Merkmalen \lstinline{review_id, user_id, business_id, stars, useful, funny, cool, text und date} enthält. Die meisten dieser Merkmale sind selbsterklärend. Erwähnenswert sind dabei jedoch die Merkmale \lstinline{useful, funny} und \lstinline{cool}, welche Reaktionen anderer Nutzer auf diese Review darstellen. Für dieses Projekt sind hingegen nur die beiden Punkte \lstinline{stars} und \lstinline{text} von Bedeutung.
Hier ist zu erkennen, dass jede Zeile der review.json eine Rezension mit den
Merkmalen \lstinline{review_id, user_id, business_id, stars, useful, funny, cool, text} und
\lstinline{date} enthält. Die meisten dieser Merkmale sind selbsterklärend. Erwähnenswert sind dabei jedoch die Merkmale \lstinline{useful, funny} und \lstinline{cool}, welche Reaktionen anderer Nutzer auf diese Review darstellen. Für dieses Projekt sind hingegen nur die beiden Punkte \lstinline{stars} und \lstinline{text} von Bedeutung.
In diesem Datensatz sind Sonderzeichen mit einem Backslash escaped.
\subsubsection{Anzahl der Reviews}
......@@ -71,7 +77,7 @@ for line in open(data_path,encoding="utf8"):
print (nr_of_reviews))
\end{lstlisting}
Das Programm liefert \lstinline{8021122} zurück.
Das Programm liefert die Anzahl \lstinline{8021122} zurück.
\subsubsection{Reviewlänge}\label{subsubsec:reviewlength}
\begin{lstlisting}[inputencoding=latin1,caption={Programm zur Ermittlung der Reviewlänge},label={list:rev_len}]
......
......@@ -4,8 +4,7 @@ Für das Trainieren des Word2Vec-Modells
wird in dieser Arbeit die Open-Source-Library Gensim verwendet.
Gensim bietet viele hilfreiche Funktionen und die Möglichkeit, Generatoren zu verwenden.
Um bei Gensim Generatoren benutzen zu können schreiben wir die Klasse \lstinline{MyCorpus}.
Um bei Gensim Generatoren benutzen zu können wird die Klasse \lstinline{MyCorpus} geschrieben.
\begin{lstlisting}[caption={Generator für Gensim},label={list:Corpus}]
from gensim import utils
import json
......@@ -56,6 +55,6 @@ Die Funktion erwartet den Pfad zum Word2Vec-Modell als ersten Parameter.
Der zweite Parameter ist der Datensatzpfad und wird nur benötigt, falls noch
kein Word2Vec-Modell gespeichert wurde.
Zuerst wird in Zeile 12 geprüft, ob bereits ein Word2Vec-Modell existiert, ist dies der
Fall wird dieses direkt zurückgegeben, gibt es kein Modell, so wird dieses im inneren try-Block
Zuerst wird in Zeile 12 geprüft, ob bereits ein Word2Vec-Modell existiert. Ist dies der
Fall, wird dieses direkt zurückgegeben, gibt es kein Modell, so wird dieses im inneren try-Block
mithilfe der \lstinline{myCorpus} Klasse generiert, gespeichert und zurückgeben.
\ No newline at end of file
......@@ -52,10 +52,10 @@ Dieses Numpy-Array speichert die ersten 72 Wortvektoren der Rezension,
die Zahl 72 wurde aufgrund des im Kapitel \ref{subsubsec:reviewlength} berechneten
Median der Reviewlänge gewählt.
Die for-Schleife in Zeile 11 durchläuft alle Wörter der Liste split und fügt diese,
Die for-Schleife in Zeile 11 durchläuft alle Wörter der Liste \lstinline{split} und fügt diese,
falls sie im word2Vec-Modell vertreten sind, in das \lstinline{wordVecs} Array ein.
Sind mehr als 72 Wörter in der Liste \lstinline{Split} wird die Schleife abgebrochen,
Sind mehr als 72 Wörter in der Liste \lstinline{split} wird die Schleife abgebrochen,
wenn das Array vollständig gefüllt ist.
Sollten sich weniger als 72 Wörter in der Liste befinden,
......@@ -66,9 +66,9 @@ ist notwendig,
da das CNN eine feste Dimension der Eingangsdaten benötigt.
Anschließend wird in Zeile 18 geprüft, ob weniger als 5 Wortvektoren in dem Array
stehen, ist dies der Fall, wird eine Exception geworfen.
stehen. Ist dies der Fall, wird eine Exception geworfen.
Nach dem implementieren der Funktion \lstinline{getSentenceVectorCNN} muss das CNN erstellt werden.
Nach dem Implementieren der Funktion \lstinline{getSentenceVectorCNN} muss das CNN erstellt werden.
\begin{lstlisting}[caption={CNN},label={list:modelCNN}]
import numpy as np
from tensorflow.keras.models import Sequential
......@@ -101,14 +101,14 @@ Die \noteable{MaxPooling1D-Schichten} dienen dazu die Informationen nach den
Faltungen zu verdichten.
Die Matrix, die als Ergebnis der zweiten \noteable{MaxPooling1D-Schicht} entsteht,
wird anschließend in Zeile 12 in einen Vektor umgewandelt,
dieser Vektor wird als Eingang des dichten neuronalen Netzes benutzt.
wird anschließend in Zeile 12 in einen Vektor umgewandelt.
Dieser Vektor wird als Eingang des dichten neuronalen Netzes benutzt.
Für das dichte neuronale Netz wird hier wieder der Ansatz verfolgt,
die Schichten inkrementell zu verkleinern, um eine Verdichtung der
Information zu erzwingen.
Zuletzt muss das neuronale Netz noch kompiliert werden, dies geschieht in
Zeile 18. Hierbei wird wie gehabt der optimizer \lstinline{adam} gewählt und die
Zuletzt muss das neuronale Netz noch kompiliert werden, was in Zeile 18
geschieht. Hierbei wird wie gehabt der optimizer \lstinline{adam} gewählt und die
Fehlerfunktion \lstinline[literate={\_}{}{0\discretionary{\_}{}{\_}}]{sparse_categorical_crossentropy} sowie die Metrik
\lstinline{sparse_categorical_accuracy} verwendet.
......@@ -165,8 +165,8 @@ modelNN.evaluate(testData)
\end{lstlisting}
Hierfür wird die Größe der Trainingsmenge durch die BatchSize geteilt (Zeile 24).
Um ein Overfitting zu verhindern, wird, wie beim Mean-Modell auch schon in
Zeile 25 ein Earlystop definiert.
Um ein Overfitting zu verhindern wird, wie beim Mean-Modell auch schon in
Zeile 25, ein Earlystop definiert.
Dieser unterbricht das Training vorzeitig, falls acht Epochen lang keine
Verbesserung auf der Validierungsmenge erzielt wird.
......@@ -186,7 +186,7 @@ Dafür wird in Zeile 34 zunächst wieder ein Generator angelegt. Mit dem
Parameter \lstinline{loop=False} wird gewährleistet, dass der Generator den Datensatz nur
einmal durchläuft. Dieser Generator kann nun in
Zeile 35 an die Methode \lstinline{evaluate} übergeben werden.
Das Evaluieren zeigt, dass dieses Modell zu $81.44\%$ die Klassen der Testmenge richtig klassifiziert.
Das Evaluieren zeigt, dass dieses Modell zu $81.44\,\%$ die Klassen der Testmenge richtig klassifiziert.
\begin{lstlisting}[caption={CNN - Klassengewichte},label={list:modelCNNWeights},numbers=none]
Y_train=[]
......@@ -233,13 +233,13 @@ zurückliefert.
\label{tab:conf_w_cnn}
\end{table}
Aus der Tabelle \ref{tab:conf_w_cnn} lässt sich ablesen, dass negative Bewertungen zu $83.14\%$ richtig als
negative Bewertung klassifiziert werden, zu $13.77\%$ als neutrale Bewertung und zu $3.08\%$
Aus der Tabelle \ref{tab:conf_w_cnn} lässt sich ablesen, dass negative Bewertungen zu $83.14\,\%$ richtig als
negative Bewertung klassifiziert werden, zu $13.77\,\%$ als neutrale Bewertung und zu $3.08\,\%$
als positive Bewertung.
Neutrale Bewertungen werden zu $63.54\%$ richtig als neutrale Bewertung klassifiziert, zu $19.70\%$
als positive Bewertung und zu $16.76\%$ als negative Bewertung.
Neutrale Bewertungen werden zu $63.54\,\%$ richtig als neutrale Bewertung klassifiziert, zu $19.70\,\%$
als positive Bewertung und zu $16.76\,\%$ als negative Bewertung.
Positive Bewertungen werden zu $83.67\%$ richtig
als positive Bewertung klassifiziert, zu $13.16\%$ als neutrale Bewertung und zu $3.16\%$
Positive Bewertungen werden zu $83.67\,\%$ richtig
als positive Bewertung klassifiziert, zu $13.16\,\%$ als neutrale Bewertung und zu $3.16\,\%$
als negative Bewertung.
\ No newline at end of file
......@@ -8,8 +8,8 @@ Es ist somit naheliegend, dass Wörter, die mit einer negativen Rezension assozi
werden, ein anderes Gebiet des Vektorraumes belegen als jene, die mit positiven Rezensionen
assoziiert werden.
Der Gedanke für dieses Modell ist es, den Mittelwert aller Wortvektoren in
einer Rezension zu ermitteln und somit eine Art Satzvektor zu erhalten. Diese Satzvektoren
Der Gedanke dieses Modell ist es, den Mittelwert aller Wortvektoren in
einer Rezension zu ermitteln und somit eine Art \textit{Satzvektor} zu erhalten. Diese Satzvektoren
werden als Eingangswerte genutzt, um mithilfe eines neuronalen Netzes eine
Klassifikation der Rezensionen durchzuführen.
......@@ -19,11 +19,12 @@ Somit ist es möglich, auf die Generatoren zu verzichten und die Trainingsdaten
Arbeitsspeicher zu halten.
Dies hilft, die benötigte Trainingszeit zu reduzieren.
Sollte die Arbeitsspeicherkapazität nicht ausreichen, befindet sich eine Implementierung die Generatoren benutzt im Anhang.
\wip{referenzieren und Tatsächlich einfügen}
Sollte die Arbeitsspeicherkapazität nicht ausreichen,
befindet sich eine Implementierung, welche Generatoren benutzt, im Git-Repository.
\wip{Link zu Gitlab?}
Um das Word2Vec-Modell zu erhalten, importieren wir die im Listing \ref{list:gw2v} geschriebene Funktion
\lstinline{getWordVecModel}.
Um das Word2Vec-Modell zu erhalten, wird die im Listing \ref{list:gw2v} geschriebene Funktion
\lstinline{getWordVecModel} importiert.
\begin{lstlisting}[caption={Satzvektorfunktion},label={list:mean1}]
from gensim import utils
......@@ -89,7 +90,7 @@ Sind keine Daten vorhanden,
wird der gesamte Datensatz durchlaufen und für jede einzelne Rezension der Satzvektor ermittelt.
Befindet sich kein Wort der Rezension im Word2Vec-Modell so wird diese Rezension in Zeile 33 übersprungen.
Die Bewertungen werden wie folgt codiert: Negativ (0), Neutral (1) und Positiv (2).
Die Bewertungen werden wie folgt codiert: negativ (0), neutral (1) und positiv (2).
Anschließend werden die generierten Daten gespeichert, um bei mehrfacher Ausführung Zeit
zu sparen.
Danach werden die Daten in Zeile 45 in Trainings- und Testdaten aufgeteilt, hierfür wird die Funktion \lstinline{train_test_split} von \lstinline{sklearn} verwendet.
......@@ -106,8 +107,8 @@ modelNN.add(Dense(15,activation='relu'))
modelNN.add(Dense(3,activation='softmax'))
modelNN.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=["sparse_categorical_accuracy"])
\end{lstlisting}
Hier wurde ein dichtes mehrschichtiges neuronales Netzwerk verwendet, wobei die
Eingangsdimension, der Dimension der Satzvektoren (in diesem Fall 100) entspricht.
Hier wurde ein dichtes, mehrschichtiges neuronales Netzwerk verwendet, wobei die
Eingangsdimension der Dimension der Satzvektoren (in diesem Fall 100) entspricht.
Bis auf die Ausgangsschicht wurde für alle Schichten des neuronalen Netzwerks
die Aktivierungsfunktion \lstinline{relu} verwendet.
Die Ausgangsschicht selbst verwendet die Aktivierungsfunktion
......@@ -118,11 +119,11 @@ Klassifikationen üblich, bewusst kleiner gewählt, um eine Verdichtung der Info
Nachdem die Struktur des neuronalen Netzwerkes nun feststeht, muss das Netz noch kompiliert werden. Hierzu werden in
Zeile 54 einige Parameter gesetzt. Für den Optimierungsalgorithmus wird \lstinline{adam} gewählt.
Für die Fehlerfunktion, hier loss genannt, wird \lstinline{sparse_categorical_crossentropy} benutzt.
Für die Fehlerfunktion, hier \lstinline{loss} genannt, wird \lstinline{sparse_categorical_crossentropy} benutzt.
Die Fehlerfunktion \lstinline{sparse_categorical_crossentropy} ermöglicht im Gegensatz zur
\lstinline{binary_crossentropy} mehr als zwei Klassen zu Klassifizieren. Eine weitere
mögliche Fehlerfunktion ist die \lstinline{categorical_crossentropy}, hierzu müssten
Die Fehlerfunktion \lstinline{sparse_categorical_crossentropy} ermöglicht es im Gegensatz zur
\lstinline{binary_crossentropy} mehr als zwei Klassen zu klassifizieren. Eine weitere
mögliche Fehlerfunktion ist die \lstinline{categorical_crossentropy}. Hierzu müssten
bloß die Zielwerte \noteable{One-Hot-Encoded} werden.
Zuletzt wird für den Parameter \lstinline{Metrics} der Wert \lstinline{sparse_categorical_accuracy}
übergeben.
......@@ -146,10 +147,10 @@ dem vorzeitigen Stopp wieder hergestellt.
In Zeile 59 findet das tatsächliche Training des neuronalen Netzes statt.
Hierfür werden der Methode \lstinline{fit} die Trainingsdaten übergeben. Der Parameter
\lstinline{validation_split = 0.2} sorgt dafür, dass $20 \%$ der Trainingsdaten als
\lstinline{validation_split = 0.2} sorgt dafür, dass $20\,\%$ der Trainingsdaten als
Validierungsmenge genommen werden. Hierbei ist aber anzumerken, dass es sich bei den
Trainingsdaten ohnehin schon nur um $80 \%$ des Datensatzes handelt,
weswegen die tatsächliche Validierungsmenge $16 \%$ des Datensatzes beinhaltet.
Trainingsdaten ohnehin schon nur um $80\,\%$ des Datensatzes handelt,
weswegen die tatsächliche Validierungsmenge $16\,\%$ des Datensatzes beinhaltet.
Die \lstinline{batch_size} wird aufgrund des großen Datensatzes auf 2048 gesetzt, um das Optimieren der Gewichte zu
beschleunigen. Eine kleinere \lstinline{batch_size} hat beim Experimentieren in diesem Fall nicht zu einer schnelleren Konvergenz
......@@ -162,8 +163,8 @@ die Methode \lstinline{fit} übergebenen, Klassengewichte.
\begin{lstlisting}[caption={Neuronales Netz - Evaluieren},label={list:mean5},firstnumber=60]
modelNN.evaluate(X_test,Y_test)
\end{lstlisting}
Um das Modell zu evaluieren, wird in Zeile 60 die Methode evaluate mit den Testdaten aufgerufen.
Das hier trainierte neuronale Netzwerk klassifiziert $80.02 \%$ der Testdaten richtig.
Um das Modell zu evaluieren, wird in Zeile 60 die Methode \lstinline{evaluate} mit den Testdaten aufgerufen.
Das hier trainierte neuronale Netzwerk klassifiziert $80.02\,\%$ der Testdaten richtig.
\subsubsection{Konfusionsmatrix}
Die bereits berechnete Genauigkeit ist ein gutes erstes Leistungsmerkmal des
Klassifikators. Um den Klassifikator noch besser einschätzen zu können,
......@@ -188,21 +189,22 @@ confusion_matrix(Y_test,y_pred,normalize='true')
\label{tab:m_w}
\end{table}
Wie in Tabelle \ref{tab:m_w} zu sehen ist, werden negative Bewertungen zu $80.46\%$
richtig als negative Bewertung klassifiziert, $17.27\%$ werden als
neutral klassifiziert und $2.28\%$ werden als positiv klassifiziert.
Wie in Tabelle \ref{tab:m_w} zu sehen ist, werden negative Bewertungen zu $80.46\,\%$
richtig als negative Bewertung klassifiziert, $17.27\,\%$ werden als
neutral und $2.28\,\%$ werden als positiv klassifiziert.
Neutrale Bewertungen werden zu $68.44\%$ richtig klassifiziert,
jedoch werden $16.82\%$ der neutralen Bewertungen falsch als
negativ klassifiziert und zu $14.74\%$ falsch als positiv klassifiziert.
Neutrale Bewertungen werden zu $68.44\,\%$ richtig klassifiziert,
jedoch werden $16.82\,\%$ der neutralen Bewertungen falsch als
negativ und zu $14.74\,\%$ falsch als positiv klassifiziert.
Die positiven Bewertungen werden zu $81.72\%$ richtig als positive
Bewertungen klassifiziert, zu $15.86\%$ als neutral und zu
$2.42\%$ als negativ klassifiziert.
Die positiven Bewertungen werden zu $81.72\,\%$ richtig als positive
Bewertungen klassifiziert, zu $15.86\,\%$ als neutral und zu
$2.42\,\%$ als negativ klassifiziert.
Das gleiche Modell ohne die Gewichtung der Klassen erreicht eine Genauigkeit
von $85.7\%$. Betrachtet man jedoch die Konfusionsmatrix in Tabelle \ref{tab:conf_no_w}, so
sieht man, dass dort bloß $27\%$ der neutralen Rezensionen richtig klassifiziert wurden.
von $85.7\,\%$. Betrachtet man jedoch die Konfusionsmatrix in
Tabelle \ref{tab:conf_no_w} so
sieht man, dass dort bloß $27\,\%$ der neutralen Rezensionen richtig klassifiziert wurden.
\begin{table}[ht]
\def\arraystretch{1.3}
\begin{center}
......
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment