├── Deep learning loss functions.ipynb ├── INTRO ML 01 - Machine learning - a very basic introduction.ipynb ├── INTRO ML 02 - gradient descent for machine learning.ipynb ├── LICENSE.txt ├── README.md ├── SUPPLEMENTARY - Convolutions with sliding windows.ipynb ├── SUPPLEMENTARY - Gabor filters.ipynb ├── SUPPLEMENTARY - Standardisation.ipynb ├── TUTORIAL 01 - Using a pretrained conv-net - VGG net.ipynb ├── TUTORIAL 02 - Using a pretrained VGG-16 conv-net to find a peacock.ipynb ├── TUTORIAL 03 - Image region-level saliency using VGG-16 conv-net.ipynb ├── TUTORIAL 04 - Image pixel-level saliency using VGG-16 conv-net.ipynb ├── TUTORIAL 05 - Dogs vs cats with standard learning.ipynb ├── TUTORIAL 05 - Dogs vs cats with transfer learning and data augmentation.ipynb ├── TUTORIAL 05 - Dogs vs cats with transfer learning.ipynb ├── imagenet_classes.py ├── images ├── P1013781.JPG ├── P8131065.JPG └── fruit.jpg ├── requirements.txt └── utils.py /INTRO ML 01 - Machine learning - a very basic introduction.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Machine Learning - a very basic introduction\n", 8 | "\n", 9 | "#### An over simplified 'in-a-nutshell' of how it works, sort of -- Geoff French\n", 10 | "\n", 11 | "In this notebook we show how samples are positioned in N-dimensional space. Dividing this space into regions allows us to classify (guess the type) of novel, as-of-yet unseen samples.\n", 12 | "\n", 13 | "In this example we are going to train a classifier on Fisher's Iris Dataset and plot its decision surface." 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "First, some imports:" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 13, 26 | "metadata": { 27 | "collapsed": false 28 | }, 29 | "outputs": [], 30 | "source": [ 31 | "%matplotlib inline\n", 32 | "\n", 33 | "import numpy as np\n", 34 | "from matplotlib import pyplot as plt\n", 35 | "from sklearn.datasets import load_iris\n", 36 | "import seaborn as sns\n", 37 | "from sklearn.neighbors import KNeighborsClassifier\n", 38 | "from sklearn.svm import LinearSVC\n", 39 | "from sklearn.ensemble import RandomForestClassifier" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "### Load the data\n", 47 | "\n", 48 | "The feature vectors for each sample can be found in the `data` attribute and the ground truth classes (of which there are 3) can be found in the `target` attribute." 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 8, 54 | "metadata": { 55 | "collapsed": false 56 | }, 57 | "outputs": [], 58 | "source": [ 59 | "# Load\n", 60 | "iris = load_iris()\n", 61 | "\n", 62 | "# Get features and ground truth\n", 63 | "X = iris.data\n", 64 | "Y = iris.target\n", 65 | "\n", 66 | "# Extract sepal length and petal width features (0 and 3)\n", 67 | "X03 = np.append(X[:,0:1], X[:,3:4], axis=1)" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "### Scatter plot of data\n", 75 | "\n", 76 | "First, lets produce a scatter plot of sepal length and petal width, with the colour of the points indicating ground truth class:" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 16, 82 | "metadata": { 83 | "collapsed": false 84 | }, 85 | "outputs": [ 86 | { 87 | "data": { 88 | "image/png": "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\n6RUTNZECKZYAAAAASUVORK5CYII=\n", 89 | "text/plain": [ 90 | "" 91 | ] 92 | }, 93 | "metadata": {}, 94 | "output_type": "display_data" 95 | } 96 | ], 97 | "source": [ 98 | "# Figure\n", 99 | "plt.figure(figsize=(10,8))\n", 100 | "\n", 101 | "# Scatter plot of the data points\n", 102 | "plt.scatter(X[Y==0,0], X[Y==0,3], color='red')\n", 103 | "plt.scatter(X[Y==1,0], X[Y==1,3], color='blue')\n", 104 | "plt.scatter(X[Y==2,0], X[Y==2,3], color='green')\n", 105 | "\n", 106 | "# Labels\n", 107 | "plt.title('Fisher\\'s iris datset')\n", 108 | "plt.xlabel('Sepal length')\n", 109 | "plt.ylabel('Petal width')\n", 110 | "\n", 111 | "# Show\n", 112 | "plt.show()" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "### Train a classifier\n", 120 | "\n", 121 | "If we were given measurements of a flower of unknown species, how could we predict its species from its measurements?\n", 122 | "\n", 123 | "We would need to divide the space seen in the plot above into regions in which a flower is most likely to be member of that species.\n", 124 | "\n", 125 | "The classifiers in Scikit-learn do just this; they compute parameters to control the way in which an algorithm divides the space up into regions.\n", 126 | "\n", 127 | "#### Define classifier plotting helper function\n", 128 | "\n", 129 | "This function plots the data points in the data set in addition to plotting the decision surface that shows the regions of space that the classifier will assign to the 3 classes." 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 18, 135 | "metadata": { 136 | "collapsed": true 137 | }, 138 | "outputs": [], 139 | "source": [ 140 | "def clf_decision_surface_plot(clf):\n", 141 | " # Generate the co-ordinates at which we will ask the classifier to predict\n", 142 | " # the probabilities of the classes\n", 143 | " xx, yy = np.meshgrid(np.arange(4.0, 8.5, 0.01),\n", 144 | " np.arange(-0.5, 3.0, 0.01))\n", 145 | "\n", 146 | " # Predict classes for all grid points\n", 147 | " Y_pred = clf.predict(np.c_[xx.ravel(), yy.ravel()])\n", 148 | "\n", 149 | " # New figure\n", 150 | " plt.figure(figsize=(10,8))\n", 151 | "\n", 152 | " # Plot the contours of the boundaries corresponding to each class\n", 153 | " plt.contourf(xx, yy, (Y_pred == 0).reshape(xx.shape), 1, cmap='OrRd', alpha=.4)\n", 154 | " plt.contourf(xx, yy, (Y_pred == 1).reshape(xx.shape), 1, cmap='Blues', alpha=.4)\n", 155 | " plt.contourf(xx, yy, (Y_pred == 2).reshape(xx.shape), 1, cmap='Greens', alpha=.4)\n", 156 | "\n", 157 | " # Plot the data points\n", 158 | " plt.scatter(X[Y==0,0], X[Y==0,3], color='red')\n", 159 | " plt.scatter(X[Y==1,0], X[Y==1,3], color='blue')\n", 160 | " plt.scatter(X[Y==2,0], X[Y==2,3], color='green')\n", 161 | "\n", 162 | " # Labels\n", 163 | " plt.title('Fisher\\'s iris datset')\n", 164 | " plt.xlabel('Sepal length')\n", 165 | " plt.ylabel('Petal width')\n", 166 | "\n", 167 | " # Show\n", 168 | " plt.show()" 169 | ] 170 | }, 171 | { 172 | "cell_type": "markdown", 173 | "metadata": {}, 174 | "source": [ 175 | "#### Nearest neighbour classifier\n", 176 | "\n", 177 | "In this case, we're going to train a nearest neighbours classifier on the dataset, only using the sepal length and petal width features:" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": 19, 183 | "metadata": { 184 | "collapsed": false 185 | }, 186 | "outputs": [ 187 | { 188 | "data": { 189 | "image/png": "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\npJz4f8I9E12FFEBsAAAAAElFTkSuQmCC\n", 190 | "text/plain": [ 191 | "" 192 | ] 193 | }, 194 | "metadata": {}, 195 | "output_type": "display_data" 196 | } 197 | ], 198 | "source": [ 199 | "# Build a nearest neighbours classifier that uses the 3 nearest neighbours to make a decision\n", 200 | "nn_clf = KNeighborsClassifier(3)\n", 201 | "# Train on the dataset\n", 202 | "nn_clf.fit(X03, Y)\n", 203 | "# Plot the decision surface\n", 204 | "clf_decision_surface_plot(nn_clf)" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "The decision surface of the nearest neighbors classifier is quite complex and attempts to follow the points in the dataset.\n", 212 | "\n", 213 | "#### Linear support vector classifier\n", 214 | "\n", 215 | "Now, lets try a linear support vector classifier:" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": 25, 221 | "metadata": { 222 | "collapsed": false 223 | }, 224 | "outputs": [ 225 | { 226 | "data": { 227 | "image/png": "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\nYII=\n", 228 | "text/plain": [ 229 | "" 230 | ] 231 | }, 232 | "metadata": {}, 233 | "output_type": "display_data" 234 | } 235 | ], 236 | "source": [ 237 | "# Linear classifier\n", 238 | "lclf = LinearSVC()\n", 239 | "# Train\n", 240 | "lclf.fit(X03, Y)\n", 241 | "# Plot the decision surface\n", 242 | "clf_decision_surface_plot(lclf)" 243 | ] 244 | }, 245 | { 246 | "cell_type": "markdown", 247 | "metadata": {}, 248 | "source": [ 249 | "The linear support vector classifier finds simple lines to separate the data points\n", 250 | "\n", 251 | "#### Random forest classifier\n", 252 | "\n", 253 | "Now, lets try a random forest:" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": 26, 259 | "metadata": { 260 | "collapsed": false 261 | }, 262 | "outputs": [ 263 | { 264 | "data": { 265 | "image/png": "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\n", 266 | "text/plain": [ 267 | "" 268 | ] 269 | }, 270 | "metadata": {}, 271 | "output_type": "display_data" 272 | } 273 | ], 274 | "source": [ 275 | "fclf = RandomForestClassifier()\n", 276 | "fclf.fit(X03, Y)\n", 277 | "\n", 278 | "clf_plot(fclf)" 279 | ] 280 | }, 281 | { 282 | "cell_type": "markdown", 283 | "metadata": {}, 284 | "source": [ 285 | "The random forest classifier is composed of decisions trees that split the space along lines that are aligned to the X and Y axes." 286 | ] 287 | } 288 | ], 289 | "metadata": { 290 | "anaconda-cloud": {}, 291 | "kernelspec": { 292 | "display_name": "Python 2", 293 | "language": "python", 294 | "name": "python2" 295 | }, 296 | "language_info": { 297 | "codemirror_mode": { 298 | "name": "ipython", 299 | "version": 2 300 | }, 301 | "file_extension": ".py", 302 | "mimetype": "text/x-python", 303 | "name": "python", 304 | "nbconvert_exporter": "python", 305 | "pygments_lexer": "ipython2", 306 | "version": "2.7.12" 307 | } 308 | }, 309 | "nbformat": 4, 310 | "nbformat_minor": 1 311 | } 312 | -------------------------------------------------------------------------------- /INTRO ML 02 - gradient descent for machine learning.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Gradient descent for machine learning - a quick introduction\n", 8 | "\n", 9 | "In this notebook we are going to use gradient descent to estimate the parameters of a model. In this case we are going to compute the parameters to convert temperatures fom Farenheit to Kelvin.\n", 10 | "\n", 11 | "Given that we are approaching this from a machine learning perspective, we are going to determine our scaling factor and offset value by gradient descent, given some example temperatures on both scales. In other words, we are going to *learn* the parameters from the data.\n", 12 | "\n", 13 | "First, some imports:" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 1, 19 | "metadata": { 20 | "collapsed": true 21 | }, 22 | "outputs": [], 23 | "source": [ 24 | "import numpy as np\n", 25 | "import pandas as pd" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "Our data set:" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "metadata": { 39 | "collapsed": true 40 | }, 41 | "outputs": [], 42 | "source": [ 43 | "INDEX = ['Boiling point of He',\n", 44 | " 'Boiling point of N',\n", 45 | " 'Melting point of H2O',\n", 46 | " 'Body temperature',\n", 47 | " 'Boiling point of H2O']\n", 48 | "\n", 49 | "X = np.array([-452.1, -320.4, 32.0, 98.6, 212.0])\n", 50 | "Y = np.array([4.22, 77.36, 273.2, 310.5, 373.2])" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "Show our data set in a table:" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 3, 63 | "metadata": { 64 | "collapsed": false 65 | }, 66 | "outputs": [ 67 | { 68 | "data": { 69 | "text/html": [ 70 | "
\n", 71 | "\n", 72 | " \n", 73 | " \n", 74 | " \n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | "
Fahrenheit ($x$)Kelvin ($y$)
Boiling point of He-452.14.22
Boiling point of N-320.477.36
Melting point of H2O32.0273.20
Body temperature98.6310.50
Boiling point of H2O212.0373.20
\n", 107 | "
" 108 | ], 109 | "text/plain": [ 110 | " Fahrenheit ($x$) Kelvin ($y$)\n", 111 | "Boiling point of He -452.1 4.22\n", 112 | "Boiling point of N -320.4 77.36\n", 113 | "Melting point of H2O 32.0 273.20\n", 114 | "Body temperature 98.6 310.50\n", 115 | "Boiling point of H2O 212.0 373.20" 116 | ] 117 | }, 118 | "execution_count": 3, 119 | "metadata": {}, 120 | "output_type": "execute_result" 121 | } 122 | ], 123 | "source": [ 124 | "pd.DataFrame(np.stack([X, Y]).T, index=INDEX,\n", 125 | " columns=['Fahrenheit ($x$)', 'Kelvin ($y$)'])" 126 | ] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "metadata": {}, 131 | "source": [ 132 | "## Model - linear regression\n", 133 | "\n", 134 | "Temperatures can be converted using a linear model of the form $y=ax+b$.\n", 135 | "\n", 136 | "$x$ and $y$ are samples in our dataset; $X=\\{x_0...X_N\\}$ and $Y=\\{y_0...Y_N\\}$ while $a$ and $b$ are the model parameters.\n", 137 | "\n", 138 | "### Initialise model\n", 139 | "\n", 140 | "Lets try initialising the parameters $a$ randomly and $b$ to 0 and see what it predicts:" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 4, 146 | "metadata": { 147 | "collapsed": false 148 | }, 149 | "outputs": [ 150 | { 151 | "name": "stdout", 152 | "output_type": "stream", 153 | "text": [ 154 | "a=1.58879502645, b=0.0\n" 155 | ] 156 | }, 157 | { 158 | "data": { 159 | "text/html": [ 160 | "
\n", 161 | "\n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | "
Fahrenheit ($x$)Kelvin ($y$)$y_{pred}$
Boiling point of He-452.14.22-718.294231
Boiling point of N-320.477.36-509.049926
Melting point of H2O32.0273.2050.841441
Body temperature98.6310.50156.655190
Boiling point of H2O212.0373.20336.824546
\n", 203 | "
" 204 | ], 205 | "text/plain": [ 206 | " Fahrenheit ($x$) Kelvin ($y$) $y_{pred}$\n", 207 | "Boiling point of He -452.1 4.22 -718.294231\n", 208 | "Boiling point of N -320.4 77.36 -509.049926\n", 209 | "Melting point of H2O 32.0 273.20 50.841441\n", 210 | "Body temperature 98.6 310.50 156.655190\n", 211 | "Boiling point of H2O 212.0 373.20 336.824546" 212 | ] 213 | }, 214 | "execution_count": 4, 215 | "metadata": {}, 216 | "output_type": "execute_result" 217 | } 218 | ], 219 | "source": [ 220 | "# Lets initialise `a` to between 1.0 and 2.0; it is therefore impossible\n", 221 | "# for it to choose a (nearly) correct value at the start, forcing our model to do some work.\n", 222 | "a = np.random.uniform(1.0, 2.0, size=())\n", 223 | "b = 0.0\n", 224 | "\n", 225 | "print('a={}, b={}'.format(a, b))\n", 226 | "\n", 227 | "Y_pred = X * a + b\n", 228 | "pd.DataFrame(np.stack([X, Y, Y_pred]).T, index=INDEX,\n", 229 | " columns=['Fahrenheit ($x$)', 'Kelvin ($y$)', '$y_{pred}$'])" 230 | ] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": {}, 235 | "source": [ 236 | "### How good is our guess?\n", 237 | "\n", 238 | "To estimate the accuracy of our model, lets compute the squared error. We use the squared error since its value will always be positive and larger errors will have a greater cost due to being squared:" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": 5, 244 | "metadata": { 245 | "collapsed": false 246 | }, 247 | "outputs": [ 248 | { 249 | "data": { 250 | "text/html": [ 251 | "
\n", 252 | "\n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | " \n", 263 | " \n", 264 | " \n", 265 | " \n", 266 | " \n", 267 | " \n", 268 | " \n", 269 | " \n", 270 | " \n", 271 | " \n", 272 | " \n", 273 | " \n", 274 | " \n", 275 | " \n", 276 | " \n", 277 | " \n", 278 | " \n", 279 | " \n", 280 | " \n", 281 | " \n", 282 | " \n", 283 | " \n", 284 | " \n", 285 | " \n", 286 | " \n", 287 | " \n", 288 | " \n", 289 | " \n", 290 | " \n", 291 | " \n", 292 | " \n", 293 | " \n", 294 | " \n", 295 | " \n", 296 | " \n", 297 | " \n", 298 | " \n", 299 | "
Fahrenheit ($x$)Kelvin ($y$)$y_{pred}$squared err ($\\epsilon$)
Boiling point of He-452.14.22-718.294231522026.814658
Boiling point of N-320.477.36-509.049926343876.601867
Melting point of H2O32.0273.2050.84144149443.328829
Body temperature98.6310.50156.65519023668.225685
Boiling point of H2O212.0373.20336.8245461323.173682
\n", 300 | "
" 301 | ], 302 | "text/plain": [ 303 | " Fahrenheit ($x$) Kelvin ($y$) $y_{pred}$ \\\n", 304 | "Boiling point of He -452.1 4.22 -718.294231 \n", 305 | "Boiling point of N -320.4 77.36 -509.049926 \n", 306 | "Melting point of H2O 32.0 273.20 50.841441 \n", 307 | "Body temperature 98.6 310.50 156.655190 \n", 308 | "Boiling point of H2O 212.0 373.20 336.824546 \n", 309 | "\n", 310 | " squared err ($\\epsilon$) \n", 311 | "Boiling point of He 522026.814658 \n", 312 | "Boiling point of N 343876.601867 \n", 313 | "Melting point of H2O 49443.328829 \n", 314 | "Body temperature 23668.225685 \n", 315 | "Boiling point of H2O 1323.173682 " 316 | ] 317 | }, 318 | "execution_count": 5, 319 | "metadata": {}, 320 | "output_type": "execute_result" 321 | } 322 | ], 323 | "source": [ 324 | "sqr_err = (Y_pred - Y)**2\n", 325 | "\n", 326 | "pd.DataFrame(np.stack([X, Y, Y_pred, sqr_err]).T, index=INDEX,\n", 327 | " columns=['Fahrenheit ($x$)', 'Kelvin ($y$)', '$y_{pred}$', 'squared err ($\\epsilon$)'])" 328 | ] 329 | }, 330 | { 331 | "cell_type": "markdown", 332 | "metadata": {}, 333 | "source": [ 334 | "#### Reducing the error\n", 335 | "\n", 336 | "We reduce the error by taking the gradient of the squared error with respect to the parameters $a$ and $b$ and iteratively modifying the values of $a$ and $b$ in the direction of the negated gradient.\n", 337 | "\n", 338 | "Lets determine the expressions for the gradient of the squared error $\\epsilon$ with respect to $a$ and $b$:\n", 339 | "\n", 340 | "$\\epsilon_i = (ax_i + b - y_i)^2 = a^2x_i^2 + 2abx_i - 2ax_iy_i + b^2 + y_i^2 - 2by_i$\n", 341 | "\n", 342 | "\n", 343 | "In terms of $a$: $\\epsilon_i = a^2x_i^2 + a(2bx_i - 2x_iy_i) + b^2 + y_i^2 - 2by_i$\n", 344 | "\n", 345 | "So ${d\\epsilon_i\\over{da}} = 2ax_i^2 + 2bx_i - 2x_iy_i$\n", 346 | "\n", 347 | "\n", 348 | "In terms of $b$: $\\epsilon = b^2 + b(2ax_i - 2y_i) + a^2x_i^2- 2ax_iy_i - 2by_i$\n", 349 | "\n", 350 | "So ${d\\epsilon_i\\over{db}} = 2b + 2ax_i - 2y_i$\n", 351 | "\n", 352 | "\n", 353 | "The above expressions apply to single samples only. To apply them to all of our 5 data points, we need to use the mean squared error. The mean squared error is the sum of the individual errors divided by the number of data points $N$. The derivative of the mean squared error w.r.t. $a$ and $b$ will also be the sum of the individual derivatives, divided by $N$.\n", 354 | "\n", 355 | "#### Gradient descent\n", 356 | "\n", 357 | "Gradient descent is performed iteratively; each parameter is modified independently as so:\n", 358 | "\n", 359 | "$a' = a - \\gamma {d\\epsilon_i\\over{da}}$\n", 360 | "\n", 361 | "$b' = b - \\gamma {d\\epsilon_i\\over{db}}$\n", 362 | "\n", 363 | "where $\\gamma$ is the learning rate.\n", 364 | "\n", 365 | "#### Implementation\n", 366 | "\n", 367 | "We now have all we need to define some gradient descent helper functions:" 368 | ] 369 | }, 370 | { 371 | "cell_type": "code", 372 | "execution_count": 6, 373 | "metadata": { 374 | "collapsed": true 375 | }, 376 | "outputs": [], 377 | "source": [ 378 | "def iterative_gradient_descent_step(a, b, lr):\n", 379 | " \"\"\"\n", 380 | " A single gradient descent iteration\n", 381 | " \n", 382 | " :param a: current value of `a`\n", 383 | " :param b: current value of `b`\n", 384 | " :param lr: learning rate\n", 385 | " \n", 386 | " :return: a tuple `(a_next, b_next)` that are the values of `a` and `b` after the iteration.\n", 387 | " \"\"\"\n", 388 | " # Derivative of a and b w.r.t. epsilon:\n", 389 | " da_depsilon = (2 * a * X**2 + 2 * b * X - 2 * X * Y).mean()\n", 390 | " db_depsilon = (2 * b + 2 * a * X - 2 * Y).mean()\n", 391 | " \n", 392 | " # Gradient descent:\n", 393 | " a = a - da_depsilon * lr\n", 394 | " b = b - db_depsilon * lr\n", 395 | " \n", 396 | " # Return new values\n", 397 | " return a, b\n", 398 | "\n", 399 | "\n", 400 | "def state_as_table(a, b):\n", 401 | " \"\"\"\n", 402 | " Helper function to generate a Pandas DataFrame showing the current state, including predicted values and errors\n", 403 | " \n", 404 | " :param a: current value of `a`\n", 405 | " :param b: current value of `b`\n", 406 | " \n", 407 | " :return: tuple `(df, mean_sqr_err)` where `df` is the Pandas DataFrame and `sqr_err` is the mean squared error\n", 408 | " \"\"\"\n", 409 | " Y_pred = X * a + b\n", 410 | " sqr_err = (Y_pred - Y)**2\n", 411 | "\n", 412 | " df = pd.DataFrame(np.stack([X, Y, Y_pred, sqr_err]).T, index=INDEX,\n", 413 | " columns=['Fahrenheit ($x$)', 'Kelvin ($y$)', '$y_{pred}$', 'squared err ($\\epsilon$)']) \n", 414 | " return df, sqr_err.mean()" 415 | ] 416 | }, 417 | { 418 | "cell_type": "markdown", 419 | "metadata": {}, 420 | "source": [ 421 | "Define learning rate and show initial state:" 422 | ] 423 | }, 424 | { 425 | "cell_type": "code", 426 | "execution_count": 7, 427 | "metadata": { 428 | "collapsed": false 429 | }, 430 | "outputs": [ 431 | { 432 | "name": "stdout", 433 | "output_type": "stream", 434 | "text": [ 435 | "a = 1.58879502645, b = 0.0, mean sqr. err. = 188067.628944\n" 436 | ] 437 | }, 438 | { 439 | "data": { 440 | "text/html": [ 441 | "
\n", 442 | "\n", 443 | " \n", 444 | " \n", 445 | " \n", 446 | " \n", 447 | " \n", 448 | " \n", 449 | " \n", 450 | " \n", 451 | " \n", 452 | " \n", 453 | " \n", 454 | " \n", 455 | " \n", 456 | " \n", 457 | " \n", 458 | " \n", 459 | " \n", 460 | " \n", 461 | " \n", 462 | " \n", 463 | " \n", 464 | " \n", 465 | " \n", 466 | " \n", 467 | " \n", 468 | " \n", 469 | " \n", 470 | " \n", 471 | " \n", 472 | " \n", 473 | " \n", 474 | " \n", 475 | " \n", 476 | " \n", 477 | " \n", 478 | " \n", 479 | " \n", 480 | " \n", 481 | " \n", 482 | " \n", 483 | " \n", 484 | " \n", 485 | " \n", 486 | " \n", 487 | " \n", 488 | " \n", 489 | "
Fahrenheit ($x$)Kelvin ($y$)$y_{pred}$squared err ($\\epsilon$)
Boiling point of He-452.14.22-718.294231522026.814658
Boiling point of N-320.477.36-509.049926343876.601867
Melting point of H2O32.0273.2050.84144149443.328829
Body temperature98.6310.50156.65519023668.225685
Boiling point of H2O212.0373.20336.8245461323.173682
\n", 490 | "
" 491 | ], 492 | "text/plain": [ 493 | " Fahrenheit ($x$) Kelvin ($y$) $y_{pred}$ \\\n", 494 | "Boiling point of He -452.1 4.22 -718.294231 \n", 495 | "Boiling point of N -320.4 77.36 -509.049926 \n", 496 | "Melting point of H2O 32.0 273.20 50.841441 \n", 497 | "Body temperature 98.6 310.50 156.655190 \n", 498 | "Boiling point of H2O 212.0 373.20 336.824546 \n", 499 | "\n", 500 | " squared err ($\\epsilon$) \n", 501 | "Boiling point of He 522026.814658 \n", 502 | "Boiling point of N 343876.601867 \n", 503 | "Melting point of H2O 49443.328829 \n", 504 | "Body temperature 23668.225685 \n", 505 | "Boiling point of H2O 1323.173682 " 506 | ] 507 | }, 508 | "execution_count": 7, 509 | "metadata": {}, 510 | "output_type": "execute_result" 511 | } 512 | ], 513 | "source": [ 514 | "LEARNING_RATE = 0.00001\n", 515 | "N_ITERATIONS = 50000\n", 516 | "\n", 517 | "df, mean_sqr_err = state_as_table(a, b)\n", 518 | "print('a = {}, b = {}, mean sqr. err. = {}'.format(a, b, mean_sqr_err))\n", 519 | "df" 520 | ] 521 | }, 522 | { 523 | "cell_type": "markdown", 524 | "metadata": {}, 525 | "source": [ 526 | "#### Gradient descent\n", 527 | "\n", 528 | "Run this cell repeatedly to see gradient descent in action:" 529 | ] 530 | }, 531 | { 532 | "cell_type": "code", 533 | "execution_count": 31, 534 | "metadata": { 535 | "collapsed": false 536 | }, 537 | "outputs": [ 538 | { 539 | "name": "stdout", 540 | "output_type": "stream", 541 | "text": [ 542 | "a = 0.555810262011, b = 255.484566228, mean sqr. err. = 0.0131644123508\n" 543 | ] 544 | }, 545 | { 546 | "data": { 547 | "text/html": [ 548 | "
\n", 549 | "\n", 550 | " \n", 551 | " \n", 552 | " \n", 553 | " \n", 554 | " \n", 555 | " \n", 556 | " \n", 557 | " \n", 558 | " \n", 559 | " \n", 560 | " \n", 561 | " \n", 562 | " \n", 563 | " \n", 564 | " \n", 565 | " \n", 566 | " \n", 567 | " \n", 568 | " \n", 569 | " \n", 570 | " \n", 571 | " \n", 572 | " \n", 573 | " \n", 574 | " \n", 575 | " \n", 576 | " \n", 577 | " \n", 578 | " \n", 579 | " \n", 580 | " \n", 581 | " \n", 582 | " \n", 583 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 587 | " \n", 588 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 592 | " \n", 593 | " \n", 594 | " \n", 595 | " \n", 596 | "
Fahrenheit ($x$)Kelvin ($y$)$y_{pred}$squared err ($\\epsilon$)
Boiling point of He-452.14.224.2027470.000298
Boiling point of N-320.477.3677.4029580.001845
Melting point of H2O32.0273.20273.2704950.004969
Body temperature98.6310.50310.2874580.045174
Boiling point of H2O212.0373.20373.3163420.013535
\n", 597 | "
" 598 | ], 599 | "text/plain": [ 600 | " Fahrenheit ($x$) Kelvin ($y$) $y_{pred}$ \\\n", 601 | "Boiling point of He -452.1 4.22 4.202747 \n", 602 | "Boiling point of N -320.4 77.36 77.402958 \n", 603 | "Melting point of H2O 32.0 273.20 273.270495 \n", 604 | "Body temperature 98.6 310.50 310.287458 \n", 605 | "Boiling point of H2O 212.0 373.20 373.316342 \n", 606 | "\n", 607 | " squared err ($\\epsilon$) \n", 608 | "Boiling point of He 0.000298 \n", 609 | "Boiling point of N 0.001845 \n", 610 | "Melting point of H2O 0.004969 \n", 611 | "Body temperature 0.045174 \n", 612 | "Boiling point of H2O 0.013535 " 613 | ] 614 | }, 615 | "execution_count": 31, 616 | "metadata": {}, 617 | "output_type": "execute_result" 618 | } 619 | ], 620 | "source": [ 621 | "for i in xrange(N_ITERATIONS):\n", 622 | " a, b = iterative_gradient_descent_step(a, b, LEARNING_RATE)\n", 623 | "\n", 624 | "df, mean_sqr_err = state_as_table(a, b)\n", 625 | "print('a = {}, b = {}, mean sqr. err. = {}'.format(a, b, mean_sqr_err))\n", 626 | "df" 627 | ] 628 | }, 629 | { 630 | "cell_type": "markdown", 631 | "metadata": {}, 632 | "source": [ 633 | "## Evaluation\n", 634 | "\n", 635 | "The formula for conversion from Farenheit to Kelvin is:\n", 636 | "\n", 637 | "$T_K = {5\\over9}T_F + 255.372$\n", 638 | "\n", 639 | "Therefore:\n", 640 | "\n", 641 | "$a = 0.556$\n", 642 | "\n", 643 | "$b = 255.372$\n", 644 | "\n", 645 | "\n", 646 | "If the above cell was run enough times, $a$ and $b$ should have reached values that are close to the above ideal values (some error is expected as the input data has some small rounding errors)." 647 | ] 648 | }, 649 | { 650 | "cell_type": "markdown", 651 | "metadata": {}, 652 | "source": [ 653 | "## Conclusions\n", 654 | "\n", 655 | "There are some problems with the model above; namely that a very low learning rate and huge number of iterations were required. This is because using a larger learning rate causes the parameters to take huge steps in one direction or another, often causing them to oscillate between negative and positive values with rapidly increasing magnitudes, after which the model 'explodes'.\n", 656 | "\n", 657 | "This would be addressed by standardising the data in `X` and `Y` by subtracting the mean and dividing by the standard deviation. This would allow a much higher learning rate and smaller number of iterations to suffice.\n", 658 | "\n", 659 | "That said, this notebook demonstrates the use of gradient descent to train a simple linear regression model; I hope you have found it helpful." 660 | ] 661 | } 662 | ], 663 | "metadata": { 664 | "kernelspec": { 665 | "display_name": "Python 2", 666 | "language": "python", 667 | "name": "python2" 668 | }, 669 | "language_info": { 670 | "codemirror_mode": { 671 | "name": "ipython", 672 | "version": 2 673 | }, 674 | "file_extension": ".py", 675 | "mimetype": "text/x-python", 676 | "name": "python", 677 | "nbconvert_exporter": "python", 678 | "pygments_lexer": "ipython2", 679 | "version": "2.7.12" 680 | } 681 | }, 682 | "nbformat": 4, 683 | "nbformat_minor": 1 684 | } 685 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Geoffrey French 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deep Learning Tutorial 2 | 3 | #### by Geoff French 4 | 5 | 6 | ## Table of Contents 7 | 8 | - PyData Amsterdam 2017 slides 9 | - Requirements 10 | - Notebooks for the tutorial 11 | - The Python modules 12 | 13 | 14 | ## Slides 15 | 16 | This repo has been used to accompany various talks that I have given, one of which was at PyData Amsterdam 2017. The slides for that talk probably refer to Theano and Lasagne; two neural network toolkits that are no longer developed and maintained. You can find these slides on 17 | [Speakdeck](https://speakerdeck.com/britefury/deep-learning-advanced-techniques-tutorial-pydata-amsterdam-2017). 18 | 19 | 20 | 21 | ## Requirements 22 | 23 | I recommend using the [Anaconda](http://www.continuum.io/downloads) Python distribution, using Python 3.6. 24 | Anaconda will provide Python, Numpy, Matplotlib and [Scikit-image](http://github.com/scikit-image/scikit-image). 25 | 26 | You will need to have the following installed: 27 | 28 | - [PyTorch and torchvision](http://pytorch.org) - get version 1.0. 29 | - OpenCV - use `conda` to install it on Linux. On windows go to [Unofficial Windows Binaries for Python Extension Packages](https://www.lfd.uci.edu/~gohlke/pythonlibs/), download the `.whl` (wheel) file and install it using `pip install `. 30 | 31 | 32 | 33 | ## Notebooks for the tutorial 34 | 35 | ### Using a pre-trained VGG network 36 | 37 | Using a pre-trained network to classify an image: 38 | 39 | [Using a pretrained conv-net - VGG net.ipynb](TUTORIAL 01 - Using a pretrained conv-net - VGG net.ipynb) 40 | 41 | Converting a network for use in a convolutional fashion: 42 | 43 | [Using a pretrained VGG-19 conv-net to find a peacock.ipynb](TUTORIAL 02 - Using a pretrained VGG-19 conv-net to find a peacock.ipynb) 44 | 45 | 46 | 47 | ### Saliency 48 | 49 | Saliency tells you which parts of the image had most influence over a network's prediction. 50 | Two approaches are demonstrated: [region level saliency](TUTORIAL 03 - Image region-level saliency using VGG-19 conv-net.ipynb) 51 | and [pixel level saliency](TUTORIAL 04 - Image pixel-level saliency using VGG-19 conv-net.ipynb) 52 | 53 | 54 | ### Transfer learning 55 | 56 | Transfer learning is the process by which we adapt a pre-trained neural network for other uses. To demonstrate it we train a classifier on the [Kaggle Cats vs Dogs](https://www.kaggle.com/c/dogs-vs-cats) dataset. There are 3 notebooks that demonstrate the effect of using transfer learning and data augmentation: 57 | 58 | [Dogs vs cats with standard learning.ipynb](TUTORIAL 05 - Dogs vs cats with standard learning.ipynb) - train a neural network *without* transfer learning; gets around 10% error rate. 59 | 60 | [Dogs vs cats with transfer learning.ipynb](TUTORIAL 05 - Dogs vs cats with transfer learning.ipynb) - train a neural network *with* transfer learning; gets 5-6% error rate 61 | 62 | [Dogs vs cats with transfer learning and data augmentation.ipynb](TUTORIAL 05 - Dogs vs cats with transfer learning and data augmentation.ipynb) - train a neural network with transfer learning and data augmentation; gets 2.7-3.7% error rate 63 | 64 | 65 | 66 | 67 | 68 | ## The Python modules 69 | 70 | A brief description of the Python modules in this repo: 71 | 72 | `utils.py` - utility functions - main converting images for use with pre-trained models 73 | 74 | `imagenet_classes.py` - provides a dictionary if ImageNet class names, so that we can give meaningful names to the predictions of a pre-trained network. 75 | -------------------------------------------------------------------------------- /imagenet_classes.py: -------------------------------------------------------------------------------- 1 | # ImageNet classes 2 | # Taken from: 3 | # https://gist.githubusercontent.com/yrevar/942d3a0ac09ec9e5eb3a/raw/238f720ff059c1f82f368259d1ca4ffa5dd8f9f5/imagenet1000_clsidx_to_labels.txt 4 | 5 | IMAGENET_CLASSES = \ 6 | {0: 'tench, Tinca tinca', 7 | 1: 'goldfish, Carassius auratus', 8 | 2: 'great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias', 9 | 3: 'tiger shark, Galeocerdo cuvieri', 10 | 4: 'hammerhead, hammerhead shark', 11 | 5: 'electric ray, crampfish, numbfish, torpedo', 12 | 6: 'stingray', 13 | 7: 'cock', 14 | 8: 'hen', 15 | 9: 'ostrich, Struthio camelus', 16 | 10: 'brambling, Fringilla montifringilla', 17 | 11: 'goldfinch, Carduelis carduelis', 18 | 12: 'house finch, linnet, Carpodacus mexicanus', 19 | 13: 'junco, snowbird', 20 | 14: 'indigo bunting, indigo finch, indigo bird, Passerina cyanea', 21 | 15: 'robin, American robin, Turdus migratorius', 22 | 16: 'bulbul', 23 | 17: 'jay', 24 | 18: 'magpie', 25 | 19: 'chickadee', 26 | 20: 'water ouzel, dipper', 27 | 21: 'kite', 28 | 22: 'bald eagle, American eagle, Haliaeetus leucocephalus', 29 | 23: 'vulture', 30 | 24: 'great grey owl, great gray owl, Strix nebulosa', 31 | 25: 'European fire salamander, Salamandra salamandra', 32 | 26: 'common newt, Triturus vulgaris', 33 | 27: 'eft', 34 | 28: 'spotted salamander, Ambystoma maculatum', 35 | 29: 'axolotl, mud puppy, Ambystoma mexicanum', 36 | 30: 'bullfrog, Rana catesbeiana', 37 | 31: 'tree frog, tree-frog', 38 | 32: 'tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui', 39 | 33: 'loggerhead, loggerhead turtle, Caretta caretta', 40 | 34: 'leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea', 41 | 35: 'mud turtle', 42 | 36: 'terrapin', 43 | 37: 'box turtle, box tortoise', 44 | 38: 'banded gecko', 45 | 39: 'common iguana, iguana, Iguana iguana', 46 | 40: 'American chameleon, anole, Anolis carolinensis', 47 | 41: 'whiptail, whiptail lizard', 48 | 42: 'agama', 49 | 43: 'frilled lizard, Chlamydosaurus kingi', 50 | 44: 'alligator lizard', 51 | 45: 'Gila monster, Heloderma suspectum', 52 | 46: 'green lizard, Lacerta viridis', 53 | 47: 'African chameleon, Chamaeleo chamaeleon', 54 | 48: 'Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis', 55 | 49: 'African crocodile, Nile crocodile, Crocodylus niloticus', 56 | 50: 'American alligator, Alligator mississipiensis', 57 | 51: 'triceratops', 58 | 52: 'thunder snake, worm snake, Carphophis amoenus', 59 | 53: 'ringneck snake, ring-necked snake, ring snake', 60 | 54: 'hognose snake, puff adder, sand viper', 61 | 55: 'green snake, grass snake', 62 | 56: 'king snake, kingsnake', 63 | 57: 'garter snake, grass snake', 64 | 58: 'water snake', 65 | 59: 'vine snake', 66 | 60: 'night snake, Hypsiglena torquata', 67 | 61: 'boa constrictor, Constrictor constrictor', 68 | 62: 'rock python, rock snake, Python sebae', 69 | 63: 'Indian cobra, Naja naja', 70 | 64: 'green mamba', 71 | 65: 'sea snake', 72 | 66: 'horned viper, cerastes, sand viper, horned asp, Cerastes cornutus', 73 | 67: 'diamondback, diamondback rattlesnake, Crotalus adamanteus', 74 | 68: 'sidewinder, horned rattlesnake, Crotalus cerastes', 75 | 69: 'trilobite', 76 | 70: 'harvestman, daddy longlegs, Phalangium opilio', 77 | 71: 'scorpion', 78 | 72: 'black and gold garden spider, Argiope aurantia', 79 | 73: 'barn spider, Araneus cavaticus', 80 | 74: 'garden spider, Aranea diademata', 81 | 75: 'black widow, Latrodectus mactans', 82 | 76: 'tarantula', 83 | 77: 'wolf spider, hunting spider', 84 | 78: 'tick', 85 | 79: 'centipede', 86 | 80: 'black grouse', 87 | 81: 'ptarmigan', 88 | 82: 'ruffed grouse, partridge, Bonasa umbellus', 89 | 83: 'prairie chicken, prairie grouse, prairie fowl', 90 | 84: 'peacock', 91 | 85: 'quail', 92 | 86: 'partridge', 93 | 87: 'African grey, African gray, Psittacus erithacus', 94 | 88: 'macaw', 95 | 89: 'sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita', 96 | 90: 'lorikeet', 97 | 91: 'coucal', 98 | 92: 'bee eater', 99 | 93: 'hornbill', 100 | 94: 'hummingbird', 101 | 95: 'jacamar', 102 | 96: 'toucan', 103 | 97: 'drake', 104 | 98: 'red-breasted merganser, Mergus serrator', 105 | 99: 'goose', 106 | 100: 'black swan, Cygnus atratus', 107 | 101: 'tusker', 108 | 102: 'echidna, spiny anteater, anteater', 109 | 103: 'platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus', 110 | 104: 'wallaby, brush kangaroo', 111 | 105: 'koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus', 112 | 106: 'wombat', 113 | 107: 'jellyfish', 114 | 108: 'sea anemone, anemone', 115 | 109: 'brain coral', 116 | 110: 'flatworm, platyhelminth', 117 | 111: 'nematode, nematode worm, roundworm', 118 | 112: 'conch', 119 | 113: 'snail', 120 | 114: 'slug', 121 | 115: 'sea slug, nudibranch', 122 | 116: 'chiton, coat-of-mail shell, sea cradle, polyplacophore', 123 | 117: 'chambered nautilus, pearly nautilus, nautilus', 124 | 118: 'Dungeness crab, Cancer magister', 125 | 119: 'rock crab, Cancer irroratus', 126 | 120: 'fiddler crab', 127 | 121: 'king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica', 128 | 122: 'American lobster, Northern lobster, Maine lobster, Homarus americanus', 129 | 123: 'spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish', 130 | 124: 'crayfish, crawfish, crawdad, crawdaddy', 131 | 125: 'hermit crab', 132 | 126: 'isopod', 133 | 127: 'white stork, Ciconia ciconia', 134 | 128: 'black stork, Ciconia nigra', 135 | 129: 'spoonbill', 136 | 130: 'flamingo', 137 | 131: 'little blue heron, Egretta caerulea', 138 | 132: 'American egret, great white heron, Egretta albus', 139 | 133: 'bittern', 140 | 134: 'crane', 141 | 135: 'limpkin, Aramus pictus', 142 | 136: 'European gallinule, Porphyrio porphyrio', 143 | 137: 'American coot, marsh hen, mud hen, water hen, Fulica americana', 144 | 138: 'bustard', 145 | 139: 'ruddy turnstone, Arenaria interpres', 146 | 140: 'red-backed sandpiper, dunlin, Erolia alpina', 147 | 141: 'redshank, Tringa totanus', 148 | 142: 'dowitcher', 149 | 143: 'oystercatcher, oyster catcher', 150 | 144: 'pelican', 151 | 145: 'king penguin, Aptenodytes patagonica', 152 | 146: 'albatross, mollymawk', 153 | 147: 'grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus', 154 | 148: 'killer whale, killer, orca, grampus, sea wolf, Orcinus orca', 155 | 149: 'dugong, Dugong dugon', 156 | 150: 'sea lion', 157 | 151: 'Chihuahua', 158 | 152: 'Japanese spaniel', 159 | 153: 'Maltese dog, Maltese terrier, Maltese', 160 | 154: 'Pekinese, Pekingese, Peke', 161 | 155: 'Shih-Tzu', 162 | 156: 'Blenheim spaniel', 163 | 157: 'papillon', 164 | 158: 'toy terrier', 165 | 159: 'Rhodesian ridgeback', 166 | 160: 'Afghan hound, Afghan', 167 | 161: 'basset, basset hound', 168 | 162: 'beagle', 169 | 163: 'bloodhound, sleuthhound', 170 | 164: 'bluetick', 171 | 165: 'black-and-tan coonhound', 172 | 166: 'Walker hound, Walker foxhound', 173 | 167: 'English foxhound', 174 | 168: 'redbone', 175 | 169: 'borzoi, Russian wolfhound', 176 | 170: 'Irish wolfhound', 177 | 171: 'Italian greyhound', 178 | 172: 'whippet', 179 | 173: 'Ibizan hound, Ibizan Podenco', 180 | 174: 'Norwegian elkhound, elkhound', 181 | 175: 'otterhound, otter hound', 182 | 176: 'Saluki, gazelle hound', 183 | 177: 'Scottish deerhound, deerhound', 184 | 178: 'Weimaraner', 185 | 179: 'Staffordshire bullterrier, Staffordshire bull terrier', 186 | 180: 'American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier', 187 | 181: 'Bedlington terrier', 188 | 182: 'Border terrier', 189 | 183: 'Kerry blue terrier', 190 | 184: 'Irish terrier', 191 | 185: 'Norfolk terrier', 192 | 186: 'Norwich terrier', 193 | 187: 'Yorkshire terrier', 194 | 188: 'wire-haired fox terrier', 195 | 189: 'Lakeland terrier', 196 | 190: 'Sealyham terrier, Sealyham', 197 | 191: 'Airedale, Airedale terrier', 198 | 192: 'cairn, cairn terrier', 199 | 193: 'Australian terrier', 200 | 194: 'Dandie Dinmont, Dandie Dinmont terrier', 201 | 195: 'Boston bull, Boston terrier', 202 | 196: 'miniature schnauzer', 203 | 197: 'giant schnauzer', 204 | 198: 'standard schnauzer', 205 | 199: 'Scotch terrier, Scottish terrier, Scottie', 206 | 200: 'Tibetan terrier, chrysanthemum dog', 207 | 201: 'silky terrier, Sydney silky', 208 | 202: 'soft-coated wheaten terrier', 209 | 203: 'West Highland white terrier', 210 | 204: 'Lhasa, Lhasa apso', 211 | 205: 'flat-coated retriever', 212 | 206: 'curly-coated retriever', 213 | 207: 'golden retriever', 214 | 208: 'Labrador retriever', 215 | 209: 'Chesapeake Bay retriever', 216 | 210: 'German short-haired pointer', 217 | 211: 'vizsla, Hungarian pointer', 218 | 212: 'English setter', 219 | 213: 'Irish setter, red setter', 220 | 214: 'Gordon setter', 221 | 215: 'Brittany spaniel', 222 | 216: 'clumber, clumber spaniel', 223 | 217: 'English springer, English springer spaniel', 224 | 218: 'Welsh springer spaniel', 225 | 219: 'cocker spaniel, English cocker spaniel, cocker', 226 | 220: 'Sussex spaniel', 227 | 221: 'Irish water spaniel', 228 | 222: 'kuvasz', 229 | 223: 'schipperke', 230 | 224: 'groenendael', 231 | 225: 'malinois', 232 | 226: 'briard', 233 | 227: 'kelpie', 234 | 228: 'komondor', 235 | 229: 'Old English sheepdog, bobtail', 236 | 230: 'Shetland sheepdog, Shetland sheep dog, Shetland', 237 | 231: 'collie', 238 | 232: 'Border collie', 239 | 233: 'Bouvier des Flandres, Bouviers des Flandres', 240 | 234: 'Rottweiler', 241 | 235: 'German shepherd, German shepherd dog, German police dog, alsatian', 242 | 236: 'Doberman, Doberman pinscher', 243 | 237: 'miniature pinscher', 244 | 238: 'Greater Swiss Mountain dog', 245 | 239: 'Bernese mountain dog', 246 | 240: 'Appenzeller', 247 | 241: 'EntleBucher', 248 | 242: 'boxer', 249 | 243: 'bull mastiff', 250 | 244: 'Tibetan mastiff', 251 | 245: 'French bulldog', 252 | 246: 'Great Dane', 253 | 247: 'Saint Bernard, St Bernard', 254 | 248: 'Eskimo dog, husky', 255 | 249: 'malamute, malemute, Alaskan malamute', 256 | 250: 'Siberian husky', 257 | 251: 'dalmatian, coach dog, carriage dog', 258 | 252: 'affenpinscher, monkey pinscher, monkey dog', 259 | 253: 'basenji', 260 | 254: 'pug, pug-dog', 261 | 255: 'Leonberg', 262 | 256: 'Newfoundland, Newfoundland dog', 263 | 257: 'Great Pyrenees', 264 | 258: 'Samoyed, Samoyede', 265 | 259: 'Pomeranian', 266 | 260: 'chow, chow chow', 267 | 261: 'keeshond', 268 | 262: 'Brabancon griffon', 269 | 263: 'Pembroke, Pembroke Welsh corgi', 270 | 264: 'Cardigan, Cardigan Welsh corgi', 271 | 265: 'toy poodle', 272 | 266: 'miniature poodle', 273 | 267: 'standard poodle', 274 | 268: 'Mexican hairless', 275 | 269: 'timber wolf, grey wolf, gray wolf, Canis lupus', 276 | 270: 'white wolf, Arctic wolf, Canis lupus tundrarum', 277 | 271: 'red wolf, maned wolf, Canis rufus, Canis niger', 278 | 272: 'coyote, prairie wolf, brush wolf, Canis latrans', 279 | 273: 'dingo, warrigal, warragal, Canis dingo', 280 | 274: 'dhole, Cuon alpinus', 281 | 275: 'African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus', 282 | 276: 'hyena, hyaena', 283 | 277: 'red fox, Vulpes vulpes', 284 | 278: 'kit fox, Vulpes macrotis', 285 | 279: 'Arctic fox, white fox, Alopex lagopus', 286 | 280: 'grey fox, gray fox, Urocyon cinereoargenteus', 287 | 281: 'tabby, tabby cat', 288 | 282: 'tiger cat', 289 | 283: 'Persian cat', 290 | 284: 'Siamese cat, Siamese', 291 | 285: 'Egyptian cat', 292 | 286: 'cougar, puma, catamount, mountain lion, painter, panther, Felis concolor', 293 | 287: 'lynx, catamount', 294 | 288: 'leopard, Panthera pardus', 295 | 289: 'snow leopard, ounce, Panthera uncia', 296 | 290: 'jaguar, panther, Panthera onca, Felis onca', 297 | 291: 'lion, king of beasts, Panthera leo', 298 | 292: 'tiger, Panthera tigris', 299 | 293: 'cheetah, chetah, Acinonyx jubatus', 300 | 294: 'brown bear, bruin, Ursus arctos', 301 | 295: 'American black bear, black bear, Ursus americanus, Euarctos americanus', 302 | 296: 'ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus', 303 | 297: 'sloth bear, Melursus ursinus, Ursus ursinus', 304 | 298: 'mongoose', 305 | 299: 'meerkat, mierkat', 306 | 300: 'tiger beetle', 307 | 301: 'ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle', 308 | 302: 'ground beetle, carabid beetle', 309 | 303: 'long-horned beetle, longicorn, longicorn beetle', 310 | 304: 'leaf beetle, chrysomelid', 311 | 305: 'dung beetle', 312 | 306: 'rhinoceros beetle', 313 | 307: 'weevil', 314 | 308: 'fly', 315 | 309: 'bee', 316 | 310: 'ant, emmet, pismire', 317 | 311: 'grasshopper, hopper', 318 | 312: 'cricket', 319 | 313: 'walking stick, walkingstick, stick insect', 320 | 314: 'cockroach, roach', 321 | 315: 'mantis, mantid', 322 | 316: 'cicada, cicala', 323 | 317: 'leafhopper', 324 | 318: 'lacewing, lacewing fly', 325 | 319: "dragonfly, darning needle, devil's darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk", 326 | 320: 'damselfly', 327 | 321: 'admiral', 328 | 322: 'ringlet, ringlet butterfly', 329 | 323: 'monarch, monarch butterfly, milkweed butterfly, Danaus plexippus', 330 | 324: 'cabbage butterfly', 331 | 325: 'sulphur butterfly, sulfur butterfly', 332 | 326: 'lycaenid, lycaenid butterfly', 333 | 327: 'starfish, sea star', 334 | 328: 'sea urchin', 335 | 329: 'sea cucumber, holothurian', 336 | 330: 'wood rabbit, cottontail, cottontail rabbit', 337 | 331: 'hare', 338 | 332: 'Angora, Angora rabbit', 339 | 333: 'hamster', 340 | 334: 'porcupine, hedgehog', 341 | 335: 'fox squirrel, eastern fox squirrel, Sciurus niger', 342 | 336: 'marmot', 343 | 337: 'beaver', 344 | 338: 'guinea pig, Cavia cobaya', 345 | 339: 'sorrel', 346 | 340: 'zebra', 347 | 341: 'hog, pig, grunter, squealer, Sus scrofa', 348 | 342: 'wild boar, boar, Sus scrofa', 349 | 343: 'warthog', 350 | 344: 'hippopotamus, hippo, river horse, Hippopotamus amphibius', 351 | 345: 'ox', 352 | 346: 'water buffalo, water ox, Asiatic buffalo, Bubalus bubalis', 353 | 347: 'bison', 354 | 348: 'ram, tup', 355 | 349: 'bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis', 356 | 350: 'ibex, Capra ibex', 357 | 351: 'hartebeest', 358 | 352: 'impala, Aepyceros melampus', 359 | 353: 'gazelle', 360 | 354: 'Arabian camel, dromedary, Camelus dromedarius', 361 | 355: 'llama', 362 | 356: 'weasel', 363 | 357: 'mink', 364 | 358: 'polecat, fitch, foulmart, foumart, Mustela putorius', 365 | 359: 'black-footed ferret, ferret, Mustela nigripes', 366 | 360: 'otter', 367 | 361: 'skunk, polecat, wood pussy', 368 | 362: 'badger', 369 | 363: 'armadillo', 370 | 364: 'three-toed sloth, ai, Bradypus tridactylus', 371 | 365: 'orangutan, orang, orangutang, Pongo pygmaeus', 372 | 366: 'gorilla, Gorilla gorilla', 373 | 367: 'chimpanzee, chimp, Pan troglodytes', 374 | 368: 'gibbon, Hylobates lar', 375 | 369: 'siamang, Hylobates syndactylus, Symphalangus syndactylus', 376 | 370: 'guenon, guenon monkey', 377 | 371: 'patas, hussar monkey, Erythrocebus patas', 378 | 372: 'baboon', 379 | 373: 'macaque', 380 | 374: 'langur', 381 | 375: 'colobus, colobus monkey', 382 | 376: 'proboscis monkey, Nasalis larvatus', 383 | 377: 'marmoset', 384 | 378: 'capuchin, ringtail, Cebus capucinus', 385 | 379: 'howler monkey, howler', 386 | 380: 'titi, titi monkey', 387 | 381: 'spider monkey, Ateles geoffroyi', 388 | 382: 'squirrel monkey, Saimiri sciureus', 389 | 383: 'Madagascar cat, ring-tailed lemur, Lemur catta', 390 | 384: 'indri, indris, Indri indri, Indri brevicaudatus', 391 | 385: 'Indian elephant, Elephas maximus', 392 | 386: 'African elephant, Loxodonta africana', 393 | 387: 'lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens', 394 | 388: 'giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca', 395 | 389: 'barracouta, snoek', 396 | 390: 'eel', 397 | 391: 'coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch', 398 | 392: 'rock beauty, Holocanthus tricolor', 399 | 393: 'anemone fish', 400 | 394: 'sturgeon', 401 | 395: 'gar, garfish, garpike, billfish, Lepisosteus osseus', 402 | 396: 'lionfish', 403 | 397: 'puffer, pufferfish, blowfish, globefish', 404 | 398: 'abacus', 405 | 399: 'abaya', 406 | 400: "academic gown, academic robe, judge's robe", 407 | 401: 'accordion, piano accordion, squeeze box', 408 | 402: 'acoustic guitar', 409 | 403: 'aircraft carrier, carrier, flattop, attack aircraft carrier', 410 | 404: 'airliner', 411 | 405: 'airship, dirigible', 412 | 406: 'altar', 413 | 407: 'ambulance', 414 | 408: 'amphibian, amphibious vehicle', 415 | 409: 'analog clock', 416 | 410: 'apiary, bee house', 417 | 411: 'apron', 418 | 412: 'ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin', 419 | 413: 'assault rifle, assault gun', 420 | 414: 'backpack, back pack, knapsack, packsack, rucksack, haversack', 421 | 415: 'bakery, bakeshop, bakehouse', 422 | 416: 'balance beam, beam', 423 | 417: 'balloon', 424 | 418: 'ballpoint, ballpoint pen, ballpen, Biro', 425 | 419: 'Band Aid', 426 | 420: 'banjo', 427 | 421: 'bannister, banister, balustrade, balusters, handrail', 428 | 422: 'barbell', 429 | 423: 'barber chair', 430 | 424: 'barbershop', 431 | 425: 'barn', 432 | 426: 'barometer', 433 | 427: 'barrel, cask', 434 | 428: 'barrow, garden cart, lawn cart, wheelbarrow', 435 | 429: 'baseball', 436 | 430: 'basketball', 437 | 431: 'bassinet', 438 | 432: 'bassoon', 439 | 433: 'bathing cap, swimming cap', 440 | 434: 'bath towel', 441 | 435: 'bathtub, bathing tub, bath, tub', 442 | 436: 'beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon', 443 | 437: 'beacon, lighthouse, beacon light, pharos', 444 | 438: 'beaker', 445 | 439: 'bearskin, busby, shako', 446 | 440: 'beer bottle', 447 | 441: 'beer glass', 448 | 442: 'bell cote, bell cot', 449 | 443: 'bib', 450 | 444: 'bicycle-built-for-two, tandem bicycle, tandem', 451 | 445: 'bikini, two-piece', 452 | 446: 'binder, ring-binder', 453 | 447: 'binoculars, field glasses, opera glasses', 454 | 448: 'birdhouse', 455 | 449: 'boathouse', 456 | 450: 'bobsled, bobsleigh, bob', 457 | 451: 'bolo tie, bolo, bola tie, bola', 458 | 452: 'bonnet, poke bonnet', 459 | 453: 'bookcase', 460 | 454: 'bookshop, bookstore, bookstall', 461 | 455: 'bottlecap', 462 | 456: 'bow', 463 | 457: 'bow tie, bow-tie, bowtie', 464 | 458: 'brass, memorial tablet, plaque', 465 | 459: 'brassiere, bra, bandeau', 466 | 460: 'breakwater, groin, groyne, mole, bulwark, seawall, jetty', 467 | 461: 'breastplate, aegis, egis', 468 | 462: 'broom', 469 | 463: 'bucket, pail', 470 | 464: 'buckle', 471 | 465: 'bulletproof vest', 472 | 466: 'bullet train, bullet', 473 | 467: 'butcher shop, meat market', 474 | 468: 'cab, hack, taxi, taxicab', 475 | 469: 'caldron, cauldron', 476 | 470: 'candle, taper, wax light', 477 | 471: 'cannon', 478 | 472: 'canoe', 479 | 473: 'can opener, tin opener', 480 | 474: 'cardigan', 481 | 475: 'car mirror', 482 | 476: 'carousel, carrousel, merry-go-round, roundabout, whirligig', 483 | 477: "carpenter's kit, tool kit", 484 | 478: 'carton', 485 | 479: 'car wheel', 486 | 480: 'cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM', 487 | 481: 'cassette', 488 | 482: 'cassette player', 489 | 483: 'castle', 490 | 484: 'catamaran', 491 | 485: 'CD player', 492 | 486: 'cello, violoncello', 493 | 487: 'cellular telephone, cellular phone, cellphone, cell, mobile phone', 494 | 488: 'chain', 495 | 489: 'chainlink fence', 496 | 490: 'chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour', 497 | 491: 'chain saw, chainsaw', 498 | 492: 'chest', 499 | 493: 'chiffonier, commode', 500 | 494: 'chime, bell, gong', 501 | 495: 'china cabinet, china closet', 502 | 496: 'Christmas stocking', 503 | 497: 'church, church building', 504 | 498: 'cinema, movie theater, movie theatre, movie house, picture palace', 505 | 499: 'cleaver, meat cleaver, chopper', 506 | 500: 'cliff dwelling', 507 | 501: 'cloak', 508 | 502: 'clog, geta, patten, sabot', 509 | 503: 'cocktail shaker', 510 | 504: 'coffee mug', 511 | 505: 'coffeepot', 512 | 506: 'coil, spiral, volute, whorl, helix', 513 | 507: 'combination lock', 514 | 508: 'computer keyboard, keypad', 515 | 509: 'confectionery, confectionary, candy store', 516 | 510: 'container ship, containership, container vessel', 517 | 511: 'convertible', 518 | 512: 'corkscrew, bottle screw', 519 | 513: 'cornet, horn, trumpet, trump', 520 | 514: 'cowboy boot', 521 | 515: 'cowboy hat, ten-gallon hat', 522 | 516: 'cradle', 523 | 517: 'crane', 524 | 518: 'crash helmet', 525 | 519: 'crate', 526 | 520: 'crib, cot', 527 | 521: 'Crock Pot', 528 | 522: 'croquet ball', 529 | 523: 'crutch', 530 | 524: 'cuirass', 531 | 525: 'dam, dike, dyke', 532 | 526: 'desk', 533 | 527: 'desktop computer', 534 | 528: 'dial telephone, dial phone', 535 | 529: 'diaper, nappy, napkin', 536 | 530: 'digital clock', 537 | 531: 'digital watch', 538 | 532: 'dining table, board', 539 | 533: 'dishrag, dishcloth', 540 | 534: 'dishwasher, dish washer, dishwashing machine', 541 | 535: 'disk brake, disc brake', 542 | 536: 'dock, dockage, docking facility', 543 | 537: 'dogsled, dog sled, dog sleigh', 544 | 538: 'dome', 545 | 539: 'doormat, welcome mat', 546 | 540: 'drilling platform, offshore rig', 547 | 541: 'drum, membranophone, tympan', 548 | 542: 'drumstick', 549 | 543: 'dumbbell', 550 | 544: 'Dutch oven', 551 | 545: 'electric fan, blower', 552 | 546: 'electric guitar', 553 | 547: 'electric locomotive', 554 | 548: 'entertainment center', 555 | 549: 'envelope', 556 | 550: 'espresso maker', 557 | 551: 'face powder', 558 | 552: 'feather boa, boa', 559 | 553: 'file, file cabinet, filing cabinet', 560 | 554: 'fireboat', 561 | 555: 'fire engine, fire truck', 562 | 556: 'fire screen, fireguard', 563 | 557: 'flagpole, flagstaff', 564 | 558: 'flute, transverse flute', 565 | 559: 'folding chair', 566 | 560: 'football helmet', 567 | 561: 'forklift', 568 | 562: 'fountain', 569 | 563: 'fountain pen', 570 | 564: 'four-poster', 571 | 565: 'freight car', 572 | 566: 'French horn, horn', 573 | 567: 'frying pan, frypan, skillet', 574 | 568: 'fur coat', 575 | 569: 'garbage truck, dustcart', 576 | 570: 'gasmask, respirator, gas helmet', 577 | 571: 'gas pump, gasoline pump, petrol pump, island dispenser', 578 | 572: 'goblet', 579 | 573: 'go-kart', 580 | 574: 'golf ball', 581 | 575: 'golfcart, golf cart', 582 | 576: 'gondola', 583 | 577: 'gong, tam-tam', 584 | 578: 'gown', 585 | 579: 'grand piano, grand', 586 | 580: 'greenhouse, nursery, glasshouse', 587 | 581: 'grille, radiator grille', 588 | 582: 'grocery store, grocery, food market, market', 589 | 583: 'guillotine', 590 | 584: 'hair slide', 591 | 585: 'hair spray', 592 | 586: 'half track', 593 | 587: 'hammer', 594 | 588: 'hamper', 595 | 589: 'hand blower, blow dryer, blow drier, hair dryer, hair drier', 596 | 590: 'hand-held computer, hand-held microcomputer', 597 | 591: 'handkerchief, hankie, hanky, hankey', 598 | 592: 'hard disc, hard disk, fixed disk', 599 | 593: 'harmonica, mouth organ, harp, mouth harp', 600 | 594: 'harp', 601 | 595: 'harvester, reaper', 602 | 596: 'hatchet', 603 | 597: 'holster', 604 | 598: 'home theater, home theatre', 605 | 599: 'honeycomb', 606 | 600: 'hook, claw', 607 | 601: 'hoopskirt, crinoline', 608 | 602: 'horizontal bar, high bar', 609 | 603: 'horse cart, horse-cart', 610 | 604: 'hourglass', 611 | 605: 'iPod', 612 | 606: 'iron, smoothing iron', 613 | 607: "jack-o'-lantern", 614 | 608: 'jean, blue jean, denim', 615 | 609: 'jeep, landrover', 616 | 610: 'jersey, T-shirt, tee shirt', 617 | 611: 'jigsaw puzzle', 618 | 612: 'jinrikisha, ricksha, rickshaw', 619 | 613: 'joystick', 620 | 614: 'kimono', 621 | 615: 'knee pad', 622 | 616: 'knot', 623 | 617: 'lab coat, laboratory coat', 624 | 618: 'ladle', 625 | 619: 'lampshade, lamp shade', 626 | 620: 'laptop, laptop computer', 627 | 621: 'lawn mower, mower', 628 | 622: 'lens cap, lens cover', 629 | 623: 'letter opener, paper knife, paperknife', 630 | 624: 'library', 631 | 625: 'lifeboat', 632 | 626: 'lighter, light, igniter, ignitor', 633 | 627: 'limousine, limo', 634 | 628: 'liner, ocean liner', 635 | 629: 'lipstick, lip rouge', 636 | 630: 'Loafer', 637 | 631: 'lotion', 638 | 632: 'loudspeaker, speaker, speaker unit, loudspeaker system, speaker system', 639 | 633: "loupe, jeweler's loupe", 640 | 634: 'lumbermill, sawmill', 641 | 635: 'magnetic compass', 642 | 636: 'mailbag, postbag', 643 | 637: 'mailbox, letter box', 644 | 638: 'maillot', 645 | 639: 'maillot, tank suit', 646 | 640: 'manhole cover', 647 | 641: 'maraca', 648 | 642: 'marimba, xylophone', 649 | 643: 'mask', 650 | 644: 'matchstick', 651 | 645: 'maypole', 652 | 646: 'maze, labyrinth', 653 | 647: 'measuring cup', 654 | 648: 'medicine chest, medicine cabinet', 655 | 649: 'megalith, megalithic structure', 656 | 650: 'microphone, mike', 657 | 651: 'microwave, microwave oven', 658 | 652: 'military uniform', 659 | 653: 'milk can', 660 | 654: 'minibus', 661 | 655: 'miniskirt, mini', 662 | 656: 'minivan', 663 | 657: 'missile', 664 | 658: 'mitten', 665 | 659: 'mixing bowl', 666 | 660: 'mobile home, manufactured home', 667 | 661: 'Model T', 668 | 662: 'modem', 669 | 663: 'monastery', 670 | 664: 'monitor', 671 | 665: 'moped', 672 | 666: 'mortar', 673 | 667: 'mortarboard', 674 | 668: 'mosque', 675 | 669: 'mosquito net', 676 | 670: 'motor scooter, scooter', 677 | 671: 'mountain bike, all-terrain bike, off-roader', 678 | 672: 'mountain tent', 679 | 673: 'mouse, computer mouse', 680 | 674: 'mousetrap', 681 | 675: 'moving van', 682 | 676: 'muzzle', 683 | 677: 'nail', 684 | 678: 'neck brace', 685 | 679: 'necklace', 686 | 680: 'nipple', 687 | 681: 'notebook, notebook computer', 688 | 682: 'obelisk', 689 | 683: 'oboe, hautboy, hautbois', 690 | 684: 'ocarina, sweet potato', 691 | 685: 'odometer, hodometer, mileometer, milometer', 692 | 686: 'oil filter', 693 | 687: 'organ, pipe organ', 694 | 688: 'oscilloscope, scope, cathode-ray oscilloscope, CRO', 695 | 689: 'overskirt', 696 | 690: 'oxcart', 697 | 691: 'oxygen mask', 698 | 692: 'packet', 699 | 693: 'paddle, boat paddle', 700 | 694: 'paddlewheel, paddle wheel', 701 | 695: 'padlock', 702 | 696: 'paintbrush', 703 | 697: "pajama, pyjama, pj's, jammies", 704 | 698: 'palace', 705 | 699: 'panpipe, pandean pipe, syrinx', 706 | 700: 'paper towel', 707 | 701: 'parachute, chute', 708 | 702: 'parallel bars, bars', 709 | 703: 'park bench', 710 | 704: 'parking meter', 711 | 705: 'passenger car, coach, carriage', 712 | 706: 'patio, terrace', 713 | 707: 'pay-phone, pay-station', 714 | 708: 'pedestal, plinth, footstall', 715 | 709: 'pencil box, pencil case', 716 | 710: 'pencil sharpener', 717 | 711: 'perfume, essence', 718 | 712: 'Petri dish', 719 | 713: 'photocopier', 720 | 714: 'pick, plectrum, plectron', 721 | 715: 'pickelhaube', 722 | 716: 'picket fence, paling', 723 | 717: 'pickup, pickup truck', 724 | 718: 'pier', 725 | 719: 'piggy bank, penny bank', 726 | 720: 'pill bottle', 727 | 721: 'pillow', 728 | 722: 'ping-pong ball', 729 | 723: 'pinwheel', 730 | 724: 'pirate, pirate ship', 731 | 725: 'pitcher, ewer', 732 | 726: "plane, carpenter's plane, woodworking plane", 733 | 727: 'planetarium', 734 | 728: 'plastic bag', 735 | 729: 'plate rack', 736 | 730: 'plow, plough', 737 | 731: "plunger, plumber's helper", 738 | 732: 'Polaroid camera, Polaroid Land camera', 739 | 733: 'pole', 740 | 734: 'police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria', 741 | 735: 'poncho', 742 | 736: 'pool table, billiard table, snooker table', 743 | 737: 'pop bottle, soda bottle', 744 | 738: 'pot, flowerpot', 745 | 739: "potter's wheel", 746 | 740: 'power drill', 747 | 741: 'prayer rug, prayer mat', 748 | 742: 'printer', 749 | 743: 'prison, prison house', 750 | 744: 'projectile, missile', 751 | 745: 'projector', 752 | 746: 'puck, hockey puck', 753 | 747: 'punching bag, punch bag, punching ball, punchball', 754 | 748: 'purse', 755 | 749: 'quill, quill pen', 756 | 750: 'quilt, comforter, comfort, puff', 757 | 751: 'racer, race car, racing car', 758 | 752: 'racket, racquet', 759 | 753: 'radiator', 760 | 754: 'radio, wireless', 761 | 755: 'radio telescope, radio reflector', 762 | 756: 'rain barrel', 763 | 757: 'recreational vehicle, RV, R.V.', 764 | 758: 'reel', 765 | 759: 'reflex camera', 766 | 760: 'refrigerator, icebox', 767 | 761: 'remote control, remote', 768 | 762: 'restaurant, eating house, eating place, eatery', 769 | 763: 'revolver, six-gun, six-shooter', 770 | 764: 'rifle', 771 | 765: 'rocking chair, rocker', 772 | 766: 'rotisserie', 773 | 767: 'rubber eraser, rubber, pencil eraser', 774 | 768: 'rugby ball', 775 | 769: 'rule, ruler', 776 | 770: 'running shoe', 777 | 771: 'safe', 778 | 772: 'safety pin', 779 | 773: 'saltshaker, salt shaker', 780 | 774: 'sandal', 781 | 775: 'sarong', 782 | 776: 'sax, saxophone', 783 | 777: 'scabbard', 784 | 778: 'scale, weighing machine', 785 | 779: 'school bus', 786 | 780: 'schooner', 787 | 781: 'scoreboard', 788 | 782: 'screen, CRT screen', 789 | 783: 'screw', 790 | 784: 'screwdriver', 791 | 785: 'seat belt, seatbelt', 792 | 786: 'sewing machine', 793 | 787: 'shield, buckler', 794 | 788: 'shoe shop, shoe-shop, shoe store', 795 | 789: 'shoji', 796 | 790: 'shopping basket', 797 | 791: 'shopping cart', 798 | 792: 'shovel', 799 | 793: 'shower cap', 800 | 794: 'shower curtain', 801 | 795: 'ski', 802 | 796: 'ski mask', 803 | 797: 'sleeping bag', 804 | 798: 'slide rule, slipstick', 805 | 799: 'sliding door', 806 | 800: 'slot, one-armed bandit', 807 | 801: 'snorkel', 808 | 802: 'snowmobile', 809 | 803: 'snowplow, snowplough', 810 | 804: 'soap dispenser', 811 | 805: 'soccer ball', 812 | 806: 'sock', 813 | 807: 'solar dish, solar collector, solar furnace', 814 | 808: 'sombrero', 815 | 809: 'soup bowl', 816 | 810: 'space bar', 817 | 811: 'space heater', 818 | 812: 'space shuttle', 819 | 813: 'spatula', 820 | 814: 'speedboat', 821 | 815: "spider web, spider's web", 822 | 816: 'spindle', 823 | 817: 'sports car, sport car', 824 | 818: 'spotlight, spot', 825 | 819: 'stage', 826 | 820: 'steam locomotive', 827 | 821: 'steel arch bridge', 828 | 822: 'steel drum', 829 | 823: 'stethoscope', 830 | 824: 'stole', 831 | 825: 'stone wall', 832 | 826: 'stopwatch, stop watch', 833 | 827: 'stove', 834 | 828: 'strainer', 835 | 829: 'streetcar, tram, tramcar, trolley, trolley car', 836 | 830: 'stretcher', 837 | 831: 'studio couch, day bed', 838 | 832: 'stupa, tope', 839 | 833: 'submarine, pigboat, sub, U-boat', 840 | 834: 'suit, suit of clothes', 841 | 835: 'sundial', 842 | 836: 'sunglass', 843 | 837: 'sunglasses, dark glasses, shades', 844 | 838: 'sunscreen, sunblock, sun blocker', 845 | 839: 'suspension bridge', 846 | 840: 'swab, swob, mop', 847 | 841: 'sweatshirt', 848 | 842: 'swimming trunks, bathing trunks', 849 | 843: 'swing', 850 | 844: 'switch, electric switch, electrical switch', 851 | 845: 'syringe', 852 | 846: 'table lamp', 853 | 847: 'tank, army tank, armored combat vehicle, armoured combat vehicle', 854 | 848: 'tape player', 855 | 849: 'teapot', 856 | 850: 'teddy, teddy bear', 857 | 851: 'television, television system', 858 | 852: 'tennis ball', 859 | 853: 'thatch, thatched roof', 860 | 854: 'theater curtain, theatre curtain', 861 | 855: 'thimble', 862 | 856: 'thresher, thrasher, threshing machine', 863 | 857: 'throne', 864 | 858: 'tile roof', 865 | 859: 'toaster', 866 | 860: 'tobacco shop, tobacconist shop, tobacconist', 867 | 861: 'toilet seat', 868 | 862: 'torch', 869 | 863: 'totem pole', 870 | 864: 'tow truck, tow car, wrecker', 871 | 865: 'toyshop', 872 | 866: 'tractor', 873 | 867: 'trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi', 874 | 868: 'tray', 875 | 869: 'trench coat', 876 | 870: 'tricycle, trike, velocipede', 877 | 871: 'trimaran', 878 | 872: 'tripod', 879 | 873: 'triumphal arch', 880 | 874: 'trolleybus, trolley coach, trackless trolley', 881 | 875: 'trombone', 882 | 876: 'tub, vat', 883 | 877: 'turnstile', 884 | 878: 'typewriter keyboard', 885 | 879: 'umbrella', 886 | 880: 'unicycle, monocycle', 887 | 881: 'upright, upright piano', 888 | 882: 'vacuum, vacuum cleaner', 889 | 883: 'vase', 890 | 884: 'vault', 891 | 885: 'velvet', 892 | 886: 'vending machine', 893 | 887: 'vestment', 894 | 888: 'viaduct', 895 | 889: 'violin, fiddle', 896 | 890: 'volleyball', 897 | 891: 'waffle iron', 898 | 892: 'wall clock', 899 | 893: 'wallet, billfold, notecase, pocketbook', 900 | 894: 'wardrobe, closet, press', 901 | 895: 'warplane, military plane', 902 | 896: 'washbasin, handbasin, washbowl, lavabo, wash-hand basin', 903 | 897: 'washer, automatic washer, washing machine', 904 | 898: 'water bottle', 905 | 899: 'water jug', 906 | 900: 'water tower', 907 | 901: 'whiskey jug', 908 | 902: 'whistle', 909 | 903: 'wig', 910 | 904: 'window screen', 911 | 905: 'window shade', 912 | 906: 'Windsor tie', 913 | 907: 'wine bottle', 914 | 908: 'wing', 915 | 909: 'wok', 916 | 910: 'wooden spoon', 917 | 911: 'wool, woolen, woollen', 918 | 912: 'worm fence, snake fence, snake-rail fence, Virginia fence', 919 | 913: 'wreck', 920 | 914: 'yawl', 921 | 915: 'yurt', 922 | 916: 'web site, website, internet site, site', 923 | 917: 'comic book', 924 | 918: 'crossword puzzle, crossword', 925 | 919: 'street sign', 926 | 920: 'traffic light, traffic signal, stoplight', 927 | 921: 'book jacket, dust cover, dust jacket, dust wrapper', 928 | 922: 'menu', 929 | 923: 'plate', 930 | 924: 'guacamole', 931 | 925: 'consomme', 932 | 926: 'hot pot, hotpot', 933 | 927: 'trifle', 934 | 928: 'ice cream, icecream', 935 | 929: 'ice lolly, lolly, lollipop, popsicle', 936 | 930: 'French loaf', 937 | 931: 'bagel, beigel', 938 | 932: 'pretzel', 939 | 933: 'cheeseburger', 940 | 934: 'hotdog, hot dog, red hot', 941 | 935: 'mashed potato', 942 | 936: 'head cabbage', 943 | 937: 'broccoli', 944 | 938: 'cauliflower', 945 | 939: 'zucchini, courgette', 946 | 940: 'spaghetti squash', 947 | 941: 'acorn squash', 948 | 942: 'butternut squash', 949 | 943: 'cucumber, cuke', 950 | 944: 'artichoke, globe artichoke', 951 | 945: 'bell pepper', 952 | 946: 'cardoon', 953 | 947: 'mushroom', 954 | 948: 'Granny Smith', 955 | 949: 'strawberry', 956 | 950: 'orange', 957 | 951: 'lemon', 958 | 952: 'fig', 959 | 953: 'pineapple, ananas', 960 | 954: 'banana', 961 | 955: 'jackfruit, jak, jack', 962 | 956: 'custard apple', 963 | 957: 'pomegranate', 964 | 958: 'hay', 965 | 959: 'carbonara', 966 | 960: 'chocolate sauce, chocolate syrup', 967 | 961: 'dough', 968 | 962: 'meat loaf, meatloaf', 969 | 963: 'pizza, pizza pie', 970 | 964: 'potpie', 971 | 965: 'burrito', 972 | 966: 'red wine', 973 | 967: 'espresso', 974 | 968: 'cup', 975 | 969: 'eggnog', 976 | 970: 'alp', 977 | 971: 'bubble', 978 | 972: 'cliff, drop, drop-off', 979 | 973: 'coral reef', 980 | 974: 'geyser', 981 | 975: 'lakeside, lakeshore', 982 | 976: 'promontory, headland, head, foreland', 983 | 977: 'sandbar, sand bar', 984 | 978: 'seashore, coast, seacoast, sea-coast', 985 | 979: 'valley, vale', 986 | 980: 'volcano', 987 | 981: 'ballplayer, baseball player', 988 | 982: 'groom, bridegroom', 989 | 983: 'scuba diver', 990 | 984: 'rapeseed', 991 | 985: 'daisy', 992 | 986: "yellow lady's slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum", 993 | 987: 'corn', 994 | 988: 'acorn', 995 | 989: 'hip, rose hip, rosehip', 996 | 990: 'buckeye, horse chestnut, conker', 997 | 991: 'coral fungus', 998 | 992: 'agaric', 999 | 993: 'gyromitra', 1000 | 994: 'stinkhorn, carrion fungus', 1001 | 995: 'earthstar', 1002 | 996: 'hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa', 1003 | 997: 'bolete', 1004 | 998: 'ear, spike, capitulum', 1005 | 999: 'toilet tissue, toilet paper, bathroom tissue'} -------------------------------------------------------------------------------- /images/P1013781.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Britefury/deep-learning-tutorial-pydata/b2d7e32ef8479b22433aac0baeb85cc98676198c/images/P1013781.JPG -------------------------------------------------------------------------------- /images/P8131065.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Britefury/deep-learning-tutorial-pydata/b2d7e32ef8479b22433aac0baeb85cc98676198c/images/P8131065.JPG -------------------------------------------------------------------------------- /images/fruit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Britefury/deep-learning-tutorial-pydata/b2d7e32ef8479b22433aac0baeb85cc98676198c/images/fruit.jpg -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | matplotlib 3 | scikit-image 4 | -e git+https://github.com/Theano/Theano#egg=Theano 5 | -e git+https://github.com/Britefury/Lasagne#egg=Lasagne 6 | -e git+https://github.com/mila-udem/fuel.git#egg=fuel 7 | 8 | 9 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import skimage.util 3 | 4 | 5 | def prepare_image(im, image_mean, image_std, image_size=224): 6 | """ 7 | Prepare an image for classification with VGG; scale and crop to `image_size` x `image_size`. 8 | Convert RGB channel order to BGR. 9 | Subtract mean value. 10 | 11 | :param im: input RGB image as numpy array (height, width, channel) 12 | :param image_size: output image size, default=224. If `None`, scaling and cropping will not be done. 13 | :return: (raw_image, vgg_image) where `raw_image` is the scaled and cropped image with dtype=uint8 and 14 | `vgg_image` is the image with BGR channel order and axes (sample, channel, height, width). 15 | """ 16 | # If the image is greyscale, convert it to RGB 17 | if len(im.shape) == 2: 18 | im = im[:, :, np.newaxis] 19 | im = np.repeat(im, 3, axis=2) 20 | 21 | # Convert to float type 22 | im = skimage.util.img_as_float(im) 23 | 24 | if image_size is not None: 25 | # Scale the image so that its smallest dimension is the desired size 26 | h, w, _ = im.shape 27 | if h < w: 28 | if h != image_size: 29 | im = skimage.transform.resize(im, (image_size, w * image_size / h), preserve_range=True) 30 | else: 31 | if w != image_size: 32 | im = skimage.transform.resize(im, (h * image_size / w, image_size), preserve_range=True) 33 | 34 | # Crop the central `image_size` x `image_size` region of the image 35 | h, w, _ = im.shape 36 | im = im[h // 2 - image_size // 2:h // 2 + image_size // 2, w // 2 - image_size // 2:w // 2 + image_size // 2] 37 | 38 | rawim = im.copy() 39 | 40 | # Shuffle axes from (height, width, channel) to (channel, height, width) 41 | im = np.swapaxes(np.swapaxes(im, 1, 2), 0, 1) 42 | 43 | # Subtract the mean and divide by the std-dev 44 | # Note that we add two axes to the mean and std-dev for height and width so that they broadcast with the image array 45 | im = (im - image_mean[:, None, None]) / image_std[:, None, None] 46 | 47 | # Add the sample axis to the image; (channel, height, width) -> (sample, channel, height, width) 48 | im = im[None, ...] 49 | 50 | return rawim, im.astype(np.float32) 51 | 52 | 53 | def inv_prepare_image(image, image_mean, image_std): 54 | """ 55 | Perform the inverse of `prepare_image`; usually used to display an image prepared for classification 56 | using a VGG net. 57 | 58 | :param im: the image to process 59 | :return: processed image 60 | """ 61 | if len(image.shape) == 4: 62 | # We have a sample dimension; can collapse it if there is only 1 sample 63 | if image.shape[0] == 1: 64 | image = image[0] 65 | else: 66 | raise ValueError('Sample dimension has > 1 samples ({})'.format(image.shape[0])) 67 | 68 | # Move the channel axis: (C, H, W) -> (H, W, C) 69 | image = image.transpose(1, 2, 0) 70 | # Add the mean 71 | image = image * image_std + image_mean 72 | # Clip to [0,1] range 73 | image = image.clip(0.0, 1.0) 74 | # Convert to uint8 type 75 | image = skimage.util.img_as_ubyte(image) 76 | return image 77 | --------------------------------------------------------------------------------