avatarJaimin Mungalpara

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

10415

Abstract

tr">target_characters</span> = set()</pre></div><div id="0461"><pre><span class="hljs-keyword">for</span> <span class="hljs-type">char</span> in input_text:</pre></div><div id="1f1d"><pre> <span class="hljs-keyword">for</span> <span class="hljs-keyword">chars</span> <span class="hljs-keyword">in</span> <span class="hljs-keyword">char</span>:</pre></div><div id="4e11"><pre> <span class="hljs-built_in"> if </span>chars<span class="hljs-built_in"> not </span>in input_characters:</pre></div><div id="33db"><pre> input_characters.<span class="hljs-built_in">add</span>(<span class="hljs-keyword">chars</span>)</pre></div><div id="6e45"><pre><span class="hljs-keyword">for</span> <span class="hljs-type">char</span> in target_text:</pre></div><div id="269d"><pre> <span class="hljs-keyword">for</span> <span class="hljs-keyword">chars</span> <span class="hljs-keyword">in</span> <span class="hljs-keyword">char</span>:</pre></div><div id="db37"><pre> <span class="hljs-built_in"> if </span>chars<span class="hljs-built_in"> not </span>in target_characters:</pre></div><div id="cdef"><pre> target_characters.<span class="hljs-built_in">add</span>(<span class="hljs-keyword">chars</span>)</pre></div><div id="bb0e"><pre><span class="hljs-variable">input_characters</span> = <span class="hljs-function"><span class="hljs-title">sorted</span>(<span class="hljs-title">list</span>(<span class="hljs-variable">input_characters</span>))</span></pre></div><div id="ad94"><pre><span class="hljs-variable">target_characters</span> = <span class="hljs-function"><span class="hljs-title">sorted</span>(<span class="hljs-title">list</span>(<span class="hljs-variable">target_characters</span>))</span></pre></div><div id="5b24"><pre><span class="hljs-attr">num_encoder_tokens</span> = len(input_characters)</pre></div><div id="f087"><pre><span class="hljs-attr">num_decoder_tokens</span> = len(target_characters)</pre></div><div id="d646"><pre>max_encoder_seq_length = <span class="hljs-built_in">max</span>([<span class="hljs-built_in">len</span>(txt) for txt in input_text])</pre></div><div id="6bb2"><pre>max_decoder_seq_length = <span class="hljs-built_in">max</span>([<span class="hljs-built_in">len</span>(txt) for txt in target_text])</pre></div><div id="170a"><pre><span class="hljs-function"><span class="hljs-title">print</span><span class="hljs-params">(“Number of samples:”, len(input_text)</span></span>)</pre></div><div id="f154"><pre><span class="hljs-built_in">print</span>(“Number of <span class="hljs-built_in">unique</span> input <span class="hljs-built_in">tokens</span>:”, num_encoder_tokens)</pre></div><div id="1e7a"><pre><span class="hljs-built_in">print</span>(“Number of <span class="hljs-built_in">unique</span> output <span class="hljs-built_in">tokens</span>:”, num_decoder_tokens)</pre></div><div id="4776"><pre><span class="hljs-built_in">print</span>(“<span class="hljs-built_in">Max</span> <span class="hljs-keyword">sequence</span> length for inputs:”, max_encoder_seq_length)</pre></div><div id="2681"><pre><span class="hljs-built_in">print</span>(“<span class="hljs-built_in">Max</span> <span class="hljs-keyword">sequence</span> length for outputs:”, max_decoder_seq_length)</pre></div><p id="bb79">The output will be like this in this we will take number of sentences, max sentences length and input / output token which will contain unique letters .</p><div id="e6d6"><pre><span class="hljs-built_in">Number</span> of samples: <span class="hljs-number">10000</span> <span class="hljs-built_in">Number</span> of unique input tokens: <span class="hljs-number">93</span> <span class="hljs-built_in">Number</span> of unique output tokens: <span class="hljs-number">154</span> <span class="hljs-built_in">Max</span> sequence <span class="hljs-built_in">length</span> <span class="hljs-keyword">for</span> inputs: <span class="hljs-number">233</span> <span class="hljs-built_in">Max</span> sequence <span class="hljs-built_in">length</span> <span class="hljs-keyword">for</span> outputs: <span class="hljs-number">346</span></pre></div><p id="d1dc">Now, convert the data into dictionary which will take data from unique character and give a numerical value to it.</p><div id="6b10"><pre>input_token_index = dict([(<span class="hljs-type">char</span>, i) <span class="hljs-keyword">for</span> i, <span class="hljs-type">char</span> in <span class="hljs-title function_">enumerate</span><span class="hljs-params">(input_characters)</span>])</pre></div><div id="6afe"><pre>target_token_index = dict([(<span class="hljs-type">char</span>, i) <span class="hljs-keyword">for</span> i, <span class="hljs-type">char</span> in <span class="hljs-title function_">enumerate</span><span class="hljs-params">(target_characters)</span>])</pre></div><p id="0adb">Output would be like this .</p><div id="3629"><pre><span class="hljs-variable">A</span><span class="hljs-operator">:</span> <span class="hljs-number">31</span><span class="hljs-operator">,</span><span class="hljs-variable">B</span><span class="hljs-operator">:</span> <span class="hljs-number">32</span><span class="hljs-operator">,</span><span class="hljs-built_in">C</span><span class="hljs-operator">:</span> <span class="hljs-number">33</span><span class="hljs-operator">,</span><span class="hljs-built_in">D</span><span class="hljs-operator">:</span> <span class="hljs-number">34</span><span class="hljs-operator">,</span><span class="hljs-built_in">E</span><span class="hljs-operator">:</span> <span class="hljs-number">35</span><span class="hljs-operator">,</span><span class="hljs-variable">F</span><span class="hljs-operator">:</span> <span class="hljs-number">36</span><span class="hljs-operator">,</span><span class="hljs-variable">G</span><span class="hljs-operator">:</span> <span class="hljs-number">37</span><span class="hljs-operator">,</span><span class="hljs-variable">H</span><span class="hljs-operator">:</span> <span class="hljs-number">38</span><span class="hljs-operator">,</span><span class="hljs-built_in">I</span><span class="hljs-operator">:</span> <span class="hljs-number">39</span><span class="hljs-operator">,</span><span class="hljs-variable">J</span><span class="hljs-operator">:</span> <span class="hljs-number">40</span><span class="hljs-operator">,</span><span class="hljs-built_in">K</span><span class="hljs-operator">:</span> <span class="hljs-number">41</span><span class="hljs-operator">,</span><span class="hljs-variable">L</span><span class="hljs-operator">:</span> <span class="hljs-number">42</span><span class="hljs-operator">,</span><span class="hljs-variable">M</span><span class="hljs-operator">:</span> <span class="hljs-number">43</span><span class="hljs-operator">,</span><span class="hljs-built_in">N</span><span class="hljs-operator">:</span> <span class="hljs-number">44</span><span class="hljs-operator">,</span></pre></div><p id="feff">Next step would be embedding of the data. This step will take encoder input , decoder input and decoder output data. We will take dimensions according to input and output sequence length. Also the data would be one hot encoded and padded with 0 where the value is not present.</p><div id="02da"><pre><span class="hljs-attr">encoder_input_data</span> = np.zeros(</pre></div><div id="9432"><pre>(len(input_text), max_encoder_seq_length, num_encoder_tokens), d<span class="hljs-keyword">type</span>="float32"</pre></div><div id="ff0d"><pre>)</pre></div><div id="aaa1"><pre><span class="hljs-attr">decoder_input_data</span> = np.zeros(</pre></div><div id="a2b1"><pre>(len(input_text), max_decoder_seq_length, num_decoder_tokens), d<span class="hljs-keyword">type</span>="float32"</pre></div><div id="2233"><pre>)</pre></div><div id="0242"><pre><span class="hljs-attr">decoder_target_data</span> = np.zeros(</pre></div><div id="cb0d"><pre>(len(input_text), max_decoder_seq_length, num_decoder_tokens), d<span class="hljs-keyword">type</span>="float32"</pre></div><div id="9e22"><pre>)</pre></div><div id="d560"><pre>for <span class="hljs-selector-tag">i</span>, (input_texts, target_texts) in <span class="hljs-built_in">enumerate</span>(zip(input_text, target_text)):</pre></div><div id="994a"><pre> for t, char in <span class="hljs-built_in">enumerate</span>(input_texts):</pre></div><div id="3187"><pre> <span class="hljs-attribute">encoder_input_data</span>[i, t, input_token_index[char]] = <span class="hljs-number">1</span>.<span class="hljs-number">0</span></pre></div><div id="3ef9"><pre> <span class="hljs-attribute">encoder_input_data</span>[i, t + <span class="hljs-number">1</span> :, input_token_index[<span class="hljs-string">" "</span>]] = <span class="hljs-number">1</span>.<span class="hljs-number">0</span></pre></div><div id="9e98"><pre> for t, char in <span class="hljs-built_in">enumerate</span>(target_texts):</pre></div><div id="84b6"><pre># decoder_target_data <span class="hljs-keyword">is</span> ahead of decoder_input_data <span class="hljs-keyword">by</span> one timestep</pre></div><div id="790d"><pre> <span class="hljs-attribute">decoder_input_data</span>[i, t, target_token_index[char]] = <span class="hljs-number">1</span>.<span class="hljs-number">0</span></pre></div><div id="5d4d"><pre> <span class="hljs-attribute">if</span> t > <span class="hljs-number">0</span>:</pre></div><div id="f072"><pre># decoder_target_data will <span class="hljs-keyword">be</span> ahead <span class="hljs-keyword">by</span> one timestep</pre></div><div id="98fc"><pre># <span class="hljs-keyword">and</span> will <span class="hljs-keyword">not</span> <span class="hljs-keyword">include</span> the <span class="hljs-keyword">start</span> <span class="hljs-type">character</span>.</pre></div><div id="baab"><pre> <span class="hljs-attribute">decoder_target_data</span>[i, t - <span class="hljs-number">1</span>, target_token_index[char]] = <span class="hljs-number">1</span>.<span class="hljs-number">0</span></pre></div><div id="f693"><pre> <span class="hljs-attribute">decoder_input_data</span>[i, t + <span class="hljs-number">1</span> :, target_token_index[<span class="hljs-string">" "</span>]] = <span class="hljs-number">1</span>.<span class="hljs-number">0</span></pre></div><div id="97d8"><pre> <span class="hljs-attribute">decoder_target_data</span>[i, t:, target_token_index[<span class="hljs-string">" "</span>]] = <span class="hl

