From 82c09d4663518121449dbaeba52c99b064723162 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 21 Jan 2013 19:29:19 -0500 Subject: [PATCH 01/11] html init --- README.md | 27 -- index.html | 1 + ipynb/Theano Logistic Regression.ipynb | 101 ----- ...ano Tutorial (Part 1 - Introduction).ipynb | 166 -------- ...torial (Part 2 - Simple Computation).ipynb | 370 ------------------ start_ipython_server.sh | 2 - 6 files changed, 1 insertion(+), 666 deletions(-) delete mode 100644 README.md create mode 100644 index.html delete mode 100644 ipynb/Theano Logistic Regression.ipynb delete mode 100644 ipynb/Theano Tutorial (Part 1 - Introduction).ipynb delete mode 100644 ipynb/Theano Tutorial (Part 2 - Simple Computation).ipynb delete mode 100755 start_ipython_server.sh diff --git a/README.md b/README.md deleted file mode 100644 index 1f8c5c8..0000000 --- a/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# IPython Theano Tutorials - -A collection of tutorials in ipynb format that illustrate how to do various -things in Theano. - -# General - -* Theano Basics -* Adding a custom Op to Theano -* Numpy/Python function minimization using pyautodiff - - -## Machine Learning: - -### Supervised Algorithms -* Logistic Regression -* Multilayer Perceptron (MLP) -* Convolutional Network (Convnet) -* Deep Belief Network (DBN) - -### Unsupervised Algorithms - -* Restricted Boltzmann Machine (RBM) -* Autoassociator / Autoencoder (AA) -* Stochasitc Denoising auto associator (SDAA) -* Sparse coding - diff --git a/index.html b/index.html new file mode 100644 index 0000000..03f9801 --- /dev/null +++ b/index.html @@ -0,0 +1 @@ +My GitHub Page diff --git a/ipynb/Theano Logistic Regression.ipynb b/ipynb/Theano Logistic Regression.ipynb deleted file mode 100644 index c2419c2..0000000 --- a/ipynb/Theano Logistic Regression.ipynb +++ /dev/null @@ -1,101 +0,0 @@ -{ - "metadata": { - "name": "Theano Logistic Regression" - }, - "nbformat": 2, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# Initial imports", - "import numpy as np", - "import theano.tensor as T", - "from theano import shared, function", - "rng = np.random.RandomState(123)", - "" - ], - "language": "python", - "outputs": [], - "prompt_number": 4 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# Create a sample logistic regression problem.", - "true_w = rng.randn(100)", - "true_b = rng.randn()", - "xdata = rng.randn(50, 100)", - "ydata = (np.dot(xdata, true_w) + true_b) > 0.0" - ], - "language": "python", - "outputs": [], - "prompt_number": 5 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# Step 1. Declare Theano variables", - "x = T.dmatrix()", - "y = T.dvector()", - "w = shared(rng.randn(100))", - "b = shared(numpy.zeros(()))", - "print \"Initial model\"", - "print w.get_value()", - "print b.get_value()", - "" - ], - "language": "python", - "outputs": [], - "prompt_number": 10 - }, - { - "cell_type": "code", - "collapsed": true, - "input": [ - "# Step 2. Construct Theano expression graph", - "p_1 = 1 / (1 + T.exp(-T.dot(x, w) - b))", - "xent = -y * T.log(p_1) - (1 - y) * T.log(1 - p_1)", - "prediction = p_1 > 0.5", - "cost = xent.mean() + 0.01 * (w ** 2).sum()", - "gw, gb = T.grad(cost, [w, b])" - ], - "language": "python", - "outputs": [], - "prompt_number": 11 - }, - { - "cell_type": "code", - "collapsed": true, - "input": [ - "# Step 3. Compile expressions to functions", - "train = function(inputs=[x, y],", - " outputs=[prediction, xent],", - " updates={w:w - 0.1 * gw,", - " b:b - 0.1 * gb})" - ], - "language": "python", - "outputs": [], - "prompt_number": 12 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# Step 4. Perform computation", - "for loop in range(100):", - " pval, xval = train(xdata, ydata)", - " print xval.mean()" - ], - "language": "python", - "outputs": [], - "prompt_number": 16 - } - ] - } - ] -} \ No newline at end of file diff --git a/ipynb/Theano Tutorial (Part 1 - Introduction).ipynb b/ipynb/Theano Tutorial (Part 1 - Introduction).ipynb deleted file mode 100644 index 959dc3a..0000000 --- a/ipynb/Theano Tutorial (Part 1 - Introduction).ipynb +++ /dev/null @@ -1,166 +0,0 @@ -{ - "metadata": { - "name": "Theano Tutorial (Part 1 - Introduction)" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Theano Tutorial (Part 1 - Introduction)\n", - "\n", - "Theano is a Python module, so you can import it like this:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import theano" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Several of the symbols you will need to use are in the `tensor` subpackage of Theano. Let's import that subpackage under a handy name like `T` (the tutorials will frequently use this convention)." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "from theano import tensor as T" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If that succeeded you are ready for the tutorial, otherwise check your installation (see Installing Theano).\n", - "\n", - "Throughout the tutorial, bear in mind that there is a Glossary(XXX) as well as index(XXX) and modules(XXX) links in the upper-right corner of each page to help you out." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## NumPy Background\n", - "\n", - "Here are some quick guides to NumPy:\n", - "\n", - "* Numpy quick guide for Matlab users\n", - "\n", - "* Numpy User Guide\n", - "\n", - "* More detailed Numpy tutorial " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Matrix conventions for machine learning\n", - "\n", - "Rows are horizontal and columns are vertical.\n", - "Every row is an example. Therefore, inputs[10,5] is a matrix of 10 examples \n", - "where each example has dimension 5. If this would be the input of a\n", - "neural network then the weights from the input to the first hidden\n", - "layer would represent a matrix of size (5, #hid). \n", - "\n", - "Consider this array:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a = np.asarray([[1., 2], [3, 4], [5, 6]])\n", - "print a\n", - "print a.shape" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is a 3x2 matrix, i.e. there are 3 rows and 2 columns.\n", - "\n", - "To access the entry in the 3rd row (row #2) and the 1st column (column #0):" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print a[2, 0]" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To remember this, keep in mind that we read left-to-right, top-to-bottom,\n", - "so each thing that is contiguous is a row. That is, there are 3 rows\n", - "and 2 columns." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "###Broadcasting\n", - "\n", - "Numpy does *broadcasting* of arrays of different shapes during\n", - "arithmetic operations. What this means in general is that the smaller \n", - "array (or scalar) is *broadcasted* across the larger array so that they have\n", - "compatible shapes. The example below shows an instance of\n", - "*broadcastaing*:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a = numpy.asarray([1.0, 2.0, 3.0])\n", - "b = 2.0\n", - "print a * b" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The smaller array ``b`` (actually a scalar here, which works like a 0-d array) in this case is *broadcasted* to the same size\n", - "as ``a`` during the multiplication. This trick is often useful in\n", - "simplifying how expression are written. More detail about *broadcasting*\n", - "can be found in the numpy user guide." - ] - } - ], - "metadata": {} - } - ] -} \ No newline at end of file diff --git a/ipynb/Theano Tutorial (Part 2 - Simple Computation).ipynb b/ipynb/Theano Tutorial (Part 2 - Simple Computation).ipynb deleted file mode 100644 index 84107cc..0000000 --- a/ipynb/Theano Tutorial (Part 2 - Simple Computation).ipynb +++ /dev/null @@ -1,370 +0,0 @@ -{ - "metadata": { - "name": "Theano Tutorial (Part 2 - Simple Computation)" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Theano Tutorial (Part 2 - Simple Computation)\n", - "\n", - "In this first Theano tutorial we'll see how to do a simple calculation involving scalars and matrices." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding two Scalars\n", - "\n", - "To get us started with Theano and get a feel of what we're working with, \n", - "let's make a simple function: add two numbers together. Here is how you do\n", - "it:\n" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import theano.tensor as T\n", - "from theano import function\n", - "x = T.dscalar('x')\n", - "y = T.dscalar('y')\n", - "z = x + y\n", - "f = function([x, y], z)" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And now that we've created our function we can use it:\n" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f(2, 3)\n", - "f(16.3, 12.1)" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's break this down into several steps. The first step is to define\n", - "two symbols (*Variables*) representing the quantities that you want\n", - "to add. Note that from now on, we will use the term \n", - "*Variable* to mean \"symbol\" (in other words, \n", - "*x*, *y*, *z* are all *Variable* objects). The output of the function \n", - "*f* is a ``numpy.ndarray`` with zero dimensions.\n", - "\n", - "If you are following along and typing into an interpreter, you may have\n", - "noticed that there was a slight delay in executing the ``function``\n", - "instruction. Behind the scene, *f* was being compiled into C code.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### note:\n", - "\n", - "A *Variable* is the main data structure you work with when\n", - "using Theano. The symbolic inputs that you operate on are\n", - "*Variables* and what you get from applying various operations to\n", - "these inputs are also *Variables*. For example, when I type\n", - "\"`x = theano.tensor.ivector(); y = -x`\" then *x* and *y* are both Variables, i.e. instances of the\n", - "``theano.gof.graph.Variable`` class. The\n", - "type of both *x* and *y* is ``theano.tensor.ivector``.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Step 1" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "x = T.dscalar('x')\n", - "y = T.dscalar('y')" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In Theano, all symbols must be typed. In particular, ``T.dscalar``\n", - "is the type we assign to \"0-dimensional arrays (`scalar`) of doubles\n", - "(`d`)\". It is a Theano :ref:`type`.\n", - "\n", - "``dscalar`` is not a class. Therefore, neither *x* nor *y*\n", - "are actually instances of ``dscalar``. They are instances of\n", - ":class:`TensorVariable`. *x* and *y*\n", - "are, however, assigned the theano Type ``dscalar`` in their ``type``\n", - "field, as you can see here:\n" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "type(x)\n", - "x.type\n", - "T.dscalar\n", - "x.type is T.dscalar" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "By calling ``T.dscalar`` with a string argument, you create a\n", - "*Variable* representing a floating-point scalar quantity with the\n", - "given name. If you provide no argument, the symbol will be unnamed. Names\n", - "are not required, but they can help debugging.\n", - "\n", - "More will be said in a moment regarding Theano's inner structure. You\n", - "could also learn more by looking into :ref:`graphstructures`.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Step 2\n", - "The second step is to combine *x* and *y* into their sum *z*:\n", - "\n" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "z = x + y" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*z* is yet another *Variable* which represents the addition of\n", - "*x* and *y*. You can use the :ref:`pp `\n", - "function to pretty-print out the computation associated to *z*.\n" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print pp(z)\n", - "(x + y)" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Step 3\n", - "\n", - "The last step is to create a function taking *x* and *y* as inputs\n", - "and giving *z* as output:\n" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = function([x, y], z)" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The first argument to `function()` is a list of Variables\n", - "that will be provided as inputs to the function. The second argument\n", - "is a single Variable *or* a list of Variables. For either case, the second\n", - "argument is what we want to see as output when we apply the function. *f* may\n", - "then be used like a normal Python function.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Note on `eval`\n", - "\n", - "As a shortcut, you can skip step 3, and just use a variable's\n", - "`eval()` method. The `eval()` method is not as flexible\n", - "as `function()` but it can do everything we've covered in\n", - "the tutorial so far. It has the added benefit of not requiring\n", - "you to import `function()`. Here is how `eval()` works:\n", - "\n", - " import theano.tensor as T\n", - " x = T.dscalar('x')\n", - " y = T.dscalar('y')\n", - " z = x + y\n", - " z.eval({x : 16.3, y : 12.1})\n", - " array(28.4)\n", - "\n", - "We passed :func:`eval` a dictionary mapping symbolic theano\n", - "variables to the values to substitute for them, and it returned\n", - "the numerical value of the expression. `eval()` will be slower the first time you call it on a variable --\n", - "it needs to call `function()` to compile the expression behind\n", - "the scenes. Subsequent calls to `eval()` on that same variable\n", - "will be fast, because the variable caches the compiled function.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding two Matrices\n", - "\n", - "You might already have guessed how to do this. Indeed, the only change\n", - "from the previous example is that you need to instantiate *x* and\n", - "*y* using the matrix Types:\n" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "x = T.dmatrix('x')\n", - "y = T.dmatrix('y')\n", - "z = x + y\n", - "f = function([x, y], z)" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "``dmatrix`` is the Type for matrices of doubles. Then we can use\n", - "our new function on 2D arrays:\n" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f([[1, 2], [3, 4]], [[10, 20], [30, 40]])" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The variable is a NumPy array. We can also use NumPy arrays directly as\n", - "inputs:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import numpy\n", - "f(numpy.array([[1, 2], [3, 4]]), numpy.array([[10, 20], [30, 40]]))" - ], - "language": "python", - "metadata": {}, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It is possible to add scalars to matrices, vectors to matrices,\n", - "scalars to vectors, etc. The behavior of these operations is defined\n", - "by :ref:`broadcasting `.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following types are available:\n", - "\n", - "* **byte**: ``bscalar, bvector, bmatrix, brow, bcol, btensor3, btensor4``\n", - "* **16-bit integers**: ``wscalar, wvector, wmatrix, wrow, wcol, wtensor3, wtensor4``\n", - "* **32-bit integers**: ``iscalar, ivector, imatrix, irow, icol, itensor3, itensor4``\n", - "* **64-bit integers**: ``lscalar, lvector, lmatrix, lrow, lcol, ltensor3, ltensor4``\n", - "* **float**: ``fscalar, fvector, fmatrix, frow, fcol, ftensor3, ftensor4``\n", - "* **double**: ``dscalar, dvector, dmatrix, drow, dcol, dtensor3, dtensor4``\n", - "* **complex**: ``cscalar, cvector, cmatrix, crow, ccol, ctensor3, ctensor4``\n", - "\n", - "The previous list is not exhaustive and a guide to all types compatible\n", - "with NumPy arrays may be found here: :ref:`tensor creation`.\n", - "\n", - "\n", - "Note that you, the user---not the system architecture---have to choose whether your\n", - " program will use 32- or 64-bit integers (``i`` prefix vs. the ``l`` prefix)\n", - " and floats (``f`` prefix vs. the ``d`` prefix)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Exercise\n", - "\n", - "Modify and execute the following code to compute the expression: $a^2 + b^2 + 2 a b$." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import theano\n", - "a = theano.tensor.vector() # declare variable\n", - "out = a + a ** 10 # build symbolic expression\n", - "f = theano.function([a], out) # compile function\n", - "print f([0, 1, 2]) # prints `array([0, 2, 1026])`" - ], - "language": "python", - "metadata": {}, - "outputs": [] - } - ], - "metadata": {} - } - ] -} \ No newline at end of file diff --git a/start_ipython_server.sh b/start_ipython_server.sh deleted file mode 100755 index eb60a37..0000000 --- a/start_ipython_server.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -cd ipynb && ipython notebook From 4f3466691deb5b78de1ec47de456c3d111f4d3a8 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 21 Jan 2013 16:42:19 -0800 Subject: [PATCH 02/11] Create gh-pages branch via GitHub --- images/arrow-down.png | Bin 0 -> 423 bytes images/octocat-small.png | Bin 0 -> 570 bytes index.html | 91 +++++++- javascripts/scale.fix.js | 20 ++ params.json | 1 + stylesheets/pygment_trac.css | 69 ++++++ stylesheets/styles.css | 413 +++++++++++++++++++++++++++++++++++ 7 files changed, 593 insertions(+), 1 deletion(-) create mode 100644 images/arrow-down.png create mode 100644 images/octocat-small.png create mode 100644 javascripts/scale.fix.js create mode 100644 params.json create mode 100644 stylesheets/pygment_trac.css create mode 100644 stylesheets/styles.css diff --git a/images/arrow-down.png b/images/arrow-down.png new file mode 100644 index 0000000000000000000000000000000000000000..585b0bddba878b95acc961fc5c0c55c3ea2e75db GIT binary patch literal 423 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eW!3HFke0{SLNU;<^miKrK zR4D>d>0FeWSdy8arx22vo62CJZ=!E#Q zuUEhHFKq}eVcf!fOXk2252o^`A0Pfx?pl-`?tS^o=dZa}n)o-rOj#-_e`l7jy7u+r zhj0Hd|L1+)z+f_A|GJISy4qrPpME*#k;S{#M4)d)HS2xXctpM~nN-ejV$=G%1)}zh z6_&;B=NTB*Rz&o)EN^QNw)=Nauj9or^J@~D*Th}TXM8@bL&NZxPHmc!SKl9%dr^gl zqh@m|zG6sNdzVY`kauM4^m$&|dG9N?-~61nSXA6TxH5R=Pxc4Kow9qMI-LOq1%s!n KpUXO@geCw=gQOS$ literal 0 HcmV?d00001 diff --git a/images/octocat-small.png b/images/octocat-small.png new file mode 100644 index 0000000000000000000000000000000000000000..66c25398dd9090905e37aa2d48bb2d77a0ac6255 GIT binary patch literal 570 zcmV-A0>%A_P)V>IRB3Hx05~r+FEKJgdgKHE00ELo zL_t(Ijg^xed`v89bwq|>- zBcAI>wNjQ~{V)H%tlWtR3ZPgl_WI*s7zQut?CiWv)3hNC$Q&OX?xs?y7lFshPE4M* zWwYbCv9ZzqmMOqA&6xTyFpvlX0a(^MlwlaPupofy>3N$E3)SoOTg`Kw1aKY(ER{+J z8i40IIbbma`(6R7dL#-k0u){W3czrO-f82x&g$~grz@IyWqNvQc6)p4Nm@33tb3m8 zqya>Phsa&m{#?w>&fMT<@_Edvm9hja12DK_rqO6@Dy6#qH=`bjY5@o|v#Lj;wod}b>JrdoE#olbS0=7RdB$LTJ@R`4#*!KNI_tZAjO+JC<^Z)<=07*qo IM6N<$f|}m$2LJ#7 literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 03f9801..652ea52 100644 --- a/index.html +++ b/index.html @@ -1 +1,90 @@ -My GitHub Page + + + + + + IPython Theano Tutorials by jaberg + + + + + + + + +
+
+

IPython Theano Tutorials

+

(test pages for)

+ + + +

This project is maintained by jaberg

+ + +
+
+

IPython Theano Tutorials

+ +

A collection of tutorials in ipynb format that illustrate how to do various +things in Theano.

+ +

Installation

+ +

Requirements:

+ +
    +
  • numpy
  • +
  • scipy
  • +
  • matplotlib
  • +
  • IPython (>= 0.13)
  • +
  • theano
  • +
  • skdata (provides data sets for machine learning notebooks)
  • +
  • pyautodiff (required for some notebooks)
  • +

Instructions:

+ +

Download and unpack this project, and start up an ipython notebook to browse +through the tutorials.

+ +

git clone https://github.com/jaberg/IPythonTheanoTutorials.git + cd IPythonTheanoTutorials + sh start_ipython_server.sh

+ +

General

+ +
    +
  • Theano Basics
  • +
  • Adding a custom Op to Theano
  • +
  • Numpy/Python function minimization using pyautodiff
  • +

Machine Learning:

+ +

Supervised Algorithms

+ +
    +
  • Logistic Regression
  • +
  • Multilayer Perceptron (MLP)
  • +
  • Convolutional Network (Convnet)
  • +
  • Deep Belief Network (DBN)
  • +

Unsupervised Algorithms

+ +
    +
  • Restricted Boltzmann Machine (RBM)
  • +
  • Autoassociator / Autoencoder (AA)
  • +
  • Stochasitc Denoising auto associator (SDAA)
  • +
  • Sparse coding
  • +
