From 5d4fa6483777ae92a6a5c469ef860e8763e9cbc4 Mon Sep 17 00:00:00 2001 From: Valerio Maggio Date: Thu, 13 Apr 2017 06:54:02 +0200 Subject: [PATCH] Typo and Fix in MultiModal Nets + Index Notebook --- 2.4 Transfer Learning & Fine-Tuning.ipynb | 16 +- Extra Additional Materials.ipynb | 22 ++- .../3.3 LSTM for Sentence Generation.ipynb | 105 +++-------- .../5.2 Multi-Modal Networks.ipynb | 173 ++++++++++++------ imgs/multi_input_model.png | Bin 0 -> 21985 bytes solutions/sol_52.py | 26 +++ 6 files changed, 192 insertions(+), 150 deletions(-) create mode 100644 imgs/multi_input_model.png create mode 100644 solutions/sol_52.py 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 0000000000000000000000000000000000000000..7c0049871460e2b7452d8bbe037bb467178c4f32 GIT binary patch literal 21985 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