Options

js-number">1</span>.<span class="hljs-number">0</span></pre></div><p id="5b15">Now we will define Encoder and Decoder model. Which contains embedded data from previous step, LSTM layer, and dense layer . Here, as per architecture we will not consider output on encoder we will only take state h and c from encoder and pass it to decoder.</p><div id="b801"><pre><span class="hljs-comment"># Define an input sequence and process it.</span></pre></div><div id="8967"><pre>encoder_inputs = keras.Input(<span class="hljs-built_in">shape</span>=(<span class="hljs-keyword">None</span>, num_encoder_tokens))</pre></div><div id="a87b"><pre><span class="hljs-attr">encoder</span> = keras.layers.LSTM(latent_dim, return_state=<span class="hljs-literal">True</span>)</pre></div><div id="49d9"><pre><span class="hljs-built_in">encoder_outputs,</span> state_h, state_c = encoder(encoder_inputs)</pre></div><div id="2926"><pre><span class="hljs-comment"># We discard encoder_outputs and only keep the states.</span></pre></div><div id="f1c1"><pre><span class="hljs-attr">encoder_states</span> = [state_h, state_c]</pre></div><div id="154b"><pre># <span class="hljs-keyword">Set</span> up the decoder, <span class="hljs-built_in">using</span> encoder_states <span class="hljs-built_in">as</span> initial state.</pre></div><div id="5b9d"><pre>decoder_inputs = keras.Input(<span class="hljs-built_in">shape</span>=(<span class="hljs-keyword">None</span>, num_decoder_tokens))</pre></div><div id="411d"><pre># We <span class="hljs-keyword">set</span> up our decoder <span class="hljs-keyword">to</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">full</span> output <span class="hljs-keyword">sequences</span>,</pre></div><div id="63b0"><pre># <span class="hljs-keyword">and</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">internal</span> states <span class="hljs-keyword">as</span> well. We don't <span class="hljs-keyword">use</span> the</pre></div><div id="270a"><pre><span class="hljs-comment"># return states in the training model, but we will use them in inference.</span></pre></div><div id="46fe"><pre>decoder_lstm = keras.layers.LSTM(latent_dim, <span class="hljs-attribute">return_sequences</span>=<span class="hljs-literal">True</span>, <span class="hljs-attribute">return_state</span>=<span class="hljs-literal">True</span>)</pre></div><div id="4a3f"><pre>decoder_outputs, <span class="hljs-literal"></span>, <span class="hljs-literal"></span> = decoder_lstm(decoder_inputs, initial_state=encoder_states)</pre></div><div id="f5f1"><pre><span class="hljs-attr">decoder_dense</span> = keras.layers.Dense(num_decoder_tokens, activation=<span class="hljs-string">"softmax"</span>)</pre></div><div id="b5ab"><pre><span class="hljs-attr">decoder_outputs</span> = decoder_dense(decoder_outputs)</pre></div><div id="1d7d"><pre><span class="hljs-comment"># Define the model that will turn</span></pre></div><div id="f529"><pre># encoder_input_data & decoder_input_data into decoder_target_data</pre></div><div id="84d1"><pre><span class="hljs-keyword">model</span> = keras.<span class="hljs-keyword">Model</span>([encoder_inputs, decoder_inputs], decoder_outputs)</pre></div><p id="4fb2">Now we can train the model. Here optimization function is rmsprop and I have trained model up to 100 epochs.</p><div id="574e"><pre><span class="hljs-keyword">model</span>.compile(</pre></div><div id="ff74"><pre><span class="hljs-attribute">optimizer</span>=<span class="hljs-string">"rmsprop"</span>, <span class="hljs-attribute">loss</span>=<span class="hljs-string">"categorical_crossentropy"</span>, metrics=[<span class="hljs-string">"accuracy"</span>]</pre></div><div id="f5c0"><pre>)</pre></div><div id="52f6"><pre><span class="hljs-keyword">model</span>.fit(</pre></div><div id="792b"><pre><span class="hljs-string">[encoder_input_data, decoder_input_data]</span>,</pre></div><div id="a286"><pre><span class="hljs-built_in">decoder_target_data,</span></pre></div><div id="12e3"><pre><span class="hljs-attr">batch_size</span>=batch_size,</pre></div><div id="c25b"><pre><span class="hljs-attr">epochs</span>=epochs,</pre></div><div id="b03b"><pre><span class="hljs-attribute">validation_split</span>=<span class="hljs-number">0</span>.<span class="hljs-number">2</span>,</pre></div><div id="2b84"><pre>)</pre></div><div id="4123"><pre><span class="hljs-meta"># Save model</span></pre></div><div id="d801"><pre><span class="hljs-keyword">model</span>.save(<span class="hljs-string">"s2s"</span>)</pre></div><p id="6fbd">The results after training up to 100 epochs is</p><div id="bd74"><pre>Epoch <span class="hljs-number">93</span>/<span class="hljs-number">100</span> <span class="hljs-number">125</span><span class="hljs-regexp">/125 [==============================] - 11s 86ms/</span><span class="hljs-keyword">step</span> - loss: <span class="hljs-number">0.0232</span> - accuracy: <span class="hljs-number">0.9929</span> - val_loss: <span class="hljs-number">0.0399</span> - val_accuracy: <span class="hljs-number">0.9903</span> Epoch <span class="hljs-number">94</span>/<span class="hljs-number">100</span> <span class="hljs-number">125</span><span class="hljs-regexp">/125 [==============================] - 11s 87ms/</span><span class="hljs-keyword">step</span> - loss: <span class="hljs-number">0.0232</span> - accuracy: <span class="hljs-number">0.9928</span> - val_loss: <span class="hljs-number">0.0399</span> - val_accuracy: <span class="hljs-number">0.9903</span> Epoch <span class="hljs-number">95</span>/<span class="hljs-number">100</span> <span class="hljs-number">125</span><span class="hljs-regexp">/125 [==============================] - 11s 87ms/</span><span class="hljs-keyword">step</span> - loss: <span class="hljs-number">0.0230</span> - accuracy: <span class="hljs-number">0.9929</span> - val_loss: <span class="hljs-number">0.0400</span> - val_accuracy: <span class="hljs-number">0.9904</span> Epoch <span class="hljs-number">96</span>/<span class="hljs-number">100</span> <span class="hljs-number">125</span><span class="hljs-regexp">/125 [==============================] - 11s 86ms/</span><span class="hljs-keyword">step</span> - loss: <span class="hljs-number">0.0230</span> - accuracy: <span class="hljs-number">0.9929</span> - val_loss: <span class="hljs-number">0.0397</span> - val_accuracy: <span class="hljs-number">0.9902</span> Epoch <span class="hljs-number">97</span>/<span class="hljs-number">100</span> <span class="hljs-number">125</span><span class="hljs-regexp">/125 [==============================] - 11s 86ms/</span><span class="hljs-keyword">step</span> - loss: <span class="hljs-number">0.0228</span> - accuracy: <span class="hljs-number">0.9929</span> - val_loss: <span class="hljs-number">0.0392</span> - val_accuracy: <span class="hljs-number">0.9905</span> Epoch <span class="hljs-number">98</span>/<span class="hljs-number">100</span> <span class="hljs-number">125</span><span class="hljs-regexp">/125 [==============================] - 11s 86ms/</span><span class="hljs-keyword">step</span> - loss: <span class="hljs-number">0.0230</span> - accuracy: <span class="hljs-number">0.9929</span> - val_loss: <span class="hljs-number">0.0421</span> - val_accuracy: <span class="hljs-number">0.9897</span> Epoch <span class="hljs-number">99</span>/<span class="hljs-number">100</span> <span class="hljs-number">125</span><span class="hljs-regexp">/125 [==============================] - 11s 86ms/</span><span class="hljs-keyword">step</span> - loss: <span class="hljs-number">0.0230</span> - accuracy: <span class="hljs-number">0.9928</span> - val_loss: <span class="hljs-number">0.0397</span> - val_accuracy: <span class="hljs-number">0.9904</span> Epoch <span class="hljs-number">100</span>/<span class="hljs-number">100</span> <span class="hljs-number">125</span><span class="hljs-regexp">/125 [==============================] - 11s 87ms/</span><span class="hljs-keyword">step</span> - loss: <span class="hljs-number">0.0230</span> - accuracy: <span class="hljs-number">0.9928</span> - val_loss: <span class="hljs-number">0.0391</span> - val_accuracy: <span class="hljs-number">0.9906</span></pre></div><div id="a703"><pre>WARNING:<span class="hljs-built_in">abs</span><span class="hljs-variable">l:Found</span> untraced functions such <span class="hljs-keyword">as</span> lstm_cell_layer_call_fn, lstm_cell_layer_call_and_return_conditional_losses, lstm_cell_1_layer_call_fn, lstm_cell_1_layer_call_and_return_conditional_losses, lstm_cell_layer_call_fn <span class="hljs-keyword">while</span> saving (showing <span class="hljs-number">5</span> of <span class="hljs-number">10</span>). These functions will not <span class="hljs-keyword">be</span> directly callable after loading. WARNING:<span class="hljs-built_in">abs</span><span class="hljs-variable">l:Found</span> untraced functions such <span class="hljs-keyword">as</span> lstm_cell_layer_call_fn, lstm_cell_layer_call_and_return_conditional_losses, lstm_cell_1_layer_call_fn, lstm_cell_1_layer_call_and_return_conditional_losses, lstm_cell_layer_call_fn <span class="hljs-keyword">while</span> saving (showing <span class="hljs-number">5</span> of <span class="hljs-number">10</span>). These functions will not <span class="hljs-keyword">be</span> directly callable after loading.INFO:tensorflo<span class="hljs-variable">w:Assets</span> written <span class="hljs-keyword">to</span>: s2s/assetsINFO:tensorflo<span class="hljs-variable">w:Assets</span> written <span class="hljs-keyword">to</span>: s2s/assets</pre></div><h1 id="3a82">What’s Next :</h1><p id="36d0">In the next part of this series, we will use attention for english to hindi translation.</p><p id="d9d4"><b>References</b></p><ol><li><a href="https://keras.io/examples/nlp/lstm_seq2seq/">https://keras.io/examples/nlp/lstm_seq2seq/</a></li><li><a href="https://towardsdatascience.com/nlp-sequence-to-sequence-networks-part-1-processing-text-data-d141a5643b72">https://towardsdatascience.com/nlp-sequence-to-sequence-networks-part-1-processing-text-data-d141a5643b72</a></li><li><a href="https://towardsdatascience.com/nlp-sequence-to-sequence-networks-part-2-seq2seq-model-encoderdecoder-model-6c22e29fd7e1">https://towardsdatascience.com/nlp-sequence-to-sequence-networks-part-2-seq2seq-model-encoderdecoder-model-6c22e29fd7e1</a></li></ol></article></body>

