Skip to content

Instantly share code, notes, and snippets.

@georgehc
Created November 27, 2019 04:07
Show Gist options
  • Save georgehc/1a3244060ce278c0158ae7d70209d325 to your computer and use it in GitHub Desktop.
Save georgehc/1a3244060ce278c0158ae7d70209d325 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Recurrent Neural Networks Demo\n",
"\n",
"Author: Runshan Fu (Fall 2017 95-865 TA), George H. Chen\n",
"\n",
"In this demo, we will implement RNN models for sentiment analysis on IMDB reviews. We will start from the original review texts and predict the sentiment (positive or negative) for each review. This demo is borrowed from the book *Deep Learning with Python* by Francois Chollet and also uses code from user `mdaoust` in [this stackoverflow post](https://stackoverflow.com/questions/42821330/restore-original-text-from-keras-s-imdb-dataset)."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Load the dataset\n",
"We directly load the data as lists of intergers from keras. We restrict the movie reviews to the top 2000 most common words, and make all the reviews exactly 200 words (truncating as needed or padding with a special padding character; note that truncating works by removing the *start* of the review and keeping only the last 200 words; padding works by adding the special padding character to the *start* of the review)."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Using TensorFlow backend.\n"
]
}
],
"source": [
"from keras.datasets import imdb\n",
"from keras.preprocessing import sequence\n",
"\n",
"# load the dataset and only keep the top words (most frequently occurring)\n",
"vocab_size = 2000\n",
"INDEX_FROM = 2 # for dealing with some special characters; this is a technical thing related to the IMDB dataset\n",
"(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=vocab_size, index_from=INDEX_FROM)\n",
"\n",
"word_to_idx = imdb.get_word_index()\n",
"word_to_idx = {word:(word_idx + INDEX_FROM) for word, word_idx in word_to_idx.items()}\n",
"word_to_idx['<PAD>'] = 0\n",
"word_to_idx['<START>'] = 1\n",
"word_to_idx['<UNK>'] = 2\n",
"\n",
"idx_to_word = {word_idx:word for word, word_idx in word_to_idx.items()}\n",
"\n",
"# turn the lists of integers into a 2D integer tensor of shape `(samples, maxlen)`\n",
"x_train = sequence.pad_sequences(x_train, maxlen=200)\n",
"x_test = sequence.pad_sequences(x_test, maxlen=200)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(25000, 200)\n"
]
}
],
"source": [
"print(x_train.shape)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[ 4 24 99 42 837 111 49 669 2 8 34 479 283 4\n",
" 149 3 171 111 166 2 335 384 38 3 171 2 1110 16\n",
" 545 37 12 446 3 191 49 15 5 146 2 18 13 21\n",
" 3 1919 2 468 3 21 70 86 11 15 42 529 37 75\n",
" 14 12 1246 3 21 16 514 16 11 15 625 17 2 4\n",
" 61 385 11 7 315 7 105 4 3 2 2 15 479 65\n",
" 2 32 3 129 11 15 37 618 4 24 123 50 35 134\n",
" 47 24 1414 32 5 21 11 214 27 76 51 4 13 406\n",
" 15 81 2 7 3 106 116 2 14 255 3 2 6 2\n",
" 4 722 35 70 42 529 475 25 399 316 45 6 3 2\n",
" 1028 12 103 87 3 380 14 296 97 31 2 55 25 140\n",
" 5 193 2 17 3 225 21 20 133 475 25 479 4 143\n",
" 29 2 17 50 35 27 223 91 24 103 3 225 64 15\n",
" 37 1333 87 11 15 282 4 15 2 112 102 31 14 15\n",
" 2 18 177 31]\n"
]
}
],
"source": [
"print(x_train[0])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is an example of a review with positive sentiment (this particular review has been truncated, so we only see the last 200 words of the review):"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"and you could just imagine being there robert <UNK> is an amazing actor and now the same being director <UNK> father came from the same <UNK> island as myself so i loved the fact there was a real <UNK> with this film the witty <UNK> throughout the film were great it was just brilliant so much that i bought the film as soon as it was released for <UNK> and would recommend it to everyone to watch and the <UNK> <UNK> was amazing really <UNK> at the end it was so sad and you know what they say if you cry at a film it must have been good and this definitely was also <UNK> to the two little <UNK> that played the <UNK> of <UNK> and paul they were just brilliant children are often left out of the <UNK> list i think because the stars that play them all <UNK> up are such a big <UNK> for the whole film but these children are amazing and should be <UNK> for what they have done don't you think the whole story was so lovely because it was true and was <UNK> life after all that was <UNK> with us all\n"
]
}
],
"source": [
"print(' '.join(idx_to_word[idx] for idx in x_train[0]))"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"y_train[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is an example of a review with negative sentiment (this particular review has been padded at the beginning; note that when we can see the starting of a review, the first token of the actual review is a special token `<START>`):"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <START> in a far away <UNK> is a planet called <UNK> it's <UNK> people <UNK> <UNK> but the dog people <UNK> war upon these <UNK> loving people and they have no choice but to go to earth and <UNK> people up for food this is one of the <UNK> f <UNK> <UNK> ideas for a movie i've seen leave it to <UNK> <UNK> to make a movie more <UNK> than the already low standard he set in previous films it's like he <UNK> playing in a <UNK> game of <UNK> how low can he go the only <UNK> in the <UNK> are us the viewer mr <UNK> and his silly little <UNK> <UNK> actually has people who still buy this crap br br my grade f br br dvd <UNK> commentary by <UNK> <UNK> the story behind the making of 9 and a half minutes <UNK> minutes 15 seconds of behind the scenes footage <UNK> <UNK> <UNK> and <UNK> for the <UNK> <UNK> girl in gold <UNK> the <UNK> <UNK> ten violent women featuring nudity blood <UNK> of the she <UNK> the <UNK> <UNK>\n"
]
}
],
"source": [
"print(' '.join(idx_to_word[idx] for idx in x_train[-3]))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"y_train[-3]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Use pre-trained word embeddings\n",
"We use GloVe embeddings instead of learning our own task-specific word embedding. First download the pre-computed embeddings from 2014 English Wikipedia on https://nlp.stanford.edu/projects/glove/ (specifically the one with 6 billion tokens, `globe.6B.zip`). Unzip it (so that `glove.6B.100d.txt` is located in the directory `./glove/`)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We first create a dictionary that maps each English word to its corresponding 100-dimensional GloVe embedding."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Found 400000 word vectors.\n"
]
}
],
"source": [
"word_to_embedding = {}\n",
"\n",
"# we will use the 100-dimensional embedding vectors\n",
"with open(\"./glove/glove.6B.100d.txt\") as f:\n",
" # each row represents a word vector\n",
" for line in f:\n",
" values = line.split()\n",
" # the first part is word\n",
" word = values[0]\n",
" # the rest of the values form the embedding vector\n",
" embedding = np.asarray(values[1:], dtype='float32')\n",
" word_to_embedding[word] = embedding\n",
"\n",
"print('Found %s word vectors.' % len(word_to_embedding))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we create an embedding matrix, where the i-th row holds the GloVe embedding for the i-th top word (except where i=0 is the special padding token `<PAD>`, i=1 is the special `<START>` token, and i=2 is the special `<UNK>` token; for these special cases the embedding vector is left as all zeros)."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"embedding_dim = 100\n",
"\n",
"embedding_matrix = np.zeros((vocab_size, embedding_dim))\n",
"for idx in range(vocab_size):\n",
" word = idx_to_word[idx]\n",
" if word in word_to_embedding:\n",
" embedding_matrix[idx] = word_to_embedding[word]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Feedforward network with embeddings"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This first neural net is *not* a recurrent neural net. It does not do anything special to account for time series structure. This net is meant to be a baseline that we compare a recurrent neural net against. To make the comparison somewhat fair, in both cases, the last two layers have the same output dimensions: the second-to-last layer is a Dense layer with 64 neurons and `relu` activation, and the last layer is a Dense layer with 1 neuron and `sigmoid` activation."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential_1\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"embedding_1 (Embedding) (None, 200, 100) 200000 \n",
"_________________________________________________________________\n",
"flatten_1 (Flatten) (None, 20000) 0 \n",
"_________________________________________________________________\n",
"dense_1 (Dense) (None, 64) 1280064 \n",
"_________________________________________________________________\n",
"dense_2 (Dense) (None, 1) 65 \n",
"=================================================================\n",
"Total params: 1,480,129\n",
"Trainable params: 1,480,129\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"from keras.models import Sequential\n",
"from keras.layers import Embedding, Flatten, Dense\n",
"# initialize the model\n",
"feedforward_model = Sequential()\n",
"feedforward_model.add(Embedding(vocab_size, embedding_dim, input_length=200))\n",
"feedforward_model.add(Flatten())\n",
"feedforward_model.add(Dense(64, activation='relu'))\n",
"feedforward_model.add(Dense(1, activation='sigmoid'))\n",
"feedforward_model.summary()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential_1\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"embedding_1 (Embedding) (None, 200, 100) 200000 \n",
"_________________________________________________________________\n",
"flatten_1 (Flatten) (None, 20000) 0 \n",
"_________________________________________________________________\n",
"dense_1 (Dense) (None, 64) 1280064 \n",
"_________________________________________________________________\n",
"dense_2 (Dense) (None, 1) 65 \n",
"=================================================================\n",
"Total params: 1,480,129\n",
"Trainable params: 1,280,129\n",
"Non-trainable params: 200,000\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"# load the GloVe embeddings in the model\n",
"feedforward_model.layers[0].set_weights([embedding_matrix])\n",
"# set the embedding layer to be not trainable, so the weights do not change during the training\n",
"feedforward_model.layers[0].trainable = False\n",
"\n",
"feedforward_model.summary() # the summary changes after we turn off training for the 0-th layer (note the last line \"Non-trainable params\")"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Train on 20000 samples, validate on 5000 samples\n",
"Epoch 1/10\n",
"20000/20000 [==============================] - 14s 686us/step - loss: 0.6309 - acc: 0.6500 - val_loss: 0.5866 - val_acc: 0.6856\n",
"Epoch 2/10\n",
"20000/20000 [==============================] - 13s 651us/step - loss: 0.4821 - acc: 0.7722 - val_loss: 0.5610 - val_acc: 0.7232\n",
"Epoch 3/10\n",
"20000/20000 [==============================] - 13s 660us/step - loss: 0.4004 - acc: 0.8179 - val_loss: 0.5807 - val_acc: 0.7176\n",
"Epoch 4/10\n",
"20000/20000 [==============================] - 13s 673us/step - loss: 0.3227 - acc: 0.8597 - val_loss: 0.6451 - val_acc: 0.7126\n",
"Epoch 5/10\n",
"20000/20000 [==============================] - 13s 653us/step - loss: 0.2503 - acc: 0.8947 - val_loss: 0.7348 - val_acc: 0.7100\n",
"Epoch 6/10\n",
"20000/20000 [==============================] - 13s 629us/step - loss: 0.1787 - acc: 0.9286 - val_loss: 0.8210 - val_acc: 0.7106\n",
"Epoch 7/10\n",
"20000/20000 [==============================] - 14s 686us/step - loss: 0.1028 - acc: 0.9650 - val_loss: 0.9893 - val_acc: 0.7102\n",
"Epoch 8/10\n",
"20000/20000 [==============================] - 13s 674us/step - loss: 0.0681 - acc: 0.9772 - val_loss: 1.1859 - val_acc: 0.7082\n",
"Epoch 9/10\n",
"20000/20000 [==============================] - 13s 653us/step - loss: 0.0470 - acc: 0.9856 - val_loss: 1.3526 - val_acc: 0.7100\n",
"Epoch 10/10\n",
"20000/20000 [==============================] - 13s 642us/step - loss: 0.0588 - acc: 0.9783 - val_loss: 1.4186 - val_acc: 0.7048\n"
]
}
],
"source": [
"# compile and train the model\n",
"feedforward_model.compile(optimizer='adam',\n",
" loss='binary_crossentropy',\n",
" metrics=['acc'])\n",
"\n",
"history = feedforward_model.fit(x_train, y_train,\n",
" validation_split=0.2,\n",
" epochs=10,\n",
" batch_size=32)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x649c8ffd0>"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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r+GeRs8//zwf+9jHGD9+PJWVlaxcuRKAb37zmxxxxBGMHz+e2Vn87WpdSnU1VFRAr17Jayl+yM6dC2VlTcvKypLyztbh26PhSLSrDEceeWQ0t3z58p3KWjJ6dESS4psOo0cXvIpWXXvttXHDDTdERMQLL7wQkuJPf/pT4/wNGzZERMTWrVtjypQpsWzZsoiIOOaYY+Kpp56KrVu3BhAPPvhgRERcdtllcf3110dExOzZs+Pmm29urP/Vr341IiIeeOCBOOWUUyIi4vrrr49LLrkkIiKWLFkSvXr1iqeeemqnOBvieP/992PatGmN71dZWRkLFy6MiIjNmzfHpk2bYuHChTFlypSor69vsuyuaM93ZT3Tj38cUVbW9P+zrCwpL0Uso0dHSMlrqWIoxvYAaqKFvJq5I/rObnc78MADOeqooxqn7777biorK6msrOTZZ59l+fLlOy2zxx57cOqppwJw5JFHNh5VN3fmmWfuVOd3v/sd06ZNA2D8+PEcfvjheZf99a9/zaRJkxg/fjyPPfYYy5YtY+PGjbz22mt88pOfBJILnMrKynj44Ye54IIL2GOPPQDYe++9278hzArUlTpBZ8yAlSvh/feT11KcbdMZ2yNzbfSd3e42cODAxvEXXniBW2+9lT/96U8MGTKEc845J+/VvP369Wsc7927N9u2bcu77v79++9UJwp4UEx9fT2zZs3iz3/+MyNGjOCaa65pjCPfKZAR4VMjrdP0pE7QQnTG9sjcEX0p293eeustBg8ezJ577snatWt56KGHiv4eU6ZMYcGCBQD85S9/yfuLYfPmzfTq1Yvhw4fz9ttvc++99wIwdOhQhg8fzs9+9jMguRCtvr6ek08+mX//939n8+bNALz++i5dwGxWkJYOurLYCVqIztgemUv0M2bAvHkwejRIyeu8eZ3zk6yyspLDDjuMsWPHctFFF3HMMccU/T0uvfRSXnnlFcaNG8eNN97I2LFj2WuvvZrUGTZsGOeeey5jx47l05/+NJMnT26cV11dzY033si4ceOYMmUKdXV1fOITn2Dq1KlUVVUxYcIEbr755qLHbdagK3WCdgWdsj1aarwv1bC7nbFZt3Xr1ti8eXNERDz//PNRUVERW7duLXFUO/i7skJ0hU7QrqQY24NWOmMz10afde+88w4nnngi27ZtIyL43ve+R58+/hqtcF3h/i4zZmTvNgO7o6O3hzNENzNkyBAWL15c6jCsm+pJ93exHTLXRm9mLetKpzZa53GiN+tBfGpjz+REb9aD+NTGnsmJ3qwH8amNPZMTfQGOP/74nS5+uuWWW7jkkktaXW7QoEEArFmzhrPOOqvFddfU1LS6nltuuYX6nIbV0047jTfeeKOQ0M2aKOV1JlY6TvQFmD59OvPnz29SNn/+fKZPb/Upi432339/7rnnnl1+/+aJ/sEHH2TIkCG7vD7r2brC/V2scznRF+Css87i5z//Oe+99x4AK1euZM2aNUyZMqXxvPbKykqOOOIIHnjggZ2WX7lyJWPHjgWS2xNMmzaNcePGcfbZZzfedgDg4osvbrzF8bXXXgvAd7/7XdasWcMJJ5zACSecAEBFRQWvvfYaADfddBNjx45l7Nixjbc4XrlyJYceeigXXXQRhx9+OCeffHKT92nws5/9jMmTJzNx4kROOukk1q1bByTn6p9//vkcccQRjBs3rvEWCr/85S+prKxk/PjxnHjiiUXZtmbW8Qo6j17SVOBWoDdwR0R8q9n80SQPAS8HXgfOiYjadN524C9p1dURcfruBPzlL0Oe26/vlgkTIM2ReQ0bNoxJkybxy1/+kjPOOIP58+dz9tlnI4kBAwZw3333seeee/Laa6/xkY98hNNPP73Fm4TdfvvtlJWVsXTpUpYuXUplZWXjvLlz57L33nuzfft2TjzxRJYuXco//MM/cNNNN/HII48wfPjwJutavHgxd911F08++SQRweTJk/noRz/K0KFDeeGFF7j77rv5/ve/z2c/+1nuvfdezjnnnCbLT5kyhSeeeAJJ3HHHHXz729/mxhtv5Otf/zp77bUXf/lL8rVt3LiRuro6LrroIh5//HHGjBnj++GYdSNtHtFL6g3cBpwKHAZMl3RYs2rfAX4UEeOAOcD1OfM2R8SEdNitJF9Kuc03uc02EcHVV1/NuHHjOOmkk3jllVcaj4zzefzxxxsT7rhx4xg3blzjvAULFlBZWcnEiRNZtmxZ3huW5frd737Hpz/9aQYOHMigQYM488wz+e1vfwvAmDFjmDBhAtDyrZBra2s55ZRTOOKII7jhhhtYtmwZAA8//HCTp10NHTqUJ554guOOO44xY8YAvpWxWXdSyBH9JGBFRLwIIGk+cAaQm4UOAy5Lxx8B7i9mkLlaO/LuSJ/61Ke4/PLL+fOf/8zmzZsbj8Srq6upq6tj8eLF9O3bl4qKiry3Js6V72j/pZde4jvf+Q6LFi1i6NChnHfeeW2uJ1q5ZXHDLY4huc1xvqabSy+9lMsvv5zTTz+dRx99lOuuu65xvc1jzFdmZt1DIW30I4CXc6Zr07JcTwOfScc/DQyWNCydHiCpRtITkj6V7w0kzUzr1NTV1bUj/M4zaNAgjj/+eC644IImnbBvvvkm++yzD3379uWRRx5hVb6b4ec47rjjGh8A/swzz7B06VIgucXxwIED2WuvvVi3bh2/+MUvGpcZPHgwb7/9dt513X///dTX17Np0ybuu+8+jj322II/05tvvsmIEclX+cMf/rCx/OSTT+Zf//VfG6c3btzI0UcfzWOPPcZLL70E+FbGZt1JIYk+32Fc80PJK4CPSnoK+CjwCtDwNI1REVEFfA64RdKBO60sYl5EVEVEVXl5eeHRd7Lp06fz9NNPNz7hCWDGjBnU1NRQVVVFdXU1hxxySKvruPjii3nnnXcYN24c3/72t5k0aRKQPC1q4sSJHH744VxwwQVNbnE8c+ZMTj311MbO2AaVlZWcd955TJo0icmTJ3PhhRcyceLEgj/Pddddx9/93d9x7LHHNmn/v+aaa9i4cSNjx45l/PjxPPLII5SXlzNv3jzOPPNMxo8fz9lnn13w+5hZaam1n/8Ako4GrouIU9LpqwAi4voW6g8C/iciRuaZ9wPg5xHR4rmGVVVV0fy88meffZZDDz209U9iXYK/K7PSkLQ4PajeSSFH9IuAgySNkdQPmAYsbPYGwyU1rOsqkjNwkDRUUv+GOsAxNG3bNzOzDtZmoo+IbcAs4CHgWWBBRCyTNEdSw1k0xwPPSXoe+ADQcEH1oUCNpKdJOmm/FRFO9GZmnaig8+gj4kHgwWZl/ydn/B5gp+aYiPgDcMRuxtiwLp/10cW11QxoZqXRLa6MHTBgABs2bHAi6cIigg0bNjBgwIBSh2JmzXSLJ0yNHDmS2tpauuqpl5YYMGAAI0fu1AdvZiXWLRJ93759G6/INDOz9ukWTTdmZrbrnOjNOkl1NVRUQK9eyWt6gbRZh+sWTTdm3V11NcycuePB3KtWJdPg+8Fbx/MRvVknmD17R5JvUF+flJt1NCd6s06wenX7ys2KyYnerBOMGtW+crNicqI36wRz50JZWdOysrKk3KyjOdGbdYIZM2DePBg9GqTkdd48d8Ra5/BZN2adZMYMJ3YrDR/Rm5llnBO9mVnGOdGbmWWcE72ZWcY50ZuZZZwTvZlZxjnRm5llnBO9mVnGFZToJU2V9JykFZKuzDN/tKRfS1oq6VFJI3PmnSvphXQ4t5jBm5lZ29pM9JJ6A7cBpwKHAdMlHdas2neAH0XEOGAOcH267N7AtcBkYBJwraShxQvfzMzaUsgR/SRgRUS8GBFbgPnAGc3qHAb8Oh1/JGf+KcCvIuL1iNgI/AqYuvthm5lZoQpJ9COAl3Oma9OyXE8Dn0nHPw0MljSswGXNzKwDFZLolacsmk1fAXxU0lPAR4FXgG0FLoukmZJqJNXU1dUVEJJZ4fysVuvpCkn0tcABOdMjgTW5FSJiTUScGRETgdlp2ZuFLJvWnRcRVRFRVV5e3s6PYNayhme1rloFETue1epkbz1JIYl+EXCQpDGS+gHTgIW5FSQNl9SwrquAO9Pxh4CTJQ1NO2FPTsvMOoWf1WpWQKKPiG3ALJIE/SywICKWSZoj6fS02vHAc5KeBz4AzE2XfR34OsnOYhEwJy0z6xR+VqsZKGKnJvOSqqqqipqamlKHYRlRUZE01zQ3ejSsXNnZ0Zh1HEmLI6Iq3zxfGWuZ5me1mjnRW8b5Wa1mfmas9QB+Vqv1dD6iNzPLOCd6M7OMc6I3M8s4J3ozs4xzojczyzgnejOzjHOiNzPLOCd6M7OMc6I3M8s4J3ozs4xzojczyzgnejOzjHOitw7jZ7WadQ2+e6V1iIZntTY8xq/hWa3gO0madTYf0VuH8LNazboOJ3rrEH5Wq1nX4URvHWLUqPaVm1nHcaK3DuFntZp1HQUleklTJT0naYWkK/PMHyXpEUlPSVoq6bS0vELSZklL0uHfiv0BrGvys1rNuo42z7qR1Bu4Dfg4UAsskrQwIpbnVLsGWBARt0s6DHgQqEjn/TUiJhQ3bOsO/KxWs66hkCP6ScCKiHgxIrYA84EzmtUJYM90fC9gTfFCNDOz3VFIoh8BvJwzXZuW5boOOEdSLcnR/KU588akTTqPSTo23xtImimpRlJNXV1d4dGbmVmbCkn0ylMWzaanAz+IiJHAacB/SOoFrAVGRcRE4HLgJ5L2bLYsETEvIqoioqq8vLx9n8DMzFpVSKKvBQ7ImR7Jzk0znwcWAETEH4EBwPCIeC8iNqTli4G/Ah/e3aDNzKxwhST6RcBBksZI6gdMAxY2q7MaOBFA0qEkib5OUnnamYukDwIHAS8WK3gzM2tbm2fdRMQ2SbOAh4DewJ0RsUzSHKAmIhYCXwG+L+kykmad8yIiJB0HzJG0DdgOfDEiXu+wT2NmZjtRRPPm9tKqqqqKmpqaUodhZtatSFocEVX55vnKWDOzjHOiNzPLOCd6M7OMc6I3M8s4J3ozs4xzojczyzgnejOzjHOiNzPLOCd6M7OMc6I3M8s4J/oMqq6Gigro1St5ra4udURmVkpt3tTMupfqapg5E+rrk+lVq5Jp8GP9zHoqH9FnzOzZO5J8g/r6pNzMeiYn+oxZvbp95WaWfU70GTNqVPvKzSz7nOgzZu5cKCtrWlZWlpSbWc/kRJ8xM2bAvHkwejRIyeu8ee6INevJfNZNBs2Y4cRuZjv4iN7MLOOc6M3MMq6gRC9pqqTnJK2QdGWe+aMkPSLpKUlLJZ2WM++qdLnnJJ1SzODNzKxtbbbRS+oN3AZ8HKgFFklaGBHLc6pdAyyIiNslHQY8CFSk49OAw4H9gYclfTgithf7g5iZWX6FHNFPAlZExIsRsQWYD5zRrE4Ae6bjewFr0vEzgPkR8V5EvASsSNdnZmadpJBEPwJ4OWe6Ni3LdR1wjqRakqP5S9uxrJmZdaBCEr3ylEWz6enADyJiJHAa8B+SehW4LJJmSqqRVFNXV1dASGZmVqhCEn0tcEDO9Eh2NM00+DywACAi/ggMAIYXuCwRMS8iqiKiqry8vPDozcysTYUk+kXAQZLGSOpH0rm6sFmd1cCJAJIOJUn0dWm9aZL6SxoDHAT8qVjBm5lZ29o86yYitkmaBTwE9AbujIhlkuYANRGxEPgK8H1Jl5E0zZwXEQEsk7QAWA5sA77kM27MzDqXknzcdVRVVUVNTU2pwzAz61YkLY6IqnzzfGWsmVnGOdGbmWWcE72ZWcY50ZuZZZwTvZlZxjnRm5llnBO9mVnGOdGbmWWcE30RVVdDRQX06pW8VleXOiIzMz8cvGiqq2HmTKivT6ZXrUqmwQ/qNrPS8hF9kcyevSPJN6ivT8rNzErJib5IVq9uX7mZWWdxoi+SUaPaV25m1lmc6Itk7lwoK2taVlaWlJuZlZITfZHMmAHz5sHo0SAlr/PmuSPWzErPZ90U0YwZTuxm1vX4iN7MLOOc6M3MMs6J3sws45zozcwyzonezCzjCkr0kqZKek7SCklX5pl/s6Ql6fC8pDdy5m3PmbewmMGbmVnb2jy9UlJv4Dbg40AtsEjSwohY3lAnIi7LqX8pMDFnFZsjYkLxQjYzs/Yo5Ih+ErAiIl6MiC3AfOCMVupPB+4uRnBmZrb7Ckn0I4CXc6Zr07KdSBoNjAF+k1M8QFKNpCckfaqF5WamdWrq6uoKDN3MzApRSKJXnrJooe404J6I2J5TNioiqoDPAbdIOnCnlUXMi4iqiKgqLy8vICQzMytUIYm+FjggZ3oksKaFutNo1mwTEWvS1xeBR2nafm9mZh2skES/CDhI0hhJ/UiS+U5nz0g6GBgK/DGnbKik/un4cOAYYHnzZc3MrOO0edZNRGyTNAt4COgN3BkRyyTNAWoioiHpTwfmR0Rus86hwPckvU+yU/lW7tk6ZmbW8dQ0L5deVVVV1NTUlDoMM7NuRdLitD90J74y1sws45zozcwyzonezCzjnOjNzDLOid7MLOOc6M3MMs6J3sws45zozcwyzonezCzj2rwFghVu61a44Qa46SYYOBD23Rf226/lYZ99oI+/ATPrYE4zRbJkCZx/fvJ62mkwbBisXQsrVsBvfwuvv77zMr16QXl56zuD/fZLdhgDBnT+ZzKzbHCi303vvQdf/zr88z8nyf3ee+HMM/PXe/XVZFi7Nv+wZAmsWwfvv7/z8kOHtrwTyJ0ePBiU7wkCZtZjOdHvhiefhAsugOXL4X/9L7j5Zth77/x1+/eH0aOToTXbt0NdXcs7g7Vrk18Ia9fCli07L19WtnPz0Ac+kLw2H/dOwaxncKLfBfX18E//BLfcAvvvDw8+CKeeWpx19+6dHKXvuy9MbOURLRGwcWPrO4Snn4b16+GNN/KvY8CA/DuA3PGG6eHD3Z9g1l35X7edHnsMPv95+Otf4QtfgG9/G/bcs/PjkJJfD3vvDYcf3nrdLVuSXwnr1iWJf/36puPr18OaNUnT0fr1SadyPsOGtbxDaL5zGDTIvxbMugon+gK9/TZ87Wtw++3wwQ/Cb34DJ5xQ6qgK068fjBiRDG2JSH4B5O4E8u0gGnYKLf1a2GOPHUl/2LAk8Q8c2PQ1X1m+eQMGeKdhtjuc6Avw0EMwcya8/DJcdlnS+TpwYKmj6hhS0vE7dCgcfHDb9d97L/m10NpOYcMGWL0a3nkHNm1KXt97r/CYevVKtnd7dxDNX/v0SfpAtm9POrw7YzxfmZQMvXo1HZqX7UqdQpfp3TvpN9pjj/zDgAHJa+/eu/631NVEJL9W331350FKDkqGD8/WZ27gRN+KjRvh8svhBz+AQw6B3/8ejj661FF1Lf37w8iRydAe27btSPrNXwste+MNqK1tWvbuux3zOXdVQ1Lt1WvHKyRJPyJ5zR26mr59W94ZNN8p7Eq9fv2SpsV8ybdh2Ly59fntGdp6oF7DKc8f+EDTYd99dy4rL+8+OwUn+hbcfz9cfHFytHr11Unnq89lL7GiVi0AAAjJSURBVJ4+fWCvvZKhmLZvT5J+vh3E9u07Em5u8u3I8fY2OUU03QHk2xk0L9uVOtu3J7+qNm8ufGhIug3Dpk3w2mv5627fXtzvtUGfPsn/YUvDwIFJU2FuWcNOprVh+/Ydv0JffTV5XbcOXnghmc53ACHl3ynk2zGUl5f2ZAYn+mbq6uDSS+GnP4Xx4+G//gsqK0sdlRWqd++kc7wUHeTFkNus051t3dryDiJ32LIl+VVYSFLu3780yTIi6aNrSP7NdwYNw4oVyevmzTuvQ0qahdraKey/f/JabAVtNklTgVuB3sAdEfGtZvNvBhq6JsuAfSJiSDrvXOCadN43IuKHxQi82CJg/vwkyb/1VtIO/7WvJT9dzax9+vZNhu66w80l7Th4OOig1utGJL8eW9shvPoq/PGPyXh9fdPljzwSamqK/xnaTPSSegO3AR8HaoFFkhZGxPKGOhFxWU79S4GJ6fjewLVAFRDA4nTZjUX9FLtpzZqkmWbhQjjqKLjrrrZPWTQza05KLkQcPBg+9KG26zfsFBp2CP37d0xchRzRTwJWRMSLAJLmA2cAy1uoP50kuQOcAvwqIl5Pl/0VMBW4e3eCLpaIJKlffnnSXnnDDfDlL/vCIDPrHA1nih14YMe+TyEtgSOAl3Oma9OynUgaDYwBftOeZSXNlFQjqaaurq6QuHfbypVwyinJxU/jxsHSpXDFFU7yZpY9hST6fOcNtHSS0jTgnoho6HMvaNmImBcRVRFRVV5eXkBIu+799+G222DsWPjDH5LxRx9tu+3NzKy7KiTR1wIH5EyPBNa0UHcaTZtl2rNsh3v+eTj+eJg1C/7mb+CZZ+CSS7r/GQ5mZq0pJMUtAg6SNEZSP5JkvrB5JUkHA0OBP+YUPwScLGmopKHAyWlZp9q2LWl/Hz8+aaK5887kateKis6OxMys87XZIh0R2yTNIknQvYE7I2KZpDlATUQ0JP3pwPyIHdeeRcTrkr5OsrMAmNPQMdtZnnkmuZXwokVw+unJvWr2378zIzAzKy1FW9cEd7KqqqqoKcKJpFu2wLe+Bd/4RnL15b/8C5x9tm+OZWbZJGlxRFTlm5fJc0wWL06O4pcuhWnT4LvfTS5BNjPriTLVDfnuu3DVVTB5cnLfivvug7vvdpI3s54tM0f0L72UPOXpueeSh3TfeGNyq10zs54uM4l+//2Tq8tuvTW5EMrMzBKZSfT9+yd3mjQzs6Yy1UZvZmY7c6I3M8s4J3ozs4xzojczyzgnejOzjHOiNzPLOCd6M7OMc6I3M8s4J3ozs4xzojczyzgnejOzjHOiNzPLOCd6M7OMc6I3M8s4J3ozs4xzojczy7iCEr2kqZKek7RC0pUt1PmspOWSlkn6SU75dklL0mFhsQJvrroaKiqgV6/ktbq6o97JzKx7afMJU5J6A7cBHwdqgUWSFkbE8pw6BwFXAcdExEZJ++SsYnNETChy3E1UV8PMmVBfn0yvWpVMA8yY0ZHvbGbW9RVyRD8JWBERL0bEFmA+cEazOhcBt0XERoCIWF/cMFs3e/aOJN+gvj4pNzPr6QpJ9COAl3Oma9OyXB8GPizp95KekDQ1Z94ASTVp+afyvYGkmWmdmrq6unZ9AIDVq9tXbmbWkxSS6JWnLJpN9wEOAo4HpgN3SBqSzhsVEVXA54BbJB2408oi5kVEVURUlZeXFxx8g1Gj2lduZtaTFJLoa4EDcqZHAmvy1HkgIrZGxEvAcySJn4hYk76+CDwKTNzNmHcydy6UlTUtKytLys3MerpCEv0i4CBJYyT1A6YBzc+euR84AUDScJKmnBclDZXUP6f8GGA5RTZjBsybB6NHg5S8zpvnjlgzMyjgrJuI2CZpFvAQ0Bu4MyKWSZoD1ETEwnTeyZKWA9uB/x0RGyT9DfA9Se+T7FS+lXu2TjHNmOHEbmaWjyKaN7eXVlVVVdTU1JQ6DDOzbkXS4rQ/dCe+MtbMLOOc6M3MMs6J3sws45zozcwyrst1xkqqA1aVOo7dNBx4rdRBdCHeHk15e+zgbdHU7myP0RGR94rTLpfos0BSTUu93z2Rt0dT3h47eFs01VHbw003ZmYZ50RvZpZxTvQdY16pA+hivD2a8vbYwduiqQ7ZHm6jNzPLOB/Rm5llnBO9mVnGOdEXkaQDJD0i6dn0Ien/WOqYSk1Sb0lPSfp5qWMpNUlDJN0j6X/Sv5GjSx1TKUm6LP0/eUbS3ZIGlDqmziTpTknrJT2TU7a3pF9JeiF9HVqM93KiL65twFci4lDgI8CXJB1W4phK7R+BZ0sdRBdxK/DLiDgEGE8P3i6SRgD/AFRFxFiSW6BPK21Une4HwNRmZVcCv46Ig4Bfp9O7zYm+iCJibUT8OR1/m+QfufnzdXsMSSOBvwXuKHUspSZpT+A44N8BImJLRLxR2qhKrg+wh6Q+QBk7P7ku0yLiceD1ZsVnAD9Mx38I5H3Odns50XcQSRUkj018srSRlNQtwFeB90sdSBfwQaAOuCttyrpD0sBSB1UqEfEK8B1gNbAWeDMi/ru0UXUJH4iItZAcOAL7FGOlTvQdQNIg4F7gyxHxVqnjKQVJnwDWR8TiUsfSRfQBKoHbI2IisIki/SzvjtK25zOAMcD+wEBJ55Q2quxyoi8ySX1Jknx1RPxnqeMpoWOA0yWtBOYDH5P049KGVFK1QG1ENPzCu4ck8fdUJwEvRURdRGwF/hP4mxLH1BWsk7QfQPq6vhgrdaIvIkkiaYN9NiJuKnU8pRQRV0XEyIioIOlk+01E9Ngjtoh4FXhZ0sFp0YlAhzw/uZtYDXxEUln6f3MiPbhzOsdC4Nx0/FzggWKstM2Hg1u7HAP8PfAXSUvSsqsj4sESxmRdx6VAtaR+wIvA+SWOp2Qi4klJ9wB/Jjlb7Sl62O0QJN0NHA8Ml1QLXAt8C1gg6fMkO8O/K8p7+RYIZmbZ5qYbM7OMc6I3M8s4J3ozs4xzojczyzgnejOzjHOiNzPLOCd6M7OM+/8O09w9zWxswwAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# plot the accuracy rates for each epoch on training and validation data\n",
"acc = history.history['acc']\n",
"val_acc = history.history['val_acc']\n",
"epochs = range(1, len(acc) + 1)\n",
"plt.plot(epochs, acc, 'bo', label='Training acc')\n",
"plt.plot(epochs, val_acc, 'b', label='Validation acc')\n",
"plt.title('Training and validation accuracy')\n",
"plt.legend()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## LSTM"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we use an LSTM recurrent neural net. If you want to use a different kind of RNN such as `SimpleRNN` or `GRU`, simply replace `LSTM` with `SimpleRNN` or `GRU` (both in importing the layer and in adding the layer to the model)."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential_2\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"embedding_2 (Embedding) (None, 200, 100) 200000 \n",
"_________________________________________________________________\n",
"lstm_1 (LSTM) (None, 64) 42240 \n",
"_________________________________________________________________\n",
"dense_3 (Dense) (None, 1) 65 \n",
"=================================================================\n",
"Total params: 242,305\n",
"Trainable params: 42,305\n",
"Non-trainable params: 200,000\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"from keras.models import Sequential\n",
"from keras.layers import Embedding, LSTM, Dense\n",
"rnn_model = Sequential()\n",
"rnn_model.add(Embedding(vocab_size, embedding_dim, input_length=200))\n",
"rnn_model.add(LSTM(64))\n",
"rnn_model.add(Dense(1, activation='sigmoid'))\n",
"\n",
"# load the GloVe embeddings in the model\n",
"rnn_model.layers[0].set_weights([embedding_matrix])\n",
"rnn_model.layers[0].trainable = False\n",
"\n",
"rnn_model.summary()"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Train on 20000 samples, validate on 5000 samples\n",
"Epoch 1/10\n",
"20000/20000 [==============================] - 86s 4ms/step - loss: 0.5707 - acc: 0.7016 - val_loss: 0.5012 - val_acc: 0.7534\n",
"Epoch 2/10\n",
"20000/20000 [==============================] - 85s 4ms/step - loss: 0.4279 - acc: 0.8048 - val_loss: 0.4189 - val_acc: 0.8126\n",
"Epoch 3/10\n",
"20000/20000 [==============================] - 83s 4ms/step - loss: 0.3690 - acc: 0.8366 - val_loss: 0.3670 - val_acc: 0.8394\n",
"Epoch 4/10\n",
"20000/20000 [==============================] - 85s 4ms/step - loss: 0.3420 - acc: 0.8520 - val_loss: 0.3361 - val_acc: 0.8522\n",
"Epoch 5/10\n",
"20000/20000 [==============================] - 87s 4ms/step - loss: 0.3173 - acc: 0.8627 - val_loss: 0.3382 - val_acc: 0.8510\n",
"Epoch 6/10\n",
"20000/20000 [==============================] - 83s 4ms/step - loss: 0.2980 - acc: 0.8733 - val_loss: 0.3764 - val_acc: 0.8352\n",
"Epoch 7/10\n",
"20000/20000 [==============================] - 86s 4ms/step - loss: 0.2806 - acc: 0.8801 - val_loss: 0.3622 - val_acc: 0.8526\n",
"Epoch 8/10\n",
"20000/20000 [==============================] - 82s 4ms/step - loss: 0.2617 - acc: 0.8915 - val_loss: 0.3367 - val_acc: 0.8544\n",
"Epoch 9/10\n",
"20000/20000 [==============================] - 83s 4ms/step - loss: 0.2462 - acc: 0.8951 - val_loss: 0.3822 - val_acc: 0.8280\n",
"Epoch 10/10\n",
"20000/20000 [==============================] - 83s 4ms/step - loss: 0.2273 - acc: 0.9056 - val_loss: 0.3363 - val_acc: 0.8638\n"
]
}
],
"source": [
"# compile and train the model\n",
"rnn_model.compile(optimizer='adam',\n",
" loss='binary_crossentropy',\n",
" metrics=['acc'])\n",
"history = rnn_model.fit(x_train, y_train,\n",
" validation_split=0.2,\n",
" epochs=10,\n",
" batch_size=32)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# plot the accuracy rates for each epoch on training and validation data\n",
"acc = history.history['acc']\n",
"val_acc = history.history['val_acc']\n",
"epochs = range(1, len(acc) + 1)\n",
"plt.plot(epochs, acc, 'bo', label='Training acc')\n",
"plt.plot(epochs, val_acc, 'b', label='Validation acc')\n",
"plt.title('Training and validation accuracy')\n",
"plt.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Finally evaluate on test data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We now compare the test set raw classification accuracies of the feedforward neural net vs the LSTM model. Keep in mind that we have set both of these models up so that right before the final logistic regression classification layer, we are representing each review as a feature vector of length 64. The LSTM model learns a much better 64-dimensional feature space to use (as evidenced by its dramatically higher prediction accuracy on the test set)."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"25000/25000 [==============================] - 2s 85us/step\n",
"Test accuracy: 0.700439989566803\n"
]
}
],
"source": [
"test_loss, test_acc = feedforward_model.evaluate(x_test, y_test)\n",
"print('Test accuracy:', test_acc)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"25000/25000 [==============================] - 22s 868us/step\n",
"Test accuracy: 0.8664799928665161\n"
]
}
],
"source": [
"test_loss, test_acc = rnn_model.evaluate(x_test, y_test)\n",
"print('Test accuracy:', test_acc)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To get predictions, we use the `predict_classes` function (note that there is a `predict` function that outputs whatever is the neural net's final output, which in this case is the probability of positive sentiment per test example, since the final layer is a Dense layer with 1 neuron and sigmoid activation)."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"predicted_labels = rnn_model.predict_classes(x_test)"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0],\n",
" [1],\n",
" [1],\n",
" ...,\n",
" [0],\n",
" [0],\n",
" [1]], dtype=int32)"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"predicted_labels"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.86648"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.mean(predicted_labels.flatten() == y_test)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In case you're wondering how the predicted labels are computed, we can simply look at the raw neural net outputs (which are probabilities) and threshold at probability 0.5 (i.e., declare every test example with probability at least 0.5 of having positive sentiment to be in the positive sentiment class and declare all other test examples to have negative sentiment)."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"test_set_predicted_probs = rnn_model.predict(x_test)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0.00192991],\n",
" [0.9505013 ],\n",
" [0.7850129 ],\n",
" ...,\n",
" [0.00563908],\n",
" [0.06085095],\n",
" [0.7172326 ]], dtype=float32)"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"test_set_predicted_probs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The code below computes the test set accuracy of `rnn_model`. Note that `test_set_predicted_probs >= .5` converts the test set predicted probabilities into actual classifications (1 if the predicted probability is greater than .5 and 0 otherwise). Flattening is needed since `test_set_predicted_probs >= .5` is actually a 2D array."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.86648"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.mean((test_set_predicted_probs >= .5).flatten() == y_test)"
]
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.7.4"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment