Loading the lesson...
In the print dialog, choose "Save as PDF" as the destination.
Neural Networks - Lesson 10
Building and comparing a standard LSTM vs. a Bidirectional LSTM for text classification
20 possible groups exist (comp.graphics, sci.space, rec.autos, talk.politics.misc, ...); this lab uses 10 selected categoriesfrom sklearn.datasets import fetch_20newsgroups
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.layers import Embedding, LSTM, Dense, Bidirectional10 chosen categoriescategories = ['sci.space', 'comp.graphics', 'rec.sport.baseball', 'talk.politics.misc',
'sci.electronics', 'soc.religion.christian', 'rec.autos',
'talk.politics.mideast', 'comp.sys.mac.hardware', 'misc.forsale']
newsgroups = fetch_20newsgroups(subset='train', categories=categories)
texts = newsgroups.data
labels = newsgroups.target
# len(texts) -> 57500-9 mapping to newsgroups.target_namesRaw text
one post
Tokenizer
top vocab_size words
Integer sequence
texts_to_sequences
Padded sequence
fixed length
Tokenizer(num_words=vocab_size) restricts vocabulary to the top N most frequent words; rarer words are droppedfit_on_texts builds the word-to-integer dictionary; texts_to_sequences converts text into integer listspad_sequences pads/truncates every sequence to the same fixed lengthvocab_size, maxlen = 10000, 200
tokenizer = Tokenizer(num_words=vocab_size)
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)
padded_sequences = pad_sequences(sequences, maxlen=maxlen, padding='post')
encoder = LabelBinarizer()
one_hot_labels = encoder.fit_transform(labels)input_dim: vocabulary size; output_dim: embedding vector dimensionality; input_length: fixed sequence lengthEmbedding(input_dim=vocab_size, output_dim=128, input_length=maxlen)units: number of hidden units / memory cellsreturn_sequences=True: returns the full output sequence, needed when stacking LSTM layersdropout: dropout on input connections; recurrent_dropout: dropout on the recurrent (memory-state) connections between time stepsLSTM(units=64, return_sequences=True)
LSTM(units=32, dropout=0.2, recurrent_dropout=0.2)LSTM layers, then classify into 10 categories with softmaxEmbedding
128-dim
LSTM
64 units, return_sequences
LSTM
32 units, dropout 0.2
Dense
10 units, softmax
model_lstm = Sequential()
model_lstm.add(Embedding(input_dim=vocab_size, output_dim=128, input_length=maxlen))
model_lstm.add(LSTM(units=64, return_sequences=True))
model_lstm.add(LSTM(units=32, dropout=0.2, recurrent_dropout=0.2))
model_lstm.add(Dense(10, activation='softmax'))
model_lstm.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model_lstm.fit(padded_sequences, one_hot_labels, epochs=10, batch_size=32, validation_split=0.2)Epoch 1/10 accuracy: 0.1436 val_accuracy: 0.2157
Epoch 10/10 accuracy: 0.5796 val_accuracy: 0.519110 epochsLSTM to process the sequence in both forward and backward directions.NLP performance because context from both sides of a word helps disambiguate meaningBidirectional(LSTM(units=64, dropout=0.2, recurrent_dropout=0.2))LSTM is wrapped in Bidirectionalmodel_bi = Sequential()
model_bi.add(Embedding(input_dim=vocab_size, output_dim=128, input_length=maxlen))
model_bi.add(Bidirectional(LSTM(units=64, dropout=0.2, recurrent_dropout=0.2)))
model_bi.add(Dense(10, activation='softmax'))
model_bi.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model_bi.fit(padded_sequences, one_hot_labels, epochs=10, batch_size=32, validation_split=0.2)Epoch 1/10 accuracy: 0.1717 val_accuracy: 0.3843
Epoch 5/10 accuracy: 0.9387 val_accuracy: 0.7783
Epoch 10/10 accuracy: 0.9971 val_accuracy: 0.8070sample_text = ["NASA is planning a mission to Jupiter"]
seq = tokenizer.texts_to_sequences(sample_text)
pad = pad_sequences(seq, maxlen=maxlen, padding='post')
prediction = model_bi.predict(pad)
predicted_class_index = np.argmax(prediction)
print("Actual Category:", newsgroups.target_names[predicted_class_index])NLPLSTM layer and add Dropout after itLSTM with GRU and compareEmbedding layer learns dense word representations instead of using raw one-hot vectorsreturn_sequences=True is required when stacking multiple LSTM layersdropout and recurrent_dropout regularize LSTMs against overfitting on input and recurrent connections respectivelyLSTM here (80.7% vs 51.9% val accuracy)99.7% train vs 80.7% val) is a clear overfitting signal worth addressingMahmoud Abas|LSTM on 20 Newsgroups Dataset using Keras