Encoder-Decoder model for Machine Translation

In this article I will try to explain sequence to sequence model which is encoder-decoder. Initially this model was developed for machine translation but later it was useful for many other applications like text summarization, question answering and Video captioning etc.

The reader should know about neural networks, activation functions, loss functions, optimizers, RNN, LSTM, GRU, Bidirectional LSTM. If you are not aware about RNN, LSTM, GRU or Bidirectional LSTM you can take a look at my previous articles.

Sequence to sequence model can be used with below application.

  1. Machine Translation : In a paper which was released in 2016 Google has mentioned how sequence to sequence surpassed all the previous methods in Machine translation
  2. Speech Recognition : The same model can be used in recognition of speech and Google mentioned it in another paper.
  3. Image Captioning :- In 2015 Google mentioned a research paper implemented sequence to sequence model in captioning of image and video.

Architecture of Encoder — Decoder

In a research paper in 2014 google mentioned about sequence to sequence model and how it can be used with in difference size of input and output data. For example, if we want to convert from English words to Hindi, we can see that we have 4 words in input but 6 words in output.

In this kind of problem traditional LSTM architecture can not work because of sequences which required for translations. That’s why sequence to sequence model was introduced for this kind of problems.

The architecture of encoder decoder contains 3 parts. Encoder, Encoder vector and Decoder.

