Hallo Habr.
Im
vorherigen Teil habe ich mich mit der Erstellung einer einfachen Texterkennung auf der Grundlage eines neuronalen Netzwerks befasst. Heute werden wir einen ähnlichen Ansatz verfolgen und einen automatischen Übersetzer von Texten vom Englischen ins Deutsche schreiben.

Für diejenigen, die daran interessiert sind, wie dies funktioniert, sind Details unter dem Schnitt.
Hinweis : Dieses Projekt zur Verwendung eines neuronalen Netzwerks für die Übersetzung ist ausschließlich pädagogisch, daher wird die Frage „Warum“ nicht berücksichtigt. Nur zum Spaß. Ich wollte nicht beweisen, dass diese oder jene Methode besser oder schlechter ist, es war nur interessant zu überprüfen, was passiert. Die unten verwendete Methode ist natürlich vereinfacht, aber ich hoffe, niemand hofft, dass wir in einer halben Stunde einen zweiten Lingvo schreiben werden.
Datenerfassung
Als Quelldatensatz wurde eine im Netzwerk gefundene Datei verwendet, die englische und deutsche Phrasen enthält, die durch Tabulatoren getrennt sind. Eine Reihe von Phrasen sieht ungefähr so aus:
Hi. Hallo! Hi. Grüß Gott! Run! Lauf! Wow! Potzdonner! Wow! Donnerwetter! Fire! Feuer! Help! Hilfe! Help! Zu Hülf! Stop! Stopp! Wait! Warte! Go on. Mach weiter. Hello! Hallo! I ran. Ich rannte. I see. Ich verstehe. ...
Die Datei enthält 192.000 Zeilen und hat eine Größe von 13 MB. Wir laden den Text in den Speicher und teilen die Daten in zwei Blöcke für englische und deutsche Wörter auf.
def read_text(filename): with open(filename, mode='rt', encoding='utf-8') as file: text = file.read() sents = text.strip().split('\n') return [i.split('\t') for i in sents] data = read_text("deutch.txt") deu_eng = np.array(data) deu_eng = deu_eng[:30000,:] print("Dictionary size:", deu_eng.shape)
Wir haben auch alle Wörter in Kleinbuchstaben umgewandelt und die Satzzeichen entfernt.
Der nächste Schritt besteht darin, die Daten für das neuronale Netzwerk vorzubereiten. Das Netzwerk weiß nicht, was Wörter sind, und arbeitet ausschließlich mit Zahlen. Zum Glück ist in Keras bereits die Tokenizer-Klasse integriert, die Wörter in Sätzen durch digitale Codes ersetzt.
Die Verwendung wird einfach anhand eines Beispiels veranschaulicht:
from keras.preprocessing.text import Tokenizer from keras.preprocessing.sequence import pad_sequences s = "To be or not to be" eng_tokenizer = Tokenizer() eng_tokenizer.fit_on_texts([s]) seq = eng_tokenizer.texts_to_sequences([s]) seq = pad_sequences(seq, maxlen=8, padding='post') print(seq)
Der Ausdruck "sein oder nicht sein" wird durch das Array [1 2 3 4 1 2 0 0] ersetzt, wobei es nicht schwer zu erraten ist, 1 = bis, 2 = sein, 3 = oder 4 = nicht. Wir können diese Daten bereits an das neuronale Netzwerk senden.
Neuronales Netzwerktraining
Unsere Daten sind digital bereit. Wir teilen das Array in zwei Blöcke für Eingabe- (englische Zeilen) und Ausgabedaten (deutsche Zeilen). Wir werden auch eine separate Einheit zur Validierung des Lernprozesses vorbereiten.
Jetzt können wir ein Modell eines neuronalen Netzwerks erstellen und mit dem Training beginnen. Wie Sie sehen können, enthält das neuronale Netzwerk LSTM-Schichten mit Speicherzellen. Obwohl es wahrscheinlich in einem „normalen“ Netzwerk funktionieren würde, können diejenigen, die dies wünschen, selbst nachsehen.
def make_model(in_vocab, out_vocab, in_timesteps, out_timesteps, n): model = Sequential() model.add(Embedding(in_vocab, n, input_length=in_timesteps, mask_zero=True)) model.add(LSTM(n)) model.add(Dropout(0.3)) model.add(RepeatVector(out_timesteps)) model.add(LSTM(n, return_sequences=True)) model.add(Dropout(0.3)) model.add(Dense(out_vocab, activation='softmax')) model.compile(optimizer=optimizers.RMSprop(lr=0.001), loss='sparse_categorical_crossentropy') return model eng_vocab_size = len(eng_tokenizer.word_index) + 1 deu_vocab_size = len(deu_tokenizer.word_index) + 1 eng_length, deu_length = 8, 8 model = make_model(eng_vocab_size, deu_vocab_size, eng_length, deu_length, 512) num_epochs = 40 model.fit(trainX, trainY.reshape(trainY.shape[0], trainY.shape[1], 1), epochs=num_epochs, batch_size=512, validation_split=0.2, callbacks=None, verbose=1) model.save('en-de-model.h5')
Das Training selbst sieht ungefähr so aus:

