From 71b7cf6dd78bc61b927afa4333dc96dc4dc1647d Mon Sep 17 00:00:00 2001 From: "Lucas Lopes Oliveira (lopesoll)" Date: Fri, 10 Mar 2023 16:45:55 +0000 Subject: [PATCH] Add files via upload --- Seq2Seq translation model.ipynb | 844 ++++++++++++++++++++++++++++++++ 1 file changed, 844 insertions(+) create mode 100644 Seq2Seq translation model.ipynb diff --git a/Seq2Seq translation model.ipynb b/Seq2Seq translation model.ipynb new file mode 100644 index 0000000..b236523 --- /dev/null +++ b/Seq2Seq translation model.ipynb @@ -0,0 +1,844 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 21, + "id": "63a0d16f", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from tensorflow.keras.layers import Input, LSTM, Dense, RepeatVector, Embedding\n", + "from tensorflow.keras import Model\n", + "from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping\n", + "from tensorflow.keras.models import load_model\n", + "from tensorflow.keras.preprocessing.sequence import pad_sequences\n", + "from tensorflow.keras.preprocessing.text import Tokenizer\n", + "from keras.utils.vis_utils import plot_model\n", + "import matplotlib.pyplot as plt\n", + "from nltk.translate.bleu_score import sentence_bleu, corpus_bleu\n", + "from nltk.tokenize import word_tokenize" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "96100a91", + "metadata": {}, + "outputs": [], + "source": [ + "df=pd.read_csv(\"eng-fr.csv\")\n", + "#df=df.sample(40000, random_state=42)\n", + "df=df[:40000]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "3bf99a74", + "metadata": {}, + "outputs": [], + "source": [ + "import re\n", + "# remove unwanted characters\n", + "def remove_chars(text):\n", + " # pattern to match unwanted characters\n", + " pattern = r'[^\\w\\s]'\n", + " # replace unwanted characters with space\n", + " text = re.sub(pattern, ' ', text)\n", + " # remove multiple spaces\n", + " text = re.sub('\\s+', ' ', text).strip()\n", + " return text\n", + "\n", + "df = df.applymap(lambda s: s.lower())\n", + "df['English words/sentences'] = df['English words/sentences'].apply(remove_chars)\n", + "df['French words/sentences'] = df['French words/sentences'].apply(remove_chars)\n", + "eng, fr = df[\"English words/sentences\"], df[\"French words/sentences\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f316ab31", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(7, 15)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#calculate the maximum length of a sentence (nr of words)\n", + "max_len_eng_sentence = [len(s.split()) for s in eng]\n", + "max_len_fr_sentence = [len(s.split()) for s in fr]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "1e817b79", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "9332\n", + "15\n", + "5156\n", + "7\n" + ] + } + ], + "source": [ + "#create french tokenizer\n", + "fr_tokenizer = Tokenizer()\n", + "fr_tokenizer.fit_on_texts(fr)\n", + "#get vocabulary size and maximum length of a sentence \n", + "fr_vocab_size = len(fr_tokenizer.word_index) + 1\n", + "fr_length = max(max_len_fr_sentence)\n", + "print(fr_vocab_size)\n", + "print(fr_length)\n", + "\n", + "#create english tokenizer\n", + "eng_tokenizer = Tokenizer()\n", + "eng_tokenizer.fit_on_texts(eng)\n", + "#get vocabulary size and maximum length of a sentence \n", + "eng_vocab_size = len(eng_tokenizer.word_index) + 1\n", + "eng_length = max(max_len_eng_sentence)\n", + "print(eng_vocab_size)\n", + "print(eng_length)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f5d31d1c", + "metadata": {}, + "outputs": [], + "source": [ + "#split data into train and test \n", + "from sklearn.model_selection import train_test_split\n", + "train_eng, test_eng, train_fr, test_fr = train_test_split(eng, fr, test_size=0.1, random_state=42)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "732478ae", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "((4000, 15), (4000, 7))" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#fit the tokenizer and add padding to the training and testing data\n", + "train_fr_encoded = fr_tokenizer.texts_to_sequences(train_fr)\n", + "train_fr_encoded = pad_sequences(train_fr_encoded, maxlen=fr_length, padding='post')\n", + "\n", + "train_eng_encoded = eng_tokenizer.texts_to_sequences(train_eng)\n", + "train_eng_encoded = pad_sequences(train_eng_encoded, maxlen=eng_length, padding='post')\n", + "\n", + "test_fr_encoded = fr_tokenizer.texts_to_sequences(test_fr)\n", + "test_fr_encoded = pad_sequences(test_fr_encoded, maxlen=fr_length, padding='post')\n", + "\n", + "test_eng_encoded = eng_tokenizer.texts_to_sequences(test_eng)\n", + "test_eng_encoded = pad_sequences(test_eng_encoded, maxlen=eng_length, padding='post')\n", + "\n", + "test_fr_encoded.shape, test_eng_encoded.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "88561285", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model: \"model\"\n", + "_________________________________________________________________\n", + " Layer (type) Output Shape Param # \n", + "=================================================================\n", + " Encoder_Input (InputLayer) [(None, 7)] 0 \n", + " \n", + " Encoder_embedding (Embeddin (None, 7, 256) 1319936 \n", + " g) \n", + " \n", + " Encoder_LSTM (LSTM) (None, 256) 525312 \n", + " \n", + " Reperat_Vector (RepeatVecto (None, 15, 256) 0 \n", + " r) \n", + " \n", + " Decoder_LSTM (LSTM) (None, 15, 256) 525312 \n", + " \n", + " Decoder_Softmax (Dense) (None, 15, 9332) 2398324 \n", + " \n", + "=================================================================\n", + "Total params: 4,768,884\n", + "Trainable params: 4,768,884\n", + "Non-trainable params: 0\n", + "_________________________________________________________________\n" + ] + } + ], + "source": [ + "#create the model \n", + "# create the input layer for the encoder\n", + "encoder_inputs= Input(shape=(eng_length,), name='Encoder_Input')\n", + "# create an embedding layer for the encoder input\n", + "encoder_embedding=Embedding(eng_vocab_size, 256, name='Encoder_embedding')(encoder_inputs)\n", + "# create a LSTM layer with 256 units for the encoder\n", + "encoder_lstm=LSTM(256, name='Encoder_LSTM')(encoder_embedding)\n", + "# Repeat the encoder output fr_length times\n", + "repeat_vector=RepeatVector(fr_length, name='Repeat_Vector')(encoder_lstm)\n", + "\n", + "# Define a LSTM layer with 256 units for the decoder\n", + "decoder_lstm=LSTM(256, return_sequences=True, name='Decoder_LSTM')(repeat_vector)\n", + "# Define a Dense layer for the decoder output\n", + "decoder_softmax=Dense(fr_vocab_size, activation=\"softmax\", name='Decoder_Softmax')(decoder_lstm)\n", + "# Define the model with the encoder input as input and the decoder output as output\n", + "model= Model(inputs=encoder_inputs, outputs=decoder_softmax)\n", + "\n", + "# Compile the model \n", + "model.compile(optimizer=\"rmsprop\", loss=\"sparse_categorical_crossentropy\", metrics=['accuracy'])\n", + "model.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "9c68204c", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#plot the model\n", + "from keras.utils import plot_model\n", + "plot_model(model, to_file='model.png', show_shapes=True, show_layer_names=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "890fb658", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/100\n", + "64/64 [==============================] - 67s 986ms/step - loss: 3.3326 - accuracy: 0.6865 - val_loss: 2.1809 - val_accuracy: 0.7102\n", + "Epoch 2/100\n", + "64/64 [==============================] - 61s 954ms/step - loss: 2.1077 - accuracy: 0.7084 - val_loss: 2.0131 - val_accuracy: 0.7158\n", + "Epoch 3/100\n", + "64/64 [==============================] - 61s 958ms/step - loss: 1.9839 - accuracy: 0.7148 - val_loss: 1.9478 - val_accuracy: 0.7156\n", + "Epoch 4/100\n", + "64/64 [==============================] - 61s 956ms/step - loss: 1.9316 - accuracy: 0.7158 - val_loss: 1.9157 - val_accuracy: 0.7169\n", + "Epoch 5/100\n", + "64/64 [==============================] - 60s 936ms/step - loss: 1.9112 - accuracy: 0.7164 - val_loss: 1.9096 - val_accuracy: 0.7175\n", + "Epoch 6/100\n", + "64/64 [==============================] - 60s 931ms/step - loss: 1.8933 - accuracy: 0.7182 - val_loss: 1.9011 - val_accuracy: 0.7217\n", + "Epoch 7/100\n", + "64/64 [==============================] - 60s 933ms/step - loss: 1.8798 - accuracy: 0.7205 - val_loss: 1.8798 - val_accuracy: 0.7225\n", + "Epoch 8/100\n", + "64/64 [==============================] - 60s 935ms/step - loss: 1.8654 - accuracy: 0.7219 - val_loss: 1.9422 - val_accuracy: 0.7180\n", + "Epoch 9/100\n", + "64/64 [==============================] - 60s 933ms/step - loss: 1.8558 - accuracy: 0.7227 - val_loss: 1.8634 - val_accuracy: 0.7250\n", + "Epoch 10/100\n", + "64/64 [==============================] - 60s 932ms/step - loss: 1.8423 - accuracy: 0.7240 - val_loss: 1.8592 - val_accuracy: 0.7251\n", + "Epoch 11/100\n", + "64/64 [==============================] - 60s 930ms/step - loss: 1.8314 - accuracy: 0.7256 - val_loss: 1.8370 - val_accuracy: 0.7246\n", + "Epoch 12/100\n", + "64/64 [==============================] - 60s 931ms/step - loss: 1.8220 - accuracy: 0.7270 - val_loss: 1.8214 - val_accuracy: 0.7288\n", + "Epoch 13/100\n", + "64/64 [==============================] - 60s 933ms/step - loss: 1.8135 - accuracy: 0.7277 - val_loss: 1.8351 - val_accuracy: 0.7257\n", + "Epoch 14/100\n", + "64/64 [==============================] - 61s 954ms/step - loss: 1.8059 - accuracy: 0.7286 - val_loss: 1.8158 - val_accuracy: 0.7276\n", + "Epoch 15/100\n", + "64/64 [==============================] - 63s 984ms/step - loss: 1.7999 - accuracy: 0.7291 - val_loss: 1.8177 - val_accuracy: 0.7273\n", + "Epoch 16/100\n", + "64/64 [==============================] - 60s 935ms/step - loss: 1.7907 - accuracy: 0.7300 - val_loss: 1.8428 - val_accuracy: 0.7234\n", + "Epoch 17/100\n", + "64/64 [==============================] - 60s 938ms/step - loss: 1.7839 - accuracy: 0.7305 - val_loss: 1.8015 - val_accuracy: 0.7319\n", + "Epoch 18/100\n", + "64/64 [==============================] - 60s 935ms/step - loss: 1.7763 - accuracy: 0.7314 - val_loss: 1.7842 - val_accuracy: 0.7334\n", + "Epoch 19/100\n", + "64/64 [==============================] - 60s 937ms/step - loss: 1.7677 - accuracy: 0.7324 - val_loss: 1.7858 - val_accuracy: 0.7340\n", + "Epoch 20/100\n", + "64/64 [==============================] - 60s 934ms/step - loss: 1.7594 - accuracy: 0.7338 - val_loss: 1.8034 - val_accuracy: 0.7297\n", + "Epoch 21/100\n", + "64/64 [==============================] - 60s 939ms/step - loss: 1.7508 - accuracy: 0.7346 - val_loss: 1.7792 - val_accuracy: 0.7341\n", + "Epoch 22/100\n", + "64/64 [==============================] - 59s 929ms/step - loss: 1.7412 - accuracy: 0.7359 - val_loss: 1.7605 - val_accuracy: 0.7372\n", + "Epoch 23/100\n", + "64/64 [==============================] - 60s 932ms/step - loss: 1.7292 - accuracy: 0.7377 - val_loss: 1.7479 - val_accuracy: 0.7402\n", + "Epoch 24/100\n", + "64/64 [==============================] - 60s 933ms/step - loss: 1.7151 - accuracy: 0.7398 - val_loss: 1.7390 - val_accuracy: 0.7402\n", + "Epoch 25/100\n", + "64/64 [==============================] - 59s 930ms/step - loss: 1.7026 - accuracy: 0.7408 - val_loss: 1.7341 - val_accuracy: 0.7406\n", + "Epoch 26/100\n", + "64/64 [==============================] - 60s 931ms/step - loss: 1.6902 - accuracy: 0.7420 - val_loss: 1.7177 - val_accuracy: 0.7432\n", + "Epoch 27/100\n", + "64/64 [==============================] - 60s 932ms/step - loss: 1.6752 - accuracy: 0.7444 - val_loss: 1.7078 - val_accuracy: 0.7421\n", + "Epoch 28/100\n", + "64/64 [==============================] - 60s 930ms/step - loss: 1.6597 - accuracy: 0.7463 - val_loss: 1.6868 - val_accuracy: 0.7467\n", + "Epoch 29/100\n", + "64/64 [==============================] - 59s 928ms/step - loss: 1.6456 - accuracy: 0.7485 - val_loss: 1.6678 - val_accuracy: 0.7491\n", + "Epoch 30/100\n", + "64/64 [==============================] - 59s 929ms/step - loss: 1.6319 - accuracy: 0.7507 - val_loss: 1.6539 - val_accuracy: 0.7491\n", + "Epoch 31/100\n", + "64/64 [==============================] - 60s 934ms/step - loss: 1.6187 - accuracy: 0.7522 - val_loss: 1.6439 - val_accuracy: 0.7541\n", + "Epoch 32/100\n", + "64/64 [==============================] - 60s 933ms/step - loss: 1.6052 - accuracy: 0.7541 - val_loss: 1.6314 - val_accuracy: 0.7543\n", + "Epoch 33/100\n", + "64/64 [==============================] - 60s 934ms/step - loss: 1.5913 - accuracy: 0.7560 - val_loss: 1.6236 - val_accuracy: 0.7559\n", + "Epoch 34/100\n", + "64/64 [==============================] - 60s 942ms/step - loss: 1.5807 - accuracy: 0.7576 - val_loss: 1.6197 - val_accuracy: 0.7563\n", + "Epoch 35/100\n", + "64/64 [==============================] - 58s 912ms/step - loss: 1.5699 - accuracy: 0.7587 - val_loss: 1.6049 - val_accuracy: 0.7584\n", + "Epoch 36/100\n", + "64/64 [==============================] - 59s 926ms/step - loss: 1.5603 - accuracy: 0.7603 - val_loss: 1.6051 - val_accuracy: 0.7593\n", + "Epoch 37/100\n", + "64/64 [==============================] - 58s 903ms/step - loss: 1.5503 - accuracy: 0.7618 - val_loss: 1.6053 - val_accuracy: 0.7616\n", + "Epoch 38/100\n", + "64/64 [==============================] - 60s 934ms/step - loss: 1.5406 - accuracy: 0.7633 - val_loss: 1.5776 - val_accuracy: 0.7642\n", + "Epoch 39/100\n", + "64/64 [==============================] - 58s 902ms/step - loss: 1.5309 - accuracy: 0.7651 - val_loss: 1.5778 - val_accuracy: 0.7627\n", + "Epoch 40/100\n", + "64/64 [==============================] - 60s 932ms/step - loss: 1.5220 - accuracy: 0.7659 - val_loss: 1.5600 - val_accuracy: 0.7642\n", + "Epoch 41/100\n", + "64/64 [==============================] - 59s 915ms/step - loss: 1.5124 - accuracy: 0.7671 - val_loss: 1.5573 - val_accuracy: 0.7639\n", + "Epoch 42/100\n", + "64/64 [==============================] - 59s 929ms/step - loss: 1.5032 - accuracy: 0.7689 - val_loss: 1.5625 - val_accuracy: 0.7671\n", + "Epoch 43/100\n", + "64/64 [==============================] - 60s 932ms/step - loss: 1.4935 - accuracy: 0.7703 - val_loss: 1.5408 - val_accuracy: 0.7679\n", + "Epoch 44/100\n", + "64/64 [==============================] - 59s 923ms/step - loss: 1.4842 - accuracy: 0.7713 - val_loss: 1.5266 - val_accuracy: 0.7701\n", + "Epoch 45/100\n", + "64/64 [==============================] - 60s 937ms/step - loss: 1.4745 - accuracy: 0.7723 - val_loss: 1.5265 - val_accuracy: 0.7702\n", + "Epoch 46/100\n", + "64/64 [==============================] - 58s 912ms/step - loss: 1.4667 - accuracy: 0.7733 - val_loss: 1.5238 - val_accuracy: 0.7688\n", + "Epoch 47/100\n", + "64/64 [==============================] - 59s 924ms/step - loss: 1.4580 - accuracy: 0.7748 - val_loss: 1.5150 - val_accuracy: 0.7706\n", + "Epoch 48/100\n", + "64/64 [==============================] - 58s 910ms/step - loss: 1.4489 - accuracy: 0.7756 - val_loss: 1.5304 - val_accuracy: 0.7670\n", + "Epoch 49/100\n", + "64/64 [==============================] - 60s 940ms/step - loss: 1.4419 - accuracy: 0.7765 - val_loss: 1.5184 - val_accuracy: 0.7722\n", + "Epoch 50/100\n", + "64/64 [==============================] - 60s 932ms/step - loss: 1.4337 - accuracy: 0.7775 - val_loss: 1.5022 - val_accuracy: 0.7729\n", + "Epoch 51/100\n", + "64/64 [==============================] - 59s 925ms/step - loss: 1.4260 - accuracy: 0.7782 - val_loss: 1.4906 - val_accuracy: 0.7766\n", + "Epoch 52/100\n", + "64/64 [==============================] - 60s 934ms/step - loss: 1.4190 - accuracy: 0.7793 - val_loss: 1.4786 - val_accuracy: 0.7757\n", + "Epoch 53/100\n", + "64/64 [==============================] - 60s 936ms/step - loss: 1.4112 - accuracy: 0.7801 - val_loss: 1.4856 - val_accuracy: 0.7739\n", + "Epoch 54/100\n", + "64/64 [==============================] - 59s 923ms/step - loss: 1.4045 - accuracy: 0.7808 - val_loss: 1.4742 - val_accuracy: 0.7785\n", + "Epoch 55/100\n", + "64/64 [==============================] - 60s 945ms/step - loss: 1.3971 - accuracy: 0.7818 - val_loss: 1.4632 - val_accuracy: 0.7782\n", + "Epoch 56/100\n", + "64/64 [==============================] - 61s 949ms/step - loss: 1.3900 - accuracy: 0.7825 - val_loss: 1.4676 - val_accuracy: 0.7771\n", + "Epoch 57/100\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "64/64 [==============================] - 60s 944ms/step - loss: 1.3835 - accuracy: 0.7832 - val_loss: 1.4466 - val_accuracy: 0.7804\n", + "Epoch 58/100\n", + "64/64 [==============================] - 61s 949ms/step - loss: 1.3759 - accuracy: 0.7841 - val_loss: 1.4625 - val_accuracy: 0.7795\n", + "Epoch 59/100\n", + "64/64 [==============================] - 60s 940ms/step - loss: 1.3696 - accuracy: 0.7847 - val_loss: 1.4471 - val_accuracy: 0.7812\n", + "Epoch 60/100\n", + "64/64 [==============================] - 60s 942ms/step - loss: 1.3634 - accuracy: 0.7855 - val_loss: 1.4335 - val_accuracy: 0.7816\n", + "Epoch 61/100\n", + "64/64 [==============================] - 61s 949ms/step - loss: 1.3582 - accuracy: 0.7860 - val_loss: 1.4254 - val_accuracy: 0.7827\n", + "Epoch 62/100\n", + "64/64 [==============================] - 60s 942ms/step - loss: 1.3511 - accuracy: 0.7867 - val_loss: 1.4250 - val_accuracy: 0.7838\n", + "Epoch 63/100\n", + "64/64 [==============================] - 61s 951ms/step - loss: 1.3444 - accuracy: 0.7872 - val_loss: 1.4377 - val_accuracy: 0.7817\n", + "Epoch 64/100\n", + "64/64 [==============================] - 61s 953ms/step - loss: 1.3388 - accuracy: 0.7878 - val_loss: 1.4179 - val_accuracy: 0.7847\n", + "Epoch 65/100\n", + "64/64 [==============================] - 61s 947ms/step - loss: 1.3322 - accuracy: 0.7885 - val_loss: 1.4147 - val_accuracy: 0.7843\n", + "Epoch 66/100\n", + "64/64 [==============================] - 59s 930ms/step - loss: 1.3272 - accuracy: 0.7891 - val_loss: 1.4056 - val_accuracy: 0.7853\n", + "Epoch 67/100\n", + "64/64 [==============================] - 60s 932ms/step - loss: 1.3206 - accuracy: 0.7894 - val_loss: 1.3961 - val_accuracy: 0.7860\n", + "Epoch 68/100\n", + "64/64 [==============================] - 60s 936ms/step - loss: 1.3153 - accuracy: 0.7901 - val_loss: 1.4083 - val_accuracy: 0.7832\n", + "Epoch 69/100\n", + "64/64 [==============================] - 60s 943ms/step - loss: 1.3101 - accuracy: 0.7905 - val_loss: 1.3947 - val_accuracy: 0.7862\n", + "Epoch 70/100\n", + "64/64 [==============================] - 61s 949ms/step - loss: 1.3037 - accuracy: 0.7911 - val_loss: 1.3884 - val_accuracy: 0.7871\n", + "Epoch 71/100\n", + "64/64 [==============================] - 61s 950ms/step - loss: 1.2975 - accuracy: 0.7916 - val_loss: 1.3885 - val_accuracy: 0.7867\n", + "Epoch 72/100\n", + "64/64 [==============================] - 61s 951ms/step - loss: 1.2933 - accuracy: 0.7921 - val_loss: 1.3808 - val_accuracy: 0.7879\n", + "Epoch 73/100\n", + "64/64 [==============================] - 61s 959ms/step - loss: 1.2880 - accuracy: 0.7923 - val_loss: 1.3793 - val_accuracy: 0.7885\n", + "Epoch 74/100\n", + "64/64 [==============================] - 62s 963ms/step - loss: 1.2819 - accuracy: 0.7930 - val_loss: 1.3728 - val_accuracy: 0.7885\n", + "Epoch 75/100\n", + "64/64 [==============================] - 62s 965ms/step - loss: 1.2747 - accuracy: 0.7937 - val_loss: 1.3722 - val_accuracy: 0.7874\n", + "Epoch 76/100\n", + "64/64 [==============================] - 62s 963ms/step - loss: 1.2700 - accuracy: 0.7942 - val_loss: 1.3701 - val_accuracy: 0.7883\n", + "Epoch 77/100\n", + "64/64 [==============================] - 62s 969ms/step - loss: 1.2646 - accuracy: 0.7946 - val_loss: 1.3617 - val_accuracy: 0.7885\n", + "Epoch 78/100\n", + "64/64 [==============================] - 62s 974ms/step - loss: 1.2595 - accuracy: 0.7951 - val_loss: 1.3726 - val_accuracy: 0.7893\n", + "Epoch 79/100\n", + "64/64 [==============================] - 60s 942ms/step - loss: 1.2546 - accuracy: 0.7957 - val_loss: 1.3537 - val_accuracy: 0.7900\n", + "Epoch 80/100\n", + "64/64 [==============================] - 61s 947ms/step - loss: 1.2486 - accuracy: 0.7960 - val_loss: 1.3432 - val_accuracy: 0.7910\n", + "Epoch 81/100\n", + "64/64 [==============================] - 60s 940ms/step - loss: 1.2426 - accuracy: 0.7966 - val_loss: 1.3421 - val_accuracy: 0.7915\n", + "Epoch 82/100\n", + "64/64 [==============================] - 61s 946ms/step - loss: 1.2385 - accuracy: 0.7969 - val_loss: 1.3483 - val_accuracy: 0.7898\n", + "Epoch 83/100\n", + "64/64 [==============================] - 61s 948ms/step - loss: 1.2327 - accuracy: 0.7977 - val_loss: 1.3351 - val_accuracy: 0.7914\n", + "Epoch 84/100\n", + "64/64 [==============================] - 61s 960ms/step - loss: 1.2276 - accuracy: 0.7980 - val_loss: 1.3583 - val_accuracy: 0.7906\n", + "Epoch 85/100\n", + "64/64 [==============================] - 61s 954ms/step - loss: 1.2221 - accuracy: 0.7984 - val_loss: 1.3335 - val_accuracy: 0.7908\n", + "Epoch 86/100\n", + "64/64 [==============================] - 60s 941ms/step - loss: 1.2168 - accuracy: 0.7989 - val_loss: 1.3270 - val_accuracy: 0.7922\n", + "Epoch 87/100\n", + "64/64 [==============================] - 60s 937ms/step - loss: 1.2116 - accuracy: 0.7995 - val_loss: 1.3230 - val_accuracy: 0.7936\n", + "Epoch 88/100\n", + "64/64 [==============================] - 61s 958ms/step - loss: 1.2069 - accuracy: 0.7999 - val_loss: 1.3136 - val_accuracy: 0.7938\n", + "Epoch 89/100\n", + "64/64 [==============================] - 60s 944ms/step - loss: 1.2012 - accuracy: 0.8008 - val_loss: 1.3188 - val_accuracy: 0.7939\n", + "Epoch 90/100\n", + "64/64 [==============================] - 60s 934ms/step - loss: 1.1955 - accuracy: 0.8010 - val_loss: 1.3250 - val_accuracy: 0.7948\n", + "Epoch 91/100\n", + "64/64 [==============================] - 60s 936ms/step - loss: 1.1907 - accuracy: 0.8013 - val_loss: 1.3162 - val_accuracy: 0.7935\n", + "Epoch 92/100\n", + "64/64 [==============================] - 60s 936ms/step - loss: 1.1863 - accuracy: 0.8020 - val_loss: 1.3137 - val_accuracy: 0.7937\n", + "Epoch 93/100\n", + "64/64 [==============================] - 60s 937ms/step - loss: 1.1805 - accuracy: 0.8026 - val_loss: 1.3008 - val_accuracy: 0.7956\n", + "Epoch 94/100\n", + "64/64 [==============================] - 60s 940ms/step - loss: 1.1764 - accuracy: 0.8025 - val_loss: 1.3036 - val_accuracy: 0.7945\n", + "Epoch 95/100\n", + "64/64 [==============================] - 60s 940ms/step - loss: 1.1711 - accuracy: 0.8035 - val_loss: 1.2928 - val_accuracy: 0.7961\n", + "Epoch 96/100\n", + "64/64 [==============================] - 60s 933ms/step - loss: 1.1667 - accuracy: 0.8037 - val_loss: 1.2971 - val_accuracy: 0.7951\n", + "Epoch 97/100\n", + "64/64 [==============================] - 60s 943ms/step - loss: 1.1608 - accuracy: 0.8046 - val_loss: 1.2945 - val_accuracy: 0.7963\n", + "Epoch 98/100\n", + "64/64 [==============================] - 60s 933ms/step - loss: 1.1558 - accuracy: 0.8047 - val_loss: 1.3045 - val_accuracy: 0.7940\n", + "Epoch 99/100\n", + "64/64 [==============================] - 60s 936ms/step - loss: 1.1505 - accuracy: 0.8055 - val_loss: 1.2926 - val_accuracy: 0.7955\n", + "Epoch 100/100\n", + "64/64 [==============================] - 60s 935ms/step - loss: 1.1460 - accuracy: 0.8059 - val_loss: 1.2775 - val_accuracy: 0.7976\n" + ] + } + ], + "source": [ + "#create callback monitoring loss with patience 3\n", + "#stop training if loss does not improve in 3 straight epochs\n", + "callback = EarlyStopping(monitor='loss', patience=3)\n", + "\n", + "#fit the model\n", + "history = model.fit(train_eng_encoded, train_fr_encoded.reshape(train_fr_encoded.shape[0], train_fr_encoded.shape[1], 1), \n", + " epochs=100, batch_size=512, callbacks=[callback], validation_split = 0.1, verbose=1)#callbacks=[callback]," + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "fbb6f265", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAD4CAYAAAD8Zh1EAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAApx0lEQVR4nO3deXyVV4H/8c/JvpN9IQmEsG+BUEppaSmUqqXWWmvH4li1dWGsOlZ/+hq3GbUzP2d0RjvVmdGO67jQ+qt0tdNNKxRqC2UpDWEJYQsJCVnJvifn98e5hCQkECDh5rn5vl+v+0rufZ775ByW7z055zznGGstIiLifUH+LoCIiIwOBbqISIBQoIuIBAgFuohIgFCgi4gEiBB//eDk5GSbk5Pjrx8vIuJJu3btqrHWpgx1zG+BnpOTw86dO/3140VEPMkYUzLcMXW5iIgECAW6iEiAUKCLiAQIv/Whi0hg6erqoqysjPb2dn8XJSBERESQlZVFaGjoiN+jQBeRUVFWVkZsbCw5OTkYY/xdHE+z1lJbW0tZWRnTpk0b8fvU5SIio6K9vZ2kpCSF+SgwxpCUlHTRv+0o0EVk1CjMR8+l/Fl6LtCLTjXx/ZeLqG3u8HdRRETGFc8F+pHqZv7jz4epVqCLSD/19fX86Ec/uuj33XrrrdTX149+gfzAc4EeFuyK3Nnd6+eSiMh4Mlyg9/T0nPd9zz//PPHx8WNUqivLc7NcwkIU6CJyrq985SscOXKExYsXExoaSkxMDBkZGezZs4f9+/dzxx13UFpaSnt7Ow888ADr168Hzi5D0tzczNq1a7n++ut5/fXXyczM5JlnniEyMtLPNRs5zwZ6hwJdZNx68A/72F/eOKrXnDc5jm++Z/6wx7/zne9QWFjInj172Lx5M+9+97spLCzsm/b3i1/8gsTERNra2rj66qt5//vfT1JS0oBrFBcX89hjj/HTn/6UD3zgAzzxxBPcc889o1qPseTZQFcLXUTOZ9myZQPmcP/whz/kqaeeAqC0tJTi4uJzAn3atGksXrwYgKuuuorjx49fqeKOCs8Ferha6CLj3vla0ldKdHR03/ebN2/mT3/6E2+88QZRUVGsWrVqyDne4eHhfd8HBwfT1tZ2Rco6Wjw3KHom0Dt7FOgiclZsbCxNTU1DHmtoaCAhIYGoqCgOHjzItm3brnDprgzPtdDDgoMBdbmIyEBJSUmsWLGCBQsWEBkZSVpaWt+xW265hUceeYS8vDxmz57N8uXL/VjSseO9QFcfuogM49FHHx3y9fDwcF544YUhj53pJ09OTqawsLDv9S996UujXr6x5rkul7OBfv65pSIiE413A1196CIiA3gv0HWnqIjIkDwX6KHBbgUyBbqIyECeC3RjDGEhQZqHLiIyiOcCHdxcdAW6iMhAng10DYqKyOWIiYkBoLy8nLvuumvIc1atWsXOnTvPe52HH36Y1tbWvuf+XI7Xk4EeFhykPnQRGRWTJ09m48aNl/z+wYHuz+V4vRnoIQp0ERnoy1/+8oD10L/1rW/x4IMPsmbNGpYsWcLChQt55plnznnf8ePHWbBgAQBtbW2sW7eOvLw87r777gFrudx///0sXbqU+fPn881vfhNwC36Vl5ezevVqVq9eDbjleGtqagB46KGHWLBgAQsWLODhhx/u+3lz587lk5/8JPPnz+ed73znqK0Z47k7RUGBLjLuvfAVOLV3dK+ZvhDWfmfYw+vWrePzn/88n/70pwF4/PHHefHFF/nCF75AXFwcNTU1LF++nNtvv33Y/Tp//OMfExUVRUFBAQUFBSxZsqTv2Le//W0SExPp6elhzZo1FBQU8LnPfY6HHnqITZs2kZycPOBau3bt4pe//CXbt2/HWss111zDjTfeSEJCwpgt0+vdFrr60EWkn/z8fKqqqigvL+ftt98mISGBjIwMvva1r5GXl8fNN9/MyZMnqaysHPYaW7Zs6QvWvLw88vLy+o49/vjjLFmyhPz8fPbt28f+/fvPW57XXnuN973vfURHRxMTE8Odd97J1q1bgbFbptebLXT1oYuMb+dpSY+lu+66i40bN3Lq1CnWrVvHhg0bqK6uZteuXYSGhpKTkzPksrn9DdV6P3bsGN/73vfYsWMHCQkJ3HvvvRe8jrV22GNjtUyvd1voCnQRGWTdunX87ne/Y+PGjdx11100NDSQmppKaGgomzZtoqSk5LzvX7lyJRs2bACgsLCQgoICABobG4mOjmbSpElUVlYOWOhruGV7V65cydNPP01raystLS089dRT3HDDDaNY23N5s4UeEkxDW5e/iyEi48z8+fNpamoiMzOTjIwMPvShD/Ge97yHpUuXsnjxYubMmXPe999///3cd9995OXlsXjxYpYtWwbAokWLyM/P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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "#save the model\n", + "model.save('seq2seq.h5')\n", + "\n", + "#plot the loss history over the epochs\n", + "plt.plot(history.history['loss'])\n", + "plt.plot(history.history['val_loss'])\n", + "plt.legend(['train','validation'])" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "57f64bf7", + "metadata": {}, + "outputs": [], + "source": [ + "#Create a dictionary from word indices to words in the French vocabulary\n", + "fr_idx2word = {word:key for key, word in fr_tokenizer.word_index.items()}\n", + "\n", + "#Define a function that generates prediction text from prediction tokenized sequences \n", + "def generate_prediction_texts(pred_seqs, idx2word_map):\n", + " pred_texts = []\n", + " for prediction in preds:\n", + " #create an empty list to store the translated words in the prediction sequence\n", + " translated = []\n", + " for i in range(len(prediction)):\n", + " #Get the word corresponding to the current word token index in the French vocabulary, or None if not found\n", + " word_pred = fr_idx2word.get(prediction[i], None)\n", + " if i > 0:\n", + " #if the current word is the same as the previous word, add an empty string to the list\n", + " if (word_pred == fr_idx2word.get(prediction[i-1], None)) or (word_pred == None):\n", + " translated.append('')\n", + " #add the current word to the translated list\n", + " else:\n", + " translated.append(word_pred) \n", + " else:\n", + " #If this is the first word in the sequence and it is None, add an empty string to the translated list\n", + " if(word_pred == None):\n", + " translated.append('')\n", + " #Otherwise, add the current word to the translated list\n", + " else:\n", + " translated.append(word_pred) \n", + " #Join the translated words into a string and add it to the list of predicted texts\n", + " pred_texts.append(' '.join(translated))\n", + " #Return predicted texts\n", + " return pred_texts" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "d85a1638", + "metadata": {}, + "outputs": [], + "source": [ + "#get the model\n", + "model=load_model('./seq2seq.h5')" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "2b2eb44b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "125/125 [==============================] - 5s 41ms/step\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
sourcetargetpredicted
13787don t talk to mene me parle pasne me pas
5128he is awesomeil est génialil est
9125they quarreledelles se sont disputéeselles ont
35041i have a bad sunburnj ai un mauvais coup de soleilj ai un
\n", + "
" + ], + "text/plain": [ + " source target \\\n", + "13787 don t talk to me ne me parle pas \n", + "5128 he is awesome il est génial \n", + "9125 they quarreled elles se sont disputées \n", + "35041 i have a bad sunburn j ai un mauvais coup de soleil \n", + "\n", + " predicted \n", + "13787 ne me pas \n", + "5128 il est \n", + "9125 elles ont \n", + "35041 j ai un " + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Predict the target sequences for the test data\n", + "pred_probs = model.predict(test_eng_enc.reshape((test_eng_enc.shape[0], test_eng_enc.shape[1])), verbose=1)\n", + "preds = [np.argmax(i, axis=1) for i in pred_probs]\n", + "\n", + "#convert the prediction from indices to text using the function defined before\n", + "pred_texts = generate_prediction_texts(pred_seqs=preds, idx2word_map=fr_idx2word)\n", + "#plot the original english sentence, the target french and the predicted french\n", + "pred_df = pd.DataFrame({'source': test_eng, 'target' : test_fr, 'predicted' : pred_texts})\n", + "pred_df.head(50)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "4a8699fd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
sourcetargetpredicted
13787don t talk to mene me parle pasne me pas
5128he is awesomeil est génialil est
9125they quarreledelles se sont disputéeselles ont
35041i have a bad sunburnj ai un mauvais coup de soleilj ai un
3510i am workingje suis en train de travaillerje suis
\n", + "
" + ], + "text/plain": [ + " source target \\\n", + "13787 don t talk to me ne me parle pas \n", + "5128 he is awesome il est génial \n", + "9125 they quarreled elles se sont disputées \n", + "35041 i have a bad sunburn j ai un mauvais coup de soleil \n", + "3510 i am working je suis en train de travailler \n", + "\n", + " predicted \n", + "13787 ne me pas \n", + "5128 il est \n", + "9125 elles ont \n", + "35041 j ai un \n", + "3510 je suis " + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pred_df[11:16]" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "baca08b4", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\lucas\\anaconda3\\lib\\site-packages\\nltk\\translate\\bleu_score.py:552: UserWarning: \n", + "The hypothesis contains 0 counts of 2-gram overlaps.\n", + "Therefore the BLEU score evaluates to 0, independently of\n", + "how many N-gram overlaps of lower order it contains.\n", + "Consider using lower n-gram order or use SmoothingFunction()\n", + " warnings.warn(_msg)\n", + "C:\\Users\\lucas\\anaconda3\\lib\\site-packages\\nltk\\translate\\bleu_score.py:552: UserWarning: \n", + "The hypothesis contains 0 counts of 3-gram overlaps.\n", + "Therefore the BLEU score evaluates to 0, independently of\n", + "how many N-gram overlaps of lower order it contains.\n", + "Consider using lower n-gram order or use SmoothingFunction()\n", + " warnings.warn(_msg)\n", + "C:\\Users\\lucas\\anaconda3\\lib\\site-packages\\nltk\\translate\\bleu_score.py:552: UserWarning: \n", + "The hypothesis contains 0 counts of 4-gram overlaps.\n", + "Therefore the BLEU score evaluates to 0, independently of\n", + "how many N-gram overlaps of lower order it contains.\n", + "Consider using lower n-gram order or use SmoothingFunction()\n", + " warnings.warn(_msg)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Average BLEU score: 0.0319\n", + "Corpus-level BLEU score: 0.1193\n" + ] + } + ], + "source": [ + "#Tokenize the test sentences and predicted translations\n", + "ref_tokenized = [[word_tokenize(sentence.lower())] for sentence in test_fr]\n", + "pred_tokenized = [word_tokenize(sentence.lower()) for sentence in pred_texts]\n", + "\n", + "#Compute BLEU score\n", + "bleu_scores = []\n", + "for i in range(len(pred_tokenized)):\n", + " bleu_scores.append(sentence_bleu(ref_tokenized[i], pred_tokenized[i]))\n", + "\n", + "#Compute corpus-level BLEU score\n", + "corpus_bleu_score = corpus_bleu(ref_tokenized, pred_tokenized)\n", + "\n", + "print(f\"Average BLEU score: {np.mean(bleu_scores):.4f}\")\n", + "print(f\"Corpus-level BLEU score: {corpus_bleu_score:.4f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bb554898", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}