http://www.wildml.com/2016/04/deep-learning-for-chatbots-part-1-introduction/

Encoder

Encoder cell are simple RNN cell (LSTM or GRU can be used for better performance ) which takes the input vectors. The input is taken as a single word vector at each and every time stamp but the out is not taken at each state. Output of each encoder cell is rejected and internal state are used to generate encoder vector. The hidden state can be calculated by this formula.

It is the simple calculation of weight applied to hidden state h at t-1 and input x at t. Now, let’s see inside of encoder.

LSTM/GRU cell take one input at a time and by this way we take sequence as an input. X1, X2, X3 …Xm are the input and Y1,Y2,Y3..Ym are the output shown in the architecture. While, h0,c0…hm,cm are the internal state which would be transferred to decoder. Where h is hidden state and c is the weights, both of it can be transferred to decoder. We can take bidirectional or stacked LSTM also in this architecture according to requirement. Here, we are no considering output Y0…Ym but we will take htct as a encoder vector and it would be passed to decoder. Hidden state can be calculates with below formula. It is the simple addition of weights and previous output along with current input.

Now, let’s consider and example for better understanding. Here we are passing text in the form of vectors ( In pic original text is shown). The vectors could be in the form of embedding, word2vec or one hot representation.

English text input to Encoder

In above image we can see that X1 = I , X2 = like , X3 = NLP and X4 is End of the sentence. All these text data are given to encoder input in the form of vector.

