Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/C5 - Sequence Models/Week 3/Machine Translation/nmt_utils.py
Views: 4819
import numpy as np1from faker import Faker2import random3from tqdm import tqdm4from babel.dates import format_date5from tensorflow.keras.utils import to_categorical6import tensorflow.keras.backend as K7from tensorflow.keras.models import Model8import matplotlib.pyplot as plt910fake = Faker()11Faker.seed(12345)12random.seed(12345)1314# Define format of the data we would like to generate15FORMATS = ['short',16'medium',17'long',18'full',19'full',20'full',21'full',22'full',23'full',24'full',25'full',26'full',27'full',28'd MMM YYY',29'd MMMM YYY',30'dd MMM YYY',31'd MMM, YYY',32'd MMMM, YYY',33'dd, MMM YYY',34'd MM YY',35'd MMMM YYY',36'MMMM d YYY',37'MMMM d, YYY',38'dd.MM.YY']3940# change this if you want it to work with another language41LOCALES = ['en_US']4243def load_date():44"""45Loads some fake dates46:returns: tuple containing human readable string, machine readable string, and date object47"""48dt = fake.date_object()4950try:51human_readable = format_date(dt, format=random.choice(FORMATS), locale='en_US') # locale=random.choice(LOCALES))52human_readable = human_readable.lower()53human_readable = human_readable.replace(',','')54machine_readable = dt.isoformat()5556except AttributeError as e:57return None, None, None5859return human_readable, machine_readable, dt6061def load_dataset(m):62"""63Loads a dataset with m examples and vocabularies64:m: the number of examples to generate65"""6667human_vocab = set()68machine_vocab = set()69dataset = []70Tx = 30717273for i in tqdm(range(m)):74h, m, _ = load_date()75if h is not None:76dataset.append((h, m))77human_vocab.update(tuple(h))78machine_vocab.update(tuple(m))7980human = dict(zip(sorted(human_vocab) + ['<unk>', '<pad>'],81list(range(len(human_vocab) + 2))))82inv_machine = dict(enumerate(sorted(machine_vocab)))83machine = {v:k for k,v in inv_machine.items()}8485return dataset, human, machine, inv_machine8687def preprocess_data(dataset, human_vocab, machine_vocab, Tx, Ty):8889X, Y = zip(*dataset)9091X = np.array([string_to_int(i, Tx, human_vocab) for i in X])92Y = [string_to_int(t, Ty, machine_vocab) for t in Y]9394Xoh = np.array(list(map(lambda x: to_categorical(x, num_classes=len(human_vocab)), X)))95Yoh = np.array(list(map(lambda x: to_categorical(x, num_classes=len(machine_vocab)), Y)))96979899return X, np.array(Y), Xoh, Yoh100101def string_to_int(string, length, vocab):102"""103Converts all strings in the vocabulary into a list of integers representing the positions of the104input string's characters in the "vocab"105106Arguments:107string -- input string, e.g. 'Wed 10 Jul 2007'108length -- the number of time steps you'd like, determines if the output will be padded or cut109vocab -- vocabulary, dictionary used to index every character of your "string"110111Returns:112rep -- list of integers (or '<unk>') (size = length) representing the position of the string's character in the vocabulary113"""114115#make lower to standardize116string = string.lower()117string = string.replace(',','')118119if len(string) > length:120string = string[:length]121122rep = list(map(lambda x: vocab.get(x, '<unk>'), string))123124if len(string) < length:125rep += [vocab['<pad>']] * (length - len(string))126127#print (rep)128return rep129130131def int_to_string(ints, inv_vocab):132"""133Output a machine readable list of characters based on a list of indexes in the machine's vocabulary134135Arguments:136ints -- list of integers representing indexes in the machine's vocabulary137inv_vocab -- dictionary mapping machine readable indexes to machine readable characters138139Returns:140l -- list of characters corresponding to the indexes of ints thanks to the inv_vocab mapping141"""142143l = [inv_vocab[i] for i in ints]144return l145146147EXAMPLES = ['3 May 1979', '5 Apr 09', '20th February 2016', 'Wed 10 Jul 2007']148149def run_example(model, input_vocabulary, inv_output_vocabulary, text):150encoded = string_to_int(text, TIME_STEPS, input_vocabulary)151prediction = model.predict(np.array([encoded]))152prediction = np.argmax(prediction[0], axis=-1)153return int_to_string(prediction, inv_output_vocabulary)154155def run_examples(model, input_vocabulary, inv_output_vocabulary, examples=EXAMPLES):156predicted = []157for example in examples:158predicted.append(''.join(run_example(model, input_vocabulary, inv_output_vocabulary, example)))159print('input:', example)160print('output:', predicted[-1])161return predicted162163164def softmax(x, axis=1):165"""Softmax activation function.166# Arguments167x : Tensor.168axis: Integer, axis along which the softmax normalization is applied.169# Returns170Tensor, output of softmax transformation.171# Raises172ValueError: In case `dim(x) == 1`.173"""174ndim = K.ndim(x)175if ndim == 2:176return K.softmax(x)177elif ndim > 2:178e = K.exp(x - K.max(x, axis=axis, keepdims=True))179s = K.sum(e, axis=axis, keepdims=True)180return e / s181else:182raise ValueError('Cannot apply softmax to a tensor that is 1D')183184185def plot_attention_map(modelx, input_vocabulary, inv_output_vocabulary, text, n_s = 128, num = 7):186"""187Plot the attention map.188189"""190attention_map = np.zeros((10, 30))191layer = modelx.get_layer('attention_weights')192193Ty, Tx = attention_map.shape194195human_vocab_size = 37196197# Well, this is cumbersome but this version of tensorflow-keras has a bug that affects the198# reuse of layers in a model with the functional API.199# So, I have to recreate the model based on the functional200# components and connect then one by one.201# ideally it can be done simply like this:202# layer = modelx.layers[num]203# f = Model(modelx.inputs, [layer.get_output_at(t) for t in range(Ty)])204#205206X = modelx.inputs[0]207s0 = modelx.inputs[1]208c0 = modelx.inputs[2]209s = s0210c = s0211212a = modelx.layers[2](X)213outputs = []214215for t in range(Ty):216s_prev = s217s_prev = modelx.layers[3](s_prev)218concat = modelx.layers[4]([a, s_prev])219e = modelx.layers[5](concat)220energies = modelx.layers[6](e)221alphas = modelx.layers[7](energies)222context = modelx.layers[8]([alphas, a])223# Don't forget to pass: initial_state = [hidden state, cell state] (≈ 1 line)224s, _, c = modelx.layers[10](context, initial_state = [s, c])225outputs.append(energies)226227f = Model(inputs=[X, s0, c0], outputs = outputs)228229230s0 = np.zeros((1, n_s))231c0 = np.zeros((1, n_s))232encoded = np.array(string_to_int(text, Tx, input_vocabulary)).reshape((1, 30))233encoded = np.array(list(map(lambda x: to_categorical(x, num_classes=len(input_vocabulary)), encoded)))234235236r = f([encoded, s0, c0])237238for t in range(Ty):239for t_prime in range(Tx):240attention_map[t][t_prime] = r[t][0, t_prime]241242# Normalize attention map243row_max = attention_map.max(axis=1)244attention_map = attention_map / row_max[:, None]245246prediction = modelx.predict([encoded, s0, c0])247248predicted_text = []249for i in range(len(prediction)):250predicted_text.append(int(np.argmax(prediction[i], axis=1)))251252predicted_text = list(predicted_text)253predicted_text = int_to_string(predicted_text, inv_output_vocabulary)254text_ = list(text)255256# get the lengths of the string257input_length = len(text)258output_length = Ty259260# Plot the attention_map261plt.clf()262f = plt.figure(figsize=(8, 8.5))263ax = f.add_subplot(1, 1, 1)264265# add image266i = ax.imshow(attention_map, interpolation='nearest', cmap='Blues')267268# add colorbar269cbaxes = f.add_axes([0.2, 0, 0.6, 0.03])270cbar = f.colorbar(i, cax=cbaxes, orientation='horizontal')271cbar.ax.set_xlabel('Alpha value (Probability output of the "softmax")', labelpad=2)272273# add labels274ax.set_yticks(range(output_length))275ax.set_yticklabels(predicted_text[:output_length])276277ax.set_xticks(range(input_length))278ax.set_xticklabels(text_[:input_length], rotation=45)279280ax.set_xlabel('Input Sequence')281ax.set_ylabel('Output Sequence')282283# add grid and legend284ax.grid()285286#f.show()287288return attention_map289290291