3294 lines
134 KiB
Plaintext
3294 lines
134 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6d2db899",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- HTML file automatically generated from DocOnce source (https://github.com/doconce/doconce/)\n",
|
|
"doconce format html chapter13.do.txt -->"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f4908a97",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"# Recurrent neural networks: Overarching view\n",
|
|
"\n",
|
|
"Till now our focus has been, including convolutional neural networks\n",
|
|
"as well, on feedforward neural networks. The output or the activations\n",
|
|
"flow only in one direction, from the input layer to the output layer.\n",
|
|
"\n",
|
|
"A recurrent neural network (RNN) looks very much like a feedforward\n",
|
|
"neural network, except that it also has connections pointing\n",
|
|
"backward. \n",
|
|
"\n",
|
|
"RNNs are used to analyze time series data such as stock prices, and\n",
|
|
"tell you when to buy or sell. In autonomous driving systems, they can\n",
|
|
"anticipate car trajectories and help avoid accidents. More generally,\n",
|
|
"they can work on sequences of arbitrary lengths, rather than on\n",
|
|
"fixed-sized inputs like all the nets we have discussed so far. For\n",
|
|
"example, they can take sentences, documents, or audio samples as\n",
|
|
"input, making them extremely useful for natural language processing\n",
|
|
"systems such as automatic translation and speech-to-text.\n",
|
|
"\n",
|
|
"More to text to be added"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "43cb4913",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## A simple example"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "cf6b9dab",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"image/png": "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\n",
|
|
"text/plain": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {
|
|
"filenames": {
|
|
"image/png": "/Users/MortenImac/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/chapter13_3_0.png"
|
|
},
|
|
"needs_background": "light"
|
|
},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2021-12-08 06:58:41.160539: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: SSE4.1 SSE4.2 AVX AVX2 FMA\n",
|
|
"To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
|
|
"2021-12-08 06:58:41.346810: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:185] None of the MLIR Optimization Passes are enabled (registered 2)\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Model: \"sequential\"\n",
|
|
"_________________________________________________________________\n",
|
|
"Layer (type) Output Shape Param # \n",
|
|
"=================================================================\n",
|
|
"simple_rnn (SimpleRNN) (None, 32) 1184 \n",
|
|
"_________________________________________________________________\n",
|
|
"dense (Dense) (None, 8) 264 \n",
|
|
"_________________________________________________________________\n",
|
|
"dense_1 (Dense) (None, 1) 9 \n",
|
|
"=================================================================\n",
|
|
"Total params: 1,457\n",
|
|
"Trainable params: 1,457\n",
|
|
"Non-trainable params: 0\n",
|
|
"_________________________________________________________________\n",
|
|
"Epoch 1/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 1s - loss: 0.4255\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 2/100\n",
|
|
"50/50 - 0s - loss: 0.4030\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 3/100\n",
|
|
"50/50 - 0s - loss: 0.3958\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 4/100\n",
|
|
"50/50 - 0s - loss: 0.3931\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 5/100\n",
|
|
"50/50 - 0s - loss: 0.3914\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 6/100\n",
|
|
"50/50 - 0s - loss: 0.3898\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 7/100\n",
|
|
"50/50 - 0s - loss: 0.3882\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 8/100\n",
|
|
"50/50 - 0s - loss: 0.3885\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 9/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3871\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 10/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3876\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 11/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3867\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 12/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3850\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 13/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3854\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 14/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3802\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 15/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3842\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 16/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3820\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 17/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3842\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 18/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3827\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 19/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3819\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 20/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3818\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 21/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3803\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 22/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3833\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 23/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3804\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 24/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3811\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 25/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3805\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 26/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3779\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 27/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3791\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 28/100\n",
|
|
"50/50 - 0s - loss: 0.3805\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 29/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3794\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 30/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3776\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 31/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3784\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 32/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3748\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 33/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3773\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 34/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3759\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 35/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3765\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 36/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3772\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 37/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3760\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 38/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3753\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 39/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3739\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 40/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3753\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 41/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3729\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 42/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3748\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 43/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3749\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 44/100\n",
|
|
"50/50 - 0s - loss: 0.3725\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 45/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3713\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 46/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3722\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 47/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3721\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 48/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3711\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 49/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3688\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 50/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3718\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 51/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3679\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 52/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3704\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 53/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3687\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 54/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3672\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 55/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3674\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 56/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3669\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 57/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3684\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 58/100"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3668\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 59/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3673\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 60/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3655\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 61/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3659\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 62/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3647\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 63/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3646\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 64/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3628\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 65/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3646\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 66/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3643\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 67/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3645\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 68/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3627\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 69/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3624\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 70/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3615\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 71/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3605\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 72/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3609\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 73/100\n",
|
|
"50/50 - 0s - loss: 0.3617\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 74/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3604\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 75/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3606\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 76/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3598\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 77/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3595\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 78/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3593\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 79/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3585\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 80/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3587\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 81/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3572\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 82/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3567\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 83/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3576\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 84/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3577\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 85/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3548\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 86/100\n",
|
|
"50/50 - 0s - loss: 0.3575\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 87/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3551\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 88/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3556\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 89/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3546\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 90/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3560\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 91/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3558\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 92/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3538\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 93/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3525\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 94/100\n",
|
|
"50/50 - 0s - loss: 0.3525\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 95/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3543\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 96/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3514\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 97/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3529\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 98/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3522\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 99/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3522\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 100/100\n",
|
|
"50/50 - 0s - loss: 0.3498\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"0.3469819128513336\n"
|
|
]
|
|
},
|
|
{
|
|
"ename": "KeyError",
|
|
"evalue": "(slice(None, None, None), None)",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
|
"\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
|
|
"\u001b[0;32m/var/folders/jy/g42mrgv128v34gnnhxwk9nrc0000gp/T/ipykernel_47724/2517560119.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 65\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 66\u001b[0m \u001b[0mindex\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 67\u001b[0;31m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mdf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 68\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mpredicted\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 69\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maxvline\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mTp\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"r\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/anaconda3/lib/python3.8/site-packages/matplotlib/pyplot.py\u001b[0m in \u001b[0;36mplot\u001b[0;34m(scalex, scaley, data, *args, **kwargs)\u001b[0m\n\u001b[1;32m 3017\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0m_copy_docstring_and_deprecators\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mAxes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3018\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mscalex\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mscaley\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3019\u001b[0;31m return gca().plot(\n\u001b[0m\u001b[1;32m 3020\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mscalex\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mscalex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mscaley\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mscaley\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3021\u001b[0m **({\"data\": data} if data is not None else {}), **kwargs)\n",
|
|
"\u001b[0;32m~/anaconda3/lib/python3.8/site-packages/matplotlib/axes/_axes.py\u001b[0m in \u001b[0;36mplot\u001b[0;34m(self, scalex, scaley, data, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1603\u001b[0m \"\"\"\n\u001b[1;32m 1604\u001b[0m \u001b[0mkwargs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcbook\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnormalize_kwargs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmlines\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mLine2D\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1605\u001b[0;31m \u001b[0mlines\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_lines\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1606\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mline\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mlines\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1607\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_line\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mline\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/anaconda3/lib/python3.8/site-packages/matplotlib/axes/_base.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, data, *args, **kwargs)\u001b[0m\n\u001b[1;32m 313\u001b[0m \u001b[0mthis\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 314\u001b[0m \u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 315\u001b[0;31m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_plot_args\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mthis\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 316\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 317\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mget_next_color\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/anaconda3/lib/python3.8/site-packages/matplotlib/axes/_base.py\u001b[0m in \u001b[0;36m_plot_args\u001b[0;34m(self, tup, kwargs, return_kwargs)\u001b[0m\n\u001b[1;32m 489\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxy\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 490\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_check_1d\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxy\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 491\u001b[0;31m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_check_1d\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxy\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 492\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 493\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mindex_of\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxy\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/anaconda3/lib/python3.8/site-packages/matplotlib/cbook/__init__.py\u001b[0m in \u001b[0;36m_check_1d\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 1360\u001b[0m message='Support for multi-dimensional indexing')\n\u001b[1;32m 1361\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1362\u001b[0;31m \u001b[0mndim\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndim\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1363\u001b[0m \u001b[0;31m# we have definitely hit a pandas index or series object\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1364\u001b[0m \u001b[0;31m# cast to a numpy array.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/anaconda3/lib/python3.8/site-packages/pandas/core/frame.py\u001b[0m in \u001b[0;36m__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 3456\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcolumns\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnlevels\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3457\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_getitem_multilevel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3458\u001b[0;31m \u001b[0mindexer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcolumns\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_loc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3459\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mis_integer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindexer\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3460\u001b[0m \u001b[0mindexer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mindexer\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/anaconda3/lib/python3.8/site-packages/pandas/core/indexes/range.py\u001b[0m in \u001b[0;36mget_loc\u001b[0;34m(self, key, method, tolerance)\u001b[0m\n\u001b[1;32m 386\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mValueError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 387\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 388\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 389\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_loc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmethod\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtolerance\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtolerance\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 390\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;31mKeyError\u001b[0m: (slice(None, None, None), None)"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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\n",
|
|
"text/plain": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {
|
|
"filenames": {
|
|
"image/png": "/Users/MortenImac/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/chapter13_3_192.png"
|
|
},
|
|
"needs_background": "light"
|
|
},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"%matplotlib inline\n",
|
|
"\n",
|
|
"# Start importing packages\n",
|
|
"import pandas as pd\n",
|
|
"import numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"import tensorflow as tf\n",
|
|
"from tensorflow.keras import datasets, layers, models\n",
|
|
"from tensorflow.keras.layers import Input\n",
|
|
"from tensorflow.keras.models import Model, Sequential \n",
|
|
"from tensorflow.keras.layers import Dense, SimpleRNN, LSTM, GRU\n",
|
|
"from tensorflow.keras import optimizers \n",
|
|
"from tensorflow.keras import regularizers \n",
|
|
"from tensorflow.keras.utils import to_categorical \n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"# convert into dataset matrix\n",
|
|
"def convertToMatrix(data, step):\n",
|
|
" X, Y =[], []\n",
|
|
" for i in range(len(data)-step):\n",
|
|
" d=i+step \n",
|
|
" X.append(data[i:d,])\n",
|
|
" Y.append(data[d,])\n",
|
|
" return np.array(X), np.array(Y)\n",
|
|
"\n",
|
|
"step = 4\n",
|
|
"N = 1000 \n",
|
|
"Tp = 800 \n",
|
|
"\n",
|
|
"t=np.arange(0,N)\n",
|
|
"x=np.sin(0.02*t)+2*np.random.rand(N)\n",
|
|
"df = pd.DataFrame(x)\n",
|
|
"df.head()\n",
|
|
"\n",
|
|
"plt.plot(df)\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"values=df.values\n",
|
|
"train,test = values[0:Tp,:], values[Tp:N,:]\n",
|
|
"\n",
|
|
"# add step elements into train and test\n",
|
|
"test = np.append(test,np.repeat(test[-1,],step))\n",
|
|
"train = np.append(train,np.repeat(train[-1,],step))\n",
|
|
" \n",
|
|
"trainX,trainY =convertToMatrix(train,step)\n",
|
|
"testX,testY =convertToMatrix(test,step)\n",
|
|
"trainX = np.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))\n",
|
|
"testX = np.reshape(testX, (testX.shape[0], 1, testX.shape[1]))\n",
|
|
"\n",
|
|
"model = Sequential()\n",
|
|
"model.add(SimpleRNN(units=32, input_shape=(1,step), activation=\"relu\"))\n",
|
|
"model.add(Dense(8, activation=\"relu\")) \n",
|
|
"model.add(Dense(1))\n",
|
|
"model.compile(loss='mean_squared_error', optimizer='rmsprop')\n",
|
|
"model.summary()\n",
|
|
"\n",
|
|
"model.fit(trainX,trainY, epochs=100, batch_size=16, verbose=2)\n",
|
|
"trainPredict = model.predict(trainX)\n",
|
|
"testPredict= model.predict(testX)\n",
|
|
"predicted=np.concatenate((trainPredict,testPredict),axis=0)\n",
|
|
"\n",
|
|
"trainScore = model.evaluate(trainX, trainY, verbose=0)\n",
|
|
"print(trainScore)\n",
|
|
"\n",
|
|
"index = df.index.values\n",
|
|
"plt.plot(index,df)\n",
|
|
"plt.plot(index,predicted)\n",
|
|
"plt.axvline(df.index[Tp], c=\"r\")\n",
|
|
"plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "897a47c7",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## An extrapolation example\n",
|
|
"\n",
|
|
"The following code provides an example of how recurrent neural\n",
|
|
"networks can be used to extrapolate to unknown values of physics data\n",
|
|
"sets. Specifically, the data sets used in this program come from\n",
|
|
"a quantum mechanical many-body calculation of energies as functions of the number of particles."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "6776ae2a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"# For matrices and calculations\n",
|
|
"import numpy as np\n",
|
|
"# For machine learning (backend for keras)\n",
|
|
"import tensorflow as tf\n",
|
|
"# User-friendly machine learning library\n",
|
|
"# Front end for TensorFlow\n",
|
|
"import tensorflow.keras\n",
|
|
"# Different methods from Keras needed to create an RNN\n",
|
|
"# This is not necessary but it shortened function calls \n",
|
|
"# that need to be used in the code.\n",
|
|
"from tensorflow.keras import datasets, layers, models\n",
|
|
"from tensorflow.keras.layers import Input\n",
|
|
"from tensorflow.keras import regularizers\n",
|
|
"from tensorflow.keras.models import Model, Sequential\n",
|
|
"from tensorflow.keras.layers import Dense, SimpleRNN, LSTM, GRU\n",
|
|
"# For timing the code\n",
|
|
"from timeit import default_timer as timer\n",
|
|
"# For plotting\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"\n",
|
|
"\n",
|
|
"# The data set\n",
|
|
"datatype='VaryDimension'\n",
|
|
"X_tot = np.arange(2, 42, 2)\n",
|
|
"y_tot = np.array([-0.03077640549, -0.08336233266, -0.1446729567, -0.2116753732, -0.2830637392, -0.3581341341, -0.436462435, -0.5177783846,\n",
|
|
"\t-0.6019067271, -0.6887363571, -0.7782028952, -0.8702784034, -0.9649652536, -1.062292565, -1.16231451, \n",
|
|
"\t-1.265109911, -1.370782966, -1.479465113, -1.591317992, -1.70653767])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "35227d36",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"The way the recurrent neural networks are trained in this program\n",
|
|
"differs from how machine learning algorithms are usually trained.\n",
|
|
"Typically a machine learning algorithm is trained by learning the\n",
|
|
"relationship between the x data and the y data. In this program, the\n",
|
|
"recurrent neural network will be trained to recognize the relationship\n",
|
|
"in a sequence of y values. This is type of data formatting is\n",
|
|
"typically used time series forcasting, but it can also be used in any\n",
|
|
"extrapolation (time series forecasting is just a specific type of\n",
|
|
"extrapolation along the time axis). This method of data formatting\n",
|
|
"does not use the x data and assumes that the y data are evenly spaced.\n",
|
|
"\n",
|
|
"For a standard machine learning algorithm, the training data has the\n",
|
|
"form of (x,y) so the machine learning algorithm learns to assiciate a\n",
|
|
"y value with a given x value. This is useful when the test data has x\n",
|
|
"values within the same range as the training data. However, for this\n",
|
|
"application, the x values of the test data are outside of the x values\n",
|
|
"of the training data and the traditional method of training a machine\n",
|
|
"learning algorithm does not work as well. For this reason, the\n",
|
|
"recurrent neural network is trained on sequences of y values of the\n",
|
|
"form ((y1, y2), y3), so that the network is concerned with learning\n",
|
|
"the pattern of the y data and not the relation between the x and y\n",
|
|
"data. As long as the pattern of y data outside of the training region\n",
|
|
"stays relatively stable compared to what was inside the training\n",
|
|
"region, this method of training can produce accurate extrapolations to\n",
|
|
"y values far removed from the training data set."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "7dc577d1",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# FORMAT_DATA\n",
|
|
"def format_data(data, length_of_sequence = 2): \n",
|
|
" \"\"\"\n",
|
|
" Inputs:\n",
|
|
" data(a numpy array): the data that will be the inputs to the recurrent neural\n",
|
|
" network\n",
|
|
" length_of_sequence (an int): the number of elements in one iteration of the\n",
|
|
" sequence patter. For a function approximator use length_of_sequence = 2.\n",
|
|
" Returns:\n",
|
|
" rnn_input (a 3D numpy array): the input data for the recurrent neural network. Its\n",
|
|
" dimensions are length of data - length of sequence, length of sequence, \n",
|
|
" dimnsion of data\n",
|
|
" rnn_output (a numpy array): the training data for the neural network\n",
|
|
" Formats data to be used in a recurrent neural network.\n",
|
|
" \"\"\"\n",
|
|
"\n",
|
|
" X, Y = [], []\n",
|
|
" for i in range(len(data)-length_of_sequence):\n",
|
|
" # Get the next length_of_sequence elements\n",
|
|
" a = data[i:i+length_of_sequence]\n",
|
|
" # Get the element that immediately follows that\n",
|
|
" b = data[i+length_of_sequence]\n",
|
|
" # Reshape so that each data point is contained in its own array\n",
|
|
" a = np.reshape (a, (len(a), 1))\n",
|
|
" X.append(a)\n",
|
|
" Y.append(b)\n",
|
|
" rnn_input = np.array(X)\n",
|
|
" rnn_output = np.array(Y)\n",
|
|
"\n",
|
|
" return rnn_input, rnn_output\n",
|
|
"\n",
|
|
"\n",
|
|
"# ## Defining the Recurrent Neural Network Using Keras\n",
|
|
"# \n",
|
|
"# The following method defines a simple recurrent neural network in keras consisting of one input layer, one hidden layer, and one output layer.\n",
|
|
"\n",
|
|
"def rnn(length_of_sequences, batch_size = None, stateful = False):\n",
|
|
" \"\"\"\n",
|
|
" Inputs:\n",
|
|
" length_of_sequences (an int): the number of y values in \"x data\". This is determined\n",
|
|
" when the data is formatted\n",
|
|
" batch_size (an int): Default value is None. See Keras documentation of SimpleRNN.\n",
|
|
" stateful (a boolean): Default value is False. See Keras documentation of SimpleRNN.\n",
|
|
" Returns:\n",
|
|
" model (a Keras model): The recurrent neural network that is built and compiled by this\n",
|
|
" method\n",
|
|
" Builds and compiles a recurrent neural network with one hidden layer and returns the model.\n",
|
|
" \"\"\"\n",
|
|
" # Number of neurons in the input and output layers\n",
|
|
" in_out_neurons = 1\n",
|
|
" # Number of neurons in the hidden layer\n",
|
|
" hidden_neurons = 200\n",
|
|
" # Define the input layer\n",
|
|
" inp = Input(batch_shape=(batch_size, \n",
|
|
" length_of_sequences, \n",
|
|
" in_out_neurons)) \n",
|
|
" # Define the hidden layer as a simple RNN layer with a set number of neurons and add it to \n",
|
|
" # the network immediately after the input layer\n",
|
|
" rnn = SimpleRNN(hidden_neurons, \n",
|
|
" return_sequences=False,\n",
|
|
" stateful = stateful,\n",
|
|
" name=\"RNN\")(inp)\n",
|
|
" # Define the output layer as a dense neural network layer (standard neural network layer)\n",
|
|
" #and add it to the network immediately after the hidden layer.\n",
|
|
" dens = Dense(in_out_neurons,name=\"dense\")(rnn)\n",
|
|
" # Create the machine learning model starting with the input layer and ending with the \n",
|
|
" # output layer\n",
|
|
" model = Model(inputs=[inp],outputs=[dens])\n",
|
|
" # Compile the machine learning model using the mean squared error function as the loss \n",
|
|
" # function and an Adams optimizer.\n",
|
|
" model.compile(loss=\"mean_squared_error\", optimizer=\"adam\") \n",
|
|
" return model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "1978b6a1",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Predicting New Points With A Trained Recurrent Neural Network"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "d4ad417a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def test_rnn (x1, y_test, plot_min, plot_max):\n",
|
|
" \"\"\"\n",
|
|
" Inputs:\n",
|
|
" x1 (a list or numpy array): The complete x component of the data set\n",
|
|
" y_test (a list or numpy array): The complete y component of the data set\n",
|
|
" plot_min (an int or float): the smallest x value used in the training data\n",
|
|
" plot_max (an int or float): the largest x valye used in the training data\n",
|
|
" Returns:\n",
|
|
" None.\n",
|
|
" Uses a trained recurrent neural network model to predict future points in the \n",
|
|
" series. Computes the MSE of the predicted data set from the true data set, saves\n",
|
|
" the predicted data set to a csv file, and plots the predicted and true data sets w\n",
|
|
" while also displaying the data range used for training.\n",
|
|
" \"\"\"\n",
|
|
" # Add the training data as the first dim points in the predicted data array as these\n",
|
|
" # are known values.\n",
|
|
" y_pred = y_test[:dim].tolist()\n",
|
|
" # Generate the first input to the trained recurrent neural network using the last two \n",
|
|
" # points of the training data. Based on how the network was trained this means that it\n",
|
|
" # will predict the first point in the data set after the training data. All of the \n",
|
|
" # brackets are necessary for Tensorflow.\n",
|
|
" next_input = np.array([[[y_test[dim-2]], [y_test[dim-1]]]])\n",
|
|
" # Save the very last point in the training data set. This will be used later.\n",
|
|
" last = [y_test[dim-1]]\n",
|
|
"\n",
|
|
" # Iterate until the complete data set is created.\n",
|
|
" for i in range (dim, len(y_test)):\n",
|
|
" # Predict the next point in the data set using the previous two points.\n",
|
|
" next = model.predict(next_input)\n",
|
|
" # Append just the number of the predicted data set\n",
|
|
" y_pred.append(next[0][0])\n",
|
|
" # Create the input that will be used to predict the next data point in the data set.\n",
|
|
" next_input = np.array([[last, next[0]]], dtype=np.float64)\n",
|
|
" last = next\n",
|
|
"\n",
|
|
" # Print the mean squared error between the known data set and the predicted data set.\n",
|
|
" print('MSE: ', np.square(np.subtract(y_test, y_pred)).mean())\n",
|
|
" # Save the predicted data set as a csv file for later use\n",
|
|
" name = datatype + 'Predicted'+str(dim)+'.csv'\n",
|
|
" np.savetxt(name, y_pred, delimiter=',')\n",
|
|
" # Plot the known data set and the predicted data set. The red box represents the region that was used\n",
|
|
" # for the training data.\n",
|
|
" fig, ax = plt.subplots()\n",
|
|
" ax.plot(x1, y_test, label=\"true\", linewidth=3)\n",
|
|
" ax.plot(x1, y_pred, 'g-.',label=\"predicted\", linewidth=4)\n",
|
|
" ax.legend()\n",
|
|
" # Created a red region to represent the points used in the training data.\n",
|
|
" ax.axvspan(plot_min, plot_max, alpha=0.25, color='red')\n",
|
|
" plt.show()\n",
|
|
"\n",
|
|
"# Check to make sure the data set is complete\n",
|
|
"assert len(X_tot) == len(y_tot)\n",
|
|
"\n",
|
|
"# This is the number of points that will be used in as the training data\n",
|
|
"dim=12\n",
|
|
"\n",
|
|
"# Separate the training data from the whole data set\n",
|
|
"X_train = X_tot[:dim]\n",
|
|
"y_train = y_tot[:dim]\n",
|
|
"\n",
|
|
"\n",
|
|
"# Generate the training data for the RNN, using a sequence of 2\n",
|
|
"rnn_input, rnn_training = format_data(y_train, 2)\n",
|
|
"\n",
|
|
"\n",
|
|
"# Create a recurrent neural network in Keras and produce a summary of the \n",
|
|
"# machine learning model\n",
|
|
"model = rnn(length_of_sequences = rnn_input.shape[1])\n",
|
|
"model.summary()\n",
|
|
"\n",
|
|
"# Start the timer. Want to time training+testing\n",
|
|
"start = timer()\n",
|
|
"# Fit the model using the training data genenerated above using 150 training iterations and a 5%\n",
|
|
"# validation split. Setting verbose to True prints information about each training iteration.\n",
|
|
"hist = model.fit(rnn_input, rnn_training, batch_size=None, epochs=150, \n",
|
|
" verbose=True,validation_split=0.05)\n",
|
|
"\n",
|
|
"for label in [\"loss\",\"val_loss\"]:\n",
|
|
" plt.plot(hist.history[label],label=label)\n",
|
|
"\n",
|
|
"plt.ylabel(\"loss\")\n",
|
|
"plt.xlabel(\"epoch\")\n",
|
|
"plt.title(\"The final validation loss: {}\".format(hist.history[\"val_loss\"][-1]))\n",
|
|
"plt.legend()\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"# Use the trained neural network to predict more points of the data set\n",
|
|
"test_rnn(X_tot, y_tot, X_tot[0], X_tot[dim-1])\n",
|
|
"# Stop the timer and calculate the total time needed.\n",
|
|
"end = timer()\n",
|
|
"print('Time: ', end-start)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e2cad4fc",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Changing the size of the recurrent neural network and its parameters\n",
|
|
"can drastically change the results you get from the model. The below\n",
|
|
"code takes the simple recurrent neural network from above and adds a\n",
|
|
"second hidden layer, changes the number of neurons in the hidden\n",
|
|
"layer, and explicitly declares the activation function of the hidden\n",
|
|
"layers to be a sigmoid function. The loss function and optimizer can\n",
|
|
"also be changed but are kept the same as the above network. These\n",
|
|
"parameters can be tuned to provide the optimal result from the\n",
|
|
"network. For some ideas on how to improve the performance of a\n",
|
|
"[recurrent neural network](https://danijar.com/tips-for-training-recurrent-neural-networks)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "c39f1516",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def rnn_2layers(length_of_sequences, batch_size = None, stateful = False):\n",
|
|
" \"\"\"\n",
|
|
" Inputs:\n",
|
|
" length_of_sequences (an int): the number of y values in \"x data\". This is determined\n",
|
|
" when the data is formatted\n",
|
|
" batch_size (an int): Default value is None. See Keras documentation of SimpleRNN.\n",
|
|
" stateful (a boolean): Default value is False. See Keras documentation of SimpleRNN.\n",
|
|
" Returns:\n",
|
|
" model (a Keras model): The recurrent neural network that is built and compiled by this\n",
|
|
" method\n",
|
|
" Builds and compiles a recurrent neural network with two hidden layers and returns the model.\n",
|
|
" \"\"\"\n",
|
|
" # Number of neurons in the input and output layers\n",
|
|
" in_out_neurons = 1\n",
|
|
" # Number of neurons in the hidden layer, increased from the first network\n",
|
|
" hidden_neurons = 500\n",
|
|
" # Define the input layer\n",
|
|
" inp = Input(batch_shape=(batch_size, \n",
|
|
" length_of_sequences, \n",
|
|
" in_out_neurons)) \n",
|
|
" # Create two hidden layers instead of one hidden layer. Explicitly set the activation\n",
|
|
" # function to be the sigmoid function (the default value is hyperbolic tangent)\n",
|
|
" rnn1 = SimpleRNN(hidden_neurons, \n",
|
|
" return_sequences=True, # This needs to be True if another hidden layer is to follow\n",
|
|
" stateful = stateful, activation = 'sigmoid',\n",
|
|
" name=\"RNN1\")(inp)\n",
|
|
" rnn2 = SimpleRNN(hidden_neurons, \n",
|
|
" return_sequences=False, activation = 'sigmoid',\n",
|
|
" stateful = stateful,\n",
|
|
" name=\"RNN2\")(rnn1)\n",
|
|
" # Define the output layer as a dense neural network layer (standard neural network layer)\n",
|
|
" #and add it to the network immediately after the hidden layer.\n",
|
|
" dens = Dense(in_out_neurons,name=\"dense\")(rnn2)\n",
|
|
" # Create the machine learning model starting with the input layer and ending with the \n",
|
|
" # output layer\n",
|
|
" model = Model(inputs=[inp],outputs=[dens])\n",
|
|
" # Compile the machine learning model using the mean squared error function as the loss \n",
|
|
" # function and an Adams optimizer.\n",
|
|
" model.compile(loss=\"mean_squared_error\", optimizer=\"adam\") \n",
|
|
" return model\n",
|
|
"\n",
|
|
"# Check to make sure the data set is complete\n",
|
|
"assert len(X_tot) == len(y_tot)\n",
|
|
"\n",
|
|
"# This is the number of points that will be used in as the training data\n",
|
|
"dim=12\n",
|
|
"\n",
|
|
"# Separate the training data from the whole data set\n",
|
|
"X_train = X_tot[:dim]\n",
|
|
"y_train = y_tot[:dim]\n",
|
|
"\n",
|
|
"\n",
|
|
"# Generate the training data for the RNN, using a sequence of 2\n",
|
|
"rnn_input, rnn_training = format_data(y_train, 2)\n",
|
|
"\n",
|
|
"\n",
|
|
"# Create a recurrent neural network in Keras and produce a summary of the \n",
|
|
"# machine learning model\n",
|
|
"model = rnn_2layers(length_of_sequences = 2)\n",
|
|
"model.summary()\n",
|
|
"\n",
|
|
"# Start the timer. Want to time training+testing\n",
|
|
"start = timer()\n",
|
|
"# Fit the model using the training data genenerated above using 150 training iterations and a 5%\n",
|
|
"# validation split. Setting verbose to True prints information about each training iteration.\n",
|
|
"hist = model.fit(rnn_input, rnn_training, batch_size=None, epochs=150, \n",
|
|
" verbose=True,validation_split=0.05)\n",
|
|
"\n",
|
|
"\n",
|
|
"# This section plots the training loss and the validation loss as a function of training iteration.\n",
|
|
"# This is not required for analyzing the couple cluster data but can help determine if the network is\n",
|
|
"# being overtrained.\n",
|
|
"for label in [\"loss\",\"val_loss\"]:\n",
|
|
" plt.plot(hist.history[label],label=label)\n",
|
|
"\n",
|
|
"plt.ylabel(\"loss\")\n",
|
|
"plt.xlabel(\"epoch\")\n",
|
|
"plt.title(\"The final validation loss: {}\".format(hist.history[\"val_loss\"][-1]))\n",
|
|
"plt.legend()\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"# Use the trained neural network to predict more points of the data set\n",
|
|
"test_rnn(X_tot, y_tot, X_tot[0], X_tot[dim-1])\n",
|
|
"# Stop the timer and calculate the total time needed.\n",
|
|
"end = timer()\n",
|
|
"print('Time: ', end-start)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "842c7602",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Other Types of Recurrent Neural Networks\n",
|
|
"\n",
|
|
"Besides a simple recurrent neural network layer, there are two other\n",
|
|
"commonly used types of recurrent neural network layers: Long Short\n",
|
|
"Term Memory (LSTM) and Gated Recurrent Unit (GRU). For a short\n",
|
|
"introduction to these layers see <https://medium.com/mindboard/lstm-vs-gru-experimental-comparison-955820c21e8b>\n",
|
|
"and <https://medium.com/mindboard/lstm-vs-gru-experimental-comparison-955820c21e8b>.\n",
|
|
"\n",
|
|
"The first network created below is similar to the previous network,\n",
|
|
"but it replaces the SimpleRNN layers with LSTM layers. The second\n",
|
|
"network below has two hidden layers made up of GRUs, which are\n",
|
|
"preceeded by two dense (feeddorward) neural network layers. These\n",
|
|
"dense layers \"preprocess\" the data before it reaches the recurrent\n",
|
|
"layers. This architecture has been shown to improve the performance\n",
|
|
"of recurrent neural networks (see the link above and also\n",
|
|
"<https://arxiv.org/pdf/1807.02857.pdf>."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "6f0e9b62",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def lstm_2layers(length_of_sequences, batch_size = None, stateful = False):\n",
|
|
" \"\"\"\n",
|
|
" Inputs:\n",
|
|
" length_of_sequences (an int): the number of y values in \"x data\". This is determined\n",
|
|
" when the data is formatted\n",
|
|
" batch_size (an int): Default value is None. See Keras documentation of SimpleRNN.\n",
|
|
" stateful (a boolean): Default value is False. See Keras documentation of SimpleRNN.\n",
|
|
" Returns:\n",
|
|
" model (a Keras model): The recurrent neural network that is built and compiled by this\n",
|
|
" method\n",
|
|
" Builds and compiles a recurrent neural network with two LSTM hidden layers and returns the model.\n",
|
|
" \"\"\"\n",
|
|
" # Number of neurons on the input/output layer and the number of neurons in the hidden layer\n",
|
|
" in_out_neurons = 1\n",
|
|
" hidden_neurons = 250\n",
|
|
" # Input Layer\n",
|
|
" inp = Input(batch_shape=(batch_size, \n",
|
|
" length_of_sequences, \n",
|
|
" in_out_neurons)) \n",
|
|
" # Hidden layers (in this case they are LSTM layers instead if SimpleRNN layers)\n",
|
|
" rnn= LSTM(hidden_neurons, \n",
|
|
" return_sequences=True,\n",
|
|
" stateful = stateful,\n",
|
|
" name=\"RNN\", use_bias=True, activation='tanh')(inp)\n",
|
|
" rnn1 = LSTM(hidden_neurons, \n",
|
|
" return_sequences=False,\n",
|
|
" stateful = stateful,\n",
|
|
" name=\"RNN1\", use_bias=True, activation='tanh')(rnn)\n",
|
|
" # Output layer\n",
|
|
" dens = Dense(in_out_neurons,name=\"dense\")(rnn1)\n",
|
|
" # Define the midel\n",
|
|
" model = Model(inputs=[inp],outputs=[dens])\n",
|
|
" # Compile the model\n",
|
|
" model.compile(loss='mean_squared_error', optimizer='adam') \n",
|
|
" # Return the model\n",
|
|
" return model\n",
|
|
"\n",
|
|
"def dnn2_gru2(length_of_sequences, batch_size = None, stateful = False):\n",
|
|
" \"\"\"\n",
|
|
" Inputs:\n",
|
|
" length_of_sequences (an int): the number of y values in \"x data\". This is determined\n",
|
|
" when the data is formatted\n",
|
|
" batch_size (an int): Default value is None. See Keras documentation of SimpleRNN.\n",
|
|
" stateful (a boolean): Default value is False. See Keras documentation of SimpleRNN.\n",
|
|
" Returns:\n",
|
|
" model (a Keras model): The recurrent neural network that is built and compiled by this\n",
|
|
" method\n",
|
|
" Builds and compiles a recurrent neural network with four hidden layers (two dense followed by\n",
|
|
" two GRU layers) and returns the model.\n",
|
|
" \"\"\" \n",
|
|
" # Number of neurons on the input/output layers and hidden layers\n",
|
|
" in_out_neurons = 1\n",
|
|
" hidden_neurons = 250\n",
|
|
" # Input layer\n",
|
|
" inp = Input(batch_shape=(batch_size, \n",
|
|
" length_of_sequences, \n",
|
|
" in_out_neurons)) \n",
|
|
" # Hidden Dense (feedforward) layers\n",
|
|
" dnn = Dense(hidden_neurons/2, activation='relu', name='dnn')(inp)\n",
|
|
" dnn1 = Dense(hidden_neurons/2, activation='relu', name='dnn1')(dnn)\n",
|
|
" # Hidden GRU layers\n",
|
|
" rnn1 = GRU(hidden_neurons, \n",
|
|
" return_sequences=True,\n",
|
|
" stateful = stateful,\n",
|
|
" name=\"RNN1\", use_bias=True)(dnn1)\n",
|
|
" rnn = GRU(hidden_neurons, \n",
|
|
" return_sequences=False,\n",
|
|
" stateful = stateful,\n",
|
|
" name=\"RNN\", use_bias=True)(rnn1)\n",
|
|
" # Output layer\n",
|
|
" dens = Dense(in_out_neurons,name=\"dense\")(rnn)\n",
|
|
" # Define the model\n",
|
|
" model = Model(inputs=[inp],outputs=[dens])\n",
|
|
" # Compile the mdoel\n",
|
|
" model.compile(loss='mean_squared_error', optimizer='adam') \n",
|
|
" # Return the model\n",
|
|
" return model\n",
|
|
"\n",
|
|
"# Check to make sure the data set is complete\n",
|
|
"assert len(X_tot) == len(y_tot)\n",
|
|
"\n",
|
|
"# This is the number of points that will be used in as the training data\n",
|
|
"dim=12\n",
|
|
"\n",
|
|
"# Separate the training data from the whole data set\n",
|
|
"X_train = X_tot[:dim]\n",
|
|
"y_train = y_tot[:dim]\n",
|
|
"\n",
|
|
"\n",
|
|
"# Generate the training data for the RNN, using a sequence of 2\n",
|
|
"rnn_input, rnn_training = format_data(y_train, 2)\n",
|
|
"\n",
|
|
"\n",
|
|
"# Create a recurrent neural network in Keras and produce a summary of the \n",
|
|
"# machine learning model\n",
|
|
"# Change the method name to reflect which network you want to use\n",
|
|
"model = dnn2_gru2(length_of_sequences = 2)\n",
|
|
"model.summary()\n",
|
|
"\n",
|
|
"# Start the timer. Want to time training+testing\n",
|
|
"start = timer()\n",
|
|
"# Fit the model using the training data genenerated above using 150 training iterations and a 5%\n",
|
|
"# validation split. Setting verbose to True prints information about each training iteration.\n",
|
|
"hist = model.fit(rnn_input, rnn_training, batch_size=None, epochs=150, \n",
|
|
" verbose=True,validation_split=0.05)\n",
|
|
"\n",
|
|
"\n",
|
|
"# This section plots the training loss and the validation loss as a function of training iteration.\n",
|
|
"# This is not required for analyzing the couple cluster data but can help determine if the network is\n",
|
|
"# being overtrained.\n",
|
|
"for label in [\"loss\",\"val_loss\"]:\n",
|
|
" plt.plot(hist.history[label],label=label)\n",
|
|
"\n",
|
|
"plt.ylabel(\"loss\")\n",
|
|
"plt.xlabel(\"epoch\")\n",
|
|
"plt.title(\"The final validation loss: {}\".format(hist.history[\"val_loss\"][-1]))\n",
|
|
"plt.legend()\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"# Use the trained neural network to predict more points of the data set\n",
|
|
"test_rnn(X_tot, y_tot, X_tot[0], X_tot[dim-1])\n",
|
|
"# Stop the timer and calculate the total time needed.\n",
|
|
"end = timer()\n",
|
|
"print('Time: ', end-start)\n",
|
|
"\n",
|
|
"\n",
|
|
"# ### Training Recurrent Neural Networks in the Standard Way (i.e. learning the relationship between the X and Y data)\n",
|
|
"# \n",
|
|
"# Finally, comparing the performace of a recurrent neural network using the standard data formatting to the performance of the network with time sequence data formatting shows the benefit of this type of data formatting with extrapolation.\n",
|
|
"\n",
|
|
"# Check to make sure the data set is complete\n",
|
|
"assert len(X_tot) == len(y_tot)\n",
|
|
"\n",
|
|
"# This is the number of points that will be used in as the training data\n",
|
|
"dim=12\n",
|
|
"\n",
|
|
"# Separate the training data from the whole data set\n",
|
|
"X_train = X_tot[:dim]\n",
|
|
"y_train = y_tot[:dim]\n",
|
|
"\n",
|
|
"# Reshape the data for Keras specifications\n",
|
|
"X_train = X_train.reshape((dim, 1))\n",
|
|
"y_train = y_train.reshape((dim, 1))\n",
|
|
"\n",
|
|
"\n",
|
|
"# Create a recurrent neural network in Keras and produce a summary of the \n",
|
|
"# machine learning model\n",
|
|
"# Set the sequence length to 1 for regular data formatting \n",
|
|
"model = rnn(length_of_sequences = 1)\n",
|
|
"model.summary()\n",
|
|
"\n",
|
|
"# Start the timer. Want to time training+testing\n",
|
|
"start = timer()\n",
|
|
"# Fit the model using the training data genenerated above using 150 training iterations and a 5%\n",
|
|
"# validation split. Setting verbose to True prints information about each training iteration.\n",
|
|
"hist = model.fit(X_train, y_train, batch_size=None, epochs=150, \n",
|
|
" verbose=True,validation_split=0.05)\n",
|
|
"\n",
|
|
"\n",
|
|
"# This section plots the training loss and the validation loss as a function of training iteration.\n",
|
|
"# This is not required for analyzing the couple cluster data but can help determine if the network is\n",
|
|
"# being overtrained.\n",
|
|
"for label in [\"loss\",\"val_loss\"]:\n",
|
|
" plt.plot(hist.history[label],label=label)\n",
|
|
"\n",
|
|
"plt.ylabel(\"loss\")\n",
|
|
"plt.xlabel(\"epoch\")\n",
|
|
"plt.title(\"The final validation loss: {}\".format(hist.history[\"val_loss\"][-1]))\n",
|
|
"plt.legend()\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"# Use the trained neural network to predict the remaining data points\n",
|
|
"X_pred = X_tot[dim:]\n",
|
|
"X_pred = X_pred.reshape((len(X_pred), 1))\n",
|
|
"y_model = model.predict(X_pred)\n",
|
|
"y_pred = np.concatenate((y_tot[:dim], y_model.flatten()))\n",
|
|
"\n",
|
|
"# Plot the known data set and the predicted data set. The red box represents the region that was used\n",
|
|
"# for the training data.\n",
|
|
"fig, ax = plt.subplots()\n",
|
|
"ax.plot(X_tot, y_tot, label=\"true\", linewidth=3)\n",
|
|
"ax.plot(X_tot, y_pred, 'g-.',label=\"predicted\", linewidth=4)\n",
|
|
"ax.legend()\n",
|
|
"# Created a red region to represent the points used in the training data.\n",
|
|
"ax.axvspan(X_tot[0], X_tot[dim], alpha=0.25, color='red')\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"# Stop the timer and calculate the total time needed.\n",
|
|
"end = timer()\n",
|
|
"print('Time: ', end-start)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0752ba7f",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"# Generative Models\n",
|
|
"\n",
|
|
"**Generative models** describe a class of statistical models that are a contrast\n",
|
|
"to **discriminative models**. Informally we say that generative models can\n",
|
|
"generate new data instances while discriminative models discriminate between\n",
|
|
"different kinds of data instances. A generative model could generate new photos\n",
|
|
"of animals that look like 'real' animals while a discriminative model could tell\n",
|
|
"a dog from a cat. More formally, given a data set $x$ and a set of labels /\n",
|
|
"targets $y$. Generative models capture the joint probability $p(x, y)$, or\n",
|
|
"just $p(x)$ if there are no labels, while discriminative models capture the\n",
|
|
"conditional probability $p(y | x)$. Discriminative models generally try to draw\n",
|
|
"boundaries in the data space (often high dimensional), while generative models\n",
|
|
"try to model how data is placed throughout the space.\n",
|
|
"\n",
|
|
"**Note**: this material is thanks to Linus Ekstrøm."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "784138f8",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Generative Adversarial Networks\n",
|
|
"\n",
|
|
"**Generative Adversarial Networks** are a type of unsupervised machine learning\n",
|
|
"algorithm proposed by [Goodfellow et. al](https://arxiv.org/pdf/1406.2661.pdf)\n",
|
|
"in 2014 (short and good article).\n",
|
|
"\n",
|
|
"The simplest formulation of\n",
|
|
"the model is based on a game theoretic approach, *zero sum game*, where we pit\n",
|
|
"two neural networks against one another. We define two rival networks, one\n",
|
|
"generator $g$, and one discriminator $d$. The generator directly produces\n",
|
|
"samples"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "a42f89ee",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto1\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" x = g(z; \\theta^{(g)})\n",
|
|
"\\label{_auto1} \\tag{1}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "abe7212f",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"The discriminator attempts to distinguish between samples drawn from the\n",
|
|
"training data and samples drawn from the generator. In other words, it tries to\n",
|
|
"tell the difference between the fake data produced by $g$ and the actual data\n",
|
|
"samples we want to do prediction on. The discriminator outputs a probability\n",
|
|
"value given by"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0821eaee",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto2\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" d(x; \\theta^{(d)})\n",
|
|
"\\label{_auto2} \\tag{2}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "55e0ccf6",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"indicating the probability that $x$ is a real training example rather than a\n",
|
|
"fake sample the generator has generated. The simplest way to formulate the\n",
|
|
"learning process in a generative adversarial network is a zero-sum game, in\n",
|
|
"which a function"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f37ece14",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto3\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" v(\\theta^{(g)}, \\theta^{(d)})\n",
|
|
"\\label{_auto3} \\tag{3}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d6d6d5fa",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"determines the reward for the discriminator, while the generator gets the\n",
|
|
"conjugate reward"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "3c74b45c",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto4\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" -v(\\theta^{(g)}, \\theta^{(d)})\n",
|
|
"\\label{_auto4} \\tag{4}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "605ac8c9",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"During learning both of the networks maximize their own reward function, so that\n",
|
|
"the generator gets better and better at tricking the discriminator, while the\n",
|
|
"discriminator gets better and better at telling the difference between the fake\n",
|
|
"and real data. The generator and discriminator alternate on which one trains at\n",
|
|
"one time (i.e. for one epoch). In other words, we keep the generator constant\n",
|
|
"and train the discriminator, then we keep the discriminator constant to train\n",
|
|
"the generator and repeat. It is this back and forth dynamic which lets GANs\n",
|
|
"tackle otherwise intractable generative problems. As the generator improves with\n",
|
|
" training, the discriminator's performance gets worse because it cannot easily\n",
|
|
" tell the difference between real and fake. If the generator ends up succeeding\n",
|
|
" perfectly, the the discriminator will do no better than random guessing i.e.\n",
|
|
" 50\\%. This progression in the training poses a problem for the convergence\n",
|
|
" criteria for GANs. The discriminator feedback gets less meaningful over time,\n",
|
|
" if we continue training after this point then the generator is effectively\n",
|
|
" training on junk data which can undo the learning up to that point. Therefore,\n",
|
|
" we stop training when the discriminator starts outputting $1/2$ everywhere.\n",
|
|
"\n",
|
|
"At convergence we have"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "cfec7462",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto5\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" g^* = \\underset{g}{\\mathrm{argmin}}\\hspace{2pt}\n",
|
|
" \\underset{d}{\\mathrm{max}}v(\\theta^{(g)}, \\theta^{(d)})\n",
|
|
"\\label{_auto5} \\tag{5}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "37c65d4c",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"The default choice for $v$ is"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c868a092",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto6\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" v(\\theta^{(g)}, \\theta^{(d)}) = \\mathbb{E}_{x\\sim p_\\mathrm{data}}\\log d(x)\n",
|
|
" + \\mathbb{E}_{x\\sim p_\\mathrm{model}}\n",
|
|
" \\log (1 - d(x))\n",
|
|
"\\label{_auto6} \\tag{6}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ad465af3",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"The main motivation for the design of GANs is that the learning process requires\n",
|
|
"neither approximate inference (variational autoencoders for example) nor\n",
|
|
"approximation of a partition function. In the case where"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "27858a4e",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto7\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" \\underset{d}{\\mathrm{max}}v(\\theta^{(g)}, \\theta^{(d)})\n",
|
|
"\\label{_auto7} \\tag{7}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "86006023",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"is convex in $\\theta^{(g)} then the procedure is guaranteed to converge and is\n",
|
|
"asymptotically consistent\n",
|
|
"( [Seth Lloyd on QuGANs](https://arxiv.org/pdf/1804.09139.pdf) ).\n",
|
|
"\n",
|
|
"This is in\n",
|
|
"general not the case and it is possible to get situations where the training\n",
|
|
"process never converges because the generator and discriminator chase one\n",
|
|
"another around in the parameter space indefinitely. A much deeper discussion on\n",
|
|
"the currently open research problem of GAN convergence is available\n",
|
|
"[here](https://www.deeplearningbook.org/contents/generative_models.html). To\n",
|
|
"anyone interested in learning more about GANs it is a highly recommended read.\n",
|
|
"Direct quote: \"In this best-performing formulation, the generator aims to\n",
|
|
"increase the log probability that the discriminator makes a mistake, rather than\n",
|
|
"aiming to decrease the log probability that the discriminator makes the correct\n",
|
|
"prediction.\" [Another interesting read](https://arxiv.org/abs/1701.00160)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "2fee38bd",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Writing Our First Generative Adversarial Network\n",
|
|
"Let us now move on to actually implementing a GAN in tensorflow. We will study\n",
|
|
"the performance of our GAN on the MNIST dataset. This code is based on and\n",
|
|
"adapted from the\n",
|
|
"[google tutorial](https://www.tensorflow.org/tutorials/generative/dcgan)\n",
|
|
"\n",
|
|
"First we import our libraries"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "004a0b53",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import os\n",
|
|
"import time\n",
|
|
"import numpy as np\n",
|
|
"import tensorflow as tf\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"from tensorflow.keras import layers\n",
|
|
"from tensorflow.keras.utils import plot_model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "353af161",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Next we define our hyperparameters and import our data the usual way"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "8cbaf16a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"BUFFER_SIZE = 60000\n",
|
|
"BATCH_SIZE = 256\n",
|
|
"EPOCHS = 30\n",
|
|
"\n",
|
|
"data = tf.keras.datasets.mnist.load_data()\n",
|
|
"(train_images, train_labels), (test_images, test_labels) = data\n",
|
|
"train_images = np.reshape(train_images, (train_images.shape[0],\n",
|
|
" 28,\n",
|
|
" 28,\n",
|
|
" 1)).astype('float32')\n",
|
|
"\n",
|
|
"# we normalize between -1 and 1\n",
|
|
"train_images = (train_images - 127.5) / 127.5\n",
|
|
"training_dataset = tf.data.Dataset.from_tensor_slices(\n",
|
|
" train_images).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "822b8cc7",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"### MNIST and GANs\n",
|
|
"\n",
|
|
"Let's have a quick look"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"id": "52b5965c",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"plt.imshow(train_images[0], cmap='Greys')\n",
|
|
"plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "21c5199c",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Now we define our two models. This is where the 'magic' happens. There are a\n",
|
|
"huge amount of possible formulations for both models. A lot of engineering and\n",
|
|
"trial and error can be done here to try to produce better performing models. For\n",
|
|
"more advanced GANs this is by far the step where you can 'make or break' a\n",
|
|
"model.\n",
|
|
"\n",
|
|
"We start with the generator. As stated in the introductory text the generator\n",
|
|
"$g$ upsamples from a random sample to the shape of what we want to predict. In\n",
|
|
"our case we are trying to predict MNIST images ($28\\times 28$ pixels)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"id": "356759c7",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def generator_model():\n",
|
|
" \"\"\"\n",
|
|
" The generator uses upsampling layers tf.keras.layers.Conv2DTranspose() to\n",
|
|
" produce an image from a random seed. We start with a Dense layer taking this\n",
|
|
" random sample as an input and subsequently upsample through multiple\n",
|
|
" convolutional layers.\n",
|
|
" \"\"\"\n",
|
|
"\n",
|
|
" # we define our model\n",
|
|
" model = tf.keras.Sequential()\n",
|
|
"\n",
|
|
"\n",
|
|
" # adding our input layer. Dense means that every neuron is connected and\n",
|
|
" # the input shape is the shape of our random noise. The units need to match\n",
|
|
" # in some sense the upsampling strides to reach our desired output shape.\n",
|
|
" # we are using 100 random numbers as our seed\n",
|
|
" model.add(layers.Dense(units=7*7*BATCH_SIZE,\n",
|
|
" use_bias=False,\n",
|
|
" input_shape=(100, )))\n",
|
|
" # we normalize the output form the Dense layer\n",
|
|
" model.add(layers.BatchNormalization())\n",
|
|
" # and add an activation function to our 'layer'. LeakyReLU avoids vanishing\n",
|
|
" # gradient problem\n",
|
|
" model.add(layers.LeakyReLU())\n",
|
|
" model.add(layers.Reshape((7, 7, BATCH_SIZE)))\n",
|
|
" assert model.output_shape == (None, 7, 7, BATCH_SIZE)\n",
|
|
" # even though we just added four keras layers we think of everything above\n",
|
|
" # as 'one' layer\n",
|
|
"\n",
|
|
" # next we add our upscaling convolutional layers\n",
|
|
" model.add(layers.Conv2DTranspose(filters=128,\n",
|
|
" kernel_size=(5, 5),\n",
|
|
" strides=(1, 1),\n",
|
|
" padding='same',\n",
|
|
" use_bias=False))\n",
|
|
" model.add(layers.BatchNormalization())\n",
|
|
" model.add(layers.LeakyReLU())\n",
|
|
" assert model.output_shape == (None, 7, 7, 128)\n",
|
|
"\n",
|
|
" model.add(layers.Conv2DTranspose(filters=64,\n",
|
|
" kernel_size=(5, 5),\n",
|
|
" strides=(2, 2),\n",
|
|
" padding='same',\n",
|
|
" use_bias=False))\n",
|
|
" model.add(layers.BatchNormalization())\n",
|
|
" model.add(layers.LeakyReLU())\n",
|
|
" assert model.output_shape == (None, 14, 14, 64)\n",
|
|
"\n",
|
|
" model.add(layers.Conv2DTranspose(filters=1,\n",
|
|
" kernel_size=(5, 5),\n",
|
|
" strides=(2, 2),\n",
|
|
" padding='same',\n",
|
|
" use_bias=False,\n",
|
|
" activation='tanh'))\n",
|
|
" assert model.output_shape == (None, 28, 28, 1)\n",
|
|
"\n",
|
|
" return model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "854bcd6b",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"And there we have our 'simple' generator model. Now we move on to defining our\n",
|
|
"discriminator model $d$, which is a convolutional neural network based image\n",
|
|
"classifier."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"id": "41473304",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def discriminator_model():\n",
|
|
" \"\"\"\n",
|
|
" The discriminator is a convolutional neural network based image classifier\n",
|
|
" \"\"\"\n",
|
|
"\n",
|
|
" # we define our model\n",
|
|
" model = tf.keras.Sequential()\n",
|
|
" model.add(layers.Conv2D(filters=64,\n",
|
|
" kernel_size=(5, 5),\n",
|
|
" strides=(2, 2),\n",
|
|
" padding='same',\n",
|
|
" input_shape=[28, 28, 1]))\n",
|
|
" model.add(layers.LeakyReLU())\n",
|
|
" # adding a dropout layer as you do in conv-nets\n",
|
|
" model.add(layers.Dropout(0.3))\n",
|
|
"\n",
|
|
"\n",
|
|
" model.add(layers.Conv2D(filters=128,\n",
|
|
" kernel_size=(5, 5),\n",
|
|
" strides=(2, 2),\n",
|
|
" padding='same'))\n",
|
|
" model.add(layers.LeakyReLU())\n",
|
|
" # adding a dropout layer as you do in conv-nets\n",
|
|
" model.add(layers.Dropout(0.3))\n",
|
|
"\n",
|
|
" model.add(layers.Flatten())\n",
|
|
" model.add(layers.Dense(1))\n",
|
|
"\n",
|
|
" return model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "353af567",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Let us take a look at our models."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"id": "f899d4e3",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"generator = generator_model()\n",
|
|
"plot_model(generator, show_shapes=True, rankdir='LR')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"id": "87ef384b",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"discriminator = discriminator_model()\n",
|
|
"plot_model(discriminator, show_shapes=True, rankdir='LR')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b2bef82d",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Next we need a few helper objects we will use in training"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"id": "e397847a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)\n",
|
|
"generator_optimizer = tf.keras.optimizers.Adam(1e-4)\n",
|
|
"discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "db3396cc",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"The first object, *cross_entropy* is our loss function and the two others are\n",
|
|
"our optimizers. Notice we use the same learning rate for both $g$ and $d$. This\n",
|
|
"is because they need to improve their accuracy at approximately equal speeds to\n",
|
|
"get convergence (not necessarily exactly equal). Now we define our loss\n",
|
|
"functions"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"id": "931eaced",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def generator_loss(fake_output):\n",
|
|
" loss = cross_entropy(tf.ones_like(fake_output), fake_output)\n",
|
|
"\n",
|
|
" return loss"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 16,
|
|
"id": "0c4a44bb",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def discriminator_loss(real_output, fake_output):\n",
|
|
" real_loss = cross_entropy(tf.ones_like(real_output), real_output)\n",
|
|
" fake_loss = cross_entropy(tf.zeros_liks(fake_output), fake_output)\n",
|
|
" total_loss = real_loss + fake_loss\n",
|
|
"\n",
|
|
" return total_loss"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "fcf8f066",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Next we define a kind of seed to help us compare the learning process over\n",
|
|
"multiple training epochs."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"id": "eea2bbee",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"noise_dimension = 100\n",
|
|
"n_examples_to_generate = 16\n",
|
|
"seed_images = tf.random.normal([n_examples_to_generate, noise_dimension])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "94a6e341",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Now we have everything we need to define our training step, which we will apply\n",
|
|
"for every step in our training loop. Notice the @tf.function flag signifying\n",
|
|
"that the function is tensorflow 'compiled'. Removing this flag doubles the\n",
|
|
"computation time."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 18,
|
|
"id": "8d48470b",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"@tf.function\n",
|
|
"def train_step(images):\n",
|
|
" noise = tf.random.normal([BATCH_SIZE, noise_dimension])\n",
|
|
"\n",
|
|
" with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:\n",
|
|
" generated_images = generator(noise, training=True)\n",
|
|
"\n",
|
|
" real_output = discriminator(images, training=True)\n",
|
|
" fake_output = discriminator(generated_images, training=True)\n",
|
|
"\n",
|
|
" gen_loss = generator_loss(fake_output)\n",
|
|
" disc_loss = discriminator_loss(real_output, fake_output)\n",
|
|
"\n",
|
|
" gradients_of_generator = gen_tape.gradient(gen_loss,\n",
|
|
" generator.trainable_variables)\n",
|
|
" gradients_of_discriminator = disc_tape.gradient(disc_loss,\n",
|
|
" discriminator.trainable_variables)\n",
|
|
" generator_optimizer.apply_gradients(zip(gradients_of_generator,\n",
|
|
" generator.trainable_variables))\n",
|
|
" discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator,\n",
|
|
" discriminator.trainable_variables))\n",
|
|
"\n",
|
|
" return gen_loss, disc_loss"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "62015b88",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Next we define a helper function to produce an output over our training epochs\n",
|
|
"to see the predictive progression of our generator model. **Note**: I am including\n",
|
|
"this code here, but comment it out in the training loop."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 19,
|
|
"id": "b189ed96",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def generate_and_save_images(model, epoch, test_input):\n",
|
|
" # we're making inferences here\n",
|
|
" predictions = model(test_input, training=False)\n",
|
|
"\n",
|
|
" fig = plt.figure(figsize=(4, 4))\n",
|
|
"\n",
|
|
" for i in range(predictions.shape[0]):\n",
|
|
" plt.subplot(4, 4, i+1)\n",
|
|
" plt.imshow(predictions[i, :, :, 0] * 127.5 + 127.5, cmap='gray')\n",
|
|
" plt.axis('off')\n",
|
|
"\n",
|
|
" plt.savefig(f'./images_from_seed_images/image_at_epoch_{str(epoch).zfill(3)}.png')\n",
|
|
" plt.close()\n",
|
|
" #plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ba2c82d5",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Setting up checkpoints to periodically save our model during training so that\n",
|
|
"everything is not lost even if the program were to somehow terminate while\n",
|
|
"training."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 20,
|
|
"id": "a0e2fc8a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Setting up checkpoints to save model during training\n",
|
|
"checkpoint_dir = './training_checkpoints'\n",
|
|
"checkpoint_prefix = os.path.join(checkpoint_dir, 'ckpt')\n",
|
|
"checkpoint = tf.train.Checkpoint(generator_optimizer=generator_optimizer,\n",
|
|
" discriminator_optimizer=discriminator_optimizer,\n",
|
|
" generator=generator,\n",
|
|
" discriminator=discriminator)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4d93a0f7",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Now we define our training loop"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 21,
|
|
"id": "a1275556",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def train(dataset, epochs):\n",
|
|
" generator_loss_list = []\n",
|
|
" discriminator_loss_list = []\n",
|
|
"\n",
|
|
" for epoch in range(epochs):\n",
|
|
" start = time.time()\n",
|
|
"\n",
|
|
" for image_batch in dataset:\n",
|
|
" gen_loss, disc_loss = train_step(image_batch)\n",
|
|
" generator_loss_list.append(gen_loss.numpy())\n",
|
|
" discriminator_loss_list.append(disc_loss.numpy())\n",
|
|
"\n",
|
|
" #generate_and_save_images(generator, epoch + 1, seed_images)\n",
|
|
"\n",
|
|
" if (epoch + 1) % 15 == 0:\n",
|
|
" checkpoint.save(file_prefix=checkpoint_prefix)\n",
|
|
"\n",
|
|
" print(f'Time for epoch {epoch} is {time.time() - start}')\n",
|
|
"\n",
|
|
" #generate_and_save_images(generator, epochs, seed_images)\n",
|
|
"\n",
|
|
" loss_file = './data/lossfile.txt'\n",
|
|
" with open(loss_file, 'w') as outfile:\n",
|
|
" outfile.write(str(generator_loss_list))\n",
|
|
" outfile.write('\\n')\n",
|
|
" outfile.write('\\n')\n",
|
|
" outfile.write(str(discriminator_loss_list))\n",
|
|
" outfile.write('\\n')\n",
|
|
" outfile.write('\\n')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6ff3a75a",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"To train simply call this function. **Warning**: this might take a long time so\n",
|
|
"there is a folder of a pretrained network already included in the repository."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 22,
|
|
"id": "371ed41a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"train(train_dataset, EPOCHS)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "654399f1",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Now to avoid having to train and everything, which will take a while depending\n",
|
|
"on your computer setup we now load in the model which produced the above gif."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 23,
|
|
"id": "dec4b560",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir))\n",
|
|
"restored_generator = checkpoint.generator\n",
|
|
"restored_discriminator = checkpoint.discriminator\n",
|
|
"\n",
|
|
"print(restored_generator)\n",
|
|
"print(restored_discriminator)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "296bfa5c",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"We have successfully loaded in our latest model. Let us now play around a bit\n",
|
|
"and see what kind of things we can learn about this model. Our generator takes\n",
|
|
"an array of 100 numbers. One idea can be to try to systematically change our\n",
|
|
"input. Let us try and see what we get"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 24,
|
|
"id": "eecfbb1f",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def generate_latent_points(number=100, scale_means=1, scale_stds=1):\n",
|
|
" latent_dim = 100\n",
|
|
" means = scale_means * tf.linspace(-1, 1, num=latent_dim)\n",
|
|
" stds = scale_stds * tf.linspace(-1, 1, num=latent_dim)\n",
|
|
" latent_space_value_range = tf.random.normal([number, latent_dim],\n",
|
|
" means,\n",
|
|
" stds,\n",
|
|
" dtype=tf.float64)\n",
|
|
"\n",
|
|
" return latent_space_value_range\n",
|
|
"\n",
|
|
"def generate_images(latent_points):\n",
|
|
" # notice we set training to false because we are making inferences\n",
|
|
" generated_images = restored_generator.predict(latent_points)\n",
|
|
"\n",
|
|
" return generated_images"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 25,
|
|
"id": "333a593d",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def plot_result(generated_images, number=100):\n",
|
|
" # obviously this assumes sqrt number is an int\n",
|
|
" fig, axs = plt.subplots(int(np.sqrt(number)), int(np.sqrt(number)),\n",
|
|
" figsize=(10, 10))\n",
|
|
"\n",
|
|
" for i in range(int(np.sqrt(number))):\n",
|
|
" for j in range(int(np.sqrt(number))):\n",
|
|
" axs[i, j].imshow(generated_images[i*j], cmap='Greys')\n",
|
|
" axs[i, j].axis('off')\n",
|
|
"\n",
|
|
" plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 26,
|
|
"id": "2f5f0154",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"generated_images = generate_images(generate_latent_points())\n",
|
|
"plot_result(generated_images)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ff581bf2",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"We see that the generator generates images that look like MNIST\n",
|
|
"numbers: $1, 4, 7, 9$. Let's try to tweak it a bit more to see if we are able\n",
|
|
"to generate a similar plot where we generate every MNIST number. Let us now try\n",
|
|
"to 'move' a bit around in the latent space. **Note**: decrease the plot number if\n",
|
|
"these following cells take too long to run on your computer."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 27,
|
|
"id": "d3617ad8",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"plot_number = 225\n",
|
|
"\n",
|
|
"generated_images = generate_images(generate_latent_points(number=plot_number,\n",
|
|
" scale_means=5,\n",
|
|
" scale_stds=1))\n",
|
|
"plot_result(generated_images, number=plot_number)\n",
|
|
"\n",
|
|
"generated_images = generate_images(generate_latent_points(number=plot_number,\n",
|
|
" scale_means=-5,\n",
|
|
" scale_stds=1))\n",
|
|
"plot_result(generated_images, number=plot_number)\n",
|
|
"\n",
|
|
"generated_images = generate_images(generate_latent_points(number=plot_number,\n",
|
|
" scale_means=1,\n",
|
|
" scale_stds=5))\n",
|
|
"plot_result(generated_images, number=plot_number)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "1a074f93",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Again, we have found something interesting. *Moving* around using our means\n",
|
|
"takes us from digit to digit, while *moving* around using our standard\n",
|
|
"deviations seem to increase the number of different digits! In the last image\n",
|
|
"above, we can barely make out every MNIST digit. Let us make on last plot using\n",
|
|
"this information by upping the standard deviation of our Gaussian noises."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 28,
|
|
"id": "4ef8937d",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"plot_number = 400\n",
|
|
"generated_images = generate_images(generate_latent_points(number=plot_number,\n",
|
|
" scale_means=1,\n",
|
|
" scale_stds=10))\n",
|
|
"plot_result(generated_images, number=plot_number)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "385a2d0a",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"A pretty cool result! We see that our generator indeed has learned a\n",
|
|
"distribution which qualitatively looks a whole lot like the MNIST dataset.\n",
|
|
"\n",
|
|
"Another interesting way to explore the latent space of our generator model is by\n",
|
|
"interpolating between the MNIST digits. This section is largely based on\n",
|
|
"[this excellent blogpost](https://machinelearningmastery.com/how-to-interpolate-and-perform-vector-arithmetic-with-faces-using-a-generative-adversarial-network/)\n",
|
|
"by Jason Brownlee.\n",
|
|
"\n",
|
|
"So let us start by defining a function to interpolate between two points in the\n",
|
|
"latent space."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 29,
|
|
"id": "57de87b8",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def interpolation(point_1, point_2, n_steps=10):\n",
|
|
" ratios = np.linspace(0, 1, num=n_steps)\n",
|
|
" vectors = []\n",
|
|
" for i, ratio in enumerate(ratios):\n",
|
|
" vectors.append(((1.0 - ratio) * point_1 + ratio * point_2))\n",
|
|
"\n",
|
|
" return tf.stack(vectors)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "cfb76bb6",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Now we have all we need to do our interpolation analysis."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 30,
|
|
"id": "e25decef",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"plot_number = 100\n",
|
|
"latent_points = generate_latent_points(number=plot_number)\n",
|
|
"results = None\n",
|
|
"for i in range(0, 2*np.sqrt(plot_number), 2):\n",
|
|
" interpolated = interpolation(latent_points[i], latent_points[i+1])\n",
|
|
" generated_images = generate_images(interpolated)\n",
|
|
"\n",
|
|
" if results is None:\n",
|
|
" results = generated_images\n",
|
|
" else:\n",
|
|
" results = tf.stack((results, generated_images))\n",
|
|
"\n",
|
|
"plot_results(results, plot_number)"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"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.8.12"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
} |