Encoder Vector

  • This is the hidden state (h4) produced from the encoder part of the model. Which is shown in above figure and formula is also given.
  • This vector store the information in sequence. For example as per property of LSTM it stores the information of precious state, at h4 state it it encapsulate the information for all input elements in order to help the decoder make accurate predictions.

Decoder

  • Same as encoder decoder also consist of series of RNN/LSTM. Here we are taking an output at each time stamp t.
  • Each RNN cell produce output y_t with the previous output y_t-1 and hidden state ht-1. Which can be calculated with below formula
  • Output y_t is calculated with ht and y_t-1. So we can calculate y_t with below formula. Also as mentioned in a research paper of encoder decoder we use softmax function to determine the output as this prediction is probabilistic.

To continue with example mentioned above the embedded vector is given as an input to decoder. To understand starting and ending of the sentence we will add start_ at the starting and _end at the ending of the sentence in the training dataset. So our training data will look like this.

X = “I Love NLP”

Y = “Start_ मुझे एनएलपी पसंद है _End”

Visually this can be shown as below. Input as a encoder vector and hidden state are given to decoder input. The decoder decode the starting of the sentence from Start_ and it will convert the sentence into hindi. The decoder will understand end of the sentence with _End word.

At each and every stage the loss is calculated between actual and predicted words y and ŷ. Based on calculated loss the weights are getting updated in back propagation and finally the sentence would be converted in Hindi.