Wie Sie sehen, ist der Vorgang nicht schnell und dauert auf einer Core i7 + GeForce 1060 für einen Satz von 30.000 Zeilen etwa eine halbe Stunde. Am Ende des Trainings (es muss nur einmal durchgeführt werden) wird das Modell in einer Datei gespeichert und kann dann wiederverwendet werden.
Um die Übersetzung zu erhalten, verwenden wir die Funktion Predict_classes, deren Eingabe wir einige einfache Sätze übermitteln. Die Funktion get_word wird verwendet, um Wörter in Zahlen umzukehren.
model = load_model('en-de-model.h5') def get_word(n, tokenizer): if n == 0: return "" for word, index in tokenizer.word_index.items(): if index == n: return word return "" phrs_enc = encode_sequences(eng_tokenizer, eng_length, ["the weather is nice today", "my name is tom", "how old are you", "where is the nearest shop"]) preds = model.predict_classes(phrs_enc) print("Preds:", preds.shape) print(preds[0]) print(get_word(preds[0][0], deu_tokenizer), get_word(preds[0][1], deu_tokenizer), get_word(preds[0][2], deu_tokenizer), get_word(preds[0][3], deu_tokenizer)) print(preds[1]) print(get_word(preds[1][0], deu_tokenizer), get_word(preds[1][1], deu_tokenizer), get_word(preds[1][2], deu_tokenizer), get_word(preds[1][3], deu_tokenizer)) print(preds[2]) print(get_word(preds[2][0], deu_tokenizer), get_word(preds[2][1], deu_tokenizer), get_word(preds[2][2], deu_tokenizer), get_word(preds[2][3], deu_tokenizer)) print(preds[3]) print(get_word(preds[3][0], deu_tokenizer), get_word(preds[3][1], deu_tokenizer), get_word(preds[3][2], deu_tokenizer), get_word(preds[3][3], deu_tokenizer))
Ergebnisse
Das Merkwürdigste sind nun die Ergebnisse. Es ist interessant zu sehen, wie das neuronale Netzwerk die Entsprechung zwischen englischen und deutschen Phrasen lernt und sich daran erinnert. Ich habe speziell 2 Sätze leichter und 2 schwerer genommen, um den Unterschied zu erkennen.
5 Minuten Training"Das Wetter ist heute schön" - "das ist ist tom"
"Mein Name ist Tom" - "wie für Tom Tom"
"Wie alt bist du" - "wie geht ist es"
"Wo ist das nächste Geschäft" - "wo ist der"
Wie Sie sehen, gibt es bisher nur wenige „Treffer“. Ein Fragment des Ausdrucks „Wie alt bist du?“ Verwechselte das neuronale Netzwerk mit dem Ausdruck „Wie geht es dir?“ Und produzierte die Übersetzung „Wie geht es?“ (Wie geht es dir?). In der Phrase "wo ist ..." identifizierte das neuronale Netzwerk nur das Verb wo und produzierte die Übersetzung "wo ist der" (wo ist es?), Was im Prinzip nicht ohne Bedeutung ist. Im Allgemeinen ungefähr das Gleiche wie ein Neuling in der Gruppe A1 ins Deutsche übersetzt;)
10 Minuten Training"Das Wetter ist heute schön" - "das haus ist bereit"
"Mein Name ist tom" - "mein heißer heißer tom"
"Wie alt bist du" - "wie alt sind sie"
"Wo ist das nächste Geschäft" - "wo ist paris"
Einige Fortschritte sind sichtbar. Der erste Satz ist völlig fehl am Platz. In der zweiten Phrase „lernte“ das neuronale Netz das Verb heiß (genannt), aber „mein heißer heißer Tom“ ist immer noch falsch, obwohl Sie die Bedeutung bereits erraten können. Der dritte Satz ist bereits richtig. Im vierten Teil lautet der richtige erste Teil „wo ist“, aber der nächste Laden wurde aus irgendeinem Grund durch Paris ersetzt.
30 Minuten Training"Das Wetter ist heute schön" - "das ist ist aus"
"Mein Name ist Tom" - "" Tom "ist mein Name"
"Wie alt bist du" - "wie alt sind sie"
"Wo ist das nächste Geschäft" - "wo ist der"
Wie Sie sehen können, ist der zweite Satz korrekt geworden, obwohl das Design etwas ungewöhnlich aussieht. Die dritte Phrase ist richtig, aber die 1. und 4. Phrase wurden noch nicht „gelernt“. Damit habe
ich den Prozess abgeschlossen
, um Strom zu sparen .
Fazit
Wie Sie sehen, funktioniert dies im Prinzip. Ich möchte mir eine neue Sprache mit solcher Geschwindigkeit merken :) Natürlich ist das Ergebnis bisher nicht perfekt, aber das Training mit 190.000 Zeilen würde mehr als eine Stunde dauern.
Für diejenigen, die alleine experimentieren möchten, befindet sich der Quellcode unter dem Spoiler. Das Programm kann theoretisch jedes Sprachpaar verwenden, nicht nur Englisch und Deutsch (die Datei sollte in UTF-8-Codierung vorliegen). Das Thema Übersetzungsqualität bleibt ebenfalls offen, es gibt etwas zu testen.
Das Wörterbuch selbst ist zu groß, um es an den Artikel anzuhängen. Der Link befindet sich in den Kommentaren.
Wie immer alle erfolgreichen Experimente.