View file src/colab/tf_l10c03_nlp_constructing_text_generation_model.py - Download

# -*- coding: utf-8 -*-
"""Copie de l10c03_nlp_constructing_text_generation_model.ipynb

Automatically generated by Colab.

Original file is located at
    https://colab.research.google.com/drive/1Co4ZK7ne3TPJxcVB0vxf6PtLHS92OVXE

https://colab.research.google.com/github/tensorflow/examples/blob/master/courses/udacity_intro_to_tensorflow_for_deep_learning/l10c03_nlp_constructing_text_generation_model.ipynb

##### Copyright 2020 The TensorFlow Authors.
"""

#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""# Constructing a Text Generation Model

Run in Google Colab View source on GitHub
Using most of the techniques you've already learned, it's now possible to generate new text by predicting the next word that follows a given seed word. To practice this method, we'll use the [Kaggle Song Lyrics Dataset](https://www.kaggle.com/mousehead/songlyrics). ## Import TensorFlow and related functions """ import tensorflow as tf from tensorflow.keras.preprocessing.text import Tokenizer from tensorflow.keras.preprocessing.sequence import pad_sequences # Other imports for processing data import string import numpy as np import pandas as pd """## Get the Dataset As noted above, we'll utilize the [Song Lyrics dataset](https://www.kaggle.com/mousehead/songlyrics) on Kaggle. """ !wget --no-check-certificate \ https://drive.google.com/uc?id=1LiJFZd41ofrWoBtW-pMYsfz1w8Ny0Bj8 \ -O /tmp/songdata.csv """## **First 10 Songs** Let's first look at just 10 songs from the dataset, and see how things perform. ### Preprocessing Let's perform some basic preprocessing to get rid of punctuation and make everything lowercase. We'll then split the lyrics up by line and tokenize the lyrics. """ def tokenize_corpus(corpus, num_words=-1): # Fit a Tokenizer on the corpus if num_words > -1: tokenizer = Tokenizer(num_words=num_words) else: tokenizer = Tokenizer() tokenizer.fit_on_texts(corpus) return tokenizer def create_lyrics_corpus(dataset, field): # Remove all other punctuation dataset[field] = dataset[field].str.replace('[{}]'.format(string.punctuation), '') # Make it lowercase dataset[field] = dataset[field].str.lower() # Make it one long string to split by line lyrics = dataset[field].str.cat() corpus = lyrics.split('\n') # Remove any trailing whitespace for l in range(len(corpus)): corpus[l] = corpus[l].rstrip() # Remove any empty lines corpus = [l for l in corpus if l != ''] return corpus # Read the dataset from csv - just first 10 songs for now dataset = pd.read_csv('/tmp/songdata.csv', dtype=str)[:10] # Create the corpus using the 'text' column containing lyrics corpus = create_lyrics_corpus(dataset, 'text') # Tokenize the corpus tokenizer = tokenize_corpus(corpus) total_words = len(tokenizer.word_index) + 1 print(tokenizer.word_index) print(total_words) """### Create Sequences and Labels After preprocessing, we next need to create sequences and labels. Creating the sequences themselves is similar to before with `texts_to_sequences`, but also including the use of [N-Grams](https://towardsdatascience.com/introduction-to-language-models-n-gram-e323081503d9); creating the labels will now utilize those sequences as well as utilize one-hot encoding over all potential output words. """ sequences = [] for line in corpus: token_list = tokenizer.texts_to_sequences([line])[0] for i in range(1, len(token_list)): n_gram_sequence = token_list[:i+1] sequences.append(n_gram_sequence) # Pad sequences for equal input length max_sequence_len = max([len(seq) for seq in sequences]) sequences = np.array(pad_sequences(sequences, maxlen=max_sequence_len, padding='pre')) # Split sequences between the "input" sequence and "output" predicted word input_sequences, labels = sequences[:,:-1], sequences[:,-1] # One-hot encode the labels one_hot_labels = tf.keras.utils.to_categorical(labels, num_classes=total_words) # Check out how some of our data is being stored # The Tokenizer has just a single index per word print(tokenizer.word_index['know']) print(tokenizer.word_index['feeling']) # Input sequences will have multiple indexes print(input_sequences[5]) print(input_sequences[6]) # And the one hot labels will be as long as the full spread of tokenized words print(one_hot_labels[5]) print(one_hot_labels[6]) """### Train a Text Generation Model Building an RNN to train our text generation model will be very similar to the sentiment models you've built previously. The only real change necessary is to make sure to use Categorical instead of Binary Cross Entropy as the loss function - we could use Binary before since the sentiment was only 0 or 1, but now there are hundreds of categories. From there, we should also consider using *more* epochs than before, as text generation can take a little longer to converge than sentiment analysis, *and* we aren't working with all that much data yet. I'll set it at 200 epochs here since we're only use part of the dataset, and training will tail off quite a bit over that many epochs. """ from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Embedding, LSTM, Dense, Bidirectional model = Sequential() model.add(Embedding(total_words, 64, input_length=max_sequence_len-1)) model.add(Bidirectional(LSTM(20))) model.add(Dense(total_words, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) history = model.fit(input_sequences, one_hot_labels, epochs=200, verbose=1) """### View the Training Graph""" import matplotlib.pyplot as plt def plot_graphs(history, string): plt.plot(history.history[string]) plt.xlabel("Epochs") plt.ylabel(string) plt.show() plot_graphs(history, 'accuracy') """### Generate new lyrics! It's finally time to generate some new lyrics from the trained model, and see what we get. To do so, we'll provide some "seed text", or an input sequence for the model to start with. We'll also decide just how long of an output sequence we want - this could essentially be infinite, as the input plus the previous output will be continuously fed in for a new output word (at least up to our max sequence length). """ seed_text = "im feeling chills" next_words = 100 for _ in range(next_words): token_list = tokenizer.texts_to_sequences([seed_text])[0] token_list = pad_sequences([token_list], maxlen=max_sequence_len-1, padding='pre') predicted = np.argmax(model.predict(token_list), axis=-1) output_word = "" for word, index in tokenizer.word_index.items(): if index == predicted: output_word = word break seed_text += " " + output_word print(seed_text)