Implementation of Encoder Decoder with Keras

I have taken dataset for the training from here. Code can be found here.

Import all the required libraries

import numpy as np
import tensorflow as tf
from tensorflow import keras
import pandas as pd
batch_size = 64 # Batch size for training.
epochs = 100 # Number of epochs to train for.
latent_dim = 256 # Latent dimensionality of the encoding space.
num_samples = 10000 # Number of samples to train on.
# Path to the data txt file on disk.

Import Dataset of Hindi and English sentences

hindi_sen = open('IITB.en-hi.hi').read().split("\n")[:-1]
eng_sen = open('IITB.en-hi.en').read().split("\n")[:-1]

Create a set of input and target character in which we will take unique character which are used in Hindi and English sentences.

# Vectorize the data.
input_characters = set()
target_characters = set()
for char in input_text:
    for chars in char:
       if chars not in input_characters:
           input_characters.add(chars)
for char in target_text:
    for chars in char:
       if chars not in target_characters:
          target_characters.add(chars)
input_characters = sorted(list(input_characters))
target_characters = sorted(list(target_characters))
num_encoder_tokens = len(input_characters)
num_decoder_tokens = len(target_characters)
max_encoder_seq_length = max([len(txt) for txt in input_text])
max_decoder_seq_length = max([len(txt) for txt in target_text])
print(“Number of samples:”, len(input_text))
print(“Number of unique input tokens:”, num_encoder_tokens)
print(“Number of unique output tokens:”, num_decoder_tokens)
print(“Max sequence length for inputs:”, max_encoder_seq_length)
print(“Max sequence length for outputs:”, max_decoder_seq_length)

