Ich studiere derzeit dieses Papier , in dem CNN für die Phonemerkennung unter Verwendung der visuellen Darstellung von Log-Mel-Filterbänken und eines begrenzten Gewichtsverteilungsschemas angewendet wird.
Die Visualisierung von Log-Mel-Filterbänken ist eine Möglichkeit, die Daten darzustellen und zu normalisieren. Sie schlagen vor, als Spektogramm mit RGB-Farben zu visualisieren. Das Beste, was ich mir einfallen lassen könnte, wäre, es mit einer matplotlibs
Farbkarte zu zeichnen cm.jet
. Sie (als Papier) schlagen auch vor, dass jeder Rahmen mit seinen [statischen Delta Delta_ Delta] Filterbank-Energien gestapelt werden sollte. Das sieht so aus:
Die Eingabe der besteht aus einem Bildfeld von 15 Frames, die [statische Delta Delta_Detlta] Eingabeform wäre (40,45,3)
Die begrenzte Gewichtsverteilung besteht darin, die Gewichtsverteilung auf einen bestimmten Filterbankbereich zu beschränken, da Sprache in verschiedenen Frequenzbereichen unterschiedlich interpretiert wird. Daher würde eine vollständige Gewichtsverteilung bei normaler Faltung nicht funktionieren.
Ihre Implementierung einer begrenzten Gewichtsverteilung besteht darin, die Gewichte in der Gewichtsmatrix zu steuern, die jeder Faltungsschicht zugeordnet sind. Sie wenden also eine Faltung auf die gesamte Eingabe an. Das Papier wendet nur eine Faltungsschicht an, da die Verwendung mehrerer Schichten die Lokalität der aus der Faltungsschicht extrahierten Merkmalskarten zerstören würde. Der Grund, warum sie Filterbank-Energien anstelle des normalen MFCC-Koeffizienten verwenden, liegt darin, dass DCT die Lokalität der Filterbank-Energien zerstört.
Anstatt die der Faltungsschicht zugeordnete Gewichtsmatrix zu steuern, entscheide ich mich, das CNN mit mehreren Eingaben zu implementieren. Daher besteht jeder Eingang aus einem (kleiner Filterbankbereich, total_frames_with_deltas, 3). So heißt es beispielsweise auf dem Papier, dass eine Filtergröße von 8 gut sein sollte, und ich habe einen Filterbankbereich von 8 festgelegt. Daher hat jedes kleine Bildfeld die Größe (8,45,3). Jedes der kleinen Bildfelder wird mit einem Schiebefenster mit einem Schritt von 1 extrahiert - es gibt also eine große Überlappung zwischen jedem Eingang - und jeder Eingang hat seine eigene Faltungsschicht.
(input_3, input_3, input3, sollte input_1, input_2, input_3 ... gewesen sein)
Auf diese Weise ist es möglich, mehrere Faltungsschichten zu verwenden, da die Lokalität kein Problem mehr darstellt, da sie innerhalb eines Filterbankbereichs angewendet wird. Dies ist meine Theorie.
Das Papier gibt es nicht explizit an, aber ich denke, der Grund, warum sie die Phonemerkennung für mehrere Frames durchführen, besteht darin, dass ein Teil des linken und rechten Kontexts vorhanden ist, sodass nur der mittlere Frame vorhergesagt / trainiert wird. In meinem Fall setzen die ersten 7 Frames das linke Kontextfenster - der mittlere Frame wird trainiert und die letzten 7 Frames setzen das rechte Kontextfenster. Bei mehreren Frames wird also nur ein Phonem als Mitte erkannt.
Mein neuronales Netzwerk sieht derzeit so aus:
def model3():
#stride = 1
#dim = 40
#window_height = 8
#splits = ((40-8)+1)/1 = 33
next(test_generator())
next(train_generator(batch_size))
kernel_number = 200#int(math.ceil(splits))
list_of_input = [Input(shape = (window_height,total_frames_with_deltas,3)) for i in range(splits)]
list_of_conv_output = []
list_of_conv_output_2 = []
list_of_conv_output_3 = []
list_of_conv_output_4 = []
list_of_conv_output_5 = []
list_of_max_out = []
for i in range(splits):
#list_of_conv_output.append(Conv2D(filters = kernel_number , kernel_size = (15,6))(list_of_input[i]))
#list_of_conv_output.append(Conv2D(filters = kernel_number , kernel_size = (window_height-1,3))(list_of_input[i]))
list_of_conv_output.append(Conv2D(filters = kernel_number , kernel_size = (window_height,3), activation = 'relu')(list_of_input[i]))
list_of_conv_output_2.append(Conv2D(filters = kernel_number , kernel_size = (1,5))(list_of_conv_output[i]))
list_of_conv_output_3.append(Conv2D(filters = kernel_number , kernel_size = (1,7))(list_of_conv_output_2[i]))
list_of_conv_output_4.append(Conv2D(filters = kernel_number , kernel_size = (1,11))(list_of_conv_output_3[i]))
list_of_conv_output_5.append(Conv2D(filters = kernel_number , kernel_size = (1,13))(list_of_conv_output_4[i]))
#list_of_conv_output_3.append(Conv2D(filters = kernel_number , kernel_size = (3,3),padding='same')(list_of_conv_output_2[i]))
list_of_max_out.append((MaxPooling2D(pool_size=((1,11)))(list_of_conv_output_5[i])))
merge = keras.layers.concatenate(list_of_max_out)
print merge.shape
reshape = Reshape((total_frames/total_frames,-1))(merge)
dense1 = Dense(units = 1000, activation = 'relu', name = "dense_1")(reshape)
dense2 = Dense(units = 1000, activation = 'relu', name = "dense_2")(dense1)
dense3 = Dense(units = 145 , activation = 'softmax', name = "dense_3")(dense2)
#dense4 = Dense(units = 1, activation = 'linear', name = "dense_4")(dense3)
model = Model(inputs = list_of_input , outputs = dense3)
model.compile(loss="categorical_crossentropy", optimizer="SGD" , metrics = [metrics.categorical_accuracy])
reduce_lr=ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=3, verbose=1, mode='auto', epsilon=0.001, cooldown=0)
stop = EarlyStopping(monitor='val_loss', min_delta=0, patience=5, verbose=1, mode='auto')
print model.summary()
raw_input("okay?")
hist_current = model.fit_generator(train_generator(batch_size),
steps_per_epoch=10,
epochs = 10000,
verbose = 1,
validation_data = test_generator(),
validation_steps=1)
#pickle_safe = True,
#workers = 4)
Also .. jetzt kommt das Problem ..
Ich habe das Netzwerk trainiert und konnte nur eine Validierungsgenauigkeit von höchstens 0,17 erhalten, und die Genauigkeit nach vielen Epochen beträgt 1,0. (Handlung wird gerade gemacht)
fester Rahmen:
Ich bin mir nicht sicher, warum ich keine besseren Ergebnisse erhalte. Warum diese hohe Fehlerrate? Ich verwende den TIMIT-Datensatz, den auch die anderen verwenden. Warum erhalte ich dann schlechtere Ergebnisse?
Und entschuldigen Sie den langen Beitrag - ich hoffe, weitere Informationen zu meiner Entwurfsentscheidung könnten hilfreich sein - und helfen Sie zu verstehen, wie ich das Papier verstanden habe und wie ich es angewendet habe, um herauszufinden, wo mein Fehler liegen würde.