diff --git a/2.4 Transfer Learning & Fine-Tuning.ipynb b/2.4 Transfer Learning & Fine-Tuning.ipynb index 7426eb4..9b75068 100644 --- a/2.4 Transfer Learning & Fine-Tuning.ipynb +++ b/2.4 Transfer Learning & Fine-Tuning.ipynb @@ -43,9 +43,7 @@ { "cell_type": "code", "execution_count": 2, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stderr", @@ -106,7 +104,7 @@ }, "outputs": [], "source": [ - "if K.image_dim_ordering() == 'th':\n", + "if K.image_data_format() == 'channels_first':\n", " input_shape = (1, img_rows, img_cols)\n", "else:\n", " input_shape = (img_rows, img_cols, 1)" @@ -214,9 +212,7 @@ { "cell_type": "code", "execution_count": 8, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -255,9 +251,7 @@ { "cell_type": "code", "execution_count": 9, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -361,7 +355,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.2" + "version": "3.5.3" } }, "nbformat": 4, diff --git a/Extra Additional Materials.ipynb b/Extra Additional Materials.ipynb index 265d679..a6a6984 100644 --- a/Extra Additional Materials.ipynb +++ b/Extra Additional Materials.ipynb @@ -8,13 +8,23 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": { "collapsed": true }, - "outputs": [], - "source": [] + "source": [ + "- [Perceptron and Adaline Implementation](./additional materials/1.1.1 Perceptron and Adaline.ipynb)\n", + "\n", + "- [MLP and MNIST](./additional materials/1.1.2 MLP and MNIST.ipynb)\n", + "\n", + "- [Quick Theano Tutorial](./additional materials/1.5.1 Introduction - Theano.ipynb)\n", + "\n", + "- [LSTM for Sentence Generation](./additional materials/3.3 LSTM for Sentence Generation.ipynb)\n", + "\n", + "- [Custom Layers in Keras](./additional materials/5.1 Custom Layer.ipynb)\n", + "\n", + "- [Multi-Modal Networks](./additional materials/5.2 Multi-Modal Networks.ipynb)" + ] } ], "metadata": { @@ -33,9 +43,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.2" + "version": "3.5.3" } }, "nbformat": 4, - "nbformat_minor": 0 + "nbformat_minor": 1 } diff --git a/additional materials/3.3 LSTM for Sentence Generation.ipynb b/additional materials/3.3 LSTM for Sentence Generation.ipynb index 9abc183..83aabf6 100644 --- a/additional materials/3.3 LSTM for Sentence Generation.ipynb +++ b/additional materials/3.3 LSTM for Sentence Generation.ipynb @@ -2,9 +2,7 @@ "cells": [ { "cell_type": "markdown", - "metadata": { - "collapsed": false - }, + "metadata": {}, "source": [ "\n", "# RNN using LSTM \n", @@ -44,9 +42,7 @@ { "cell_type": "code", "execution_count": 3, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "from keras.optimizers import SGD\n", @@ -82,9 +78,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "DATA_DIRECTORY = os.path.join(os.path.abspath(os.path.curdir), '..', 'data', 'word_embeddings')\n", @@ -121,9 +115,7 @@ { "cell_type": "code", "execution_count": 85, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "filtered_male_posts = list(filter(lambda p: len(p) > 0, male_posts))\n", @@ -133,9 +125,7 @@ { "cell_type": "code", "execution_count": 86, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# text processing - one hot builds index of the words\n", @@ -158,9 +148,7 @@ { "cell_type": "code", "execution_count": 87, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# 0 for male, 1 for female\n", @@ -171,9 +159,7 @@ { "cell_type": "code", "execution_count": 88, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "from sklearn.cross_validation import train_test_split\n", @@ -186,9 +172,7 @@ { "cell_type": "code", "execution_count": 89, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -210,9 +194,7 @@ { "cell_type": "code", "execution_count": 90, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "max_features = 30000\n", @@ -229,9 +211,7 @@ { "cell_type": "code", "execution_count": 91, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "model.compile(loss='mean_squared_error', optimizer='sgd', metrics=['accuracy'])" @@ -240,9 +220,7 @@ { "cell_type": "code", "execution_count": 92, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -278,9 +256,7 @@ { "cell_type": "code", "execution_count": 93, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -297,9 +273,7 @@ { "cell_type": "code", "execution_count": 94, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -334,9 +308,7 @@ { "cell_type": "code", "execution_count": 96, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "vectorizer = TfidfVectorizer(decode_error='ignore', norm='l2', min_df=5)\n", @@ -347,9 +319,7 @@ { "cell_type": "code", "execution_count": 97, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "flattened_array_tfidf_male = tfidf_male.toarray()\n", @@ -359,9 +329,7 @@ { "cell_type": "code", "execution_count": 98, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "y_rnn = np.concatenate((np.zeros(len(flattened_array_tfidf_male)),\n", @@ -371,9 +339,7 @@ { "cell_type": "code", "execution_count": 99, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "X_train_rnn, X_test_rnn, y_train_rnn, y_test_rnn = train_test_split(np.concatenate((flattened_array_tfidf_male, \n", @@ -384,9 +350,7 @@ { "cell_type": "code", "execution_count": 100, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -436,9 +400,7 @@ { "cell_type": "code", "execution_count": 103, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -475,9 +437,7 @@ { "cell_type": "code", "execution_count": 104, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -495,9 +455,7 @@ { "cell_type": "code", "execution_count": 105, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -521,9 +479,7 @@ { "cell_type": "code", "execution_count": 106, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# reading all the male text data into one string\n", @@ -549,9 +505,7 @@ { "cell_type": "code", "execution_count": 107, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -580,9 +534,7 @@ { "cell_type": "code", "execution_count": 109, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -608,9 +560,7 @@ { "cell_type": "code", "execution_count": 74, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "auto_text_generating_male_model.compile(loss='mean_squared_error',optimizer='sgd')" @@ -649,7 +599,6 @@ "cell_type": "code", "execution_count": 113, "metadata": { - "collapsed": false, "scrolled": false }, "outputs": [ @@ -940,9 +889,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.2" + "version": "3.5.3" } }, "nbformat": 4, - "nbformat_minor": 0 + "nbformat_minor": 1 } diff --git a/additional materials/5.2 Multi-Modal Networks.ipynb b/additional materials/5.2 Multi-Modal Networks.ipynb index 3dbc9e6..f5b04cb 100644 --- a/additional materials/5.2 Multi-Modal Networks.ipynb +++ b/additional materials/5.2 Multi-Modal Networks.ipynb @@ -4,59 +4,101 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Multi-Input Networks" + "## Quick Intro to Keras Functional API" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Keras Merge Layer" + "## Preamble: All models (layers) are callables" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Multiple Sequential instances can be merged into a single output via a Merge layer. The output is a layer that can be added as first layer in a new Sequential model. For instance, here's a model with two separate input branches getting merged:" + "```python\n", + "from keras.layers import Input, Dense\n", + "from keras.models import Model\n", + "\n", + "# this returns a tensor\n", + "inputs = Input(shape=(784,))\n", + "\n", + "# a layer instance is callable on a tensor, and returns a tensor\n", + "x = Dense(64, activation='relu')(inputs)\n", + "x = Dense(64, activation='relu')(x)\n", + "predictions = Dense(10, activation='softmax')(x)\n", + "\n", + "# this creates a model that includes\n", + "# the Input layer and three Dense layers\n", + "model = Model(input=inputs, output=predictions)\n", + "model.compile(optimizer='rmsprop',\n", + " loss='categorical_crossentropy',\n", + " metrics=['accuracy'])\n", + "model.fit(data, labels) # starts training\n", + "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Example (from documentation)" + "# Multi-Input Networks" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "" + "## Keras Merge Layer" ] }, { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": false - }, - "outputs": [], + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here's a good use case for the functional API: models with multiple inputs and outputs. \n", + "\n", + "The functional API makes it easy to manipulate a large number of intertwined datastreams.\n", + "\n", + "Let's consider the following model. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ - "from keras.layers import Merge, Dense\n", - "from keras.models import Sequential\n", + "```python\n", + "from keras.layers import Dense, Input\n", + "from keras.models import Model\n", + "from keras.layers.merge import concatenate\n", "\n", - "left_branch = Sequential()\n", - "left_branch.add(Dense(32, input_dim=784))\n", + "left_input = Input(shape=(784, ), name='left_input')\n", + "left_branch = Dense(32, input_dim=784, name='left_branch')(left_input)\n", "\n", - "right_branch = Sequential()\n", - "right_branch.add(Dense(32, input_dim=784))\n", + "right_input = Input(shape=(784,), name='right_input')\n", + "right_branch = Dense(32, input_dim=784, name='right_branch')(right_input)\n", "\n", - "merged = Merge([left_branch, right_branch], mode='concat')\n", + "x = concatenate([left_branch, right_branch])\n", + "predictions = Dense(10, activation='softmax', name='main_output')(x)\n", "\n", - "final_model = Sequential()\n", - "final_model.add(merged)\n", - "final_model.add(Dense(10, activation='softmax'))" + "model = Model(inputs=[left_input, right_input], outputs=predictions)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Resulting Model will look like the following network:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" ] }, { @@ -71,8 +113,8 @@ "metadata": {}, "source": [ "```python\n", - "final_model.compile(optimizer='rmsprop', loss='categorical_crossentropy')\n", - "final_model.fit([input_data_1, input_data_2], targets) # we pass one data array per model input\n", + "model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])\n", + "model.fit([input_data_1, input_data_2], targets) # we pass one data array per model input\n", "```" ] }, @@ -80,44 +122,82 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The Merge layer supports a number of pre-defined modes:\n", - "\n", - "* `sum` (default): element-wise sum\n", - "* `concat`: tensor concatenation. You can specify the concatenation axis via the argument concat_axis.\n", - "* `mul`: element-wise multiplication\n", - "* `ave`: tensor average\n", - "* `dot`: dot product. You can specify which axes to reduce along via the argument dot_axes.\n", - "* `cos`: cosine proximity between vectors in 2D tensors." + "## Try yourself" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "You can also pass a function as the mode argument, allowing for arbitrary transformations:" + "#### Step 1: Get Data - MNIST" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# let's load MNIST data as we did in the exercise on MNIST with FC Nets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %load ../solutions/sol_52.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "```python\n", - "merged = Merge([left_branch, right_branch], mode=lambda x: x[0] - x[1])\n", - "```" + "#### Step 2: Create the Multi-Input Network" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## try yourself\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "## `evaluate` the model on test data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Keras Functional API" + "Keras supports different Merge strategies:\n", + "\n", + "* `add`: element-wise sum\n", + "* `concatenate`: tensor concatenation. You can specify the concatenation axis via the argument concat_axis.\n", + "* `multiply`: element-wise multiplication\n", + "* `average`: tensor average\n", + "* `maximum`: element-wise maximum of the inputs.\n", + "* `dot`: dot product. You can specify which axes to reduce along via the argument dot_axes. You can also specify applying any normalisation. In that case, the output of the dot product is the cosine proximity between the two samples." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### All models (layers) are callables" + "You can also pass a function as the mode argument, allowing for arbitrary transformations:" ] }, { @@ -125,24 +205,7 @@ "metadata": {}, "source": [ "```python\n", - "from keras.layers import Input, Dense\n", - "from keras.models import Model\n", - "\n", - "# this returns a tensor\n", - "inputs = Input(shape=(784,))\n", - "\n", - "# a layer instance is callable on a tensor, and returns a tensor\n", - "x = Dense(64, activation='relu')(inputs)\n", - "x = Dense(64, activation='relu')(x)\n", - "predictions = Dense(10, activation='softmax')(x)\n", - "\n", - "# this creates a model that includes\n", - "# the Input layer and three Dense layers\n", - "model = Model(input=inputs, output=predictions)\n", - "model.compile(optimizer='rmsprop',\n", - " loss='categorical_crossentropy',\n", - " metrics=['accuracy'])\n", - "model.fit(data, labels) # starts training\n", + "merged = Merge([left_branch, right_branch], mode=lambda x: x[0] - x[1])\n", "```" ] } diff --git a/imgs/multi_input_model.png b/imgs/multi_input_model.png new file mode 100644 index 0000000..7c00498 Binary files /dev/null and b/imgs/multi_input_model.png differ diff --git a/solutions/sol_52.py b/solutions/sol_52.py new file mode 100644 index 0000000..49995df --- /dev/null +++ b/solutions/sol_52.py @@ -0,0 +1,26 @@ +from keras.datasets import mnist +from keras.utils import np_utils + +img_rows, img_cols = 28, 28 +nb_classes = 10 + +(X_train, y_train), (X_test, y_test) = mnist.load_data() + +X_train = X_train.reshape(X_train.shape[0], img_rows*img_cols) +X_test = X_test.reshape(X_test.shape[0], img_rows*img_cols) + +X_train = X_train.astype('float32') +X_test = X_test.astype('float32') + +X_train /= 255 +X_test /= 255 + +print('X_train shape:', X_train.shape) +print('y_train shape:', y_train.shape) +print('X_test shape:', X_test.shape) +print('y_test shape:', y_test.shape) +print(X_train.shape[0], 'train samples') +print(X_test.shape[0], 'test samples') + +y_train = np_utils.to_categorical(y_train, nb_classes) +y_test = np_utils.to_categorical(y_test, nb_classes) \ No newline at end of file