The output will be like this in this we will take number of sentences, max sentences length and input / output token which will contain unique letters .

Number of samples: 10000
Number of unique input tokens: 93
Number of unique output tokens: 154
Max sequence length for inputs: 233
Max sequence length for outputs: 346

Now, convert the data into dictionary which will take data from unique character and give a numerical value to it.

input_token_index = dict([(char, i) for i, char in enumerate(input_characters)])
target_token_index = dict([(char, i) for i, char in enumerate(target_characters)])

Output would be like this .

A: 31,B: 32,C: 33,D: 34,E: 35,F: 36,G: 37,H: 38,I: 39,J: 40,K: 41,L: 42,M: 43,N: 44,

Next step would be embedding of the data. This step will take encoder input , decoder input and decoder output data. We will take dimensions according to input and output sequence length. Also the data would be one hot encoded and padded with 0 where the value is not present.

encoder_input_data = np.zeros(
(len(input_text), max_encoder_seq_length, num_encoder_tokens), dtype="float32"
)
decoder_input_data = np.zeros(
(len(input_text), max_decoder_seq_length, num_decoder_tokens), dtype="float32"
)
decoder_target_data = np.zeros(
(len(input_text), max_decoder_seq_length, num_decoder_tokens), dtype="float32"
)
for i, (input_texts, target_texts) in enumerate(zip(input_text, target_text)):
  for t, char in enumerate(input_texts):
    encoder_input_data[i, t, input_token_index[char]] = 1.0
  encoder_input_data[i, t + 1 :, input_token_index[" "]] = 1.0
  for t, char in enumerate(target_texts):
# decoder_target_data is ahead of decoder_input_data by one timestep
     decoder_input_data[i, t, target_token_index[char]] = 1.0
     if t > 0:
# decoder_target_data will be ahead by one timestep
# and will not include the start character.
        decoder_target_data[i, t - 1, target_token_index[char]] = 1.0
   decoder_input_data[i, t + 1 :, target_token_index[" "]] = 1.0
   decoder_target_data[i, t:, target_token_index[" "]] = 1.0

Now we will define Encoder and Decoder model. Which contains embedded data from previous step, LSTM layer, and dense layer . Here, as per architecture we will not consider output on encoder we will only take state h and c from encoder and pass it to decoder.

