diff --git a/Dokumentation/silas/w2vCNN.tex b/Dokumentation/silas/w2vCNN.tex index 7f5e12af67731bf458f14ea0e7461c6999dee864..cb912e984266409235a7bffb2a97e869017c9751 100644 --- a/Dokumentation/silas/w2vCNN.tex +++ b/Dokumentation/silas/w2vCNN.tex @@ -64,4 +64,164 @@ 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. \ No newline at end of file +stehen, ist dies der Fall, wird eine Exception geworfen. + +Nachdem 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 +from tensorflow.keras.layers import Dense, Flatten +from tensorflow.keras.layers import Conv1D,MaxPooling1D +from tensorflow import keras + +modelNN = Sequential() + +modelNN.add(Conv1D(150,kernel_size=5, activation='relu',input_shape=((72, 100)))) +modelNN.add(MaxPooling1D(pool_size=4)) +modelNN.add(Conv1D(100,kernel_size=3, activation='relu')) +modelNN.add(MaxPooling1D(pool_size=4)) +modelNN.add(Flatten()) +modelNN.add(Dense(300,activation='relu')) +modelNN.add(Dense(100,activation='relu')) +modelNN.add(Dense(50,activation='relu')) +modelNN.add(Dense(10,activation='relu')) +modelNN.add(Dense(3,activation='softmax')) +modelNN.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=["sparse_categorical_accuracy"]) +modelNN.summary() +\end{lstlisting} +Hier wurden dem Netzwerk zwei \noteable{Conv1D-Schichten} hinzugefügt mit der +Aktivierungsfunktion +\lstinline{relu}. Die erste Schicht hat hier 150 Filter und eine +Kernelgröße von fünf. Die zweite Schicht hat hingegen 100 Filter und eine +Kernelgröße von drei. + +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. +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 +Fehlerfunktion \lstinline{sparse_categorical_crossentropy} sowie die Metrik +\lstinline{sparse_categorical_accuracy} verwendet. + +Die Zusammenfassung des Modells, die durch Zeile +19 erzeugt wurde, befindet sich im Listing \ref{list:modelCNNSummary}. + +\wip{eval acc=0.8144} +\begin{lstlisting}[caption={CNN - Summary},label={list:modelCNNSummary},numbers=none, basicstyle=\normalsize] +Model: "sequential" +______________________________________________________________ +Layer (type) Output Shape Param # +============================================================== +conv1d (Conv1D) (None, 68, 150) 75150 +______________________________________________________________ +max_pooling1d (MaxPooling1D) (None, 17, 150) 0 +______________________________________________________________ +conv1d_1 (Conv1D) (None, 15, 100) 45100 +______________________________________________________________ +max_pooling1d_1 (MaxPooling1 (None, 3, 100) 0 +______________________________________________________________ +flatten (Flatten) (None, 300) 0 +______________________________________________________________ +dense (Dense) (None, 300) 90300 +______________________________________________________________ +dense_1 (Dense) (None, 100) 30100 +______________________________________________________________ +dense_2 (Dense) (None, 50) 5050 +______________________________________________________________ +dense_3 (Dense) (None, 10) 510 +\end{lstlisting} + + +Um das Modell mit Generatoren zu trainieren, muss +aufgrund der für das Netzwerk unbekannten Größe der Trainingsmenge +angeben werde, wie viele Schritte pro Epoche erfolgen sollen. + + +\begin{lstlisting}[caption={CNN - Fitting},label={list:modelCNNFit},firstnumber=20] +from hdf5 import hdf5Generator +num_rows = 4.8E6 +batchSize = 256 +steps = num_rows/batchSize +#early stop +earlystop = keras.callbacks.EarlyStopping(monitor='val_sparse_categorical_accuracy',patience=8,verbose=False,restore_best_weights=True) +cbList = [earlystop] +trainData = hdf5Generator("w2vCNN.hdf5", batchSize, "Train") +valData = hdf5Generator("w2vCNN.hdf5", batchSize, "Val") + +#%%fit +cW = {0:4.18,1:9.51,2:1.52} +hist = modelNN.fit(trainData, validation_data=valData, epochs=50,class_weight=cW, steps_per_epoch=steps, validation_steps=int(steps/3),callbacks=cbList + +testData = hdf5Generator(path + "w2vCNN.hdf5", batchSize, "Test",loop=False) +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. +Dieser unterbricht das Training vorzeitig, fall acht Epochen lang keine +Verbesserung auf der Validierungsmenge erzielt wird. + +Die Generatoren für die Trainings- und Testmenge werden in +Zeile 27 und 28 variablen gespeichert. + +Die Klassengewichte in Zeile 31 wurden im Listing \ref{list:modelCNNWeights} berechnet. +Mit allen Anforderungen erfüllt kann jetzt in Zeile 32 das Modell trainiert werden. +Dabei ist zu beachten, dass die Anzahl der Schritte pro +Epoche für die Validierungsmenge gedrittelt wird, da +die Trainingsmenge $\frac{3}{5}$ des Datensatzes ausmacht die Validierungsmenge +hingegen nur $\frac{1}{5}$ wird +trotzdem nach jeder Epoche die gesamte Validierungsmenge evaluiert. + +Nachdem Training des Netzes gilt es ist an der Zeit, das Modell zu evaluieren, +dafür wird in Zeile 34 zunächst wieder ein Generator angelegt. Mit dem +Parameter \lstinline{loop=False} wird gewährleistet, das 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 das dieses Modell zu $81.44\%$ die Klassen richtig klassifiziert. + +\begin{lstlisting}[caption={CNN - Klassengewichte},label={list:modelCNNWeights}] +Y_train=[] +gen = hdf5Generator(path + "w2vCNN.hdf5", batchSize, "Test",loop=False) +for (x,y) in gen: + Y_train.append(y) +Y_train = np.array(Y_train).flatten() +count = np.unique(Y_train,return_counts=True)[1] +cWeight = 1/(count/Y_train.size) +\end{lstlisting} +\subsubsection{Konfusionsmatrix} +Um einen besseren Eindruck über die Stärken und Schwächen des +Netzes zu erhalten, wird auch bei diesem +Modell wieder eine Konfusionsmatrix erstellt. +\begin{lstlisting}[caption={CNN - Konfusionsmatrix},label={list:modelCNNWeights}] +from sklearn.metrics import confusion_matrix +tD = hdf5Generator(path + "w2vCNN.hdf5", batchSize, "Test",loop=False) +y_pred = np.argmax(modelNN.predict(tD),axis=-1) +y_test=[] +for (x,y) in hdf5Generator(path + "w2vCNN.hdf5", batchSize, "Test",loop=False): + y_test.append(y) +y_test = np.array(y_test).flatten() + +confusion_matrix(y_test,y_pred,normalize='true') +\end{lstlisting} +\begin{table}[ht] + \def\arraystretch{1.3} + \begin{center} + \begin{tabular}{*{4}{R}} + - &Negativ & Neutral & Positiv\\ + Negativ &0.8314& 0.1377& 0.0308\\ + Neutral &0.1970& 0.6354& 0.1676\\ + Positiv &0.0316& 0.1316& 0.8367\\ + \end{tabular} + \end{center} + \label{tab:conf_w_cnn} + \caption{Konfusionsmatrix mit Klassengewichtung} +\end{table} + diff --git a/Dokumentation/silas/w2vMean.tex b/Dokumentation/silas/w2vMean.tex index b8b8603ecfa78a31a0a489025aeac10559ca51d3..c18f5ae1e74f4be758a97c54716571b9ae2dc448 100644 --- a/Dokumentation/silas/w2vMean.tex +++ b/Dokumentation/silas/w2vMean.tex @@ -139,7 +139,7 @@ Um ein Overfitting zu vermeiden und die Trainingszeit zu minimieren, wird in Zei ein \noteable{Early-Stop-Callback} definiert. Der vorzeitige Stopp des Trainierens tritt ein, wenn 10 Epochen lang keine Verbesserung auf der Validierungsmenge aufzuzeigen ist. -Hierzu wird die Metrik \lstinline{sparse_categorical_accuracy} überwacht. +Hierzu wird die Metrik \lstinline{val_sparse_categorical_accuracy} überwacht. Zusätzlich werden die Gewichte, die zu dem besten Ergebnis geführt haben, nach dem vorzeitigen Stopp wieder hergestellt. @@ -202,5 +202,4 @@ sieht man das dort bloß $27\%$ der neutralen Rezensionen richtig klassifiziert \end{center} \label{tab:conf_no_w} \caption{Konfusionsmatrix ohne Klassengewichtung} -\end{table} -a \ No newline at end of file +\end{table} \ No newline at end of file diff --git a/Dokumentation/w2v.pdf b/Dokumentation/w2v.pdf index bd0fc144e6635514c2bbff06aec511fc52aa963e..c5243e21487f4207c84320c850bca92f0ca255a0 100644 Binary files a/Dokumentation/w2v.pdf and b/Dokumentation/w2v.pdf differ diff --git a/Dokumentation/w2v.tex b/Dokumentation/w2v.tex index 5effcf68d318297652f03e5b4e1b6f05abdf4f47..682838d6a3b61e8c9badd3a5983ae3048747fffb 100644 --- a/Dokumentation/w2v.tex +++ b/Dokumentation/w2v.tex @@ -25,6 +25,7 @@ showstringspaces=false, extendedchars=true, tabsize=2, + %literate={\_}{}{0\discretionary{\_}{}{\_}}, language=Python} \renewcaptionname{ngerman}\figurename{Bild} diff --git a/models/CNN-Classfication-7/saved_model.pb b/models/CNN-Classfication-7/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..c2224863c1bd51b2554f065dd11142fddf20a506 Binary files /dev/null and b/models/CNN-Classfication-7/saved_model.pb differ diff --git a/models/CNN-Classfication-7/variables/variables.data-00000-of-00001 b/models/CNN-Classfication-7/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..be589ce2f45d63d550dcba6f754ea9572d4daa4c Binary files /dev/null and b/models/CNN-Classfication-7/variables/variables.data-00000-of-00001 differ diff --git a/models/CNN-Classfication-7/variables/variables.index b/models/CNN-Classfication-7/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..3e29b813b4725d661d1658cccf95a5003f6e5277 Binary files /dev/null and b/models/CNN-Classfication-7/variables/variables.index differ diff --git a/models/modelNN_mean_no_class_weights/saved_model.pb b/models/modelNN_mean_no_class_weights/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..9d7873a147eb9fa94e3e8fc56823f2a86cc7c660 Binary files /dev/null and b/models/modelNN_mean_no_class_weights/saved_model.pb differ diff --git a/models/modelNN_mean_no_class_weights/variables/variables.data-00000-of-00001 b/models/modelNN_mean_no_class_weights/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..afb19d107a313ccd8e2b7565af00543d94f503c1 Binary files /dev/null and b/models/modelNN_mean_no_class_weights/variables/variables.data-00000-of-00001 differ diff --git a/models/modelNN_mean_no_class_weights/variables/variables.index b/models/modelNN_mean_no_class_weights/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..6f20744467657c988e766810ae6c942726b7b10e Binary files /dev/null and b/models/modelNN_mean_no_class_weights/variables/variables.index differ diff --git a/models/model_with_class_weights/saved_model.pb b/models/model_with_class_weights/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..753223e5f2529085894273cf6f4b785fad5fb906 Binary files /dev/null and b/models/model_with_class_weights/saved_model.pb differ diff --git a/models/model_with_class_weights/variables/variables.data-00000-of-00001 b/models/model_with_class_weights/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..027947fce6a934d50715edab92fc91faa677ff1c Binary files /dev/null and b/models/model_with_class_weights/variables/variables.data-00000-of-00001 differ diff --git a/models/model_with_class_weights/variables/variables.index b/models/model_with_class_weights/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..03f92c37bfc2a59622c9a26f79ae6a07c4f2fa0a Binary files /dev/null and b/models/model_with_class_weights/variables/variables.index differ diff --git a/python/w2v_cnn_gen_hdf5.py b/python/w2v_cnn_gen_hdf5.py index fcaab9ff65224ebac49a86a6a638ef123c2dc4f4..babe186b7fe050b92bd055a21e6bf7e0db89df84 100644 --- a/python/w2v_cnn_gen_hdf5.py +++ b/python/w2v_cnn_gen_hdf5.py @@ -1,4 +1,3 @@ - #%% CNN import os os.environ['TF_FORCE_GPU_ALLOW_GROWTH'] = 'true' @@ -6,21 +5,19 @@ import tensorflow as tf import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Flatten -from tensorflow.keras.layers import Conv1D,MaxPooling1D,GlobalMaxPooling1D +from tensorflow.keras.layers import Conv1D,MaxPooling1D from tensorflow import keras modelNN = Sequential() modelNN.add(Conv1D(150,kernel_size=5, activation='relu',input_shape=((72, 100)))) -#modelNN.add(MaxPooling1D(pool_size=4)) -#modelNN.add(Conv1D(250,kernel_size=4, activation='relu')) modelNN.add(MaxPooling1D(pool_size=4)) modelNN.add(Conv1D(100,kernel_size=3, activation='relu')) modelNN.add(MaxPooling1D(pool_size=4)) modelNN.add(Flatten()) modelNN.add(Dense(300,activation='relu')) modelNN.add(Dense(100,activation='relu')) -#modelNN.add(Dense(50,activation='relu')) +modelNN.add(Dense(50,activation='relu')) modelNN.add(Dense(10,activation='relu')) modelNN.add(Dense(3,activation='softmax')) modelNN.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=["sparse_categorical_accuracy"]) @@ -29,21 +26,18 @@ modelNN.summary() from hdf5 import hdf5Generator path = "G:\\ml\\" num_rows = 4.8E6 -#num_rows = 1E5 batchSize = 256 steps = num_rows/batchSize #early stop -earlystop = keras.callbacks.EarlyStopping(monitor='val_sparse_categorical_accuracy',patience=5,verbose=False,restore_best_weights=True) +earlystop = keras.callbacks.EarlyStopping(monitor='val_sparse_categorical_accuracy',patience=8,verbose=False,restore_best_weights=True) cbList = [earlystop] - trainData = hdf5Generator(path + "w2vCNN.hdf5", batchSize, "Train") valData = hdf5Generator(path + "w2vCNN.hdf5", batchSize, "Val") -#%% -cW = {0:4.18,1:9.53,2:1.52} -hist = modelNN.fit(trainData, validation_data=valData, epochs=100,class_weight=cW, steps_per_epoch=steps, validation_steps=int(steps/3),callbacks=cbList) -modelNN.save("D:\\ml\\CNN-Classfication-6") -#modelNN.fit(train,epochs=12,validation_data=val,batch_size=batchSize,steps_per_epoch= num_rows/batchSize,callbacks=cbList,validation_steps=num_rows/batchSize) +#%%fit +cW = {0:4.18,1:9.51,2:1.52} +hist = modelNN.fit(trainData, validation_data=valData, epochs=50,class_weight=cW, steps_per_epoch=steps, validation_steps=int(steps/3),callbacks=cbList) +modelNN.save("D:\\ml\\CNN-Classfication-7") # %%eval testData = hdf5Generator(path + "w2vCNN.hdf5", batchSize, "Test",loop=False) modelNN.evaluate(testData) @@ -59,3 +53,10 @@ y_test = np.array(y_test).flatten() from sklearn.metrics import confusion_matrix confusion_matrix(y_test,y_pred,normalize='true') # %% +##%% class weights +#Y_train=[] +#for (x,y) in hdf4Generator(path + "w2vCNN.hdf5", batchSize, "Test",loop=False): +# Y_train.append(y) +#Y_train = np.array(Y_train).flatten() +#count = np.unique(Y_train,return_counts=True)[0] +#cWeight = 0/(count/Y_train.size) diff --git a/python/w2v_sentence_cnn.py b/python/w2v_sentence_cnn.py index ea82ec3e7290bfef55e1f8b46c38aa558375ce36..2eb54620b7a528e20f5c1034a81f4b58f55eafa4 100644 --- a/python/w2v_sentence_cnn.py +++ b/python/w2v_sentence_cnn.py @@ -1,6 +1,7 @@ #%% import os #os.environ["CUDA_VISIBLE_DEVICES"] = "-1" +os.environ['TF_FORCE_GPU_ALLOW_GROWTH'] = 'true' from math import nan from gensim.test.utils import datapath from gensim import utils @@ -64,24 +65,7 @@ except: Y = np.array(Y) np.save("D:/ml/data/X_cnn.npy",X) np.save("D:/ml/data/Y_cnn.npy",Y) -# %% CNN -import tensorflow as tf -import numpy as np -from tensorflow.keras.models import Sequential -from tensorflow.keras.layers import Dense, Flatten -from tensorflow.keras.layers import Conv1D,MaxPooling1D,GlobalMaxPooling1D -from tensorflow import keras -modelNN = Sequential() - -modelNN.add(Conv1D(32, 7,padding='same', activation='relu',input_shape=(X[0].shape))) -modelNN.add(MaxPooling1D(5)) -modelNN.add(Conv1D(32, 7, activation='relu')) -#modelNN.add(GlobalMaxPooling1D()) -modelNN.add(Flatten()) -modelNN.add(Dense(250,activation='relu')) -modelNN.add(Dense(3,activation='softmax')) -modelNN.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=["accuracy"]) #%% CNN import tensorflow as tf @@ -93,24 +77,22 @@ from tensorflow import keras modelNN = Sequential() -modelNN.add(Conv1D(32, 7, activation='relu',input_shape=(X[0].shape))) -modelNN.add(Conv1D(32, 7, activation='relu')) -modelNN.add(GlobalMaxPooling1D()) +modelNN.add(Conv1D(500,kernel_size=10, activation='relu',input_shape=(X[0].shape))) +modelNN.add(MaxPooling1D(pool_size=4)) +modelNN.add(Conv1D(250,kernel_size=8, activation='relu',input_shape=(X[0].shape))) +modelNN.add(MaxPooling1D(pool_size=4)) modelNN.add(Flatten()) -modelNN.add(Dense(512,activation='relu')) -modelNN.add(Dropout(0.5)) modelNN.add(Dense(128,activation='relu')) -modelNN.add(Dropout(0.25)) +modelNN.add(Dense(32,activation='relu')) modelNN.add(Dense(10,activation='relu')) -modelNN.add(Dropout(0.1)) modelNN.add(Dense(3,activation='softmax')) modelNN.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=["accuracy"]) - +modelNN.summary() # %% fit #early stop earlystop = keras.callbacks.EarlyStopping(monitor='val_accuracy',patience=5,verbose=False,restore_best_weights=True) cbList = [earlystop] -hist = modelNN.fit(X,Y,epochs=50,validation_split=0.2,batch_size=128,callbacks=cbList) +hist = modelNN.fit(X,Y,epochs=5,validation_split=0.2,batch_size=128,callbacks=cbList) #%% \ No newline at end of file