+
+ +
+ + + + \ No newline at end of file diff --git a/javascripts/scale.fix.js b/javascripts/scale.fix.js new file mode 100644 index 0000000..08716c0 --- /dev/null +++ b/javascripts/scale.fix.js @@ -0,0 +1,20 @@ +fixScale = function(doc) { + + var addEvent = 'addEventListener', + type = 'gesturestart', + qsa = 'querySelectorAll', + scales = [1, 1], + meta = qsa in doc ? doc[qsa]('meta[name=viewport]') : []; + + function fix() { + meta.content = 'width=device-width,minimum-scale=' + scales[0] + ',maximum-scale=' + scales[1]; + doc.removeEventListener(type, fix, true); + } + + if ((meta = meta[meta.length - 1]) && addEvent in doc) { + fix(); + scales = [.25, 1.6]; + doc[addEvent](type, fix, true); + } + +}; \ No newline at end of file diff --git a/params.json b/params.json new file mode 100644 index 0000000..5a4cf79 --- /dev/null +++ b/params.json @@ -0,0 +1 @@ +{"name":"IPython Theano Tutorials","body":"# IPython Theano Tutorials\r\n\r\nA collection of tutorials in ipynb format that illustrate how to do various\r\nthings in Theano.\r\n\r\n# Installation\r\n\r\n### Requirements:\r\n* numpy\r\n* scipy\r\n* matplotlib\r\n* IPython (>= 0.13)\r\n* theano\r\n* skdata (provides data sets for machine learning notebooks)\r\n* pyautodiff (required for some notebooks)\r\n\r\n### Instructions:\r\n\r\nDownload and unpack this project, and start up an ipython notebook to browse\r\nthrough the tutorials.\r\n\r\n git clone https://github.com/jaberg/IPythonTheanoTutorials.git\r\n cd IPythonTheanoTutorials\r\n sh start_ipython_server.sh\r\n\r\n\r\n# General\r\n\r\n* Theano Basics\r\n* Adding a custom Op to Theano\r\n* Numpy/Python function minimization using pyautodiff\r\n\r\n\r\n## Machine Learning:\r\n\r\n### Supervised Algorithms\r\n* Logistic Regression\r\n* Multilayer Perceptron (MLP)\r\n* Convolutional Network (Convnet)\r\n* Deep Belief Network (DBN)\r\n\r\n### Unsupervised Algorithms\r\n\r\n* Restricted Boltzmann Machine (RBM)\r\n* Autoassociator / Autoencoder (AA)\r\n* Stochasitc Denoising auto associator (SDAA)\r\n* Sparse coding\r\n\r\n","tagline":"(test pages for)","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file diff --git a/stylesheets/pygment_trac.css b/stylesheets/pygment_trac.css new file mode 100644 index 0000000..c6a6452 --- /dev/null +++ b/stylesheets/pygment_trac.css @@ -0,0 +1,69 @@ +.highlight { background: #ffffff; } +.highlight .c { color: #999988; font-style: italic } /* Comment */ +.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.highlight .k { font-weight: bold } /* Keyword */ +.highlight .o { font-weight: bold } /* Operator */ +.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ +.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ +.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #aa0000 } /* Generic.Error */ +.highlight .gh { color: #999999 } /* Generic.Heading */ +.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ +.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #555555 } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold; } /* Generic.Subheading */ +.highlight .gt { color: #aa0000 } /* Generic.Traceback */ +.highlight .kc { font-weight: bold } /* Keyword.Constant */ +.highlight .kd { font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { font-weight: bold } /* Keyword.Pseudo */ +.highlight .kr { font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */ +.highlight .m { color: #009999 } /* Literal.Number */ +.highlight .s { color: #d14 } /* Literal.String */ +.highlight .na { color: #008080 } /* Name.Attribute */ +.highlight .nb { color: #0086B3 } /* Name.Builtin */ +.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */ +.highlight .no { color: #008080 } /* Name.Constant */ +.highlight .ni { color: #800080 } /* Name.Entity */ +.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */ +.highlight .nn { color: #555555 } /* Name.Namespace */ +.highlight .nt { color: #000080 } /* Name.Tag */ +.highlight .nv { color: #008080 } /* Name.Variable */ +.highlight .ow { font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #009999 } /* Literal.Number.Float */ +.highlight .mh { color: #009999 } /* Literal.Number.Hex */ +.highlight .mi { color: #009999 } /* Literal.Number.Integer */ +.highlight .mo { color: #009999 } /* Literal.Number.Oct */ +.highlight .sb { color: #d14 } /* Literal.String.Backtick */ +.highlight .sc { color: #d14 } /* Literal.String.Char */ +.highlight .sd { color: #d14 } /* Literal.String.Doc */ +.highlight .s2 { color: #d14 } /* Literal.String.Double */ +.highlight .se { color: #d14 } /* Literal.String.Escape */ +.highlight .sh { color: #d14 } /* Literal.String.Heredoc */ +.highlight .si { color: #d14 } /* Literal.String.Interpol */ +.highlight .sx { color: #d14 } /* Literal.String.Other */ +.highlight .sr { color: #009926 } /* Literal.String.Regex */ +.highlight .s1 { color: #d14 } /* Literal.String.Single */ +.highlight .ss { color: #990073 } /* Literal.String.Symbol */ +.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #008080 } /* Name.Variable.Class */ +.highlight .vg { color: #008080 } /* Name.Variable.Global */ +.highlight .vi { color: #008080 } /* Name.Variable.Instance */ +.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */ + +.type-csharp .highlight .k { color: #0000FF } +.type-csharp .highlight .kt { color: #0000FF } +.type-csharp .highlight .nf { color: #000000; font-weight: normal } +.type-csharp .highlight .nc { color: #2B91AF } +.type-csharp .highlight .nn { color: #000000 } +.type-csharp .highlight .s { color: #A31515 } +.type-csharp .highlight .sc { color: #A31515 } diff --git a/stylesheets/styles.css b/stylesheets/styles.css new file mode 100644 index 0000000..f14d9e4 --- /dev/null +++ b/stylesheets/styles.css @@ -0,0 +1,413 @@ +@import url(https://fonts.googleapis.com/css?family=Arvo:400,700,400italic); + +/* MeyerWeb Reset */ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; +} + + +/* Base text styles */ + +body { + padding:10px 50px 0 0; + font-family:"Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + color: #232323; + background-color: #FBFAF7; + margin: 0; + line-height: 1.8em; + -webkit-font-smoothing: antialiased; + +} + +h1, h2, h3, h4, h5, h6 { + color:#232323; + margin:36px 0 10px; +} + +p, ul, ol, table, dl { + margin:0 0 22px; +} + +h1, h2, h3 { + font-family: Arvo, Monaco, serif; + line-height:1.3; + font-weight: normal; +} + +h1,h2, h3 { + display: block; + border-bottom: 1px solid #ccc; + padding-bottom: 5px; +} + +h1 { + font-size: 30px; +} + +h2 { + font-size: 24px; +} + +h3 { + font-size: 18px; +} + +h4, h5, h6 { + font-family: Arvo, Monaco, serif; + font-weight: 700; +} + +a { + color:#C30000; + font-weight:200; + text-decoration:none; +} + +a:hover { + text-decoration: underline; +} + +a small { + font-size: 12px; +} + +em { + font-style: italic; +} + +strong { + font-weight:700; +} + +ul li { + list-style: inside; + padding-left: 25px; +} + +ol li { + list-style: decimal inside; + padding-left: 20px; +} + +blockquote { + margin: 0; + padding: 0 0 0 20px; + font-style: italic; +} + +dl, dt, dd, dl p { + font-color: #444; +} + +dl dt { + font-weight: bold; +} + +dl dd { + padding-left: 20px; + font-style: italic; +} + +dl p { + padding-left: 20px; + font-style: italic; +} + +hr { + border:0; + background:#ccc; + height:1px; + margin:0 0 24px; +} + +/* Images */ + +img { + position: relative; + margin: 0 auto; + max-width: 650px; + padding: 5px; + margin: 10px 0 32px 0; + border: 1px solid #ccc; +} + + +/* Code blocks */ + +code, pre { + font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; + color:#000; + font-size:14px; +} + +pre { + padding: 4px 12px; + background: #FDFEFB; + border-radius:4px; + border:1px solid #D7D8C8; + overflow: auto; + overflow-y: hidden; + margin-bottom: 32px; +} + + +/* Tables */ + +table { + width:100%; +} + +table { + border: 1px solid #ccc; + margin-bottom: 32px; + text-align: left; + } + +th { + font-family: 'Arvo', Helvetica, Arial, sans-serif; + font-size: 18px; + font-weight: normal; + padding: 10px; + background: #232323; + color: #FDFEFB; + } + +td { + padding: 10px; + background: #ccc; + } + + +/* Wrapper */ +.wrapper { + width:960px; +} + + +/* Header */ + +header { + background-color: #171717; + color: #FDFDFB; + width:170px; + float:left; + position:fixed; + border: 1px solid #000; + -webkit-border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + padding: 34px 25px 22px 50px; + margin: 30px 25px 0 0; + -webkit-font-smoothing: antialiased; +} + +p.header { + font-size: 16px; +} + +h1.header { + font-family: Arvo, sans-serif; + font-size: 30px; + font-weight: 300; + line-height: 1.3em; + border-bottom: none; + margin-top: 0; +} + + +h1.header, a.header, a.name, header a{ + color: #fff; +} + +a.header { + text-decoration: underline; +} + +a.name { + white-space: nowrap; +} + +header ul { + list-style:none; + padding:0; +} + +header li { + list-style-type: none; + width:132px; + height:15px; + margin-bottom: 12px; + line-height: 1em; + padding: 6px 6px 6px 7px; + + background: #AF0011; + background: -moz-linear-gradient(top, #AF0011 0%, #820011 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd)); + background: -webkit-linear-gradient(top, #AF0011 0%,#820011 100%); + background: -o-linear-gradient(top, #AF0011 0%,#820011 100%); + background: -ms-linear-gradient(top, #AF0011 0%,#820011 100%); + background: linear-gradient(top, #AF0011 0%,#820011 100%); + + border-radius:4px; + border:1px solid #0D0D0D; + + -webkit-box-shadow: inset 0px 1px 1px 0 rgba(233,2,38, 1); + box-shadow: inset 0px 1px 1px 0 rgba(233,2,38, 1); + +} + +header li:hover { + background: #C3001D; + background: -moz-linear-gradient(top, #C3001D 0%, #950119 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd)); + background: -webkit-linear-gradient(top, #C3001D 0%,#950119 100%); + background: -o-linear-gradient(top, #C3001D 0%,#950119 100%); + background: -ms-linear-gradient(top, #C3001D 0%,#950119 100%); + background: linear-gradient(top, #C3001D 0%,#950119 100%); +} + +a.buttons { + -webkit-font-smoothing: antialiased; + background: url(../images/arrow-down.png) no-repeat; + font-weight: normal; + text-shadow: rgba(0, 0, 0, 0.4) 0 -1px 0; + padding: 2px 2px 2px 22px; + height: 30px; +} + +a.github { + background: url(../images/octocat-small.png) no-repeat 1px; +} + +a.buttons:hover { + color: #fff; + text-decoration: none; +} + + +/* Section - for main page content */ + +section { + width:650px; + float:right; + padding-bottom:50px; +} + + +/* Footer */ + +footer { + width:170px; + float:left; + position:fixed; + bottom:10px; + padding-left: 50px; +} + +@media print, screen and (max-width: 960px) { + + div.wrapper { + width:auto; + margin:0; + } + + header, section, footer { + float:none; + position:static; + width:auto; + } + + footer { + border-top: 1px solid #ccc; + margin:0 84px 0 50px; + padding:0; + } + + header { + padding-right:320px; + } + + section { + padding:20px 84px 20px 50px; + margin:0 0 20px; + } + + header a small { + display:inline; + } + + header ul { + position:absolute; + right:130px; + top:84px; + } +} + +@media print, screen and (max-width: 720px) { + body { + word-wrap:break-word; + } + + header { + padding:10px 20px 0; + margin-right: 0; + } + + section { + padding:10px 0 10px 20px; + margin:0 0 30px; + } + + footer { + margin: 0 0 0 30px; + } + + header ul, header p.view { + position:static; + } +} + +@media print, screen and (max-width: 480px) { + + header ul li.download { + display:none; + } + + footer { + margin: 0 0 0 20px; + } + + footer a{ + display:block; + } + +} + +@media print { + body { + padding:0.4in; + font-size:12pt; + color:#444; + } +} \ No newline at end of file From 55d820842e5fd6605e6aa38a7cdc238672551c16 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 21 Jan 2013 20:31:26 -0500 Subject: [PATCH 03/11] pages init --- README.txt | 31 + nbpages/Intro to Python.html | 886 ++++++++++++ nbpages/Intro to Scikit Data (skdata).html | 863 +++++++++++ nbpages/Links to Related Work.html | 868 +++++++++++ ...coders and Variations with PyAutodiff.html | 1280 +++++++++++++++++ nbpages/Model - Convnet with PyAutodiff.html | 1148 +++++++++++++++ nbpages/Model - LIF Neurons with Theano.html | 891 ++++++++++++ .../Model - Linear SVM with PyAutodiff.html | 1121 +++++++++++++++ ...del - Logistic Regression with Theano.html | 837 +++++++++++ ...Multilayer Perceptron with PyAutodiff.html | 1063 ++++++++++++++ nbpages/Notation for Machine Learning.html | 819 +++++++++++ nbpages/Preprocessing - Image Whitening.html | 945 ++++++++++++ ...eano Tutorial (Part 1 - Introduction).html | 875 +++++++++++ ...utorial (Part 2 - Simple Computation).html | 1058 ++++++++++++++ ...t 3 - Functions and Shared Variables).html | 945 ++++++++++++ ... Tutorial (Part 4 - Random Variables).html | 859 +++++++++++ nbpages/files/images/3wolfmoon.jpg | Bin 0 -> 128399 bytes nbpages/files/images/cnn_explained.png | Bin 0 -> 25546 bytes nbpages/files/images/conv_1D_nn.png | Bin 0 -> 17821 bytes nbpages/files/images/mlp.png | Bin 0 -> 23828 bytes nbpages/files/images/mylenet.png | Bin 0 -> 49835 bytes nbpages/files/images/sparse_1D_nn.png | Bin 0 -> 11941 bytes rebuild_nbpages.sh | 19 + 23 files changed, 14508 insertions(+) create mode 100644 README.txt create mode 100644 nbpages/Intro to Python.html create mode 100644 nbpages/Intro to Scikit Data (skdata).html create mode 100644 nbpages/Links to Related Work.html create mode 100644 nbpages/Model - Autoencoders and Variations with PyAutodiff.html create mode 100644 nbpages/Model - Convnet with PyAutodiff.html create mode 100644 nbpages/Model - LIF Neurons with Theano.html create mode 100644 nbpages/Model - Linear SVM with PyAutodiff.html create mode 100644 nbpages/Model - Logistic Regression with Theano.html create mode 100644 nbpages/Model - Multilayer Perceptron with PyAutodiff.html create mode 100644 nbpages/Notation for Machine Learning.html create mode 100644 nbpages/Preprocessing - Image Whitening.html create mode 100644 nbpages/Theano Tutorial (Part 1 - Introduction).html create mode 100644 nbpages/Theano Tutorial (Part 2 - Simple Computation).html create mode 100644 nbpages/Theano Tutorial (Part 3 - Functions and Shared Variables).html create mode 100644 nbpages/Theano Tutorial (Part 4 - Random Variables).html create mode 100644 nbpages/files/images/3wolfmoon.jpg create mode 100644 nbpages/files/images/cnn_explained.png create mode 100644 nbpages/files/images/conv_1D_nn.png create mode 100644 nbpages/files/images/mlp.png create mode 100644 nbpages/files/images/mylenet.png create mode 100644 nbpages/files/images/sparse_1D_nn.png create mode 100755 rebuild_nbpages.sh diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..dbee882 --- /dev/null +++ b/README.txt @@ -0,0 +1,31 @@ +README OF GH-PAGES BRANCH OF IPYTHON THEANO TUTORIALS +===================================================== + +The pages published for the ipython notebooks works like this: + +* index.html is auto-built using the github pages wizard thing + +* All other html files are built from ipynb files in the 'master' branch + + +## Rebuilding index.html + +Rebuild the index.html using the github wizard. Go to the IPythonTheanoTutorials +project page, and open the project "Settings". On that page, click the +"Automatic Page Generator" button, edit the text there, and publish using the +web interface. + + +## Rebuilding all the notebook html files + +1. Install nbconvert (https://github.com/ipython/nbconvert) + +2. Set up this project branch in a subfolder (recommended: "html") of the +IPythonTheanoTutorials master branch. + +3. run ./rebuild_pages.sh + +4. commit the changed html pages to [this] gh-pages branch to make them appear +on the website. + + diff --git a/nbpages/Intro to Python.html b/nbpages/Intro to Python.html new file mode 100644 index 0000000..4c548cb --- /dev/null +++ b/nbpages/Intro to Python.html @@ -0,0 +1,886 @@ + + + + + + + + + + + + + +
+

Getting Started

+

Before we dive into deep learning algorithms, lets make sure we understand the basics of the Python language and the IPython environment. Python is an interpreted language, and the iPython environment (powering this notebook) makes Python easy to learn, and fun to play with.

+

If you're new to Python or the IPython notebook, get started by running the following code fragment. You can run it by clicking on the code and either:

+
    +
  • pressing the gray button above that looks like the "play" button on a stereo
  • +
  • pressing CTRL-ENTER when the cursor is in the box
  • +
  • using the Cell drop-down menu's "Run" command
  • +
+
+
+
+
In [ ]:
+
+
print "Hello Random World"
+seed(123)
+imshow(rand(10, 10))
+
+ +
+
+
+
+

You can also edit the code and run it again the same way. The new output will replace the old output.

+

If you want to play around with Python, you might take the following as a point of departure:

+
+
+
+
In [ ]:
+
+
a = 'foo'  # -- strings are basic data types
+if 'foo' == "foo":
+    # single-quoted strings and double-quoted strings are the same
+    print """
+    In Python, "foo" and 'foo' are the same.
+    And this is a multi-line string literal.
+    """
+    
+b = 3.4    # -- floating point literal
+a = 5      # -- integer literal; notice `a` can be re-used for different types
+
+c  = (1, 2, 3)  # -- tuples are immutable sequences
+d  = [1, 2, 3]  # -- lists are mutable sequences
+
+e = {'a': 6, 5: 8, c: 'foo'}   # -- dictionary-creation syntax
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- define a function like this
+def fn(x):
+    return x + 2
+
+# -- sometimes you might see nested functions
+def f(x):
+    def g(y):
+        return x + y
+    return g
+
+add_2 = f(2)
+print 'add_2(5) =', add_2(5)
+
+# -- scoping - parameters mask variables
+x = 7  # -- global x
+def g(x): 
+    #  -- local scope - here `x` refers to the argument of g, not the global.
+    print 'local x:', x
+g(12)
+print 'global x:', x
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- positional vs. named arguments
+def multi(a, b, c=8):
+    # -- the `%` does string formatting
+    print 'multi a=%s b=%s c=%s' % (a, b, c)
+
+# -- all parameters can be assigned positionally or by name
+multi(1, 2, 3)
+multi(4, 5)
+multi(4, 5, c=12)
+multi(a=-1, b='foo', c='bar')
+
+# -- positional arguments can be pulled from a tuple or list
+args = ('do', 're', 'mi')
+multi(*args)
+
+# -- keyword arguments can be pulled from a dictionary
+kwargs = {'a': 0, 'b': -1, 'c': 1}
+multi(**kwargs)
+
+# -- all these can be combined!
+multi(8, *(88,), **{'c': 888})
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- argument unpacking implements multiple return values
+def rmulti(a):
+    return (a, a + 1)
+
+x, y = rmulti(4)
+print x
+print y
+
+ +
+
+
+
+

There are many resources to help you get oriented to use Python for +numeric scientific work. A quick bit of googling turned up the following ones, +but feel free to look further.

+ +
+ + \ No newline at end of file diff --git a/nbpages/Intro to Scikit Data (skdata).html b/nbpages/Intro to Scikit Data (skdata).html new file mode 100644 index 0000000..2d30ab3 --- /dev/null +++ b/nbpages/Intro to Scikit Data (skdata).html @@ -0,0 +1,863 @@ + + + + + + + + + + + + + +
+

Browsing through Data Sets

+

The data sets we will use throughout these tutorials are provided via the +skdata package. The skdata package provides the logic of downloading, +unpacking, and providing a meaningful Python interface to various public data +sets.

+

Running the following should show a picture of a boat, though it may have to first download the CIFAR-10 XXX data set in order to do it. +Once the data set has been downloaded, it is stored in ~/.skdata/cifar10 for re-use. Browse through the data set by changing the index into x, +or modify the code fragment to show more than one picture at a time. We'll also be using MNIST XXX and the Google Street View House Numbers (SVHN XXX) data sets.

+
+
+
+
In [ ]:
+
+
from skdata.cifar10.views import OfficialImageClassificationTask
+task = OfficialImageClassificationTask()
+print 'Image shape', task.train.x[8].shape
+imshow(task.train.x[8], interpolation='nearest')
+
+ +
+
+
+
+
+
In [ ]:
+
+
from skdata.mnist.views import OfficialImageClassification
+task = OfficialImageClassification()
+print 'Digit shape', task.train.x[0].shape
+imshow(task.train.x[0][:,:,0], cmap=cm.gray, interpolation='nearest')
+
+ +
+
+
+
+
+
In [ ]:
+
+
from skdata.svhn.view import CroppedDigitsView2
+data_view = CroppedDigitsView2(x_dtype='float32', n_train=1000)
+imshow(data_view.train.x[0].reshape(32, 32, 3))
+
+ +
+
+
+
+

Exercise 1

+

How many examples are in each data set, how big is each one? How many floating point values are in each image?

+
+
+
+
In [ ]:
+
+
# Write your answer here
+
+ +
+
+
+
+

Exercise 2

+

How are the examples of each data set sorted? Stochastic gradient descent is not very efficient when it iterates through all the examples of one class, then all the examples of the next class, etc. Do any of our data sets need to be shuffled?

+
+
+
+
In [ ]:
+
+
# Write your answer here
+
+ +
+
+
+
+

Exercise 3

+

How are the pixel colors encoded in each data set? How are the labels encoded? Tip: the labels are in train.y

+
+
+
+
In [ ]:
+
+
# Write your answer here
+
+ +
+
+
+
+

Exercise 4

+

The task objects have a test attribute as well as the train attribute which contains the test set for estimating generalization by cross-validation. How big are the test sets?

+
+
+
+
In [ ]:
+
+
# Write your answer here
+
+ +
+
+
+
+

Exercise 5

+

Something a bit more advanced - write a code fragment to lot the mean and variance in pixel values over the data set. Start with MNIST, which is grey-scale. How would you do it for a color data set? How do the pictures change when you look at per-class statistics?

+
+
+
+
In [ ]:
+
+
# Write your answer here
+
+ +
+
+
+ + \ No newline at end of file diff --git a/nbpages/Links to Related Work.html b/nbpages/Links to Related Work.html new file mode 100644 index 0000000..e655867 --- /dev/null +++ b/nbpages/Links to Related Work.html @@ -0,0 +1,868 @@ + + + + + + + + + + + + + +
+

Deep Learning in Python: Related Work

+

There are a lot of resources to help you do deep learning in Python. I've organized this page into sections: + * Deep Learning Software + * Scientific Software in Python + * Scientific Python Tutorials

+

Deep Learning Software

+

There are several software packages to be aware of, which do not necessarily have Python bindings but which may grow to include them. You don't always have to use Python!

+
    +
  • +

    Torch7 - Deep Learning software based on C and Lua

    +
  • +
  • +

    CudaConvNet - Alex Krizhevsky's software for deep convolutional nets.

    +
  • +
  • +

    PyLearn2 - Deep Learning Framework in Python based on Theano.

    +
  • +
+

Python Software Ecosystem

+

Deep learning can take your research in many directions, and it's nice that +Python has a lot of projects to help you on your way:

+
    +
  • +

    Python - the standard library is surprisingly comprehensive, get to + know what's in it.

    +
  • +
  • +

    NumPy - the defacto official n-dimensional array data type for Python. + Doing numerical work in Python, you will use these all the time.

    +
  • +
  • +

    SciPy - a library of many algorithms and utilities + that are useful across a broad range of scientific work. I originally captioned the following "especially useful" but the list grew to + include almost the entire library:

    +
  • +
  • +

    scipy.io - read and write various matrix formats including MATLAB

    +
  • +
  • +

    scipy.linalg - decompositions, inverses, etc.

    +
  • +
  • +

    scipy.ndimage - basic image processing

    +
  • +
  • +

    scipy.optimize - 1-D and N-D optimization algorithms

    +
  • +
  • +

    scipy.signal - signal processing

    +
  • +
  • +

    scipy.sparse - several sparse matrix types

    +
  • +
  • +

    scipy.special - special functions (e.g. erf)

    +
  • +
  • +

    scipy.stats - pdfs, cdfs, sampling algorithms, tests

    +
  • +
  • +

    IPython is a feature-rich Python interpreter.

    +
  • +
  • +

    Matplotlib is the most widely-used plotting library for Python. It provides an + interface similar to that of MATLAB or R. It is sometimes annoying, and not as flashy as say, + d3 but it is the workhorse of data visualization in Python.

    +
  • +
  • +

    Theano - an array expression compiler, with automatic differentiation and behind-the-scenes GPU execution.

    +
  • +
  • +

    PyAutoDiff - provides automatic differentiation for code using NumPy. + Currently this is a Theano front-end, but the API has been designed to keep Theano out of the sight of client code.

    +
  • +
  • +

    pandas - machine learning algorithms and types, mainly for working with time series. + Includes R-like data structures (like R's data frame).

    +
  • +
  • +

    Cython - a compiler for a more strongly-typed Python dialect, very useful for optimizing numeric Python code.

    +
  • +
  • +

    Copperhead - compiles natural python syntax to GPU kernels

    +
  • +
  • +

    numexpr - compiles expression strings to perform loop-fused element-wise computations

    +
  • +
  • +

    scikit-learn - well-documented and well-tested implementations of many standard ML algorithms.

    +
  • +
  • +

    scikits-image - image-processing (edge detection, color spaces, many standard algorithms)

    +
  • +
  • +

    skdata - data sets for machine learning

    +
  • +
+

Scientific Python Tutorials

+

There are several great resources to help you get oriented to use Python for +numeric scientific work.

+
    +
  • +

    Unix/Python/NumPy - This + is a really high-level intro to unix and Python. There is tons of + documentation for these things and they're kind of out of scope of these tutorials--by all means dig around the net for more background if you want + to know more.

    +
  • +
  • +

    NumPy basics

    +
  • +
  • +

    SciPy Getting Started

    +
  • +
  • +

    Deep Learning Tutorials provide code-centered introductions to + Deep Learning algorithms and architectures. + They make heavy use of Theano, and illustrate good practices + of programming with Theano.

    +
  • +
+
+ + + \ No newline at end of file diff --git a/nbpages/Model - Autoencoders and Variations with PyAutodiff.html b/nbpages/Model - Autoencoders and Variations with PyAutodiff.html new file mode 100644 index 0000000..3bc0d92 --- /dev/null +++ b/nbpages/Model - Autoencoders and Variations with PyAutodiff.html @@ -0,0 +1,1280 @@ + + + + + + + + + + + + + +
+

Auto-Encoders and Denoising Auto-Encoders

+

The auto-encoder (AE) is a classic unsupervised algorithm for non-linear dimensionality reduction. +The de-noising auto-encoder (DAE) is an extension of the auto-encoder introduced as a building block for deep networks in [Vincent08]. +This tutorial introduces the autoencoder as an unsupervised feature learning algorithm for the MNIST data set, and then develops the denoising autoencoder. +See section 4.6 of [Bengio09]_ for an overview of auto-encoders.

+
+
+
+
In [ ]:
+
+
# Before we get started with the rest of the tutorial, 
+# run this once (and again after every kernel restart)
+# to bring in all the external symbols we'll need.
+
+from functools import partial
+import logging
+import sys
+import time
+
+import numpy as np
+from numpy import dot, exp, log, newaxis, sqrt, tanh 
+rng = np.random.RandomState(123)
+
+from skdata import mnist, cifar10, svhn
+import autodiff
+
+from util import show_filters
+print '-> Imports Complete'
+
+ +
+
+
+
+

Let's also import the MNIST data set here, so that the examples in the tutorial have some data to work with. (HINT: Some of the exercises will involve using different data sets -- you can use different data sets with the tutorial code by writing a code block like this one that redefining x and x_img_res.)

+
+
+
+
In [ ]:
+
+
dtype = 'float32'   # -- this sets the working precision for data and model
+n_examples = 10000  # -- use up to 50000 examples
+
+data_view = mnist.views.OfficialImageClassification(x_dtype=dtype)
+x_as_images = data_view.train.x[:n_examples]
+x_img_res = x_as_images.shape[1:3]         # -- handy for showing filters
+x = x_as_images.reshape((n_examples, -1))  # -- rasterize images to vectors
+n_visible = x.shape[1]
+
+# -- uncomment this line to see the initial weight values
+show_filters(x[:100], x_img_res, (10, 10))
+
+ +
+
+
+
+

Autoencoders

+

Generally speaking, an autoencoder maps vector input $\mathbf{x}$ to some intermediate representation $\mathbf{y}$ and then back into the original space, in such a way that the end-point is close to $\mathbf{x}$. While the goal thus defined is simply to learn an identity function, +things get interesting when the mappings are parameterized or constrained in such a way that a general identity function is either impossible to represent or at least difficult to learn from data. When this is the case, the goal of learning is to learn a special-purpose identity function that typically works for vectors $\mathbf{x}$ that we care about, which come from some empirically interesting distribution. The $\mathbf{y}$ vector that comes out of this process contains all the important information about $x$ in a new and potentially useful way.

+

In our tutorial here we will deal with vectors $\mathbf{x}$ that come from the MNIST data set of hand-written digits. +Examples from MNIST are vectors $\mathbf{x} \in [0,1]^N$, +and we will look at the classic one-layer sigmoidal autoencoder parameterized by:

+
    +
  • matrix $W \in \mathbb{R}^{N \times M}$ - the weights
  • +
  • vector $\mathbf{b} \in \mathbb{R}^M$ - the bias
  • +
  • matrix $V \in \mathbb{R}^{M \times N}$ - the reconstruction weights
  • +
  • vector $\mathbf{c} \in \mathbb{R}^N$ - the recontruction bias
  • +
+

which encodes vectors $\mathbf{x}$ into $\mathbf{y} \in [0,1]^M$ by the deterministic mapping

+

$$ \mathbf{h} = s(\mathbf{x}\mathbf{W} + \mathbf{b}) $$

+

Where $s$ is a poinwise sigmoidal function $s(u) = 1 / (1 + e^{-u})$. +The latent representation $\mathbf{h}$, +or code is then mapped back (decoded) into +reconstruction $\mathbf{z}$ through the similar transformation

+

$$\mathbf{z} = s(\mathbf{h}\mathbf{V} + \mathbf{c}) $$.

+
+
+
+
In [ ]:
+
+
# Run this cell to define the symbols
+def logistic(u):
+    """Return logistic sigmoid of float or ndarray `u`"""
+    return 1.0 / (1.0 + exp(-u))
+
+def autoencoder(W, b, V, c, x):
+    h = logistic(dot(x, W) + b)
+    # -- using w.T here is called using "tied weights"
+    # -- using a second weight matrix here is called "untied weights"
+    z = logistic(dot(h, V) + c)
+    return z, h
+
+print '-> defined model family'
+
+ +
+
+
+
+

Training an Autoencoder

+

Training an autoencoder consists of minimizing a reconstruction cost, +taking $\mathbf{z}$ as the reconstruction of $\mathbf{x}$. +Intuitively, we want a model that reconstructs the important aspects of $\mathbf{x}$ +so that we guarantee that these aspects are preserved by $\mathbf{y}$. +Typically, mathematical formalizations of this intuition are not particularly +exotic, but they should, at the very least, respect the domain and range of $\mathbf{x}$ +and $\mathbf{z}$ respectively. +So for example, if $\mathbf{x}$ were a real-valued element of $\mathbb{R}^N$ then +we might formalize the reconstruction cost as +$|| \mathbf{x} - \mathbf{z} ||^2$, but there is no mathematical requirement +to use the $\ell_2$ norm or indeed to use a valid norm at all.

+

For our MNIST data, we will suppose that $\mathbf{x}$ is a vector Bernoulli probabilities, +and define the reconstruction cost to be the cross-entropy betwen $\mathbf{z}$ and $\mathbf{x}$:

+

$$ +L(\mathbf{x}, \mathbf{z}) = - \sum^d_{k=1}[\mathbf{x}_k \log + \mathbf{z}_k + (1 - \mathbf{x}_k)\log(1 - \mathbf{z}_k)] +$$

+

We write this in Python as:

+
+
+
+
In [ ]:
+
+
def cross_entropy(x, z):
+    # -- N.B. this is numerically bad, we're counting on Theano to fix up
+    return -(x * log(z) + (1 - x) * log(1 - z)).sum(axis=1)
+
+
+def training_criterion(W, b, V, c, x):
+    z, h = autoencoder(W, b, V, c, x)
+    L = cross_entropy(x, z).mean()
+    return L
+
+print '-> defined training_criterion'
+
+ +
+
+
+
+

Training an autoencoder is an optimization problem that is +typically treated in two steps:

+
    +
  1. Initialization - choosing a starting point for gradient-based search,
  2. +
  3. Local Search - running a gradient-based optimization algorithm
  4. +
+

Initialization +The parameters of this particular model +($W, \mathbf{b}, V, \mathbf{c}$) must be initialized +so that symmetry is broken between the columns of $W$ (also the rows of $V$), +otherwise the gradient on each column will be identical and local search will +be completely ineffective.

+

It is customary to initialize $W$ to small random values to break symmetry, +and to initialize the rest of the parameters to 0.

+
+
+
+
In [ ]:
+
+
# -- allocate and initialize a new model  (w, visbias, hidbias)
+
+# -- tip: choose the number of hidden units as a pair, so that show_filters works
+n_hidden2 = (10, 10)
+n_hidden = np.prod(n_hidden2)
+W = rng.uniform(
+        low=-4 * np.sqrt(6. / (n_hidden + n_visible)),
+        high=4 * np.sqrt(6. / (n_hidden + n_visible)),
+        size=(n_visible, n_hidden)).astype(dtype)
+V = np.zeros_like(W.T)
+b = np.zeros(n_hidden).astype(dtype)
+c = np.zeros(n_visible).astype(dtype)
+
+# -- uncomment this line to see the initial weight values
+show_filters(W.T, x_img_res, n_hidden2)
+
+ +
+
+
+
+

Local Search

+

The training criterion $L$ defined above is a deterministic and differentiable function of parameters ($W, b, V, c$) so any multi-dimensional minimization algorithm can do the job. +The speed and accuracy of a the method generally depends on the size nature of the data set, the parameters and parameterization of the model, and of course the sophistication of the minimization algorithm.

+

A classic, and still widely useful, algorithm is stochastic gradient descent.

+
+
+
+
In [ ]:
+
+
t0 = time.time()
+online_batch_size = 1 # -- =1 for "pure online", >1 for "minibatch"
+streams={'x': x.reshape((
+                         n_examples / online_batch_size,
+                         online_batch_size,
+                         n_visible))}
+W, b, V, c = autodiff.fmin_sgd(training_criterion,
+        args=(W, b, V, c),
+        streams=streams,
+        stepsize=0.001,
+        loops=1,  # -- fmin_sgd can iterate over the streams repeatedly
+        print_interval=1000,
+        )
+
+show_filters(W.T, x_img_res, n_hidden2)
+print 'Online training took %f seconds' % (time.time() - t0)
+
+ +
+
+
+
+

Another powerful minimization method is the well-known (L-BFGS) algorithm. When used as a training algorithm, it is called a batch algorithm because it does not deal well with stochastic functions, and therefore requires that we evaluate the total loss over all training examples on each cost function evaluation.

+

L-BFGS can be run right away from the random initialization, +but often what works better is to do a few loops of fmin_sgd to move the initial random parameters to a promising area of the search space, and then to refine that solution with L-BFGS.

+
+
+
+
In [ ]:
+
+
# -- BATCH TRAINING
+def batch_criterion(W, b, V, c):
+    return training_criterion(W, b, V, c, x)
+
+W, b, V, c = autodiff.fmin_l_bfgs_b(batch_criterion,
+        args=(W, b, V, c),
+        maxfun=20,    # -- how many function calls to allow?
+        iprint=1,     # -- 1 for verbose, 0 for normal, -1 for quiet
+        m=20)         # -- how well to approximate the Hessian
+
+show_filters(W.T, x_img_res, n_hidden2) 
+
+ +
+
+
+
+

That's it, we've trained an auto-encoder.

+

Autoencoder Summary

+

An autoencoder is a function that maps a vector to approximately itself, by passing it through intermediate values in such a way that the pure identify function is difficult or impossible. +An autoencoder is a non-stochastic pre-cursur to several more modern probabilistic models such as De-Noising AutoEncoders, Sparse Coding, and Restricted Boltzmann Machines. They are a flexible class of feature extraction algorithms that can be quick to train by either stochastic gradient descent, or more sophisticated minimization algorithms such as L-BFGS.

+

Spend some time running through the exercises below to get a better feel for how autoencoders work and what they can do.

+
+
+

Exercise: Linear AutoEncoder

+

If there is one linear hidden layer (the code) and +the mean squared error criterion is used to train the network, then the $k$ +hidden units learn to project the input in the span of the first $k$ +principal components of the data. If the hidden +layer is non-linear, the auto-encoder behaves differently from PCA, +with the ability to capture multi-modal aspects of the input +distribution. The departure from PCA becomes even more important when +we consider stacking multiple encoders (and their corresponding decoders) +when building a deep auto-encoder [Hinton06]_.

+

Re-inialize the weights, and try SGD on the following linear auto-encoder model.

+

HINT: if you get NaN as the Value during SGD, try lowering the step size to 0, and then slowly raising it.

+
+
+
+
In [ ]:
+
+
def squared_error(x, x_rec):
+    """Return the squared error of approximating `x` with `x_rec`"""
+    return ((x - x_rec) ** 2).sum(axis=1)
+
+def linear_autoencoder_criterion(W, c, x):
+    hid = dot(x - c, W)
+    x_rec = dot(hid, W.T)
+    cost = squared_error(x - c, x_rec)
+    return cost.mean()
+
+print linear_autoencoder_criterion(W, c, x[:3])
+
+# Modify the SGD training code (or paste it here) to train just W and c
+# using the linear_autoencoder_criterion
+# ...
+
+ +
+
+
+
+

Exercise: Regularization via Tied Weights

+

The weight matrix $V$ of the reverse mapping may be +optionally constrained by $V = W^{T}$, which is +called an autoencoder with tied weights. +This is another way to regularize the autoencoder model. +The PCA interpretation of the autoencoder (linear autoencoder), the RBM model (algorithmically similar to the autoencoder), the K-Means, and sparse coding interpretations of the auto-encoder all demand tied weights. How do the filters come out if you use the training_criterion_tied?

+
+
+
+
In [ ]:
+
+
def training_criterion_tied(W, b, c, x):
+    return training_criterion(W, b, W.T, c, x)
+
+# Now modify (or paste here) an optimization fragment that optimizes only (W, b, c)
+# ...
+# How is W changed by being tied to V ?
+
+ +
+
+
+
+

Exercise: Capacity Regularization via L2 Regularization

+

One serious potential issue with auto-encoders is that if there is no other +constraint besides minimizing the reconstruction error, +then an auto-encoder with $n$ inputs and an +encoding of dimension at least $n$ could potentially just learn +the identity function, and fail to differentiate +test examples (from the training distribution) from other input configurations. +Surprisingly, experiments reported in [Bengio07]_ nonetheless +suggest that in practice, when trained with +stochastic gradient descent, non-linear auto-encoders with more hidden units +than inputs (called overcomplete) yield useful representations +(in the sense of classification error measured on a network taking this +representation in input). A simple explanation is based on the +observation that stochastic gradient +descent with early stopping is similar to an L2 regularization of the +parameters. To achieve perfect reconstruction of continuous +inputs, a one-hidden layer auto-encoder with non-linear hidden units +(exactly like in the above code) +needs very small weights in the first (encoding) layer (to bring the non-linearity of +the hidden units in their linear regime) and very large weights in the +second (decoding) layer. +With binary inputs, very large weights are +also needed to completely minimize the reconstruction error. Since the +implicit or explicit regularization makes it difficult to reach +large-weight solutions, the optimization algorithm finds encodings which +only work well for examples similar to those in the training set, which is +what we want. It means that the representation is exploiting statistical +regularities present in the training set, rather than learning to +replicate the identity function.

+
+
+
+
In [ ]:
+
+
# The claim above is that SGD already implements an L2 regularization implicitly,
+# whereas L-BFGS less so or not at all.
+# Can you detect a difference? (I'm not sure if you can or not)
+# 
+# One way to explore the question is to let SGD and L-BFGS both run until the reconstruction
+# error is nearly zero. Can both algorithms get that far? Which one finds larger parameters?
+#
+# Now define a new training_criterion function that includes L2 penalty
+# (W ** 2).sum()
+#
+# How does an explicit L2 penalty affect SGD? What about L-BFGS?
+
+ +
+
+
+
+

Exercise: Sparsity, K-means

+

There are different ways that an auto-encoder with more hidden units +than inputs could be prevented from learning the identity, and still +capture something useful about the input in its hidden representation. +One is the addition of sparsity (forcing many of the hidden units to +be zero or near-zero), and it has been exploited very successfully +by many [Ranzato07] [Lee08].

+

One of the most extreme forms of sparsity in autoencoders is known as the K-means algorithm. +In the K-means model, the latent code hid is a vector with one 1 and the rest all 0. +K-means is typically solved using a very efficient batch EM algorithm, but we can also +tackle it with the same tools we've been using thus far.

+

How does this compare with sklearn's K-means solver?

+
+
+
+
In [ ]:
+
+
def softmax(x):
+    """Return the softmax of each row in x"""
+    x2 = x - x.max(axis=1)[:, newaxis]
+    ex = exp(x2)
+    return ex / ex.sum(axis=1)[:, newaxis]
+
+# helper functions -- run this once after a kernel restart
+# Re-run it after any change you make to these routines.
+
+def euclidean_distances2(X, Y):
+    """Return all-pairs squared distances between rows of X and Y
+    """
+    # N.B. sklearn.metrics.pairwise.euclidean_distances
+    # offers a more robust version of this routine,
+    # but which does things that autodiff currently does not support.
+    XX = np.sum(X * X, axis=1)[:, newaxis]
+    YY = np.sum(Y * Y, axis=1)[newaxis, :]
+    distances = np.maximum(XX - 2 * dot(X, Y.T) + YY, 0)
+    return distances
+    
+def k_means_real_x(w, x):
+    xw = euclidean_distances2(x, w.T)
+    # -- This calculates a hard winner
+    hid = (xw == xw.min(axis=1)[:, newaxis]).astype(dtype)
+    # -- This calculates a soft winner
+    hid = hid + softmax(xw)
+    x_rec = dot(hid/2, w.T)
+    cost = ((x - x_rec) ** 2).sum(axis=1)
+    rval = cost.mean()
+    return rval
+
+if 1:
+    W, = autodiff.fmin_sgd(k_means_real_x,
+        args=(W,),
+        streams=streams,
+        stepsize=0.001,
+        loops=2,  # -- fmin_sgd can iterate over the streams repeatedly
+        print_interval=1000,
+        )
+
+if 0:
+    W, = autodiff.fmin_l_bfgs_b(lambda W: k_means_real_x(W, x),
+        args=(W,),
+        maxfun=60,    # -- how many function calls to allow?
+        iprint=1,     # -- 1 for verbose, 0 for normal, -1 for quiet
+        m=20)         # -- how well to approximate the Hessian
+
+
+show_filters(W.T, x_img_res, n_hidden2)
+
+ +
+
+
+
+

Exercise: Sparsity via sparse coding

+

Sorry guys, this isn't implemented yet. +So the exercise is: implement FISTA, or the (Olshausen and Field, 1996) version.

+ +
+
+
+
In [ ]:
+
+
FISTA = NotImplementedError
+# real-real Sparse Coding
+def sparse_coding_real_x(x, w, hidbias, visbias, sparse_coding_algo=FISTA):
+    # -- several sparse coding algorithms have been proposed, but they all
+    # give rise to a feature learning algorithm that looks like this:
+    hid = sparse_coding_algo(x, w)
+    x_rec = dot(hid, w.T) + visbias
+    cost = ((x - x_rec) ** 2).mean(axis=1)
+    # -- the gradient on this cost wrt `w` through the sparse_coding_algo is
+    # often ignored. At least one notable exception is the work of Karol
+    # Greggor.  I feel like the Implicit Differentiation work of Drew Bagnell
+    # is another, but I'm not sure.
+    return cost, hid
+
+ +
+
+
+
+

Exercise: Denoising AutoEncoder

+

Another variation on the autoencoder theme is to add noise to the input by zeroing out some of the elements randomly. This is known as the denoising autoencoder (Vincent et al., XXX) +and it has been shown to be a form of score-matching (probabilistic model interpretation) +and a good feature extraction algorithm.

+
+
+
+
In [ ]:
+
+
def denoising_autoencoder_binary_x(W, b, c, x):
+    # -- corrupt the input by zero-ing out some values randomly
+    noisy_x = x * (rand(*x.shape) > .3)
+    hid = logistic(dot(noisy_x, W) + b)
+    x_rec = logistic(dot(hid, W.T) + c)
+    cost = cross_entropy(x, x_rec)
+    return cost.mean()
+
+W, b, c = autodiff.fmin_sgd(denoising_autoencoder_binary_x,
+        args=(W, b, c),
+        streams=streams,
+        stepsize=0.01,
+        loops=1,  # -- fmin_sgd can iterate over the streams repeatedly
+        print_interval=1000,
+        )
+
+show_filters(W.T, x_img_res, n_hidden2)
+
+ +
+
+
+
+

Exercise: Not really an autoencoder -- the Restricted Boltzmann Machine

+

The Contrastive Divergence algorithm for training Restricted Boltzmann Machines (RBMs) looks a lot like an auto-encoder from an algorithmic perspective, especially the denoising autoencoder. Tempting though it is to use the autoencoder as a unifying framework, it is a stretch to call an RBM an auto-encoder. Mathematically, it is better to train an RBM by Persistent CD (aka Stochastic Maximum Likelihood) and these methods actually work on the basis of ensuring that the RBM does not perfectly reconstruct any training instances. Nevertheless, +the following code implements the CD algorithm in a way that makes a clear connection to the other autoencoder-style models above.

+

One important difference with the cases above is that +CD is not in fact gradient descent on a cost function and although this code makes use of a difference in free energies as a cost function, it is just a trick. +Consequently, you'll see that the so-called "cost" values regularly jump both up and down even when the algorithm is working perfectly well. Computation of the likelihood of an RBM involves an infamously intractable partition function -- there are techniques for estimating it (see Ruslan Salakhutdinov's PhD thesis), but no tutorial here yet.

+
+
+
+
In [ ]:
+
+
def rbm_binary_x(w, hidbias, visbias, x):
+    hid = logistic(dot(x, w) + hidbias)
+    hid_sample = (hid > rand(*hid.shape)).astype(x.dtype)
+
+    # -- N.B. model is not actually trained to reconstruct x
+    x_rec = logistic(dot(hid_sample, w.T) + visbias)
+    x_rec_sample = (x_rec > rand(*x_rec.shape)).astype(x.dtype)
+
+    # "negative phase" hidden unit expectation
+    hid_rec = logistic(dot(x_rec_sample, w) + hidbias)
+
+    def free_energy(xx):
+        xw_b = dot(xx, w) + hidbias
+        return -log(1 + exp(xw_b)).sum(axis=1) - dot(xx, visbias)
+
+    cost = free_energy(x) - free_energy(x_rec_sample)
+    return cost.mean()
+
+W, b, c = autodiff.fmin_sgd(rbm_binary_x,
+        args=(W, b, c),
+        streams=streams,
+        stepsize=0.01,
+        loops=5,  # -- fmin_sgd can iterate over the streams repeatedly
+        print_interval=1000,
+        )
+
+show_filters(W.T, x_img_res, n_hidden2)
+
+ +
+
+
+ + \ No newline at end of file diff --git a/nbpages/Model - Convnet with PyAutodiff.html b/nbpages/Model - Convnet with PyAutodiff.html new file mode 100644 index 0000000..4f42d8d --- /dev/null +++ b/nbpages/Model - Convnet with PyAutodiff.html @@ -0,0 +1,1148 @@ + + + + + + + + + + + + + +
+

Convolutional Networks

+

This notebook has been adapted from the +Deep Learning Tutorials: Convolutional Neural Network

+

Convolutional Neural Networks (ConvNets) are MLP variants which are +specialized for image processing. +From Hubel and Wiesel's early work on the cat's visual cortex [Hubel68], +we know there exists a complex arrangement of cells within the visual cortex. +These cells are sensitive to small sub-regions of the input space, called a +_receptive field, and are tiled in such a way as to cover the entire visual +field. These filters are local in input space and are thus better suited to +exploit the strong spatially local correlation present in natural images.

+

Additionally, two basic cell types have been identified: simple cells (S) and +complex cells (C). Simple cells (S) respond maximally to specific edge-like +stimulus patterns within their receptive field. Complex cells (C) have larger +receptive fields and are locally invariant to the exact position of the +stimulus.

+
+
+
+
In [ ]:
+
+
import sys
+import time                                                                    
+                                                                               
+import numpy as np
+from numpy import arange, dot, maximum, ones, tanh, zeros
+from numpy.random import uniform                                               
+
+from skdata import mnist                                                       
+import autodiff
+
+from util import show_filters
+from util import hinge                                                         
+from util import ova_svm_prediction, ova_svm_cost                              
+from util import tanh_layer
+from util import mlp_prediction, mlp_cost
+
+# -- filterbank normalized cross-correlation                                   
+from util import fbncc 
+
+# -- max-pooling over 2x2 windows                                              
+from util import max_pool_2d_2x2
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- load and prepare the data set
+#
+# -- N.B. we're loading up x as images this time, not vectors
+dtype = 'float32'  # helps save memory and go faster
+n_examples = 10000
+data_view = mnist.views.OfficialImageClassification(x_dtype=dtype)
+n_classes = 10
+x_rows, x_cols = data_view.train.x.shape[1:3]
+# -- N.B. we shuffle the input to have shape
+#    (#examples, #channels, #rows, #cols)
+x = data_view.train.x[:n_examples].transpose(0, 3, 1, 2)
+y = data_view.train.y[:n_examples]
+y1 = -1 * ones((len(y), n_classes)).astype(dtype)
+y1[arange(len(y)), y] = 1
+
+ +
+
+
+
+

Sparse Connectivity

+

ConvNets (as well as several related computer vision architectures XXX), +exploit spatially local correlation by enforcing a local connectivity pattern between +neurons of adjacent layers. The input hidden units in the m-th layer are +connected to a local subset of units in the (m-1)-th layer, which have spatiallycontiguous receptive fields. We can illustrate this graphically as follows:

+

+

Imagine that layer m-1 is the input retina. +In the above, units in layer m +have receptive fields of width 3 with respect to the input retina and are thus only +connected to 3 adjacent neurons in the layer below (the retina). +Units in layer m have +a similar connectivity with the layer below. We say that their receptive +field with respect to the layer below is also 3, but their receptive field +with respect to the input is larger (it is 5). +The architecture thus +confines the learnt "filters" (corresponding to the input producing the strongest response) to be a spatially local pattern +(since each unit is unresponsive to variations outside of its receptive field with respect to the retina). +As shown above, stacking many such +layers leads to "filters" (not anymore linear) which become increasingly "global" however (i.e +spanning a larger region of pixel space). For example, the unit in hidden +layer m+1 can encode a non-linear feature of width 5 (in terms of pixel +space).

+
+
+

Shared Weights

+

In ConvNets, each sparse filter $h_i$ is additionally replicated across the +entire visual field. These "replicated" units form a feature map, which +share the same parametrization, i.e. the same weight vector and the same bias.

+

+

In the above figure, we show 3 hidden units belonging to the same feature map. +Weights of the same color are shared, i.e. are constrained to be identical. +Gradient descent can still be used to learn such shared parameters, and +requires only a small change to the original algorithm. The gradient of a +shared weight is simply the sum of the gradients of the parameters being +shared.

+

Why are shared weights interesting ? Replicating units in this way allows for +features to be detected regardless of their position in the visual field. +Additionally, weight sharing offers a very efficient way to do this, since it +greatly reduces the number of free parameters to learn. By controlling model +capacity, ConvNets tend to achieve better generalization on vision problems.

+

Details and Notation

+

Conceptually, a feature map is obtained by convolving the input image with a +linear filter, adding a bias term and then applying a non-linear function. If +we denote the k-th feature map at a given layer as $h^k$, whose filters +are determined by the weights $W^k$ and bias $b_k$, then the +feature map $h^k$ is obtained as follows (for $tanh$ non-linearities):

+

$$ + h^k_{ij} = \tanh ( (W^k * x)_{ij} + b_k ). +$$

+

To form a richer representation of the data, hidden layers are composed of +a set of multiple feature maps, ${h^{(k)}, k=0..K}$. +The weights $W$ of this layer can be parametrized as a 4D tensor +(destination feature map index, source feature map index, source vertical position index, source horizontal position index) +and +the biases $b$ as a vector (one element per destination feature map index). +We illustrate this graphically as follows:

+

+

Figure 1: example of a convolutional layer

+

Here, we show two layers of a ConvNet, containing 4 feature maps at layer (m-1) +and 2 feature maps ($h^0$ and $h^1$) at layer m. Pixels (neuron outputs) in +$h^0$ and $h^1$ (outlined as blue and red squares) are computed +from pixels of layer (m-1) which fall within their 2x2 receptive field in the +layer below (shown +as colored rectangles). Notice how the receptive field spans all four input +feature maps. The weights $W^0$ and $W^1$ of $h^0$ and +$h^1$ are thus 3D weight tensors. The leading dimension indexes the +input feature maps, while the other two refer to the pixel coordinates.

+

Putting it all together, $W^{kl}_{ij}$ denotes the weight connecting +each pixel of the k-th feature map at layer m, with the pixel at coordinates +(i,j) of the l-th feature map of layer (m-1).

+
+
+

Filterbank Normalized Cross-Correlation

+

Filterbank normalized cross-correlation (fbncc) implements filterbank cross-correlation (convolution with flipped filters) with the additional step of local centering and normalization (sphere-ing) of the image patch. This routine provides a very high-pass non-linear filter which is used in place of pure convolution in most modern convnets (citations needed).

+

To get a sense of what fbncc does, let's have a little fun with this classic meme...

+
+
+
+
In [ ]:
+
+
from PIL import Image
+img = Image.open('images/3wolfmoon.jpg')
+img = np.asarray(img, dtype='float32') / 255.
+
+imshow(img)
+
+# put image in 4D tensor of shape (1, 3, height, width)
+img_ = img.swapaxes(0, 2).swapaxes(1, 2).reshape(1, 3, 639, 516)
+
+rfilters = uniform(size=(4, 3, 5, 5)).astype('float32')
+out = fbncc(img_, rfilters)
+figure()
+show_filters(out.reshape((4, -1)), out.shape[2:], (1, 4))
+
+ +
+
+
+
+

Notice that a randomly initialized filter acts very much like an edge detector!

+
+
+

Max-Pooling

+

ConvNets emulate the behaviour of "complex cells" in visual cortex by +max-pooling, which is a form of +nonlinear downsampling. Max-pooling partitions the input image into +a set of non-overlapping rectangles and, for each such sub-region, outputs the +maximum value. +Max-pooling is useful in vision for two reasons: (1) it reduces the +computational complexity for upper layers and (2) it provides a form of +translation invariance. To understand the invariance argument, imagine +cascading a max-pooling layer with a convolutional layer. There are 8 +directions in which one can translate the input image by a single pixel. If +max-pooling is done over a 2x2 region, 3 out of these 8 possible +configurations will produce exactly the same output at the convolutional +layer. For max-pooling over a 3x3 window, this jumps to 5/8.

+

Since it provides additional robustness to position, max-pooling is thus a +"smart" way of reducing the dimensionality of intermediate representations.

+

Max-pooling over the standard 2x2 window is implemented by util.max_pool_2d_2x2. +It actually uses Theano's implementation of max-pooling internally, there is no native numpy implementation of max-pooling.

+
+
+
+
In [ ]:
+
+
# -- similar to tanh_layer, but we used fbncc instead of dot
+def tanh_conv_layer(W_fb, b_fb, img4):
+    activation = fbncc(img4, W_fb) + b_fb
+    activation = max_pool_2d_2x2(activation)
+    return np.tanh(activation)
+
+ +
+
+
+
+

Stacking Layers into a ConvNet

+

A ConvNet architecture interleaves convolutional and pooling layers to produce +the input to an MLP.

+

+

From an implementation point of view, this means lower-layers operate on 4D +tensors. These are then flattened to a 2D matrix of rasterized feature maps, +to be compatible with our previous MLP implementation.

+
+
+
+
In [ ]:
+
+
# -- allocate just one convolutional layer to keep the code simpler
+n_filters = 16
+patch_height = 5
+patch_width = 5
+patch_size = patch_height * patch_width
+
+W_fb = uniform(
+        low=-np.sqrt(6.0 / (patch_size + n_filters)),
+        high=np.sqrt(6.0 / (patch_size + n_filters)),
+        size=(n_filters, 1, patch_height, patch_width),
+        ).astype(x.dtype)
+b_fb = zeros((
+            n_filters,
+            x_rows - patch_height + 1,
+            x_cols - patch_width + 1),
+        dtype=x.dtype)
+
+# -- allocate tanh layer parameters
+n_hidden = 100
+
+V = uniform(low=-np.sqrt(6.0 / (b_fb.size // 4 + n_hidden)),
+                high=np.sqrt(6.0 / (b_fb.size // 4 + n_hidden)),
+                size=(b_fb.size // 4, n_hidden)).astype(x.dtype)
+c = zeros(n_hidden, dtype=x.dtype)
+
+# -- allocate the SVM at the top
+W = zeros((n_hidden, n_classes), dtype=x.dtype)
+b = zeros(n_classes, dtype=x.dtype)
+
+# -- define the ConvNet model
+def convnet_features(W_fb, b_fb, V, c, x):
+    layer1 = tanh_conv_layer(W_fb, b_fb, x)
+    layer1_size = np.prod(layer1.shape[1:])
+    layer2 = tanh_layer(V, c,
+            np.reshape(layer1, (x.shape[0], layer1_size)))
+    return layer2
+    
+def convnet_prediction(W_fb, b_fb, V, c, W, b, x):
+    layer2 = convnet_features(W_fb, b_fb, V, c, x)
+    return ova_svm_prediction(W, b, layer2)
+    
+def convnet_cost(W_fb, b_fb, V, c, W, b, x, y1):
+    layer2 = convnet_features(W_fb, b_fb, V, c, x)
+    return ova_svm_cost(W, b, layer2, y1)
+    
+print 'Initial ConvNet cost:', convnet_cost(W_fb, b_fb, V, c, W, b, x[:3], y1[:3])
+
+ +
+
+
+
+

Also of note, remark that we use the same weight initialization formula as +with the MLP. Weights are sampled randomly from a uniform distribution in the +range [-1/$D_0$, 1/$D_0$], where $D_0$ is the number of inputs to a hidden +unit. For MLPs, this was the number of units in the layer below. For ConvNets +however, we have to take into account the number of input feature maps and the +size of the receptive fields.

+
+
+

Training a ConvNet

+

Training of a ConvNet by supervised learning is done with exactly the same techniques as we used for the linear SVM and the MLP. We will look at semi-unsupervised training strategies in upcoming tutorials.

+
+
+
+
In [ ]:
+
+
# SGD minimization
+
+# -- do n_online_loops passes through the data set doing SGD
+#    This can be faster at the beginning than L-BFGS
+t0 = time.time()
+online_batch_size = 1
+n_batches = n_examples / online_batch_size
+W_fb, b_fb, V, c, W, b = autodiff.fmin_sgd(convnet_cost, (W_fb, b_fb, V, c, W, b),
+            streams={
+                'x': x.reshape((n_batches, online_batch_size,) + x.shape[1:]),
+                'y1': y1.reshape((n_batches, online_batch_size, y1.shape[1]))},
+            loops=2,
+            stepsize=0.01,
+            print_interval=1000,
+            )
+print 'SGD took %.2f seconds' % (time.time() - t0)
+show_filters(W_fb.reshape(n_filters, 5 * 5).T, (4, 4), (2, 8))
+
+ +
+
+
+
+

Testing the ConvNet

+

Testing of a trained model is also done in much the same way we tested the SVM and MLP models.

+
+
+
+
In [ ]:
+
+
train_predictions = convnet_prediction(W_fb, b_fb, V, c, W, b, x)
+train_errors = y != train_predictions
+print 'Current train set error rate', np.mean(train_errors)
+
+test_predictions = convnet_prediction(W_fb, b_fb, V, c, W, b, data_view.test.x[:].transpose(0, 3, 1, 2))
+test_errors = data_view.test.y[:] != test_predictions
+print 'Current test set error rate', np.mean(test_errors)
+
+ +
+
+
+
+

Exercises

+

Exercise: Hyperparameter optimization

+

The current hyperparameters of the convnet are not great, and the test set error is around 4%. This model should be able to score around 1% on the test set. Try adjusting hyperparameters such as:

+
    +
  • the SGD learning rate
  • +
  • the SGD mini-batch size
  • +
  • number of SGD iterations
  • +
  • the use of L-BFGS (adapt it from the mlp notebook)
  • +
  • the number of hidden units in the tanh layer
  • +
  • the patch size of the input layer
  • +
  • the number of filters in the convolutional layer
  • +
  • the amount of training data used
  • +
  • regularization of parameters
  • +
+

How all these things affect training and test error?

+

Feel free to send a pull-request back to the ipam-tutorials github page if you find good hyperparameter values!

+
+
+

Exercise: Adding an internal hidden layer

+

ConvNets in the literature have often been designed with not one, but two convolutional layers. Modify the convnet_features function to use two convolutional layers. Caveat: this will involve a few annoying reshapes, resizes, etc.

+
+
+

Exercise: Different Data Sets

+

In 1_1_getting started, we looked at three data sets in skdata: MNIST, CIFAR-10, and SVHN. The sample code above uses MNIST - try one of the other data sets and adapt the code here to run. You'll need to change the allocation of the first-layer filters to deal with the color images, and the size of the b_fb biases to match the larger input image dimensions, but I think that's it ...

+
+
+

Tips and Tricks

+

Tips and Tricks: Choosing Hyperparameters

+

ConvNets are especially tricky to train, as they add even more hyper-parameters than +a standard MLP. While the usual rules of thumb for learning rates andregularization constants still apply, the following should be kept in mind when +optimizing ConvNets.

+

Tips and Tricks: Number of filters

+

When choosing the number of filters per layer, keep in mind that computing the +activations of a single convolutional filter is much more expensive than with +traditional MLPs!

+

Assume layer $(l-1)$ contains $K^{l-1}$ feature +maps and $M \times N$ pixel positions (i.e., +number of positions times number of feature maps), +and there are $K^l$ filters at layer $l$ of shape $m \times n$. +Then computing a feature map (applying an $m \times n$ filter +at all $(M-m) \times (N-n)$ pixel positions where the +filter can be applied) costs $(M-m) \times (N-n) \times m \times n \times K^{l-1}$. +The total cost is $K^l$ times that. Things may be more complicated if +not all features at one level are connected to all features at the previous one.

+

For a standard MLP, the cost would only be $K^l \times K^{l-1}$ +where there are $K^l$ different neurons at level $l$. +As such, the number of filters used in ConvNets is typically much +smaller than the number of hidden units in MLPs and depends on the size of the +feature maps (itself a function of input image size and filter shapes).

+

Since feature map size decreases with depth, layers near the input layer will tend to +have fewer filters while layers higher up can have much more. In fact, to +equalize computation at each layer, the product of the number of features +and the number of pixel positions is typically picked to be roughly constant +across layers. To preserve the information about the input would require +keeping the total number of activations (number of feature maps times +number of pixel positions) to be non-decreasing from one layer to the next +(of course we could hope to get away with less when we are doing supervised +learning). The number of feature maps directly controls capacity and so +that depends on the number of available examples and the complexity of +the task.

+

Tips and Tricks: Filter Shape

+

Common filter shapes found in the litterature vary greatly, usually based on +the dataset. Best results on MNIST-sized images (28x28) are usually in the 5x5range on the first layer, while natural image datasets (often with hundreds of pixels in each +dimension) tend to use larger first-layer filters of shape 12x12 or 15x15.

+

The trick is thus to find the right level of "granularity" (i.e. filter +shapes) in order to create abstractions at the proper scale, given a +particular dataset.

+

Tips and Tricks: Max Pooling Shape

+

Typical values are 2x2 or no max-pooling. Very large input images may warrant +4x4 pooling in the lower-layers. Keep in mind however, that this will reduce the +dimension of the signal by a factor of 16, and may result in throwing away too +much information.

+
+ + \ No newline at end of file diff --git a/nbpages/Model - LIF Neurons with Theano.html b/nbpages/Model - LIF Neurons with Theano.html new file mode 100644 index 0000000..ab33fc1 --- /dev/null +++ b/nbpages/Model - LIF Neurons with Theano.html @@ -0,0 +1,891 @@ + + + + + + + + + + + + + +
+

Model - Leaky Integrate-and-Fire Neurons with Theano

+

Some quick hacking with Terry Stewart produced a Theano implementation of LIF neurons. He has added a more library-oriented version of this approach into Nengo, but this hacky code is probably still easier to read and play with.

+
+
+
+
In [ ]:
+
+
# -- Initial imports
+import numpy as np
+import theano
+import theano.tensor as TT
+from theano import shared, function
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- Set up our simulation to run with a particular precision
+
+floatX = theano.config.floatX  # either 'float32' or 'float64'
+
+def sharedX(obj, name):
+    """Create shared variable for ndarray'd obj with dtype=floatX
+    """
+    return shared(np.asarray(obj, dtype=floatX))
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- Assign simulation parameters
+#    Written in this way these will be *compiled in* to the
+#    tick() function below, as Theano *contants*.
+
+N = 100          # -- number of neurons
+D = 3            # -- state vector dimensionality
+
+t_rc = 0.01      # -- some capacitance constant
+t_ref = 0.001    # -- refractory period (1/max spike rate?)
+dt = 0.001       # -- simulation time-step
+pstc = 0.05      # -- post-synaptic time constant (low-pass filter on spikes in state update)
+
+encoders = np.random.randn(N, D).astype(floatX)
+decoders = np.random.randn(N, D).astype(floatX)
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- Define the recurrence of the LIF model
+
+# -- Place persistent quantities into shared variables 
+state = sharedX(np.zeros(D), 'state')
+voltage = sharedX(np.zeros(N), 'voltage')
+refractory_time = sharedX(np.zeros(N), 'refractory_time')
+J_bias = sharedX(np.random.randn(N), 'J_bias')
+Jm_prev = sharedX(np.zeros(N), 'Jm_prev')
+
+state_w_bias = TT.set_subtensor(state[0], 0.5)
+
+Jm = TT.dot(encoders, state) + J_bias
+
+# -- Euler's method
+dV = dt / t_rc * (Jm_prev - voltage)
+new_v = TT.maximum(voltage + dV, 0)
+
+post_ref = 1.0 - (refractory_time - dt) / dt  
+
+# -- Do accurate timing for when the refractory period ends   (probably not needed for FPGA neuron model)
+new_v *= TT.clip(post_ref, 0, 1)
+
+V_threshold = 1
+
+spiked = TT.switch(new_v > V_threshold, 1.0, 0.0)
+
+# -- Refractory stuff
+overshoot = (new_v - V_threshold) / dV
+spiketime = dt * (1.0 - overshoot)
+new_refractory_time = TT.switch(spiked,
+            spiketime + t_ref,
+            refractory_time - dt)
+        
+# -- low-pass filter on state
+decay = float(np.exp(-dt / pstc))
+new_state = (state * decay
+             + (1 - decay) * TT.dot(spiked, decoders) / dt)
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- Compile a function to evaluate one time-step of the model
+
+tick = function([], [],
+                updates={
+                         voltage: new_v * (1 - spiked),
+                         state: new_state,
+                         refractory_time: new_refractory_time,
+                         Jm_prev: Jm})
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- Step through time, retrieving the voltage value.
+voltages = []
+for i in range(1000):
+    tick()
+    voltages.append(voltage.get_value())
+
+ +
+
+
+
+
+
In [ ]:
+
+
lines = plot(np.asarray(voltages).T)
+
+ +
+
+
+ + + \ No newline at end of file diff --git a/nbpages/Model - Linear SVM with PyAutodiff.html b/nbpages/Model - Linear SVM with PyAutodiff.html new file mode 100644 index 0000000..05d879c --- /dev/null +++ b/nbpages/Model - Linear SVM with PyAutodiff.html @@ -0,0 +1,1121 @@ + + + + + + + + + + + + + +
+

Linear Support Vector Machine

+

The linear support vector machine (SVM) is a linear classifier parametrized by a matrix of weights $W$ and a bias vector $\mathbf{b}$. We will develop the multiclass "One vs. All" linear support vector machine, which is a concatentation of two-class support vector machines. We will suppose that our label set is the non-negative integers up to some maximum L.

+

There are other ways of setting up a multi-class SVM, such using the Crammer-Singer loss or +LaRank. +Despite theoretical limitations (lack of consistency!?) the approach is widely used. +See John Langford's page on machine learning reductions +for more perspectives on multi-class SVMs.

+

Deep architectures for classification are typically formed by classifying learned features with a +linear classifier such as an SVM or logistic regression model. +We will begin our exploration of deep architectures with the shallowest model of all: the linear SVM.

+

The Deep Learning Tutorials provide a good complementary introduction to +logistic regression.

+
+
+
+
In [ ]:
+
+
# initialize the workspace by importing several symbols
+import logging
+import sys
+import time
+
+import numpy as np
+from numpy import arange, dot, maximum, ones, tanh, zeros
+from numpy.random import randn
+
+from skdata import mnist
+import autodiff
+
+try:
+    from util import show_filters
+except:
+    print 'WARNING: show_filters will not work'
+    def show_filters(*a, **kw): pass
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- load and prepare the data set (even download if necessary)
+dtype = 'float32'
+n_examples = 50000
+n_classes = 10         # -- denoted L in the math expressions
+img_shape = (28, 28)
+
+data_view = mnist.views.OfficialVectorClassification(x_dtype=dtype)
+x = data_view.all_vectors[data_view.fit_idxs[:n_examples]]
+y = data_view.all_labels[data_view.fit_idxs[:n_examples]]
+
+ +
+
+
+
+

Supposing that our input is a vector (generally a feature vector) $\mathbf{x}$, the prediction $l^*$ of the OVA-SVM is the argmax of the affine function:

+

$$ +l^ = \operatorname{argmax}_{l=0}^{L} (\mathbf{x} W_l + \mathbf{b}_l) +$$

+
+
+
+
In [ ]:
+
+
def ova_svm_prediction(W, b, x):
+    return np.argmax(np.dot(x, W) + b, axis=1)
+
+ +
+
+
+
+

Training an SVM

+

The most standard way of training an SVM is to maximize the margin on training data. +The margin is always defined in the two-class case (where $y \in \{-1, +1\}$) +as $y * (xW + b)$. +The affine function parametrized by $W$ and $b$ defines a hyper-plane where $\mathbf{x}W + b = 0$ that the SVM interprets as a decision surface. +The margin represents how far away $\mathbf{x}W+b$ is from being on the wrong side of the decision surface: large positive values mean there is a safe distance ("margin of error?"), negative values mean that the decision surface is actually incorrect for the given $\mathbf{x}$.

+

The most standard sense in which SVMs maximize margin is via the hinge loss. The hinge loss of margin value $u$ is defined as

+

$$ +\mathrm{hinge}(u) = \max(0, 1-u) +$$

+

By maximizing the average hinge loss of the margin of training examples, we maximize a tight convex upper bound on the mis-classification rate (zero-one loss), and can +get a good binary classifier using fast algorithms for convex optimization.

+
+
+
+
In [ ]:
+
+
def hinge(u):
+    return np.maximum(0, 1 - u)
+
+ugrid = np.arange(-5, 5, .1)
+plot(ugrid, hinge(ugrid), label='hinge loss')
+plot(ugrid, ugrid < 0, label='zero-one loss')
+legend()
+
+ +
+
+
+
+

Multiclass SVM

+

In the multiclass case, it is not clear what the "correct" margin definition should be, and several useful ones have been proposed. +For the rest of this tutorial we'll develop the "one vs. all" multiclass SVM, sometimes called an OVA-SVM.

+

In the OVA-SVM, the training objective is defined by $L$ independent SVMs. +We will train an OVA-SVM by converting the integer-valued labels +$y$ to $Y \in \{-1, +1\}^{N \times L}$ and training $L$ SVMs at once. +The $L$ columns of $Y$ represent binary classification tasks. +The $L$ columns of $W$ and $L$ elements of $\mathbf{b}$ store the parameters of the $L$ SVMs.

+

The [unregularized] training objective is:

+

$$ +\mathcal{L}(\mathcal{D}; W, \mathbf{b}) = +\frac{1}{N} +\sum_{(\mathbf{x}^{(i)}, Y^{(i)}) \in \mathcal{D}} +~ +\sum_{l=1}^{L} +~ +\max \left( 0, 1 - Y^{(i)}_l (\mathbf{x}^{(i)} W_l + \mathbf{b}_l) \right) +$$

+
+
+
+
In [ ]:
+
+
# -- prepare a "1-hot" version of the labels, denoted Y in the math
+y1 = -1 * ones((len(y), n_classes)).astype(dtype)
+y1[arange(len(y)), y] = 1
+
+ +
+
+
+
+
+
In [ ]:
+
+
def ova_svm_cost(W, b, x, y1):
+    # -- one vs. all linear SVM loss
+    margin = y1 * (dot(x, W) + b)
+    cost = hinge(margin).mean(axis=0).sum()
+    return cost
+
+ +
+
+
+
+

The training itself consists in minimizing the objective $\mathcal{L}(\mathcal{D}; W, b)$ with respect to $W$ and $b$. The criterion is convex, so it doesn't much matter where we start. Zero works well in practice.

+
+
+
+
In [ ]:
+
+
# initialize the model
+W = zeros((x.shape[1], n_classes), dtype=dtype)
+b = zeros(n_classes, dtype=dtype)
+
+ +
+
+
+
+

There are many specialized SVM solvers available, but they tend to be most helpful for non-linear SVMs. In the linear case a simple combination of stochastic gradient descent (SGD) and BFGS can be very effective.

+
+
+
+
In [ ]:
+
+
# -- do n_online_loops passes through the data set doing SGD
+#    This can be faster at the beginning than L-BFGS
+t0 = time.time()
+online_batch_size = 1
+n_online_epochs = 1
+n_batches = n_examples / online_batch_size
+W, b = autodiff.fmin_sgd(ova_svm_cost, (W, b),
+            streams={
+                'x': x.reshape((n_batches, online_batch_size, x.shape[1])),
+                'y1': y1.reshape((n_batches, online_batch_size, y1.shape[1]))},
+            loops=n_online_epochs,
+            step_size=0.001,
+            print_interval=1000,
+            )
+print 'SGD took %.2f seconds' % (time.time() - t0)
+show_filters(W.T, img_shape, (2, 5))
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- L-BFGS optimization of our SVM cost.
+
+def batch_criterion(W, b):
+    return ova_svm_cost(W, b, x, y1)
+
+W, b = autodiff.fmin_l_bfgs_b(batch_criterion, (W, b), maxfun=20, m=20, iprint=1)
+
+print 'final_cost', batch_criterion(W, b)
+# -- N. B. the output from this command comes from Fortran, so iPython does not see it.
+#    To monitor progress, look at the terminal from which you launched ipython
+show_filters(W.T, img_shape, (2, 5))
+
+ +
+
+
+
+

Testing the SVM

+

Once the a classifier has been trained, we can test it for generalization accuracy on the test set. We test it by making predictions for the examples in the test set and counting up the number of classification mistakes.

+
+
+
+
In [ ]:
+
+
train_predictions = ova_svm_prediction(W, b, x)
+train_errors = y != train_predictions
+print 'Current train set error rate', np.mean(train_errors)
+
+test_predictions = ova_svm_prediction(W, b, data_view.all_vectors[data_view.tst_idxs])
+test_errors = data_view.all_labels[data_view.tst_idxs] != test_predictions
+print 'Current test set error rate', np.mean(test_errors)
+
+ +
+
+
+
+

SVM Summary

+

The linear Support Vector Machine (SVM) is an accurate and quick-to-train linear classifier. +We looked a multiclass variant called a "One vs. All" SVM, +parameterized by a matrix $W$ of weights and a vector $\mathbf{b}$ of biases. +A linear SVM can be trained by gradient descent; +whether SGD or L-BFGS works faster depends on the size of the data set and accuracy desired from the minimization process. A few iterations of SGD followed by refinement by L-BFGS is a fairly robust strategy.

+
+
+

Exercise: L1 and L2 regularization

+

Typically linear SVMs are L2-regularized. That means that in addition to $\mathcal{L}$, we minimize the sum of the squared elements of $W$:

+

$$ +\mathcal{L}_{\ell_2}(\mathcal{D}; W, b) = \mathcal{L}(\mathcal{D}; W, b) + \alpha ||W||_2^2 +$$

+
+
+
+
In [ ]:
+
+
def ova_svm_cost_l2(W, b, x):
+    raise NotImplementedError('implement me')
+
+# re-run the SGD and LBFGS training fragments after filling
+# in this function body to implement an L2-regularized SVM.
+
+# In cases where the training data are linearly separable, this can be very important.
+# How big does \alpha have to be to make any difference?
+
+ +
+
+
+
+

Exercise: Data Z-Normalization

+

Although the optimization of an SVM is a convex problem, the efficiency and stopping criteria of both SGD and L-BFGS are generally improved by centering and normalizing each input feature beforehand. The procedure is simple: subtract off the training set mean of each feature and divide by the standard deviation.

+

How does this affect the behavior of SGD and L-BFGS?

+

How should you deal with features whose standard deviation is very small? What about when it is 0?

+
+ +
+

Exercise: Different Data Sets

+

We have been using MNIST so far. How good is a linear classifier on other datasets that are typically used in deep learning? +The following two code fragments bring in access to the CIFAR-10 and SVHN data sets. +You'll have to access the shape attribute of the training images to figure out how many visible units there are, and then re-allocate W before repeating the training and testing processes.

+
+
+
+
In [ ]:
+
+
from skdata import cifar10
+n_examples = 10000
+# -- RECOMMENDED: restart the IPython kernel to clear out memory
+data_view = cifar10.view.OfficialVectorClassification(x_dtype='float32', n_train=n_examples)
+
+# Write the rest of the answer here:
+# - define x and y for training
+
+# Repeat the training steps in the code fragments above to train a linear SVM for CIFAR10
+
+ +
+
+
+
+
+
In [ ]:
+
+
from skdata import svhn
+n_examples = 10000
+# -- RECOMMENDED: restart the IPython kernel to clear out memory
+data_view = svhn.view.CroppedDigitsView2(x_dtype='float32', n_train=n_examples)
+
+# Write the rest of the answer here:
+# - define x and y for training
+
+# Repeat the training steps in the code fragments above to train a linear SVM for
+# Street View House Numbers (SVHN)
+
+ +
+
+
+
+

Bonus: Pixel colors in cifar10 and svhn are encoded as RGB triples. There are many other ways of representing color. Some of these are linearly related to RGB, others non-linearly. +The scikit-image project defines a number of color-conversion routines. +Are any of these color representations better than RGB for image classification?

+
+
+
+
In [ ]:
+
+
from skimage.color import convert_colorspace
+
+# Write your answer here
+# use convert_colorspace to define new versions of the training and testing images.
+
+# Hint - you'll have to un-rasterize the x matrix into a N-dimensional array
+#        n. examples x n. rows x n. cols x n. channels
+
+ +
+
+
+
+

Exercise: Variations on the Hinge Loss

+

You don't have to use the hinge loss to train a linear classifier. Other popular loss functions include the squared hinge loss, the "Huberized" hinge loss, and the exponential function. These functions are continuously differentiable, which you might expect to help for gradient-based optimization. Does it help? How else are these functions different? In what cases would it matter?

+
+
+
+
In [ ]:
+
+
# Write your answer here
+
+ +
+
+
+
+

Exercise: Crammer-Singer Loss for Multiclass SVM

+

TODO: VERIFY THIS QUESTION

+

The One vs. All SVM suffers, in theory, from a lack of Bayes consistency. +The Crammer-Singer loss defines the multiclass training objective differently, in a way that is Bayes-consistent.

+

To define the Crammer-Singer loss let's define +$\mathbf{h} = \mathbf{x}W + \mathbf{b}$, +and look at $\mathbf{m}$ where +$\mathbf{m}_j = 1 - \mathbf{h}_l - \mathbf{h}_j $ +for all elements $j$ that are not the correct label $l$.

+

The Crammer-Singer objective is to minimize the expectation over the dataset of +$\sum_j max(0, \mathbf{m}_{j})$.

+

Can you code this up as a training criterion and use it?

+

HINT: Start with the case of pure stochastic gradient descent, I think the batch case requires numpy's advanced indexing which not currently supported by autodiff.

+
+
+
+
In [ ]:
+
+
# Write your answer here
+
+ +
+
+
+ + \ No newline at end of file diff --git a/nbpages/Model - Logistic Regression with Theano.html b/nbpages/Model - Logistic Regression with Theano.html new file mode 100644 index 0000000..ba6c042 --- /dev/null +++ b/nbpages/Model - Logistic Regression with Theano.html @@ -0,0 +1,837 @@ + + + + + + + + + + + + + +
+

Logistic Regression with Theano (WIP)

+

This tutorial illustrates how to fit a ridge regression (aka $\ell_2$-regularized logistic regression) model to some dummy data, using Theano.

+

TODO: bring in the content from Deep Learning Tutorial

+
+
+
+
In [4]:
+
+
# Initial imports
+import numpy as np
+import theano.tensor as T
+from theano import shared, function
+rng = np.random.RandomState(123)
+
+ +
+
+
+
+
+
In [5]:
+
+
# Create a sample logistic regression problem.
+true_w = rng.randn(100)
+true_b = rng.randn()
+xdata = rng.randn(50, 100)
+ydata = (np.dot(xdata, true_w) + true_b) > 0.0
+
+ +
+
+
+
+
+
In [10]:
+
+
# Step 1. Declare Theano variables
+x = T.dmatrix()
+y = T.dvector()
+w = shared(rng.randn(100))
+b = shared(numpy.zeros(()))
+print "Initial model"
+print w.get_value()
+print b.get_value()
+
+ +
+
+
+
+
+
In [11]:
+
+
# Step 2. Construct Theano expression graph
+p_1 = 1 / (1 + T.exp(-T.dot(x, w) - b))
+xent = -y * T.log(p_1) - (1 - y) * T.log(1 - p_1)
+prediction = p_1 > 0.5
+cost = xent.mean() + 0.01 * (w ** 2).sum()
+gw, gb = T.grad(cost, [w, b])
+
+ +
+
+
+
+
+
In [12]:
+
+
# Step 3. Compile expressions to functions
+train = function(inputs=[x, y],
+                 outputs=[prediction, xent],
+                 updates={w:w - 0.1 * gw,
+                          b:b - 0.1 * gb})
+
+ +
+
+
+
+
+
In [16]:
+
+
# Step 4. Perform computation
+for loop in range(100):
+    pval, xval = train(xdata, ydata)
+    print xval.mean()
+
+ +
+
+
+ + \ No newline at end of file diff --git a/nbpages/Model - Multilayer Perceptron with PyAutodiff.html b/nbpages/Model - Multilayer Perceptron with PyAutodiff.html new file mode 100644 index 0000000..ff39949 --- /dev/null +++ b/nbpages/Model - Multilayer Perceptron with PyAutodiff.html @@ -0,0 +1,1063 @@ + + + + + + + + + + + + + +
+

Multilayer Perceptron

+

In the previous tutorial on linear SVMs, we looked at how training a model +consists in defining a training objective, and then minimizing it with respect +to model parameters by either stochastic or batch gradient descent.

+

In this tutorial we will augment our SVM with internal layers of hidden +units and turn our linear classifier into a multi-layer architecture. +An MLP with one internal layer is sometimes called a shallow architecture, +in contrast to an MLP with more internal layers which is sometimes called a deep architecture.

+

An MLP can be viewed as an SVM, where the input $\mathbf{x}$ is first transformed using a +learnt non-linear vector-valued transformation $\Phi$. +The purpose of this transformation is to map the input data into a space where it becomes linearly separable. +The vector $\Phi(\mathbf{x})$ is referred to as a hidden layer.

+

This tutorial will again tackle the problem of MNIST digit classification. +XXX

+
+
+
+
In [ ]:
+
+
import logging
+import sys
+import time
+
+import numpy as np
+from numpy import arange, dot, maximum, ones, tanh, zeros
+from numpy.random import uniform
+
+from skdata import mnist
+import autodiff
+
+from util import show_filters
+
+from util import hinge
+from util import ova_svm_prediction
+from util import ova_svm_cost
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- load and prepare the data set (even download if necessary)
+dtype = 'float32'
+n_examples = 10000
+n_classes = 10         # -- denoted L in the math expressions
+img_shape = (28, 28)
+
+data_view = mnist.views.OfficialVectorClassification(x_dtype=dtype)
+x = data_view.train.x[:n_examples]
+y = data_view.train.y[:n_examples]
+# -- prepare a "1-hot" version of the labels, denoted Y in the math
+y1 = -1 * ones((len(y), n_classes)).astype(dtype)
+y1[arange(len(y)), y] = 1
+
+ +
+
+
+
+

The MLP Model

+

Typically the function $\Phi$ is taken to be the function +$\mathbb{R}^{D_0} \rightarrow (-1, 1)^{D_1}$

+

$$ +\Phi(\mathbf{x}; V, \mathbf{c}) = \tanh( \mathbf{x} V + \mathbf{c}) +$$

+

in which $V \in \mathbb{R}^{D_0 \times D_1}$ is called a weight matrix, and +$\mathbf{c} \in \mathbb{R}^{D_1}$ is called a bias vector. +The integer $D_0$ is the number of elements in $\mathbf{x}$ (sometimes, number +of "input units"). +The integer $D_1$ is the number of "hidden units" of the MLP. +We abuse notation slightly here by using $\tanh(\mathbf{u})$ for a vector +$\mathbf{u}$ to denote +the vector of values $\tanh(\mathbf{u}i)$. +Sometimes other non-linear scalar functions are used instead of the tanh +function -- whichever one is used is called the _activation function of +layer $\Phi$.

+
+
+
+
In [ ]:
+
+
def tanh_layer(V, c, x):
+    return np.tanh(np.dot(x, V) + c)
+
+ +
+
+
+
+

When combined with an SVM classifier (recall previous tutorial), the full classification model can be written

+

$$ + \mathrm{MLP}(\mathbf{x}) = \mathrm{SVM}\left(\Phi(\mathbf{x}; V, \mathbf{c})); W, \mathbf{b} \right) +$$

+

This sort of MLP (or Artificial Neural Network - ANN) with a single hidden layer +is sometimes represented graphically as follows:

+

+

A single hidden layer of this form is sufficient to make the MLP a universal approximator. +However we will see shortly +that there are benefits to using many such hidden layers (deep learning). +See these course notes for an +introduction to MLPs, the back-propagation algorithm, and how to train MLPs.

+
+
+
+
In [ ]:
+
+
# define prediction function
+def mlp_prediction(V, c, W, b, x):
+    h = tanh_layer(V, c, x)
+    return ova_svm_prediction(W, b, h)
+
+def mlp_cost(V, c, W, b, x, y1):
+    h = tanh_layer(V, c, x)
+    return ova_svm_cost(W, b, h, y1)
+
+ +
+
+
+
+

Training an MLP

+

To train an MLP, we learn all parameters of the model ($W, \mathbf{b}, V, +\mathbf{c}$) by gradient descent, +just as we learned the parameters $W, \mathbf{b}$ previously when training the +SVM.

+

The initial values for the weights of a hidden layer ($V$) should be uniformly +sampled from a symmetric interval that depends on the activation function. +For the tanh activation function results obtained in [Xavier10]_ show that the +interval should be +$$ +\left[ -\sqrt{\frac{6}{D_0 + D_1}}, \sqrt{\frac{6}{D_0 + D_1}} \right] +$$

+

For the logistic sigmoid function $1 / (1 + e^{-u})$ the interval is slightly +different:

+

$$ +\left[ -4\sqrt{\frac{6}{D_0 + D_1}},4\sqrt{\frac{6}{D_0 + D_1}} \right] +$$.

+

This initialization ensures that at least early in training, each neuron operates in a regime of its activation function where information can easily be propagated both upward (activations flowing from inputs to outputs) and backward (gradients flowing from outputs to inputs).

+
+
+
+
In [ ]:
+
+
# initialize input layer parameters
+n_inputs = 784 # -- aka D_0
+n_hidden = 100 # -- aka D_1
+
+V = uniform(low=-np.sqrt(6.0 / (n_inputs + n_hidden)),
+                high=np.sqrt(6.0 / (n_inputs + n_hidden)),
+                size=(n_inputs, n_hidden)).astype(x.dtype)
+c = zeros(n_hidden, dtype=x.dtype)
+
+# now allocate the SVM at the top
+W = zeros((n_hidden, n_classes), dtype=x.dtype)                           
+b = zeros(n_classes, dtype=x.dtype)
+
+ +
+
+
+
+

As before, we train this model using stochastic gradient descent with +mini-batches. The difference is that we modify the cost function to include the +regularization term. L1_reg and L2_reg are the hyperparameters +controlling the weight of these regularization terms in the total cost function.

+
+
+
+
In [ ]:
+
+
# SGD minimization
+
+# -- do n_online_loops passes through the data set doing SGD
+#    This can be faster at the beginning than L-BFGS
+t0 = time.time()
+online_batch_size = 1
+n_batches = n_examples / online_batch_size
+V, c, W, b = autodiff.fmin_sgd(mlp_cost, (V, c, W, b),
+            streams={
+                'x': x.reshape((n_batches, online_batch_size, x.shape[1])),
+                'y1': y1.reshape((n_batches, online_batch_size, y1.shape[1]))},
+            loops=5,
+            stepsize=0.01,
+            print_interval=1000,
+            )
+print 'SGD took %.2f seconds' % (time.time() - t0)
+show_filters(V.T, img_shape, (10, 10))
+
+ +
+
+
+
+
+
In [ ]:
+
+
# L-BFGS minimization
+
+def batch_criterion(V, c, W, b):
+    return mlp_cost(V, c, W, b, x, y1)
+
+V, c, W, b = autodiff.fmin_l_bfgs_b(batch_criterion, (V, c, W, b), maxfun=20, m=20, iprint=1)
+
+print 'final_cost', batch_criterion(V, c, W, b)
+# -- N. B. the output from this command comes from Fortran, so iPython does not see it.
+#    To monitor progress, look at the terminal from which you launched ipython
+show_filters(V.T, img_shape, (10, 10))
+
+ +
+
+
+
+

Testing the MLP

+

Once the a classifier has been trained, we can test it for generalization accuracy on the test set. We test it by making predictions for the examples in the test set and counting up the number of classification mistakes.

+
+
+
+
In [ ]:
+
+
train_predictions = mlp_prediction(V, c, W, b, x)
+train_errors = y != train_predictions
+print 'Current train set error rate', np.mean(train_errors)
+
+test_predictions = mlp_prediction(V, c, W, b, data_view.test.x[:])
+test_errors = data_view.test.y[:] != test_predictions
+print 'Current test set error rate', np.mean(test_errors)
+
+ +
+
+
+
+

Exercises

+

Try the following exercises out to get a better feel for training MLPs.

+
+
+

Exercise: Breaking symmetry

+

It might seem more natural to initialize all of the MLP parameters to $0$. +What goes wrong when you do this?

+
+
+

Exercise: SGD vs. L-BFGS

+

Try running L-BFGS starting from the original random initialization -- how good does it get on train and test, and how long does it take to find a solution.

+

Now repeat that with various amounts of SGD before the L-BFGS. What happens?

+

Now raise the number of examples seen per iteration of SGD. How does this affect the convergence of SGD and its value as a pre-conditioner?

+
+
+

Exercise: Overfitting

+

Regularization

+
+
+

Tips and Tricks for training MLPs

+

There are several hyper-parameters in the above code, which are not (and, +generally speaking, cannot be) optimized by gradient descent. +The design of outer-loop algorithms for optimizing them is a topic of ongoing +research. +Over the last 25 years, researchers have devised various rules of thumb for choosing them. +A very good overview of these tricks can be found in Efficient +BackProp by Yann LeCun, +Leon Bottou, Genevieve Orr, and Klaus-Robert Mueller. Here, we summarize +the same issues, with an emphasis on the parameters and techniques that we +actually used in our code.

+

Tips and Tricks: Nonlinearity

+

Which non-linear activation function should you use in a neural network? +Two of the most common ones are the logistic sigmoid and the tanh functions. +For reasons explained in Section 4.4, nonlinearities that +are symmetric around the origin are preferred because they tend to produce +zero-mean inputs to the next layer (which is a desirable property). +Empirically, we have observed that the tanh has better convergence properties.

+

Tips and Tricks: Weight initialization

+

At initialization we want the weights to be small enough around the origin +so that the activation function operates near its linear regime, where gradients are +the largest. Otherwise, the gradient signal used for learning is attenuated by +each layer as it is propagated from the classifier towards the inputs. +Other desirable properties, especially for deep networks, +are to conserve variance of the activation as well as variance of back-propagated gradients from layer to layer. +This allows information to flow well upward and downward in the network and +reduces discrepancies between layers. +The initialization used above represents a good compromise between these two +constraints. +For mathematical considerations, please refer to [Xavier10]_.

+

Tips and Tricks: Learning Rate

+

Optimization by stochastic gradient descent is very sensitive to the step size or learning rate. +There is a great deal of literature on how to choose a the learning rate, and how to change it during optimization. +The simplest solution is to use a constant rate. Rule of thumb: try +several log-spaced values ($10^{-1}, 10^{-2}, \ldots$) and narrow the +(logarithmic) grid search to the region where you obtain the lowest +validation error.

+

Decreasing the learning rate over time can help a model to settle down into a +[local] minimum. +One simple rule for doing that is $\frac{\mu_0}{1 + d\times t}$ where +$\mu_0$ is the initial rate (chosen, perhaps, using the grid search +technique explained above), $d$ is a so-called "decrease constant" +which controls the rate at which the learning rate decreases (typically, a +smaller positive number, $10^{-3}$ and smaller) and $t$ is the epoch/stage.

+

Section 4.7 details +procedures for choosing a learning rate for each parameter (weight) in our +network and for choosing them adaptively based on the error of the classifier.

+

Tips and Tricks: Number of hidden units

+

The number of hidden units that gives best results is dataset-dependent. +Generally speaking, the more complicated the input distribution is, the more capacity the network +will require to model it, and so the larger the number of hidden units thatwill be needed (note that the number of weights in a layer, perhaps a more direct +measure of capacity, is $D_0\times D_1$ (recall $D_0$ is the number of inputs and +$D_1$ is the number of hidden units).

+

Unless we employ some regularization scheme (early stopping or L1/L2 +penalties), a typical number of hidden units vs. generalization performance graph will be U-shaped.

+

Tips and Tricks: Norm Regularization

+

Typical values to try for the L1/L2 regularization parameter $\lambda$ are $10^{-2}, 10^{-3}, \ldots$. +It can be useful to regularize the topmost layers in an MLP (closest +to and including the classifier itself) to prevent them from overfitting noisy +hidden layer features, and to encourage the features themselves to be more +discriminative.

+
+ + \ No newline at end of file diff --git a/nbpages/Notation for Machine Learning.html b/nbpages/Notation for Machine Learning.html new file mode 100644 index 0000000..0b55527 --- /dev/null +++ b/nbpages/Notation for Machine Learning.html @@ -0,0 +1,819 @@ + + + + + + + + + + + + + +
+

Notational Conventions:

+

This "notebook" is essentially a static page describing the notational conventions used throughout the tutorials. At some point it might migrate to a normal webpage, but for now it is here, being served up by IPython itself.

+

Data Set Notation

+

We label data sets as $\mathcal{D}$. +When the distinction is important, we +indicate train, validation, and test sets as:

+
    +
  • training data $\mathcal{D}_{train}$
  • +
  • validation data $\mathcal{D}_{valid}$
  • +
  • testing data $\mathcal{D}_{test}$
  • +
+

We only ever train on training data, but we measure performance on validation data as a way of choosing the best hyperparameters (model selection). +Testing data is only used for estimating generalization after model selection and training.

+

The tutorials mostly deal with classification problems, where each data set +$\mathcal{D}$ is an indexed set of pairs $(x^{(i)},y^{(i)})$. We +use superscripts to distinguish training set examples: +$x^{(i)} \in \mathcal{R}^D$ is thus the i-th training example of dimensionality $D$. +Similarly, +$y^{(i)} \in {0, ..., L}$ is the i-th label assigned to input +$x^{(i)}$. It is straightforward to extend these examples to +ones where $y^{(i)}$ has other types (e.g. Gaussian for regression, +or groups of multinomials for predicting multiple symbols).

+

Math and Python Conventions

+
    +
  • +

    Expressions that appear in fixed-width font like a = b + c are meant to be + interpreted as Python code, whereas expressions appearing in italics like $a + = b + c$ are meant to be interpreted as math notation.

    +
  • +
  • +

    In math notation, non-bold lower-case symols denote scalars.

    +
  • +
  • +

    In math notation, bold lower-case symbols like $\mathbf{x}$ and + $\mathbf{h}$ denote vectors.

    +
  • +
  • +

    In math notation, upper-case symbols like $W$ and $V$ typically denote + matrices.

    +
  • +
  • +

    In the LaTeX-powered "math" expressions the notation $[a, b]$ denotes + the continuous inclusive range of real-valued numbers $u$ satisfying + $0 \leq x \leq 1$. In contrast, the Python syntax [a, b] denotes a + list data structure of two elements.

    +
  • +
  • +

    Python and NumPy tend to favor C-style "row-major" matrices, and we + will follow that convention in the math sections too. + Consequently, vector-matrix products will typically be written with + the vector on the left and the matrix on the right, as in + $\mathbf{h}V$.

    +
  • +
+

Symbols and Acronyms

+
    +
  • $D$: number of input dimensions
  • +
  • $D_h^{(i)}$: number of hidden units in the $i$-th layer
  • +
  • DAE: De-noising Auto-Encoder
  • +
  • $f_{\theta}(x)$, $f(x)$ : classification function associated with a model $P(Y|x,\theta)$, defined as ${\rm argmax}_k P(Y=k|x,\theta)$ + Note that we will often drop the $\theta$ subscript
  • +
  • L: number of labels
  • +
  • $\mathcal{L}(\theta, \cal{D})$: log-likelihood of model with parameters $\theta$ on data $\cal{D}$
  • +
  • $\ell(\theta, \cal{D})$ empirical loss of the prediction function $f$ + parameterized by $\theta$ on data set $\cal{D}$
  • +
  • MLP: Multi-Layer Perceptron (usually with one hidden layer)
  • +
  • NLL: negative log-likelihood
  • +
  • RBM: Restricted Boltzmann Machine
  • +
  • SVM: Support Vector Machine
  • +
  • $\theta$: set of all parameters for a given model
  • +
+
+ + + \ No newline at end of file diff --git a/nbpages/Preprocessing - Image Whitening.html b/nbpages/Preprocessing - Image Whitening.html new file mode 100644 index 0000000..2fd6bb1 --- /dev/null +++ b/nbpages/Preprocessing - Image Whitening.html @@ -0,0 +1,945 @@ + + + + + + + + + + + + + +
+

Learning features from Image Patches

+

Unsupervised learning algorithms have often tackled image modeling by first modeling small image patches. +This tutorial walks through the process of learning features from raw image patches, and then introduces a whitening algorithm that is often used to pre-process image patches before learning. +Whitening is biologically plausible, gives rise to physiologically normal first layer features, and typically yields better supervised performance.

+

The whitening algorithm introduced here is borrowed from Adam Coates' +matlab sample code accompanying his paper +The Importance of Encoding Versus Training with Sparse Coding and Vector Quantization with Andrew Ng at ICML 2011.

+

Whitening is often not discussed in detail in papers, but it can be crucial to reproducing state-of-the-art performance. The Stanford UFLDL Tutorial +has a nice section on whitening.

+
+
+

Learning an AutoEncoder on Raw Patches

+

Building on the previous notebook on autoencoders, let's see how a standard autoencoder works out of the box on image patches.

+
+
+
+
In [ ]:
+
+
# -- SCRIPT INITIALIZATION
+
+import numpy as np
+import autodiff
+from util import show_filters
+from util import random_patches
+from util import mean_and_std
+from skdata import cifar10
+
+n_examples = 10000
+n_patches = 10000
+patch_H = 8
+patch_W = 8
+dtype='float32'
+# -- TIP: restart the IPython kernel to clear out memory
+data_view = cifar10.view.OfficialImageClassification(x_dtype=dtype, n_train=n_examples) 
+x = data_view.train.x[:n_examples]
+x_patches = random_patches(x.transpose(0, 3, 1, 2), n_patches, patch_H, patch_W, np.random)
+x_patches_flat = x_patches.reshape(n_patches, -1)
+
+# -- define a show_filters function for our rgb data
+def show_flat_rgb(X, grid_shp):
+    K = patch_W * patch_H
+    # this is a bit of funny business to show RGB
+    show_filters((X[:, :K], X[:, K:2 * K], X[:, 2 * K:], None), (patch_H, patch_W), grid_shp) 
+
+show_flat_rgb(x_patches_flat, (10, 10))
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- DEFINE THE AUTO-ENCODER
+
+def logistic(u):
+    """Return logistic sigmoid of float or ndarray `u`"""
+    return 1.0 / (1.0 + exp(-u))
+
+def squared_distance(x, z):
+    return ((x - z) ** 2).sum(axis=1)
+
+
+def training_criterion(W, b, c, x):
+    h = logistic(dot(x, W) + b)
+    z = logistic(dot(h, W.T) + c)
+    return squared_distance(x, z).mean()
+
+# -- tip: choose the number of hidden units as a pair, so that show_filters works
+n_visible = x_patches_flat.shape[1]
+n_hidden2 = (20, 20)
+n_hidden = np.prod(n_hidden2)
+W = np.random.uniform(
+        low=-4 * np.sqrt(6. / (n_hidden + n_visible)),
+        high=4 * np.sqrt(6. / (n_hidden + n_visible)),
+        size=(n_visible, n_hidden)).astype(dtype)
+b = np.zeros(n_hidden).astype(dtype)
+c = np.zeros(n_visible).astype(dtype)
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- TRAIN THE AUTOENCODER ON RAW PATCHES
+
+streams={'x': x_patches.reshape((n_examples, 1, n_visible))}
+W, b, c = autodiff.fmin_sgd(training_criterion,
+        args=(W, b, c),
+        streams=streams,
+        stepsize=0.01,
+        loops=5,  # -- fmin_sgd can iterate over the streams repeatedly
+        print_interval=1000,
+        )
+show_flat_rgb(W.T, n_hidden2)
+
+ +
+
+
+
+

As you will probably see - despite the recontruction error dropping steadily, the filters of our auto-encoder do not resemble anything like Gabor edge detectors. To see Gabors, we will need to whiten the image patches.

+
+
+

Learning an AutoEncoder on Whitened Patches

+

There are several techniques for whitening, this one combines a technique used in recent papers from Andrew Ng's group at Stanford, with techniques developed by Nicolas Pinto at MIT.

+
+
+
+
In [ ]:
+
+
# -- fun hyper-parameters to optimize. By fun, I admittedly mean annoying.
+remove_mean = True
+hard_beta = True
+beta = 10.0
+gamma = 0.01
+
+def contrast_normalize(patches):
+    X = patches
+    if X.ndim != 2:
+        raise TypeError('contrast_normalize requires flat patches')
+    if remove_mean:
+        xm = X.mean(1)
+    else:
+        xm = X[:,0] * 0
+    Xc = X - xm[:, None]
+    l2 = (Xc * Xc).sum(axis=1)
+    figure()
+    title('l2 of image patches')
+    hist(l2)
+    if hard_beta:
+        div2 = np.maximum(l2, beta)
+    else:
+        div2 = l2 + beta
+    X = Xc / np.sqrt(div2[:, None])
+    return X
+
+def ZCA_whiten(patches):
+    # -- ZCA whitening (with band-pass)
+
+    # Algorithm from Coates' sc_vq_demo.m
+
+    X = patches.reshape(len(patches), -1).astype('float64')
+
+    X = contrast_normalize(X)
+    print 'patch_whitening_filterbank_X starting ZCA'
+    M, _std = mean_and_std(X)
+    Xm = X - M
+    assert Xm.shape == X.shape
+    print 'patch_whitening_filterbank_X starting ZCA: dot', Xm.shape
+    C = np.dot(Xm.T, Xm) / (Xm.shape[0] - 1)
+    print 'patch_whitening_filterbank_X starting ZCA: eigh'
+    D, V = np.linalg.eigh(C)
+    figure()
+    plot(D)
+    title('Eigenspectrum of image patches')
+    print 'patch_whitening_filterbank_X starting ZCA: dot', V.shape
+    P = np.dot(np.sqrt(1.0 / (D + gamma)) * V, V.T)
+    assert M.ndim == 1
+    return M, P, X
+
+ZCA_M, ZCA_P, ZCA_X = ZCA_whiten(x_patches_flat)
+x_white_flat = dot(ZCA_X - ZCA_M, ZCA_P)
+figure()
+show_flat_rgb(x_white_flat[:100], (10, 10))
+title('ZCA-whitened image patches')
+show()
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- TRAIN THE AUTOENCODER ON WHITENED PATCHES
+
+# Remember to re-initialize the model parameters if you were training them
+# on the raw patches earlier
+
+whitened_streams={'x': x_white_flat.reshape((n_examples, 1, n_visible))}
+W, b, c = autodiff.fmin_sgd(training_criterion,
+        args=(W, b, c),
+        streams=whitened_streams,
+        stepsize=0.01,
+        loops=5,  # -- fmin_sgd can iterate over the streams repeatedly
+        print_interval=1000,
+        )
+show_flat_rgb(W.T, n_hidden2)
+
+ +
+
+
+ + \ No newline at end of file diff --git a/nbpages/Theano Tutorial (Part 1 - Introduction).html b/nbpages/Theano Tutorial (Part 1 - Introduction).html new file mode 100644 index 0000000..551d676 --- /dev/null +++ b/nbpages/Theano Tutorial (Part 1 - Introduction).html @@ -0,0 +1,875 @@ + + + + + + + + + + + + + +
+

Theano Tutorial (Part 1 - Introduction)

+

Theano is a Python library that allows you to define, optimize, and evaluate mathematical expressions involving multi-dimensional arrays efficiently. Theano features:

+
    +
  • tight integration with numpy – Use numpy.ndarray in Theano-compiled functions.
  • +
  • transparent use of a GPU – Perform data-intensive calculations up to 140x faster than with CPU.(float32 only)
  • +
  • efficient symbolic differentiation – Theano does your derivatives for function with one or many inputs.
  • +
  • speed and stability optimizations – Get the right answer for log(1+x) even when x is really tiny.
  • +
  • dynamic C code generation – Evaluate expressions faster.
  • +
  • extensive unit-testing and self-verification – Detect and diagnose many types of mistake.
  • +
+

Theano has been powering large-scale computationally intensive scientific investigations since 2007.

+
+
+

Download

+

Theano is now available on +PyPI, and can be installed via +$ easy_install Theano + -- or -- +$ pip install Theano

+

or by downloading and unpacking the tarball and typing python setup.py install.

+

Those interested in bleeding-edge features should obtain the latest development version, available via: +git clone git://github.com/Theano/Theano.git

+

You can then place the checkout directory on your $PYTHONPATH or use python setup.py develop to install a .pth into your site-packages directory, so that when you pull updates via Git, they will be automatically reflected the “installed” version. For more information about installation and configuration, see +installing Theano.

+

When Theano is installed, you will be able to import it in Python like this:

+
+
+
+
In [ ]:
+
+
import theano
+from theano import tensor as TT
+
+ +
+
+
+
+

Credits

+

Theano has been developed by the LISA Machine Learning group at the University of Montreal.

+
    +
  • Yoshua Bengio is the lab director who permitted and supported Theano's development.
  • +
  • Olivier Breuleux and James Bergstra wrote the initial versions (starting 2007).
  • +
  • Frederic Bastien and now Pascal Lamblin have taken over as the lead maintainers.
  • +
  • Razvan Pascanur contributed the scan module, and much maintenance.
  • +
+

Many lab members and members of the Python community at large have made significant and helpful contributions.

+
+
+

NumPy Background

+

Here are some quick guides to NumPy:

+ +
+
+

Matrix conventions for machine learning

+

Rows are horizontal and columns are vertical. +Every row is an example. Therefore, inputs[10,5] is a matrix of 10 examples +where each example has dimension 5. If this would be the input of a +neural network then the weights from the input to the first hidden +layer would represent a matrix of size (5, #hid).

+

Consider this array:

+
+
+
+
In [ ]:
+
+
a = np.asarray([[1., 2], [3, 4], [5, 6]])
+print a
+print a.shape
+
+ +
+
+
+
+

This is a 3x2 matrix, i.e. there are 3 rows and 2 columns.

+

To access the entry in the 3rd row (row #2) and the 1st column (column #0):

+
+
+
+
In [ ]:
+
+
print a[2, 0]
+
+ +
+
+
+
+

To remember this, keep in mind that we read left-to-right, top-to-bottom, +so each thing that is contiguous is a row. That is, there are 3 rows +and 2 columns.

+
+
+

Broadcasting

+

Numpy does broadcasting of arrays of different shapes during +arithmetic operations. What this means in general is that the smaller +array (or scalar) is broadcasted across the larger array so that they have +compatible shapes. The example below shows an instance of +broadcastaing:

+
+
+
+
In [ ]:
+
+
a = numpy.asarray([1.0, 2.0, 3.0])
+b = 2.0
+print a * b
+
+ +
+
+
+
+

The smaller array b (actually a scalar here, which works like a 0-d array) in this case is broadcasted to the same size +as a during the multiplication. This trick is often useful in +simplifying how expression are written. More detail about broadcasting +can be found in the numpy user guide.

+
+ + \ No newline at end of file diff --git a/nbpages/Theano Tutorial (Part 2 - Simple Computation).html b/nbpages/Theano Tutorial (Part 2 - Simple Computation).html new file mode 100644 index 0000000..189b6f2 --- /dev/null +++ b/nbpages/Theano Tutorial (Part 2 - Simple Computation).html @@ -0,0 +1,1058 @@ + + + + + + + + + + + + + +
+

Theano Tutorial (Part 2 - Simple Computation)

+

In this first Theano tutorial we'll see how to do a simple calculation involving scalars and matrices.

+
+
+

Adding Two Scalars

+

To get us started with Theano and get a feel of what we're working with, +let's make a simple function: add two numbers together. Here is how you do +it:

+
+
+
+
In [ ]:
+
+
import theano.tensor as T
+from theano import function
+x = T.dscalar('x')
+y = T.dscalar('y')
+z = x + y
+f = function([x, y], z)
+
+ +
+
+
+
+

And now that we've created our function we can use it:

+
+
+
+
In [ ]:
+
+
print f(2, 3)
+print f(16.3, 12.1)
+
+ +
+
+
+
+

Let's break this down into several steps. The first step is to define +two symbols (Variables) representing the quantities that you want +to add. Note that from now on, we will use the term +Variable to mean "symbol" (in other words, +x, y, z are all Variable objects). The output of the function +f is a numpy.ndarray with zero dimensions.

+

If you are following along and typing into an interpreter, you may have +noticed that there was a slight delay in executing the function +instruction. Behind the scene, f was being compiled into C code.

+
+
+

Note on Symbolic Variables:

+

A Variable is the main data structure you work with when +using Theano. The symbolic inputs that you operate on are +Variables and what you get from applying various operations to +these inputs are also Variables. For example, when I type +"x = theano.tensor.ivector(); y = -x" then x and y are both Variables, i.e. instances of the +theano.gof.graph.Variable class. The +type of both x and y is theano.tensor.ivector.

+
+
+

Theno Step 1 - Declaring Variables

+
+
+
+
In [ ]:
+
+
x = T.dscalar('x')
+y = T.dscalar('y')
+
+ +
+
+
+
+

In Theano, all symbols must be typed. In particular, T.dscalar +is the type we assign to "0-dimensional arrays (scalar) of doubles +(d)". It is a Theano :ref:type.

+

dscalar is not a class. Therefore, neither x nor y +are actually instances of dscalar. They are instances of +:class:TensorVariable. x and y +are, however, assigned the theano Type dscalar in their type +field, as you can see here:

+
+
+
+
In [ ]:
+
+
print type(x)
+print x.type
+print T.dscalar
+print x.type is T.dscalar
+
+ +
+
+
+
+

By calling T.dscalar with a string argument, you create a +Variable representing a floating-point scalar quantity with the +given name. If you provide no argument, the symbol will be unnamed. Names +are not required, but they can help debugging.

+

More will be said in a moment regarding Theano's inner structure. You +could also learn more by looking into :ref:graphstructures.

+
+
+

Theano Step 2 - Symbolic Expressions

+

The second step is to combine x and y into their sum z:

+
+
+
+
In [ ]:
+
+
z = x + y
+
+ +
+
+
+
+

z is yet another Variable which represents the addition of +x and y. You can use the :ref:pp <libdoc_printing> +function to pretty-print out the computation associated to z.

+
+
+
+
In [ ]:
+
+
from theano.printing import pp
+print pp(z)   # -- prints (x + y)
+
+ +
+
+
+
+

Theano Step 3 - Compiling a Function

+

The last step is to create a function taking x and y as inputs +and giving z as output:

+
+
+
+
In [ ]:
+
+
f = function([x, y], z)
+
+ +
+
+
+
+

The first argument to function() is a list of Variables +that will be provided as inputs to the function. The second argument +is a single Variable or a list of Variables. For either case, the second +argument is what we want to see as output when we apply the function. f may +then be used like a normal Python function.

+
+
+

Note on eval

+

As a shortcut, you can skip step 3, and just use a variable's +eval() method. The eval() method is not as flexible +as function() but it can do everything we've covered in +the tutorial so far. It has the added benefit of not requiring +you to import function(). Here is how eval() works:

+
import theano.tensor as T
+x = T.dscalar('x')
+y = T.dscalar('y')
+z = x + y
+z.eval({x : 16.3, y : 12.1})
+array(28.4)
+
+

We passed eval a dictionary mapping symbolic theano +variables to the values to substitute for them, and it returned +the numerical value of the expression. eval() will be slower the first time you call it on a variable -- +it needs to call function() to compile the expression behind +the scenes. Subsequent calls to eval() on that same variable +will be fast, because the variable caches the compiled function.

+
+
+

Adding Two Matrices

+

You might already have guessed how to do this. Indeed, the only change +from the previous example is that you need to instantiate x and +y using the matrix Types:

+
+
+
+
In [ ]:
+
+
x = T.dmatrix('x')
+y = T.dmatrix('y')
+z = x + y
+f = function([x, y], z)
+
+ +
+
+
+
+

dmatrix is the Type for matrices of doubles. Then we can use +our new function on 2D arrays:

+
+
+
+
In [ ]:
+
+
f([[1, 2], [3, 4]], [[10, 20], [30, 40]])
+
+ +
+
+
+
+

The variable is a NumPy array. We can also use NumPy arrays directly as +inputs:

+
+
+
+
In [ ]:
+
+
import numpy
+f(numpy.array([[1, 2], [3, 4]]), numpy.array([[10, 20], [30, 40]]))
+
+ +
+
+
+
+

It is possible to add scalars to matrices, vectors to matrices, +scalars to vectors, etc. The behavior of these operations is defined by Theano's broadcasting behavior: +[libdoc] broadcasting in NumPy and Theano.

+
+
+

The following types are available:

+
    +
  • byte: bscalar, bvector, bmatrix, brow, bcol, btensor3, btensor4
  • +
  • 16-bit integers: wscalar, wvector, wmatrix, wrow, wcol, wtensor3, wtensor4
  • +
  • 32-bit integers: iscalar, ivector, imatrix, irow, icol, itensor3, itensor4
  • +
  • 64-bit integers: lscalar, lvector, lmatrix, lrow, lcol, ltensor3, ltensor4
  • +
  • float: fscalar, fvector, fmatrix, frow, fcol, ftensor3, ftensor4
  • +
  • double: dscalar, dvector, dmatrix, drow, dcol, dtensor3, dtensor4
  • +
  • complex: cscalar, cvector, cmatrix, crow, ccol, ctensor3, ctensor4
  • +
+

The previous list is not exhaustive and a guide to all types compatible +with NumPy arrays may be found here: +[libdoc] tensor creation.

+

Note that you, the user---not the system architecture---have to choose whether your + program will use 32- or 64-bit integers (i prefix vs. the l prefix) + and floats (f prefix vs. the d prefix).

+
+
+

More Elementwise Computations (Logistic Sigmoid)

+

Here's another straightforward example, though a bit more elaborate +than adding two numbers together. Let's say that you want to compute +the logistic curve, which is given by:

+

$s(x) = \frac{1}{1 + e^{-x})}$

+

It's called a sigmoid curve because it looks "S"-shaped. If you plot it, you'll see why:

+
+
+
+
In [ ]:
+
+
x = np.arange(-5, 5, .1)
+title('logistic sigmoid')
+line = plot(x, 1 / (1 + np.exp(-x)))
+
+ +
+
+
+
+

NumPy and Theano both evaluate scalar functions like this element-wise when operating on tensor quantities such as vectors and matrices. +So if you want to compute the logistic sigmoid of each number in x, then you do it by applying all of the required operations -- division, addition, exponentiation, and division -- on entire tensors at once.

+
+
+
+
In [ ]:
+
+
x = T.dmatrix('x')
+s = 1 / (1 + T.exp(-x))
+logistic = function([x], s)
+print logistic([[0, 1], [-1, -2]])
+
+ +
+
+
+
+

At this point it would be wise to begin familiarizing yourself +more systematically with Theano's fundamental objects and operations by browsing +this section of the library: +Theano basic tensor functionality.

+

As the tutorial unfolds, you should also gradually acquaint yourself with the other +relevant areas of the library and with the relevant subjects of the documentation +entrance page.

+
+
+

Exercise

+

Modify and execute the following code to compute the expression: $a^2 + b^2 + 2 a b$.

+
+
+
+
In [ ]:
+
+
import theano
+a = theano.tensor.vector()      # declare variable
+out = a + a ** 10               # build symbolic expression
+f = theano.function([a], out)   # compile function
+print f([0, 1, 2])              # prints `array([0, 2, 1026])`
+
+ +
+
+
+ + \ No newline at end of file diff --git a/nbpages/Theano Tutorial (Part 3 - Functions and Shared Variables).html b/nbpages/Theano Tutorial (Part 3 - Functions and Shared Variables).html new file mode 100644 index 0000000..c7f1ddf --- /dev/null +++ b/nbpages/Theano Tutorial (Part 3 - Functions and Shared Variables).html @@ -0,0 +1,945 @@ + + + + + + + + + + + + + +
+

Theano Tutorial (Part 3 - Functions and Shared Variables)

+

The previous tutorials (Part 1, Part 2) have already used theano.function to create callable objects from Theano graphs. This tutorial will walk through the various capabilities of function and the important concept of shared variables.

+

The library documentation of function is a good companion to this tutorial.

+
+
+
+
In [ ]:
+
+
# -- imports we need for this tutorial
+from theano import tensor as T
+from theano import function, shared
+
+ +
+
+
+
+

Computing More than one Thing at the Same Time

+

Theano supports functions with multiple outputs. For example, we can +compute the elementwise difference, absolute difference, and +squared difference between two matrices a and b at the same time.

+

When we use the function f, it returns the three computed results as a list.

+
+
+
+
In [ ]:
+
+
a, b = T.dmatrices('a', 'b')
+diff = a - b
+abs_diff = abs(diff)
+diff_squared = diff ** 2
+
+f = function([a, b], [diff, abs_diff, diff_squared])
+
+print f([[1, 1], [1, 1]], [[0, 1], [2, 3]])
+
+ +
+
+
+
+

(Note that dmatrices produces as many outputs as names that you provide. +It is a shortcut for allocating symbolic variables that we will often use in the tutorials, +but it is not so typically used outside tutorial examples.)

+
+
+

Setting a Default Value for an Argument

+

Let's say you want to define a function that adds two numbers, except +that if you only provide one number, the other input is assumed to be +one. In Python, the default value for parameters achieves this effect. +In Theano you can achieve this effect with a Param object.

+

This makes use of the Param class which allows +you to specify properties of your function's parameters with greater detail. Here we +give a default value of 1 for y by creating a Param instance with +its default field set to 1. Inputs with default values must follow inputs without default +values (like Python's functions). There can be multiple inputs with default values. These parameters can +be set positionally or by name, as in standard Python.

+
+
+
+
In [ ]:
+
+
# -- Theano version of lambda x, y=1: x + y
+
+from theano import Param
+x, y = T.dscalars('x', 'y')
+z = x + y
+f = function([x, Param(y, default=1)], z)
+
+print f(33)
+print f(33, 2)
+print f(34)
+
+ +
+
+
+
+
+
In [ ]:
+
+
# -- Theano version of lambda x, y=1, w_by_name=2: (x + y) * w
+x, y, w = T.dscalars('x', 'y', 'w')
+z = (x + y) * w
+g = function([x, Param(y, default=1), Param(w, default=2, name='w_by_name')], z)
+print g(33)
+print g(33, 2)
+print g(33, 0, 1)
+print g(33, w_by_name=1)
+print g(33, w_by_name=1, y=0)
+
+ +
+
+
+
+

N.B.Param does not know the name of the local variables y and w +that are passed to it as arguments. If the symbolic variable objects have name +attributes (set by dscalars in the example above) then these are the +names of the keyword parameters in the functions that we build. This is +the mechanism at work in Param(y, default=1). In the case of +Param(w, default=2, name='w_by_name'), we override the symbolic variable's name +attribute with a new name to be used as the parameter name for g.)

+
+
+

Maintaining State with Shared Variables

+

It is also possible to make a function with an internal state. For example, let’s say we want to make an accumulator: at the beginning, the state is initialized to zero. Then, on each function call, the state is incremented by the function’s argument.

+

First let’s define the accumulator function. It adds its argument to the internal state, and returns the old state value.

+
+
+
+
In [ ]:
+
+
from theano import shared
+state = shared(0)
+inc = T.iscalar('inc')
+accumulator = function([inc], state, updates=[(state, state+inc)])
+
+ +
+
+
+
+

This code introduces a few new concepts. The shared function constructs so-called shared variables. These are hybrid symbolic and non-symbolic variables whose value may be shared between multiple functions. Shared variables can be used in symbolic expressions just like the objects returned by dmatrices(...) but they also have an internal value that defines the value taken by this symbolic variable in all the functions that use it. It is called a shared variable because its value is shared between many functions. The value can be accessed and modified by the .get_value() and .set_value() methods. We will come back to this soon.

+

The other new thing in this code is the updates parameter of function. updates must be supplied with a list of pairs of the form (shared-variable, new expression). It can also be a dictionary whose keys are shared-variables and values are the new expressions. Either way, it means “whenever this function runs, it will replace the .value of each shared variable with the result of the corresponding expression”. Above, our accumulator replaces the state‘s value with the sum of the state and the increment amount.

+

Let’s try it out!

+
+
+
+
In [ ]:
+
+
print state.get_value()
+print accumulator(1)
+print state.get_value()
+print accumulator(300)
+print state.get_value()
+
+ +
+
+
+
+

It is possible to reset the state. Just use the .set_value() method:

+
+
+
+
In [ ]:
+
+
state.set_value(-1)
+print accumulator(3)
+print state.get_value()
+
+ +
+
+
+
+

As we mentioned above, you can define more than one function to use the same shared variable. These functions can all update the value.

+
+
+
+
In [ ]:
+
+
decrementor = function([inc], state, updates=[(state, state-inc)])
+print decrementor(2)
+print state.get_value()
+
+ +
+
+
+
+

You might be wondering why the updates mechanism exists. You can always achieve a similar result by returning the new expressions, and working with them in NumPy as usual. While the updates mechanism can be a syntactic convenience, it is mainly there for efficiency. Updates to shared variables can sometimes be done more quickly using in-place algorithms (e.g. low-rank matrix updates). Also, Theano has more control over where and how shared variables are allocated, which is one of the important elements of getting good performance on the GPU.

+

Replacing Subgraphs at Compile Time with givens

+

It may happen that you expressed some formula using a shared variable, but you do not want to use its value. In this case, you can use the givens parameter of function which replaces a particular node in a graph for the purpose of one particular function.

+
+
+
+
In [ ]:
+
+
fn_of_state = state * 2 + inc
+foo = T.lscalar()        # the type (lscalar) must match the shared variable we
+                         # are replacing with the ``givens`` list
+skip_shared = function([inc, foo], fn_of_state, givens=[(state, foo)])
+print skip_shared(1, 3)  # we're using 3 for the state, not state.value
+print state.get_value()  # old state still there, we didn't use it
+
+ +
+
+
+
+

The givens parameter can be used to replace any symbolic variable, not just a shared variable. You can replace constants, and any other expression as long as the new expression has the same type as the one you are replacing.

+

A good way of thinking about the givens is as a mechanism that allows you to replace any part of your formula with a different expression that evaluates to a tensor of same shape and dtype.

+
+
+

Compilation Mode

+

WIP, TODO, etc.

+
+ + \ No newline at end of file diff --git a/nbpages/Theano Tutorial (Part 4 - Random Variables).html b/nbpages/Theano Tutorial (Part 4 - Random Variables).html new file mode 100644 index 0000000..74133b8 --- /dev/null +++ b/nbpages/Theano Tutorial (Part 4 - Random Variables).html @@ -0,0 +1,859 @@ + + + + + + + + + + + + + +
+

Using Random Numbers

+

Because in Theano you first express everything symbolically and +afterwards compile this expression to get functions, +using pseudo-random numbers is not as straightforward as it is in +NumPy, though also not too complicated.

+

The way to think about putting randomness into Theano's computations is +to put random variables in your graph. Theano will allocate a NumPy +RandomStream object (a random number generator) for each such +variable, and draw from it as necessary. We will call this sort of +sequence of random numbers a random stream. Random streams are at +their core shared variables, so the observations on shared variables +hold here as well. Theanos's random objects are defined and implemented in +:ref:RandomStreams<libdoc_tensor_shared_randomstreams> and, at a lower level, +in :ref:RandomStreamsBase<libdoc_tensor_raw_random>.

+

Brief Example

+

Here's a brief example. The setup code is:

+

.. If you modify this code, also change : +.. theano/tests/test_tutorial.py:T_examples.test_examples_9

+

.. code-block:: python

+
from theano.tensor.shared_randomstreams import RandomStreams
+srng = RandomStreams(seed=234)
+rv_u = srng.uniform((2,2))
+rv_n = srng.normal((2,2))
+f = function([], rv_u)
+g = function([], rv_n, no_default_updates=True)    #Not updating rv_n.rng
+nearly_zeros = function([], rv_u + rv_u - 2 * rv_u)
+
+

Here, 'rv_u' represents a random stream of 2x2 matrices of draws from a uniform +distribution. Likewise, 'rv_n' represents a random stream of 2x2 matrices of +draws from a normal distribution. The distributions that are implemented are +defined in :class:RandomStreams and, at a lower level, in :ref:raw_random<libdoc_tensor_raw_random>.

+

.. TODO: repair the latter reference on RandomStreams

+

Now let's use these objects. If we call f(), we get random uniform numbers. +The internal state of the random number generator is automatically updated, +so we get different random numbers every time.

+
+
+
+

f_val0 = f() +f_val1 = f() #different numbers from f_val0

+
+
+
+

When we add the extra argument no_default_updates=True to +function (as in g), then the random number generator state is +not affected by calling the returned function. So, for example, calling +g multiple times will return the same numbers.

+
+
+
+

g_val0 = g() # different numbers from f_val0 and f_val1 +g_val1 = g() # same numbers as g_val0!

+
+
+
+

An important remark is that a random variable is drawn at most once during any +single function execution. So the nearly_zeros function is guaranteed to +return approximately 0 (except for rounding error) even though the rv_u +random variable appears three times in the output expression.

+
+
+
+

nearly_zeros = function([], rv_u + rv_u - 2 * rv_u)

+
+
+
+

Seeding Streams

+

Random variables can be seeded individually or collectively.

+

You can seed just one random variable by seeding or assigning to the +.rng attribute, using .rng.set_value().

+
+
+
+

rng_val = rv_u.rng.get_value(borrow=True) # Get the rng for rv_u +rng_val.seed(89234) # seeds the generator +rv_u.rng.set_value(rng_val, borrow=True) # Assign back seeded rng

+
+
+
+

You can also seed all of the random variables allocated by a :class:RandomStreams +object by that object's seed method. This seed will be used to seed a +temporary random number generator, that will in turn generate seeds for each +of the random variables.

+
+
+
+

srng.seed(902340) # seeds rv_u and rv_n with different seeds each +Sharing Streams Between Functions

+
+
+
+
+

As usual for shared variables, the random number generators used for random +variables are common between functions. So our nearly_zeros function will +update the state of the generators used in function f above.

+

For example:

+
+
+
+

state_after_v0 = rv_u.rng.get_value().get_state() +nearly_zeros() # this affects rv_u's generator +v1 = f() +rng = rng.get_value(borrow=True) +rng.set_state(state_after_v0) +rv_u.rng.set_value(rng, borrow=True) +v2 = f() # v2 != v1

+
+
+
+

Other Random Distributions

+

There are :ref:other distributions implemented <libdoc_tensor_raw_random>.

+

TODO: OTHER RandomStreams base implementations (CUDA, OpenCL, MRG, etc.)

+
+ + \ No newline at end of file diff --git a/nbpages/files/images/3wolfmoon.jpg b/nbpages/files/images/3wolfmoon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a56baabbf3017abbd216b36ca3f07836c22f63df GIT binary patch literal 128399 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

RK;v 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

d zo9}qgQNOtr(uNKCAHee+=bQg-;NEpF0`R5M$>EDJ|=kl zRrZ%hdV}7Ue!tv6TbN8PH&j@;GSW#~Tc~t;^X$)OCYDN)lj%Jdx$nPbMiV88S4k%j z#~k7xd~rMjhcuX?|2b*#!WTxgNEFF$Bt?F)@k}$bX*upIgkiR8=|Uu~Kk@bOL^f^g zS9js!39nd6HH9rIDY%=gxt|}x{JoD&OkM|eYFI_5UA+bQNoS7Roaj+!RxNgAI>68w zeYxxseBN3SX%}I4l34WZAGfrBej*Upq1Yf!m1|$X{~myHlc*;iqeAWCO>&AmCY0

4{?o!sE?%1X$+KS4w zX?eEmgT`|*drl9?WpTAn=)UWLQiK%A{n;0s*7OhmPDhgUel>+Ig%+bg4FE;T^BVcF zk(Q|&(`m8aJqr?rpD(IJH;B*8x@i%tf9DJ?b4NZ%T@g*G$&R4*HiwjUyG^yBesN`O z5H0(%5B}SqG2F|f$Xzjt%gL$C2O&N=2qlj`qJszb@tQ4c54ROvuH9^Zbc{<{ee9Hl0A4zlR>sYn+1CO=(M2WitOj~ti(b-vI9+~6;kR@Cnp44t z4~BE@F31Ud14c)GF+=@O_Hoav-)<|pP8*Z+LZ(qIbANQGhEUbHn+ykw#F>Zo2)~st4|ooi{}uVWa8$ss zw{F*E4(jVIKul`hR6T6G%CCKp{%X$T$%~ptWM}k)?k^HN2x3>_3FyK`$vm+vBHHJj z*jv9BuYKNZXWh!U`{1p;P&`G`!MJ#=W(R}tJohi=YM-(+j@01EtXVa!gR!q~ZM$^H zRdscp&qooinW76#D`@Yv1j?o6Yvga0zN_b-Y(8(Z&!AgPu||q+|vdAtICd4I-i|q!H}MGnfzsZreaqtE=h{@ zQ)q0@&oFKx&L92f{?p~=^KbQU?&pif9C@HU*k4vaY9YFb&CoF!`(Zb4<^2gzfK6tH z*k+?4mtgUSN{mWf(%6}+R%-$K77d4Ax!9#=%qhB%uadcL_86*cySyGz4Mh>4bf>4~ z=O=>%x3CO{rK2Xw-W?XQvAR(^4?jJy_5yKj2OfYvqhGK9>L@t)4$L9>1w=Zq8?;hg zk3?P%i*qG+o&0O?c-$8rkkw#q$i1){N8mCYs!tFqf5mO9>Yo1a5vcA#tbK}T1rxVY zaS4^UiGga20n1!OHa)}k@ZFdomkbUSsR>d)+vO-kd)9t{G7jPx>-@}rkT5wrdV0`^ z8O$FfQ2+8o*&TzSKm}b+t4`!nTeEG>ZU7RwARwDr>q@mW>5 z&tH3@t3BCOV&#KTIlFjNCnLtwnxK2Pi%ec9$~zKQf#@=U_6`)6kTMkyRQ#N5-S1ii zb{71ol+SmKM>n+gdL-6B6c(&9=M^>0{8*k!wsG1Q zsPz`nOhSH>vN5nd-5(ezEz*^2d+JK}A^x{iGW&NmeeWCA4xnEFXa57l{R#RKH^nBf zvR(QLiV(cfxQ*8buvu2ulp(5{8oX6R%pXzv6(L;RC1DN)TV2-9;vEl!IUSaMym)2< zOk8%%LzysUOiMUGRNdM@#PnJR)B&&9N#LVccjjd$hW|G4M?#5{Q=c#s2A%6%v;Hx& zzu$NY+1fnQbD0~q!!*)?;x{%w|5di@JjT(r6^Kd+hI?QYYNw#gK4vui3nC>xydLOA zXF=&{7K|3uk@4?mpWV`sz~B(SEDt-8PoLwxgtBf2EF1FU5Y>}DCHytI{fZTOyaGW-!Spb|+}V6B|95{HCS4R)W5=C{1i#uz5+ zmZ+q-`M^(WVkM>JFatBz==SD!LsUD)B)r(yc`Ioe6U4yFo3Xd5_1ihe`2q(rt91ra z15X6PzT4d|&yH{apKhja9u7`ZT-2Gd1Z_r8A|H2s>~w3(RsJfTlbe)bQ(OKW+hoU+ zRp%9r?KFzQ4m@i(|D9q)uHOyMiNOiwqJ$#8>~&*yfBZS#}q z^01$-HI*MLmrXjI958R61((Qp+pMT{r%3)Q5x2WSBQ0$$HbAZaZmqsQ6^rF|j+Z(| z&i0Nkvg>@pB`X5%w{x?ZzaxeyI!Eeg3OCRnl0Yio&{4KcI#$OtJqg-K@V2 zkcH&q*o}2-zubdW8ICiCgXQRpf8{a+EUfO#a5yS!kln#G3f7kMOfT^LbJOE!SUOrF zhhj7DVANek;Hf>;jK-d<4Dx^`_a!~Sye#E;{s%Uh*t*wM<*>=#i%lgy$Jrw&y?{-Q zVApO0)(8t{$b1jJ<<74jlYgso}m_= zn0~{Y3k;9Sb-j`+t?bNqA)mn%s;%I*Tq{#40$ExmhMY|=mLr|B@rN9ZN83$v!dt{C zxI5Vnk4Hn3De937*hY!|1?^McL3Z(B8-bu=h60l&=! zX2X1~yZ=@a~%B15*{g7M?=e{kSaBmy&VK=A;I_cvGkqhiJz)Med zsJR6O(DhlG*0o{L9~$TQHy5gTcGo}V_#N{g1#*lJ60H~hivkUq9gTYTFAdD7J`?U3@ z;nIytI_ku;DzogZ+hORrJAjL|s_kwM90Gq~`sWN|x-QWUMEvR^?+snW77_)=?AXW9`~vsE%={yfZK3(9 z6b8XYJylS_!q)Dgs~ zmEk!w18by}xQprQ>LC2OIrRO?cdiaY`*LA9U<0!icc^Mx|FV51=Yg?pw`fSbMW`7w zS*@LiSRMY-u(~Wecz5(|e%1Xi)TjFGlk??URk=5~MN$zrERnVB`Ej-uf2H~y{=Q)n z4(5i>f=BiH_>{kTst#(po7nSlC;pp)KW5h!wzS5ICt(3ylw!>xsDBzwpi^LS;TXHi>0wR;(tzXBGf#kf-|8OIt zF~7=$_NJ5Y&nEe7%LmC$AS@cbQK?WqmPS#=|6eDiyi0We2>=GdK#+{~-O2;*!ctEv zeIh*`wwO`F06q>D^cftphSE)jgWuV3sf488q7El&2T>djZP6Y8uxl7Icf-x=e0qBT zermQ8w1IEfLA?~7c-c;?0rD4K$0i!LnUXXmJfNCYv}{wDspnn06U)A4cCLya-n02z z^iXD2<3A*lsJ>4mf4nc*RGBKFW5_fl{t_}9eZC!0J+hT}N2D3S4O%dSsZTC3p820I z+%pP#ul*Z}Wn!VB%Al%r6}BLi;Dd*xMqAW!O zfeq84{kBw5OiQ0EDCVvHVAA%1#Gy7pWze>2gi z*5LU#IjLKY`{#@l+{3D+#DkLaIO(=!G@0?5v>ZCgP`kyd1%TLy%$}nM%!OqiwM49qm z)~`1`nX2}MyaH}`L*!iQqR*_t1Ag)H`%_wa>Uko(dEJ;;?S-l9V}uWyu$T?MnJh8! z6tzPO{W+MR<0zYPyf`w;>T$&Ui`yfKhEw&8X(VY%0<}41B#m+-3)sSVXM^kjT^+6a zFwa?yUpe5+-qkU&Ql1DcaTmIp?Th^M_CZK%LhNU^^1^Tag>UNv%xe=!u4!>!vXK7+ zY~;QE1j#L~^?Wi_W`A_Ar1b0lbUyd%l4Lq>pXi0XOx*`8Qob#A$uf#hx8}g_XQVQN zb8h!pOe$j;nGhW3C+Ee+6L3;Q1cTv0IS2thL9!uk5Ue z1(5YYAhbUf)H0$u_4YW_)sSFa z%O|F?Zrq*mS*rt7m^{YJ&8ReJj3v_zleWMjv==kSgdw2)%%y?edq)P#cj#WW5Pmxyip;S>s;JI zy9$Dp2;2epQ$f?hZicY$6T}3kUp%FeO0MLTHtsHcv6SdDX&Re5&J4FAdjnMYojd6C z9>&RVpN@#ixI}WM05w~y3$KEU-#LlwecAID0_^F5DvVNraj6`Wrsf)bDE)d;zfC0x zOi-R};=WW-V{7v9>Bx`npbq4uMlrZym7lfFm>QZI4qA?hPKNW*g6yh!X~G*hFgOc3=Gai@Xx~n`D(XkBrQzx-a!}do1-P;_G$O0|pY!MM*FN3&q%9JCVe{ zZcW&?R5){;D`v9(?Y0_;E9s=~XY1oyWIf3c8;;>`!{$#~|A~ zAib4XPm&zU5KHBSia{TwvMs(Ur#=PCsRTTX83zcUB1eMKz76eXRSHYiCIt`#_Qm8) zC63X5q@|F$&yVdM-1#3M9sSjK zF2cw9{Ub+1B=#pXSA}OitXFm(rJWs+c3MP=l;%;~bkzLrYFEQ=Cg5(OT`LVM>#}d( zJJ=u5kqCRsde_Ww#!G1I&9!&(53a65$JOh5`9n0GmJq&;--?(_K^X4N)Y9%kuDy{v z?(*4uw1L|B#q0F`?tfBYDNk6*r z^;YZs(mid>KtzI^RQ96N!aw0L#S5d?l8+lck%h-=Gqva|n@_K=!ifGnV}2c#ax>sT zOG58xz|&l}CwKlJc4EcLEL~?aXQ)Z}{+blR@gx3CFTDMxS9y1&eDKRrIm*xcUgCE; ztOP~$m^F83HGIVE?$YU!2R4SrH*nH^0U7^cF zsG<6+v9Ov#aYV+qkp9%m|d5NJfNrXO5b#(nN$%M-qmLI=ysJVkZ=u<=HhhhiVWWP z5&;F-rK@hGC%ycE`fDQmLX+U&^Fdpa{B*1d9euh|ukL62=1Vne^DH zoJ~)s<&niF@;+@l{;WV1ha>f;K8!8p5?=r;>Q@KCGse!=^-W%@cGbulsAOV}nr_^! z>7QSj=8+Gw%Jf4f1_+!=p2=Av-TdcO{d#C1`g(D)xdlDO%tzf)sBNWw9uL12 zSJB)Ou~isLi=q8Xu7fvD#5sj5$x1YbzuYe6qlF(nVPMx&KOQxXlP)PQ>J*<(wL;@AIbuDn(O_Q{a>u^(-_{_A<`e^)+%^Z>N9& zn|V%<)z9^~IjC-TYqfp>W+ql)ja_RB-1W>f?5|r=>k7-4E3bt}o$Ci>WV={x3|jBL zj1zgli_W*CBLu?XE!BZsvD1|=!+*)3m5XP7aJi)9idNB2rVwQ`mLddPT=Z}x62V9L z5zM{3yp16U{I*xp;a`KRG!bmAN%)!8b~O5Q8VaZy02Y+Vs>+$ttDva4*+!$JV*Jvp zC^Qu~4utB>k!c=sRzs*d0L)2XQ|l(9$b>K{GBgw(RP2+4V%MYw{$7%Ef(=vmkIXX# zEI=<%QB95V=V6mvE@?vr@D6Aw&{RR5*DgJg{PL7ww|-GDlMpf@M8VUiHoS- z+{l@HKxr$I*_jVEq9rFLt=S1;8!UTAeJk_usnz(0(kF~QOi*1B+-EolfVq~4R6GH=zxW;zhqKqu=>s?=a$sGzCG-*@|-{2(8}(IBhxp(l~?J}fzgT}H(7y)I_XP7 z702m8#UAAo##S#0TYbQK%TiHow5vo@UBG<4g_2`iEwi&NWYW+z{b6jurh(p>SuR~p zrJGonraLL%cyp*sm3?xFmM2oQP$}jknZyvIMU>T((D^>%oA9Bsh1ye!lBc@aH_;7Ah2)r);iv*^rOylioQsq`uT zD(dNKbf%uiW01DJ^wApvfyLa4`A8ha0(`oVbdbt4!LFBaUx$QoY2aej0;jFU8W>WH z0kFOAp39Z$NN&k!F(QcZ|#M>t!WLG=;yx~ZacoxRCiJx zuvyBHfVd0kNRHKIJfMSL9joSyFHWS|C*rO@I$Y4u1(UcK5=%Yvf4ho^blrNFB+ap& zA zU~vA6pp7=IDsYk=q!J^r^U3$AXFd2&daysCDPTLffWWI8VW}xEM!u@uaAh=|u4F^{ z!nTtuxu;8`J&_DH#ip_^44$sn)>225so2tFzsiS&OFG1Wnf!++{z<0SS!#*4Z#>Ul zcl4QBKURYpS+`+X4Z_biVR*~OUMae>D8I-519)(NX2YxGe|o^TzYn(wLqQym2c}Yk z|4lL0=%{os)~OoAb#l&0lj2KEkf;wm@y*Q6E`=yH7U5j;5@wyT;U(7g8#b_|7_=7Y zWdUo@b=Q!bws4|Sh-u*Q;DjkxK2-^G9mz6%_;z{DqU8fvZ4HD7U5{Ujc{&zq?W$E^ zZfdt&9umP$2e7OUpJG-$&Mrhd6qy5}a+s7)`tv5#!{2`$ZYQda?TyX|tcJ2s@XWCRw=e56M-(+D>C#y>W6KPY^B3zkdcR-^kP5>^?!x( z3iB0KQPnl|1Ag@2w_N*~ir5I$NCG1TeldpysDAjg5P}GhWsoD_xf9)q%gJYwkRB6` zM*8DngacN9$(j?d{`CdeqAi<8r98{*^w&*6Mn9^)M$I5D#xL|{6MAm|%OsDdeD{X6z$wr5ti%ESyjXdY zH<=t70%4oUW)Q~{g)2q)S{95_74(iH_n8#?FS&Zf&_ix@TXx3mncE7nL zQ0Pbc^tP*$y5Vn0poij3^9h5vHa4m~YB)hm^e0Z$>(ckkzg3|+k~y@NJc*x(>7kwL zSt;yEZJO;I2URxL^4O01YVLULOPL zXhD<~2D7h1fvoRiW6HUg26Mzf3|5NaQp;QZgnv`4-pV+o3WP9;y!Ej?8Xi(0l@lug zm^`4s(&tEScz%Rr%f7io(8;y(f}S*!h1Y0B!WLpX2?gJJVQ0SX*z5n>Rdu|zDVe^x z=nfy>{{TJ;ZXE&y0k#5e(6(78wS7_gzA86X(lXa-bXKq`hTg@BYMrvKtyR(CCS6@DWtDGD-P}x`Q}Oe( zdhSfP2(9jWAH0Mk{>e0TDHT(t<0C&8aMUK_*9bKLz3`Cjdi)K$n5%i~6$EG^ z8f~fKo+}|P(r(h-`!s@G3Cm8ouM&`v4@FP}+Sc<5?5yLgKnpds9ED^Sq>K*ha{C~c zIBje&%l;5GA`6rZ|I=YPlzL}!FZZJ+t%|2{{AR=wun?Gm^y8elJQjs#P+~ETF%m@P z40}`USn}F*1+5>Hn`lO6f{WEaTf!}A*wy|q)tb(JS||B=770WtKYs;rz6b&01|p&>~oU3 z@_SR$9A@Y;pJ2RjGt{?f3Q*w7Y+0-3a+ zuwJi-pp2TT)Br4wC`aTjWSuXa8j(1>k_{2_TC*CLQxp?4Tgru{I=E6uVfuHStg7uM z1RPWG4jKgpEa2{EtuKcTeT5TaPYB0gOyYV8XDzceO;>S@9NQe2kwm3vX3Y%cUgCC4 ztX(~rQlyR7aF@ONh~P+vAk0T&H{N~pdpYotD-#wA9ZDF*R_?wF&$4#$FXukyICr+N zm^`#9=M>7OrXrrX1_R5lsbaJ}^G1fGBtnz0y7){@HPwByuMy^4PX!vcf%W}aM?_AM zJ+vr3!h)i_O5(?;f|fvpwwDv&BH75(Oxv8K#Z5uxUtN&9C?~?3(^O8Y6|5LN+|#V7 zU7|BGnqcPYmRlfkeDdi`j$CQ1fwbWX?Z)~L+bv6Hkezj2tak5-aSWklmetUe@TYz~ z!Ds3S^%=mvJ6RD2;s;xu*?#2QTeeL#D7~Etj;X8%bW;s84h#=-zYct0i~u$gQ)s0; zE1Cj^=}f5zzK@2h;=%h2xeu59Zk%GHy>;@V0jx{M%rlTI!KT999Ipr*ONQxX z;$JA7qSTX1&8|FbAq5UpRR0$$TWziIcEZA55l|k%q52mwQtj<);Ff`9IOe8G7yD>x zS0;-?j3n23D^4*7T-#|0{{cgpLs{gAAm$W17-8HZJVo{Tf~&F;gSE-29Z&n5Xw3J; zP75#}+rAcLOJx%KdW$MT0A$5V3&jm4PJ)?VHU#mBk#SGUvu#Z28w$sSk$TM??QT%S zSe#UAdkXu%xW&Hj5C1EB!-}pT%gmLTH`t-dvy8{Mgf(L>kOz=@(%5ltEN*#h>_*G^ zLIfxE5`x>7r=pmctJM3UvLpCJELG0`ScKtuJ9p5!cIKguOmJD}S4VHTw1_`3HNfj` z&jgzRuPwM6F}F#z?~|p6cgrj(P02BM<33<9P(m{If%^BLN-w(mg8tDY3OyQ5+=Eadqh3Z(*~ zqwF?yFFUStnq=tWApPDDjk^q<@s8QAmLT;t`5e>>SAI4QK)fxgoHl$jeG2Rm;qg!i z<^xGHTU}2;Qf&EDGAOd;v6;H&$ez1Xe85y0a!z9|B@%uvzm;X>PBF-fdq=lmMLF70 zMPClzzGjw!MJuv7;OafeD#;DH$13r7?xpF6EC5-<4ZHA)TVPWyFCz7vHr^@SfBVNk z5sL&vHYioo!>`f>K<2UZmqLCgn^A{kaMu0l0-vrY7c4C@&9nCj?S^L?l|_U{kN-bTn1L`qgt>0`KGU90&}Praw(6I zMU)uAT(M0(HVG;`q*%S`MDPXq8&vOOjzyO9eQ}NPE7c)Y6y5WslF`X^4BE($ z^wUlU#ad2gH_DT2Bf{q9JoD!gJJ_Q>B?A+#^ z2NTZ0wKm7Uc{#sZlK(n*j@6 zXzz)Zv91mMKIL)?s5A_erl`^+@|eRe3FK!e+*H#4At)yVgF;a+psY+=6$U zRf(VPg-2YT6eTI;7igU(chNx7+PDSh5Bd2#RIYHxv{a~PMxzaAg)kg*l*#jyg>;wISQjb+?W^1@d1Utgf)ekF}8^r4NBM2 z9yj@sKN&vMb?qFx!~EYy(s0uT43A@b-zhP3CtZ#-|ie%cp^D!8^& zov3Ib*}S8TJG;&|xQ-(We^rs-Htv7#p3+A;xd{}4=A$ykuk&Fx<$|)L9vlJGcD?|0 z6>?`HeH!t{HiJU<$Vi^D*3V|-AQX5UBF>oxc3&f~~eKMDB5x1FFry5RM8sa{dnANmqM3iqI za)~0X8nDqsNCDr0D{Shect|rdw@0Ic=aAg@eh-Smtg;PqN(v*gLMP0th3&oY8~m#0 z4ilWjw}Q=n^m}8X4CfI71Yk`D)eYwcHDl#u!i)7dd?6oV!GYI`!-?C)czNoTED2Yw z$=F)+l1$=6|D;4vwgdc{|N1@PkusJrZUgpxGL8eF5W=8X)$6Y3hQrZR>5JNu>F39z zZas8!)p3H?VV~Gs8US(tccd?uF{>2Tf`z#%7cg^gbs^@^eHvJAHtusYdNtuZWdRt)!tQYDlM!j>f#Sla(Zs&KN zYQIsWau*yKZBD>VU3IT*Wk(ykk&bC&6heLkHG>43C@j$JS*^l!11C49>|ZK~s!@forO!Gy_iV;esShxaGu;AsC+< ztOBrRMXAYEIhtN?St5CZdw{<3g;sg~V ziW5HmdY<$l6+k_l_;KAKwszh6_)1PX`%Er1s|0{O+nu?cCw$3wtI}5(x27s5 z|3}1q9HxY+DNAEZE_7E_k7Kt3fh3vnet6sQ8~%X8ZBwq{{l206dQOfFgExT6vAhFL z{015`^ffV2LX=lP+!?kNaNWgW=nbsX1Y>eEH)AR=sQExY4o-Ng0iB2qY@Z?=TMFY} zk&Qz53c-#!gvlE=9Q$WFKz(Il?#A=dzpgLG4?8S+d*Tj9O%c^=R88TDnf_0fb0uCn z#L+1VCzh5nZ94L5RqJhoQlJV<$Z(bxSD_DR!PJV<&|V2+4{ghFI%g)FYJH?>DN38f zDo#s2rc1zuz~Sk``;A_gf7Tzm?JMo!a;K;UJEYVn7pPR+_2~4=djmaaaI~w*zjR^M z024at!m<~K{kHi!j+yNds&x;AMakZ7O|Lyg$FXsS`^bN zM4C2@c4+bAsYbinD?#Bq-CIDXN!P-5gM14ntf^Hw{_!hftc1AIqg44u=*xs)a8J$>!uy;5jYL zjmK7_TcNKCS)|dSsv2SPo*K6}_fhoI35~Lyq9%2m;7D-=IK%Pqq=F6=5PMU9z2VsPeCmf93)v6?IDt=5{g5`SK?qNh0N4Le#t3+`KvA!# z2u=12M+5RmD{6s63c`XAjfN>lA`zo`MAeVoJZfUm*-0a-Ko#{#pqj%gxvBvD`{4dU zH#B_heUeWl$0jlylYgDRApDUzIFZB$PNlY(t8cg>`%|!O`w7}IdP1l#UjQJM`GRWQ2sNY;|x7wx5Onc zaBF@>Cg3lHT2g_G16Tbxh!j2dB;O%UmBzr93VEWep19ygWh4my6J-??MO3Ai57vo_ z1TbKzsfQ40pFeI1qpz-kQ=c6DKHQdlt>O2Xp0H-`wQaU%#(BzR-u2lY&#Q7mR zu&EkBVMD^T<&6yl)Q9sz>cZH#61G&$lvg@)!p-Z-fCkc)B7_`= z{4lJWOzG_a64b^f##D; z+-ak#gd;=KPNFqqB>5%BXFwFFp$CmKQwCg+&0*BSTMaHLyoO)f7>gu5_j*8ELi#AgDB;%9QcJnUWg? zPP3PXzlJ)0L*y$`pnL<3KUO5JfJ$mK0<{^OCZB<11x{e`1N(8An|+3>q)>E&kr>^X zwG<(kJge^E&xSJ&LJFy<0D?W^^kQ9=Fd?SC`eo1UIHcK_oC=!p11j;R5Y&w%>I8A6 zD7jdf~jyy4%7=x8Z8c>sx@jl#1DTkylidLtMD^7LBEBYbZHK3+vNc%CM${!#Klst_y z&n!^U(@NJOHF6wrtXr_^VgUoBQz4M96$GTFz~9Q!;AyUB0!mE&xDyoB&Ax?i$hq)sA>Z`W`B3L6pb<^ufbk=NWe})+B<9- znrbRf913LX2tzVy(@zg~w;dVFmIXAeXjG48F_kgZ6{r=c6&$IFfdU!~vtQRtW;uTc zMA54;M$3W5TnA%MpDsKPjwl+is9N|pDq%Cv$n1_oA_$@9fk}B{>dfYI{ao=!II$5$ cQC(C9mFG{y}RCf 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 Il4e2w51cbp82|tP literal 0 HcmV?d00001 diff --git a/nbpages/files/images/conv_1D_nn.png b/nbpages/files/images/conv_1D_nn.png new file mode 100644 index 0000000000000000000000000000000000000000..217a4cde226e9710c8c19f5101bfcffe82a46996 GIT binary patch literal 17821 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°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 TjR}7`1xZXuTCn)N&d2`&r+me> literal 0 HcmV?d00001 diff --git a/nbpages/files/images/mlp.png b/nbpages/files/images/mlp.png new file mode 100644 index 0000000000000000000000000000000000000000..246d332cf4f6afce39e5607e57d54e37b849cd9e GIT binary patch literal 23828 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

U`?d)7KCYT17aE+G#uZvj_wLPE%&KYw1i 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

0Vjkwr$sfP-7F)3rL0#=oB=& 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 KlC$B!ng0T^sCgj( literal 0 HcmV?d00001 diff --git a/nbpages/files/images/sparse_1D_nn.png b/nbpages/files/images/sparse_1D_nn.png new file mode 100644 index 0000000000000000000000000000000000000000..bb4f3697075301e08a789ab9e1173e09d20df7d1 GIT binary patch literal 11941 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 Date: Mon, 21 Jan 2013 21:09:16 -0500 Subject: [PATCH 04/11] FIX: moving html pages to have no parens in names --- ...ikit Data (skdata).html => Intro to Scikit Data _skdata_.html} | 0 ...duction).html => Theano Tutorial _Part 1 - Introduction_.html} | 0 ...n).html => Theano Tutorial _Part 2 - Simple Computation_.html} | 0 ...heano Tutorial _Part 3 - Functions and Shared Variables_.html} | 0 ...les).html => Theano Tutorial _Part 4 - Random Variables_.html} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename nbpages/{Intro to Scikit Data (skdata).html => Intro to Scikit Data _skdata_.html} (100%) rename nbpages/{Theano Tutorial (Part 1 - Introduction).html => Theano Tutorial _Part 1 - Introduction_.html} (100%) rename nbpages/{Theano Tutorial (Part 2 - Simple Computation).html => Theano Tutorial _Part 2 - Simple Computation_.html} (100%) rename nbpages/{Theano Tutorial (Part 3 - Functions and Shared Variables).html => Theano Tutorial _Part 3 - Functions and Shared Variables_.html} (100%) rename nbpages/{Theano Tutorial (Part 4 - Random Variables).html => Theano Tutorial _Part 4 - Random Variables_.html} (100%) diff --git a/nbpages/Intro to Scikit Data (skdata).html b/nbpages/Intro to Scikit Data _skdata_.html similarity index 100% rename from nbpages/Intro to Scikit Data (skdata).html rename to nbpages/Intro to Scikit Data _skdata_.html diff --git a/nbpages/Theano Tutorial (Part 1 - Introduction).html b/nbpages/Theano Tutorial _Part 1 - Introduction_.html similarity index 100% rename from nbpages/Theano Tutorial (Part 1 - Introduction).html rename to nbpages/Theano Tutorial _Part 1 - Introduction_.html diff --git a/nbpages/Theano Tutorial (Part 2 - Simple Computation).html b/nbpages/Theano Tutorial _Part 2 - Simple Computation_.html similarity index 100% rename from nbpages/Theano Tutorial (Part 2 - Simple Computation).html rename to nbpages/Theano Tutorial _Part 2 - Simple Computation_.html diff --git a/nbpages/Theano Tutorial (Part 3 - Functions and Shared Variables).html b/nbpages/Theano Tutorial _Part 3 - Functions and Shared Variables_.html similarity index 100% rename from nbpages/Theano Tutorial (Part 3 - Functions and Shared Variables).html rename to nbpages/Theano Tutorial _Part 3 - Functions and Shared Variables_.html diff --git a/nbpages/Theano Tutorial (Part 4 - Random Variables).html b/nbpages/Theano Tutorial _Part 4 - Random Variables_.html similarity index 100% rename from nbpages/Theano Tutorial (Part 4 - Random Variables).html rename to nbpages/Theano Tutorial _Part 4 - Random Variables_.html From 7390ce990a92eeb808adb609eb5d0aab7f79d48e Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 21 Jan 2013 21:14:56 -0500 Subject: [PATCH 05/11] where are the html files? --- rebuild_nbpages.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/rebuild_nbpages.sh b/rebuild_nbpages.sh index 6819088..2e1b6e4 100755 --- a/rebuild_nbpages.sh +++ b/rebuild_nbpages.sh @@ -14,6 +14,13 @@ mkdir -p nbpages/files/images set +e mv ../ipynb/*.html nbpages/ mv ../ipynb/*.png nbpages/ -set -e +#set -e + +for F in nbpages/*.html ; do + NEWF=$(echo "$F" | sed -e "s/(/_/g" -e "s/)/_/g") + echo "Sanitizing URL: $F -> $NEWF" + git mv "$F" "$NEWF" +done + cp ../ipynb/images/* nbpages/files/images/ From 37cf6032ab00560a51de744b6195577bca875ed7 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 21 Jan 2013 21:22:07 -0500 Subject: [PATCH 06/11] un-sanitizing names because I suspect I was confused --- ...ikit Data _skdata_.html => Intro to Scikit Data (skdata).html} | 0 ...duction_.html => Theano Tutorial (Part 1 - Introduction).html} | 0 ...n_.html => Theano Tutorial (Part 2 - Simple Computation).html} | 0 ...heano Tutorial (Part 3 - Functions and Shared Variables).html} | 0 ...les_.html => Theano Tutorial (Part 4 - Random Variables).html} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename nbpages/{Intro to Scikit Data _skdata_.html => Intro to Scikit Data (skdata).html} (100%) rename nbpages/{Theano Tutorial _Part 1 - Introduction_.html => Theano Tutorial (Part 1 - Introduction).html} (100%) rename nbpages/{Theano Tutorial _Part 2 - Simple Computation_.html => Theano Tutorial (Part 2 - Simple Computation).html} (100%) rename nbpages/{Theano Tutorial _Part 3 - Functions and Shared Variables_.html => Theano Tutorial (Part 3 - Functions and Shared Variables).html} (100%) rename nbpages/{Theano Tutorial _Part 4 - Random Variables_.html => Theano Tutorial (Part 4 - Random Variables).html} (100%) diff --git a/nbpages/Intro to Scikit Data _skdata_.html b/nbpages/Intro to Scikit Data (skdata).html similarity index 100% rename from nbpages/Intro to Scikit Data _skdata_.html rename to nbpages/Intro to Scikit Data (skdata).html diff --git a/nbpages/Theano Tutorial _Part 1 - Introduction_.html b/nbpages/Theano Tutorial (Part 1 - Introduction).html similarity index 100% rename from nbpages/Theano Tutorial _Part 1 - Introduction_.html rename to nbpages/Theano Tutorial (Part 1 - Introduction).html diff --git a/nbpages/Theano Tutorial _Part 2 - Simple Computation_.html b/nbpages/Theano Tutorial (Part 2 - Simple Computation).html similarity index 100% rename from nbpages/Theano Tutorial _Part 2 - Simple Computation_.html rename to nbpages/Theano Tutorial (Part 2 - Simple Computation).html diff --git a/nbpages/Theano Tutorial _Part 3 - Functions and Shared Variables_.html b/nbpages/Theano Tutorial (Part 3 - Functions and Shared Variables).html similarity index 100% rename from nbpages/Theano Tutorial _Part 3 - Functions and Shared Variables_.html rename to nbpages/Theano Tutorial (Part 3 - Functions and Shared Variables).html diff --git a/nbpages/Theano Tutorial _Part 4 - Random Variables_.html b/nbpages/Theano Tutorial (Part 4 - Random Variables).html similarity index 100% rename from nbpages/Theano Tutorial _Part 4 - Random Variables_.html rename to nbpages/Theano Tutorial (Part 4 - Random Variables).html From 9dfddc0006a7cf0528a52ae3198c70600cd74e8d Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 21 Jan 2013 21:26:16 -0500 Subject: [PATCH 07/11] new index --- README.txt | 6 ++---- index.html | 29 ++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/README.txt b/README.txt index dbee882..8e7f6bd 100644 --- a/README.txt +++ b/README.txt @@ -10,10 +10,8 @@ The pages published for the ipython notebooks works like this: ## Rebuilding index.html -Rebuild the index.html using the github wizard. Go to the IPythonTheanoTutorials -project page, and open the project "Settings". On that page, click the -"Automatic Page Generator" button, edit the text there, and publish using the -web interface. +Rebuild the index.html file by editing the index.html directly. +DO NOT regenerate it using the github wizard, it will erase everything else!! ## Rebuilding all the notebook html files diff --git a/index.html b/index.html index 652ea52..b54ed5c 100644 --- a/index.html +++ b/index.html @@ -35,6 +35,33 @@

IPython Theano Tutorials

A collection of tutorials in ipynb format that illustrate how to do various things in Theano.

+

Theano Tutorials

+ + + +
    +
  • Intro to Python.html
  • +
  • Intro to Scikit Data (skdata).html
  • +
  • Links to Related Work.html
  • +
  • Model - Autoencoders and Variations with PyAutodiff.html
  • +
  • Model - Convnet with PyAutodiff.html
  • +
  • Model - LIF Neurons with Theano.html
  • +
  • Model - Linear SVM with PyAutodiff.html
  • +
  • Model - Logistic Regression with Theano.html
  • +
  • Model - Multilayer Perceptron with PyAutodiff.html
  • +
  • Notation for Machine Learning.html
  • +
  • Preprocessing - Image Whitening.html
  • +
  • Theano Tutorial (Part 1 - Introduction).html
  • +
  • Theano Tutorial (Part 2 - Simple Computation).html
  • +
  • Theano Tutorial (Part 3 - Functions and Shared Variables).html
  • +
  • Theano Tutorial (Part 4 - Random Variables).html
  • +
+

Installation

Requirements:

@@ -87,4 +114,4 @@

Supervised Algorithms

- \ No newline at end of file + From ced36c5e82636c9bd7836c1e357871b4e5082d78 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 21 Jan 2013 21:35:07 -0500 Subject: [PATCH 08/11] ENH: added pointers to index --- index.html | 53 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/index.html b/index.html index b54ed5c..e5c4b1c 100644 --- a/index.html +++ b/index.html @@ -35,8 +35,14 @@

IPython Theano Tutorials

A collection of tutorials in ipynb format that illustrate how to do various things in Theano.

-

Theano Tutorials

+

HTML Previews

+Thanks to nbconvert we can render the tutorials as plain html +files. N.B. These tutorials are meant to be experienced with IPython, not + plain html! Still, with that said, here's what's in store if you +download and run the tutorials on your own ipython installation. + +Theano Tutorials: +Machine Learning with Theano: + + +Neuroscience with Theano: + + +Orientation to related work: + + +Using Theano indirectly via PyAutoDiff
    -
  • Intro to Python.html
  • -
  • Intro to Scikit Data (skdata).html
  • -
  • Links to Related Work.html
  • -
  • Model - Autoencoders and Variations with PyAutodiff.html
  • -
  • Model - Convnet with PyAutodiff.html
  • -
  • Model - LIF Neurons with Theano.html
  • -
  • Model - Linear SVM with PyAutodiff.html
  • -
  • Model - Logistic Regression with Theano.html
  • -
  • Model - Multilayer Perceptron with PyAutodiff.html
  • -
  • Notation for Machine Learning.html
  • -
  • Preprocessing - Image Whitening.html
  • -
  • Theano Tutorial (Part 1 - Introduction).html
  • -
  • Theano Tutorial (Part 2 - Simple Computation).html
  • -
  • Theano Tutorial (Part 3 - Functions and Shared Variables).html
  • -
  • Theano Tutorial (Part 4 - Random Variables).html
  • +
  • + Autoencoders and Variations
  • +
  • + Convnet
  • +
  • Linear SVM
  • +
  • Mulitlayer Perceptron

Installation

From c8fc58fe2461e295c4462ed71b26dc4406936b56 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 21 Jan 2013 21:35:21 -0500 Subject: [PATCH 09/11] removed sanitizing urls --- rebuild_nbpages.sh | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/rebuild_nbpages.sh b/rebuild_nbpages.sh index 2e1b6e4..856711f 100755 --- a/rebuild_nbpages.sh +++ b/rebuild_nbpages.sh @@ -14,13 +14,7 @@ mkdir -p nbpages/files/images set +e mv ../ipynb/*.html nbpages/ mv ../ipynb/*.png nbpages/ -#set -e - -for F in nbpages/*.html ; do - NEWF=$(echo "$F" | sed -e "s/(/_/g" -e "s/)/_/g") - echo "Sanitizing URL: $F -> $NEWF" - git mv "$F" "$NEWF" -done +set -e cp ../ipynb/images/* nbpages/files/images/ From 97eeb94617769e1e40287e2195537c3b66fc07a8 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 21 Jan 2013 21:37:28 -0500 Subject: [PATCH 10/11] index --- index.html | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index e5c4b1c..f93dc7c 100644 --- a/index.html +++ b/index.html @@ -38,19 +38,22 @@

IPython Theano Tutorials

HTML Previews

Thanks to nbconvert we can render the tutorials as plain html -files. N.B. These tutorials are meant to be experienced with IPython, not - plain html! Still, with that said, here's what's in store if you +files. N.B. These tutorials are meant to be experienced with IPython, not + plain html! Still, with that said, here's what's in store if you download and run the tutorials on your own ipython installation. -Theano Tutorials: +

+

Theano Tutorials:

+

-Machine Learning with Theano: +

+

Machine Learning with Theano:

+

-Neuroscience with Theano: +

+

Neuroscience with Theano:

+

-Orientation to related work: +

+

Orientation to related work:

+

-Using Theano indirectly via PyAutoDiff +

+

Using Theano indirectly via PyAutoDiff

+

Installation

From 20f34763640c9577be1f8c67c2aea212bef77abf Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 21 Jan 2013 21:38:56 -0500 Subject: [PATCH 11/11] index --- index.html | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/index.html b/index.html index f93dc7c..0b2c32d 100644 --- a/index.html +++ b/index.html @@ -114,29 +114,6 @@

Requirements:

cd IPythonTheanoTutorials sh start_ipython_server.sh

-

General

- -
    -
  • Theano Basics
  • -
  • Adding a custom Op to Theano
  • -
  • Numpy/Python function minimization using pyautodiff
  • -

Machine Learning:

- -

Supervised Algorithms

- -
    -
  • Logistic Regression
  • -
  • Multilayer Perceptron (MLP)
  • -
  • Convolutional Network (Convnet)
  • -
  • Deep Belief Network (DBN)
  • -

Unsupervised Algorithms

- -
    -
  • Restricted Boltzmann Machine (RBM)
  • -
  • Autoassociator / Autoencoder (AA)
  • -
  • Stochasitc Denoising auto associator (SDAA)
  • -
  • Sparse coding
  • -