# Define an input sequence and process it.
encoder_inputs = keras.Input(shape=(None, num_encoder_tokens))
encoder = keras.layers.LSTM(latent_dim, return_state=True)
encoder_outputs, state_h, state_c = encoder(encoder_inputs)
# We discard `encoder_outputs` and only keep the states.
encoder_states = [state_h, state_c]
# Set up the decoder, using `encoder_states` as initial state.
decoder_inputs = keras.Input(shape=(None, num_decoder_tokens))
# We set up our decoder to return full output sequences,
# and to return internal states as well. We don't use the
# return states in the training model, but we will use them in inference.
decoder_lstm = keras.layers.LSTM(latent_dim, return_sequences=True, return_state=True)
decoder_outputs, _, _ = decoder_lstm(decoder_inputs, initial_state=encoder_states)
decoder_dense = keras.layers.Dense(num_decoder_tokens, activation="softmax")
decoder_outputs = decoder_dense(decoder_outputs)
# Define the model that will turn
# `encoder_input_data` & `decoder_input_data` into `decoder_target_data`
model = keras.Model([encoder_inputs, decoder_inputs], decoder_outputs)

Now we can train the model. Here optimization function is rmsprop and I have trained model up to 100 epochs.

model.compile(
optimizer="rmsprop", loss="categorical_crossentropy", metrics=["accuracy"]
)
model.fit(
[encoder_input_data, decoder_input_data],
decoder_target_data,
batch_size=batch_size,
epochs=epochs,
validation_split=0.2,
)
# Save model
model.save("s2s")

The results after training up to 100 epochs is

Epoch 93/100
125/125 [==============================] - 11s 86ms/step - loss: 0.0232 - accuracy: 0.9929 - val_loss: 0.0399 - val_accuracy: 0.9903
Epoch 94/100
125/125 [==============================] - 11s 87ms/step - loss: 0.0232 - accuracy: 0.9928 - val_loss: 0.0399 - val_accuracy: 0.9903
Epoch 95/100
125/125 [==============================] - 11s 87ms/step - loss: 0.0230 - accuracy: 0.9929 - val_loss: 0.0400 - val_accuracy: 0.9904
Epoch 96/100
125/125 [==============================] - 11s 86ms/step - loss: 0.0230 - accuracy: 0.9929 - val_loss: 0.0397 - val_accuracy: 0.9902
Epoch 97/100
125/125 [==============================] - 11s 86ms/step - loss: 0.0228 - accuracy: 0.9929 - val_loss: 0.0392 - val_accuracy: 0.9905
Epoch 98/100
125/125 [==============================] - 11s 86ms/step - loss: 0.0230 - accuracy: 0.9929 - val_loss: 0.0421 - val_accuracy: 0.9897
Epoch 99/100
125/125 [==============================] - 11s 86ms/step - loss: 0.0230 - accuracy: 0.9928 - val_loss: 0.0397 - val_accuracy: 0.9904
Epoch 100/100
125/125 [==============================] - 11s 87ms/step - loss: 0.0230 - accuracy: 0.9928 - val_loss: 0.0391 - val_accuracy: 0.9906
WARNING:absl:Found untraced functions such as lstm_cell_layer_call_fn, lstm_cell_layer_call_and_return_conditional_losses, lstm_cell_1_layer_call_fn, lstm_cell_1_layer_call_and_return_conditional_losses, lstm_cell_layer_call_fn while saving (showing 5 of 10). These functions will not be directly callable after loading.
WARNING:absl:Found untraced functions such as lstm_cell_layer_call_fn, lstm_cell_layer_call_and_return_conditional_losses, lstm_cell_1_layer_call_fn, lstm_cell_1_layer_call_and_return_conditional_losses, lstm_cell_layer_call_fn while saving (showing 5 of 10). These functions will not be directly callable after loading.INFO:tensorflow:Assets written to: s2s/assetsINFO:tensorflow:Assets written to: s2s/assets

What’s Next :

In the next part of this series, we will use attention for english to hindi translation.

References

  1. https://keras.io/examples/nlp/lstm_seq2seq/
  2. https://towardsdatascience.com/nlp-sequence-to-sequence-networks-part-1-processing-text-data-d141a5643b72
  3. https://towardsdatascience.com/nlp-sequence-to-sequence-networks-part-2-seq2seq-model-encoderdecoder-model-6c22e29fd7e1
NLP
Encoder Decoder
Encoder
Decoder
Lstm
Recommended from ReadMedium