提交 81cdd196 authored 作者: Arnaud Bergeron's avatar Arnaud Bergeron

Remove references to deleted stuff in the docs.

上级 e22a1ac6
......@@ -2,7 +2,7 @@
Compatibility with Python versions.
===================================
Theano is compatible with Python versions >= 2.4 including 3.x series.
Theano is compatible with Python versions >= 2.6 including 3.x series.
This guide provides coding guidelines on how to maintain
comnpatibility.
......@@ -59,7 +59,6 @@ References
----------
.. _six: http://pythonhosted.org/six
.. _[What's new in Python 2.5]: http://docs.python.org/2/whatsnew/2.5.html
.. _[What's new in Python 2.6]: http://docs.python.org/2/whatsnew/2.5.html
.. _[What's new in Python 2.7]: http://docs.python.org/2/whatsnew/2.5.html
.. _[What's new in Python 3.0]: http://docs.python.org/2/whatsnew/3.0.html
......
.. _examples:
========
Examples
========
WRITEME
Should this be auto-generated?
from theano.compile import Module, Method
import theano.tensor as T
class Accumulator(Module):
def __init__(self):
super(Accumulator, self).__init__() # don't forget this
self.inc = T.dscalar()
self.state = T.dscalar()
self.new_state = self.inc + self.state
self.add = Method(inputs = self.inc,
outputs = self.new_state,
updates = {self.state: self.new_state})
self.sub = Method(inputs = self.inc,
outputs = None,
updates = {self.state: self.state - self.inc})
if __name__ == '__main__':
m = Accumulator()
acc = m.make(state = 0)
import numpy
from theano.compile import Module, Method
import theano.tensor as T
class MatrixAccumulator(Module):
def __init__(self):
super(MatrixAccumulator, self).__init__() # don't forget this
self.inc = T.dscalar()
self.state = T.dmatrix()
self.new_state = self.inc + self.state
self.add = Method(inputs = self.inc,
outputs = self.new_state,
updates = {self.state: self.new_state})
self.sub = Method(inputs = self.inc,
outputs = None,
updates = {self.state: self.state - self.inc})
def _instance_print_state(self, acc):
print '%s is: %s' % (self.state, acc.state)
def _instance_initialize(self, acc, nrows, ncols):
acc.state = numpy.zeros((nrows, ncols))
if __name__ == '__main__':
m = Accumulator()
acc = m.make(2, 5) # this calls m._instance_initialize(acc, 2, 5)
acc.print_state()
# OUTPUT:
# state is: [[ 0. 0. 0. 0. 0.]
# [ 0. 0. 0. 0. 0.]]
from theano.compile import Module, Method
import theano.tensor as T
class Accumulator(Module):
def __init__(self):
super(Accumulator, self).__init__() # don't forget this
self.inc = T.dscalar()
self.state = T.dscalar()
self.new_state = self.inc + self.state
self.add = Method(inputs = self.inc,
outputs = self.new_state,
updates = {self.state: self.new_state})
self.sub = Method(inputs = self.inc,
outputs = None,
updates = {self.state: self.state - self.inc})
def _instance_print_state(self, acc):
print '%s is: %s' % (self.state, acc.state)
if __name__ == '__main__':
m = Accumulator()
acc = m.make(state = 0)
acc.print_state() # --> prints "state is: 0.0"
from theano.compile import Module, ModuleInstance, Method
import theano.tensor as T
class AccumulatorInstance(ModuleInstance):
def print_state(self):
#self.component points to the Module from which this was compiled.
print '%s is: %s' % (self.component.state, self.state)
class Accumulator(Module):
# This line tells Theano to instantiate an AccumulatorInstance
# when make() is called.
InstanceType = AccumulatorInstance
def __init__(self):
super(Accumulator, self).__init__() # don't forget this
self.inc = T.dscalar()
self.state = T.dscalar()
self.new_state = self.inc + self.state
self.add = Method(inputs = self.inc,
outputs = self.new_state,
updates = {self.state: self.new_state})
self.sub = Method(inputs = self.inc,
outputs = None,
updates = {self.state: self.state - self.inc})
if __name__=='__main__':
m = Accumulator()
acc = m.make(state = 0)
acc.print_state() # --> prints "state is: 0.0"
import theano
import theano.tensor as T
M = theano.Module()
M.a, M.b, M.c = [T.dvector() for i in 1,2,3]
P = theano.Module()
P.m = M #include a module by nesting
x = T.dvector()
P.f = theano.Method([x], None, {M.b: M.b + x})
p = P.make() #this converts both M and P because M was nested within P
p.m.b = [4, 5, 6]
p.f(3)
print p.m.b
# prints array([7.,8.,9.])
import numpy
import unittest
import os
def makeTester(fname):
class Test(unittest.TestCase):
def test_example(self):
print 'Executing file', self.fname
Test.__name__ = fname
Test.fname = fname
return Test
def test_module_doc():
"""
This test executes all of the Module code examples.
It goes through the directory and executes all .py files.
"""
for fname in os.listdir('.'):
if fname.endswith('.py'):
f = fname.split('.')[0]
print 'Executing ', fname
execfile(fname, locals())
......@@ -239,10 +239,10 @@ for this somewhere in the future.
.. note::
:class:`FunctionGraph` is a Theano structure intended for the optimization
phase. It is used internally by function and Module and is rarely
phase. It is used internally by function and is rarely
exposed to the end user. You can use it to test out optimizations,
etc. if you are comfortable with it, but it is recommended to use
the function/Module frontends and to interface optimizations with
the function frontend and to interface optimizations with
:class:`optdb` (we'll see how to do that soon).
......
......@@ -25,12 +25,11 @@ Compilation of the computation graph
------------------------------------
Once the user has built a computation graph, she can use
``theano.function`` or a ``theano.Method`` in a ``theano.module`` in
order to make one or more functions that operate on real data. Both
function and Method take a list of input :ref:`Variables <variable>`
as well as a list of output Variables that define a precise subgraph
corresponding to the function(s) we want to define, compile that
subgraph and produce a callable.
``theano.function`` in order to make one or more functions that
operate on real data. function takes a list of input :ref:`Variables
<variable>` as well as a list of output Variables that define a
precise subgraph corresponding to the function(s) we want to define,
compile that subgraph and produce a callable.
Here is an overview of the various steps that are done with the
computation graph in the compilation phase:
......@@ -58,11 +57,10 @@ inputs declared as immutable.
Step 2 - Execute main Optimizer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Once the FunctionGraph is made, an :term:`optimizer` is produced
by the :term:`mode` passed to ``function`` or to the Method/Module's
``make`` (the Mode basically has two important fields, ``linker`` and
``optimizer``). That optimizer is applied on the FunctionGraph using its
optimize() method.
Once the FunctionGraph is made, an :term:`optimizer` is produced by
the :term:`mode` passed to ``function`` (the Mode basically has two
important fields, ``linker`` and ``optimizer``). That optimizer is
applied on the FunctionGraph using its optimize() method.
The optimizer is typically obtained through :attr:`optdb`.
......@@ -124,7 +122,7 @@ Step 4 - Wrap the thunk in a pretty package
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The thunk returned by the linker along with input and output
containers is unwieldy. ``function`` and ``Method`` hide that
complexity away so that it can be used like a normal function with
arguments and return values.
containers is unwieldy. ``function`` hides that complexity away so
that it can be used like a normal function with arguments and return
values.
......@@ -16,7 +16,6 @@ Variable local function data / variable
Shared Variable global function data / variable
Op operations carried out in computation / function definition
Type data types
Module class
=============== ===========================================================
For example:
......
......@@ -301,8 +301,6 @@ Example:
.. code-block:: python
f = T.function([a,b],[c],mode='FAST_RUN')
m = theano.Module()
minstance = m.make(mode='DebugMode')
Whenever possible, unit tests should omit this parameter. Leaving
out the mode will ensure that unit tests use the default mode.
......
......@@ -18,7 +18,6 @@
io
ops
mode
module
debugmode
profilemode
......
......@@ -117,60 +117,6 @@ We can also assign to ``inc[s]`` directly:
>>> inc[s]
array(10.0)
Advanced: Sharing Storage Between Functions
-------------------------------------------
``value`` can be a :class:`Container` as well as a literal.
This permits linking a value of a Variable in one function to the value of a Variable in another function.
By using a ``Container`` as a value we can implement shared variables between functions.
For example, consider the following program.
>>> x, s = T.scalars('xs')
>>> inc = function([x, In(s, update=(s+x), value=10.0)], [])
>>> dec = function([x, In(s, update=(s-x), value=inc.container[s])], [])
>>> dec(3)
[]
>>> print inc[s]
7.0
>>> inc(2)
[]
>>> print dec[s]
9.0
The functions ``inc`` and ``dec`` operate on a shared internal value for ``s``.
Theano's Module system uses this mechanism to share storage between Methods.
The container being shared doesn't have to correspond to the same Variable in both functions,
but that's usually how this mechanism is used.
Note that when an input's ``value`` parameter is a shared container, this
input is considered as implicit by default. This means it cannot be set by the
user.
If ``implicit`` is manually set to ``False``, then it can be set by the user,
but then it will overwrite the container's content, so one should be careful
when allowing this.
This is illustrated in the following example.
>>> dec(1, 0) # Try to manually set an implicit input
<type 'exceptions.TypeError'>: Tried to provide value for implicit input: s
>>> dec = function([x, In(s, update=(s-x), value=inc.container[s], implicit=False)], [])
>>> inc[s] = 2
>>> print dec[s] # Containers are shared
2.0
>>> dec(1)
[]
>>> print inc[s] # Calling dec decreased the value in inc's container
1.0
>>> dec(1, 0) # Update inc[s] with 0 - 1 = -1
[]
>>> print inc[s]
-1.0
>>> print dec[s] # Still shared
-1.0
Input Argument Restrictions
---------------------------
......
=======================================
:mod:`module` -- a theano object system
=======================================
.. note::
Module addresses similar needs to `shared`. New code is encouraged to
use `shared` variables.
Now that we're familiar with the basics, we introduce Theano's more
advanced interface, Module. This interface allows you to define Theano
"files" which can have variables and methods sharing
those variables. The Module system simplifies the way to define complex
systems such as a neural network.
It also lets you load and save these complex systems using Python's pickle
mechanism.
Remake of the "state" example
=============================
Let's use Module to re-implement :ref:`the example using state
<functionstateexample>`.
>>> m = Module()
>>> m.state = T.dscalar()
>>> m.inc = T.dscalar('inc')
>>> m.new_state = m.state + m.inc
>>> m.add = Method(m.inc, m.new_state, {m.state: m.new_state})
>>> m.sub = Method(m.inc, None, {m.state: m.state - m.inc})
>>> acc = m.make(state = 0)
>>> acc.state, acc.inc
(array(0.0), None)
>>> acc.add(2)
array(2.0)
>>> acc.state, acc.inc
(array(2.0), None)
>>> acc.state = 39.99
>>> acc.add(0.01)
array(40.0)
>>> acc.state
array(40.0)
>>> acc.sub(20)
>>> acc.state
array(20.0)
This deserves to be broken up a bit...
>>> m = Module()
Here we instantiate an empty Module.
If you can imagine that Theano is a way of generating code (expression
graphs),
then a ``Module()`` is like a fresh blank file.
>>> m.state = T.dscalar()
>>> m.inc = T.dscalar('inc')
Then we declare Variables for use in our Module.
Since we assign these input Variables as attributes of the Module,
they will be *member Variables* of the Module.
Member Variables are special in a few ways, which we will see shortly.
.. note::
There is no need to name the Variable explicitly here. ``m.state`` will
be given the name ``'state'`` automatically, because it is being assigned
to the attribute named ``'state'``.
.. note::
Since we made it a member of ``m``, the ``acc`` object will have an
attribute called ``inc``. This attribute will keep its default value of
None throughout the example.
>>> m.new_state = m.state + m.inc
This line creates a Variable corresponding to some symbolic computation.
Although this line also assigns a Variable to a Module attribute, it
does not become a member Variable like ``state`` and ``inc`` because it
represents an expression *result*.
>>> m.add = Method(m.inc, m.new_state, {m.state: m.new_state})
Here we declare a Method. The three arguments are as follow:
* **inputs**: a list of input Variables
* **outputs**: a list of output Variables, or ``None``. ``None`` is equivalent
to returning an empty list of outputs.
* **updates**: a dictionary mapping member Variables to Variables. When we
call the function that this Method compiles to, it will replace (update) the
values associated with the member Variables.
>>> m.sub = Method(m.inc, None, {m.state: m.state - m.inc})
We declare another Method, that has no outputs.
>>> acc = m.make(state = 0)
This line is what does the magic (well, compilation).
The ``m`` object contains symbolic things such as Variables and Methods.
Calling ``make`` on ``m`` creates an object that can do real
computation and whose attributes contain values such as numbers and numpy
ndarrays.
At this point something special happens for our member Variables too.
In the ``acc`` object, make allocates room to store numbers for ``m``'s
member Variables. By using the string ``'state'`` as a keyword
argument, we tell Theano to store the number ``0`` for the member
Variable called ``state``. By not mentioning the ``inc`` variable, we
associate ``None`` to the ``inc`` Variable.
>>> acc.state, acc.inc
(array(0.0), None)
Since ``state`` was declared as a member Variable of ``m``, we can
access it's value in the ``acc`` object by the same attribute.
Ditto for ``inc``.
.. note::
Members can also be accessed using a dictionary-like notation.
The syntax ``acc['state']`` is equivalent to ``acc.state``.
>>> acc.add(2)
array(2.0)
>>> acc.state, acc.inc
(array(2.0), None)
When we call the ``acc.add`` method, the value ``2`` is used for the
symbolic ``m.inc``. The first line evaluates the output and all the
updates given in the ``updates`` argument of the call to Method that
declared ``acc``. We only had one update which mapped ``state`` to
``new_state`` and you can see that it works as intended, adding the
argument to the internal state.
Note also that ``acc.inc`` is still ``None`` after our call. Since
``m.inc`` was listed as an input in the call to Method that created
``m.add``, when ``acc.add`` was created by the call to ``m.make``, a
private storage container was allocated to hold the first parameter.
If we had left ``m.inc`` out of the Method input list, then ``acc.add``
would have used ``acc.inc`` instead.
>>> acc.state = 39.99
The state can also be set. When we manually set the value of a member
attribute like this, then subsequent calls to the methods of our module will
use the new value.
>>> acc.add(0.01)
array(40.0)
>>> acc.state
array(40.0)
>>> acc.sub(20)
>>> acc.state
array(20.0)
Here, note that ``acc.add`` and ``acc.sub`` share access to the same ``state``
value but update it in different ways.
Using Inheritance
=================
A friendlier way to use Module is to implement your functionality as a
subclass of Module:
.. literalinclude:: ../../examples/module/accumulator.py
This is just like the previous example except slightly fancier.
.. warning::
Do not forget to call the constructor of the parent class!
(That's the call to ``super().__init__`` in the previous code block.)
If you forget it, you'll get strange behavior :(
Extending your Module with Python methods
=========================================
Let's say we want to add a method to our accumulator to print out the
state and we want to call it ``print_state``. There are two mechanisms to do
this: let's call them _instance_method and InstanceType.
Mechanism 1: _instance_method
-----------------------------
This is the preferred way of adding a few instance methods with a minimum of
boilerplate code.
All we need to do to use this mechanism is to give a method called
``_instance_print_state`` to our Module class.
Any method called like ``_instance_XXX`` will cause the object
obtained through a call to ``make`` to have a method called ``XXX``.
Note that when we define ``_instance_print_state`` there are two "self"
arguments: ``self`` which is *symbolic* and ``obj`` which is the compiled
object (the one that contains values).
Hint: ``self.state`` is the symbolic state variable and
prints out as "state", whereas ``obj.state`` is the state's actual
value in the accumulator and prints out as "0.0".
Mechanism 2: InstanceType
-------------------------
If a number of instance methods are going to be defined, and especially if you
will want to inherit from the kind of class that gets instantiated by ``make``,
you might prefer to consider using the InstanceType mechanism.
Adding custom initialization
============================
As was said in the previous section, you can add functionality with
``_instance_XXX`` methods. One of these methods is actually special:
``_instance_initialize`` will be called with whatever arguments you
give to ``make``. There is a default behavior which we have used,
where we give the states' initial values with keyword arguments
(``acc.make(state = 0)``). If you want more personalized behavior, you
can override the default with your own method, which has to be called
``_instance_initialize``.
.. TODO
Here is an example where we take width and height arguments to
initialize a state with a matrix of zeros:
Nesting Modules
===============
Probably the most powerful feature of Theano's Modules is that one can be
included as an attribute to another so that the storage of each is available
to both.
As you read through examples of Theano code, you will probably see many
instances of Modules being nested in this way.
===================================================================
:mod:`module` -- API documentation
===================================================================
.. automodule:: theano.compile.module
:members:
......@@ -64,9 +64,6 @@ would normally, by specifying the mode parameter.
>>> # with functions
>>> f = theano.function([input1,input2],[output1], mode=profmode)
>>> # with modules
>>> m = theano.Module()
>>> minst = m.make(mode=profmode)
Retrieving Timing Information
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
......
......@@ -361,7 +361,7 @@ import theano and print the config variable, as in:
.. attribute:: linker
String value: 'c|py', 'py', 'c', 'c|py_nogc', 'c&py'
String value: 'c|py', 'py', 'c', 'c|py_nogc'
Default: 'c|py'
......
......@@ -17,5 +17,3 @@ API
.. automodule:: theano.sandbox.linalg.ops
:members:
.. automodule:: theano.sandbox.linalg.kron
:members:
......@@ -19,8 +19,7 @@ Reference
.. class:: RandomStreamsBase(object)
This is the interface for the
:class:`theano.tensor.shared_randomstreams.RandomStreams` subclass and the
:class:`theano.tensor.randomstreams.RandomStreams` subclass.
:class:`theano.tensor.shared_randomstreams.RandomStreams` subclass
.. method:: binomial(self, size=(), n=1, p=0.5, ndim=None):
......
......@@ -13,10 +13,7 @@ Guide
=====
Since Theano uses a functional design, producing pseudo-random numbers in a
graph is not quite as straightforward as it is in numpy. If you are using Theano's
shared variables, then a `RandomStreams` object is probably what you want. (If you are
using Module then this tutorial will be useful but not exactly what you want.
Have a look at the :class:`RandomFunction` Op.)
graph is not quite as straightforward as it is in numpy.
The way to think about putting randomness into Theano's computations is to
put random variables in your graph. Theano will allocate a numpy RandomState
......
.. _moduleinterface:
================
Module Interface
================
A Theano Module is like Theano's version of a file.
When you instantiate a ``Module()``, you are creating a blank file.
Into this file you can put both symbolic and non-symbolic objects.
Non-symbolic objects are like constants (technically literals) in the file.
Symbolic objects are like variables and functions.
The functions in a Module are called Methods.
The variables in a Module (and submodules) are global.
Module Methods have access to all these global variables.
To use a Module, you need to compile it.
This is done by calling `Module.make()`.
The result of compiling a Module is a ModuleInstance, this is the compiled
version of your Theano file.
In the ModuleInstance, your symbolic variables have become containers (containing None),
and your Methods have become callable functions.
You should initialize the symbolic variables by calling
``ModuleInstance.initialize()`` (although make() will call it for you,
on the top-level ModuleInstance.)
You can compile a Module several times, to create multiple ModuleInstances.
Each of these will have its own copy of all program literals.
Module Graph
------------
Components can be grouped into a directed graph.
When we call `make`, this graph is replicated with ComponentInstances instead of
Components. Wheras Components are represent symbolic things (ie. Variables), ComponentInstances represent non-symbolic ones (ie. sparse matrices, ndarrays, callable functions).
.. index::
single: Component
single: component; Component
.. _component:
---------
Component
---------
All of the elements of what is called the "module system" or "modules" are
components.
A component subclass is represents a symbolic theano thing, and implements the
``build`` function.
The ``build`` function is responsible for converting the symbolic thing into a
non-symbolic thing.
Compiling with make
-------------------
Conversion from a Component graph to a ComponentInstance graph is performed by `Component.make`.
This method traverses the Component graph in multiple passes.
In the first pass (the allocate pass), it creates storage for all Variables that are contained in the graph (see
`Component.allocate`). These are the module variables.
In the second pass (the build pass), it creates functions that (in general) operate on these module variables.
This pass also serves to construct all ComponentInstance-derived instances as well, such as
`ModuleInstance`s. The objects that are returned from this second pass are the return value of
`Component.make`.
In the third pass (the initialize pass), is optional and not necessarily recursive through the
graph.
The purpose of the third pass is to call the initialize method of the ComponentInstances built
during the second pass.
During this pass the ComponentInstance graph is complete. It is a good time to fill storage
allocated in phase 1 with sensible values.
.. index::
single: External
single: component; External
.. _external:
--------
External
--------
WRITEME
.. index::
single: Member
single: component; Member
.. _member:
------
Member
------
WRITEME
.. index::
single: Method
single: component; Method
.. _method:
------
Method
------
WRITEME
.. index::
single: Module
single: component; Module
.. _module:
------
Module
------
A Module instance can contain objects as attributes.
This makes it something like a class in the way that Method is
analogous to a function.
A Module is meant to contain Components.
Attributes which are not Components themselves must at least be transform-able
into Components by :func:`.compile.module.wrap`. If a Module contains something
that is not convertible into a Component, then it is not possible to compile
that Module with ``make``.
Old Text
--------
In the Module system, the analog of the file is the `Module`, the analog of the function is the
`Method`, and the analog of the variable is the `Member`. Module, Member, and Method all work
at the symbolic level. Once a graph of Modules, Members, and Methods is ready for use, it must
be compiled with a call to `make` which will return an isomorphic structure in which Modules
have become `ModuleInstances`, Members have become `Containers`, and Methods have become
`Functions`.
This structure contains numbers and functions, and is ready for computation.
.. _module2:
######
Module
######
What is a Theano Module
=======================
Theano 'Module' is a structure which implements what could be called a
"theano class". A ``Module`` can contain ``Members``, which act like
instance variables ("state"). It can also contain an arbitrary number
of ``Methods``, which are functions that share the same ``Members`` in
addition to their own inputs. Last but not least, ``Modules`` can be
nested (explanations and examples follow). ``Module`` is meant to:
#. ease the sharing of variables between several Theano functions,
#. streamline automatic naming, and
#. allow a hierarchy of "modules" whose states can interact.
import
======
All examples suppose that you have done those import:
.. code-block:: python
#!/usr/bin/env python
import theano
import numpy as N
from theano import tensor as T
from theano.tensor import nnet as NN
from theano.compile import module as M
Module
======
A ``Module`` can contain ``Members``, ``Methods`` and inner ``Modules``. Each type has a special meaning.
.. code-block:: python
module = M.Module()
``Member``
------------
Usage:
.. code-block:: python
#module.state = variable
module.state = T.scalar()
A ``Member`` represents a state variable (i.e., whose value remains after a ``Method`` is called). It will be named automatically after that field and it will be an implicit input of all ``Methods`` of the ``Module``. Its storage (i.e. where the value is stored) will be shared by all ``Methods`` of the ``Module``.
A ``Variable`` which is the variable of a previous computation (by opposition to being ``updated``) is not a ``Member``. Internally this is called an External. You should not need to care about this.
For sharing state between modules, see ``Inner Module`` section.
``Method``
------------
Usage:
.. code-block:: python
module.method = M.Method(inputs, outputs, **updates)
Each key in the updates dictionary must be the name of an existing ``Member`` of the ``Module`` and the value associated to that key is the update expression for the state. When called on a ``ModuleInstance`` produced by the ``Module``, the method will calculate the outputs from the inputs and will update all the states as specified by the update expressions. See the basic example below.
Inner Module
------------
To share a ``Member`` between modules, the modules must be linked through the inner module mechanism.
Usage:
.. code-block:: python
module2.submodule = module
``ModuleInstance``
====================
A ``Module`` can produce a ``ModuleInstance`` with its ``make`` method. Think of this as a class and an object in C++/Java. If an attribute was a ``Member``, it will become a read/write access to actual data for the state. If it was a ``M.Method``, a function will be compiled with the proper signature and semantics.
Module Interface
================
.. code-block:: python
def make(self, mode = {'FAST_COMPILE', 'FAST_RUN', ... }, **init)
'''make''' compiles all ``Methods`` and allocates storage for all ``Members`` into a ``ModuleInstance`` object, which is returned. The ``init`` dictionary can be used to provide initial values for the members.
.. code-block:: python
def resolve(self, symbol, filter = None)
Resolves a symbol in this module. The symbol can be a string or a ``Variable``. If the string contains dots (eg ``"x.y"``), the module will resolve the symbol hierarchically in its inner modules. The filter argument is None or a class and it can be used to restrict the search to ``Member`` or ``Method`` instances for example.
.. code-block:: python
def _instance_initialize(self, inst, **init)
The inst argument is a ``ModuleInstance``. For each key, value pair in init: ``setattr(inst, key, value)`` is called. This can be easily overriden by ``Module`` subclasses to initialize an instance in different ways. If you don't know what to put their, don't put it and it will execute a default version. If you want to call the parent version call: ``M.default_initialize(inst,**init)``
Basic example
=============
The problem here is to create two functions, ``inc`` and ``dec`` and a shared state ``c`` such that ``inc(n)`` increases ``c`` by ``n`` and ``dec(n)`` decreases ``c`` by ``n``. We also want a third function, ``plus10``, which return 10 + the current state without changing the current state. Using the function interface, the feature can be implemented as follows:
.. code-block:: python
n, c = T.scalars('nc')
inc = theano.function([n, ((c, c + n), 0)], [])
dec = theano.function([n, ((c, c - n), inc.container[c])], []) # we need to pass inc's container in order to share
plus10 = theano.function([(c, inc.container[c])], c + 10)
assert inc[c] == 0
inc(2)
assert inc[c] == 2 and dec[c] == inc[c]
dec(3)
assert inc[c] == -1 and dec[c] == inc[c]
assert plus10() == 9
Now, using ``Module``:
.. code-block:: python
m = M.Module()
n = T.scalar('n')
m.c = T.scalar() # state variables
m.inc = M.Method(n, [], updates = {m.c: m.c + n}) # m.c <= m.c + n
m.dec = M.Method(n, [], updates = {m.c: m.c - n}) # k.c <= k.c - n
#m.dec = M.Method(n, [], updates = {c: m.c - n})#global c don't exist
#m.plus10 does not update the state
m.plus10 = M.Method([], m.c + 10) # m.c is always accessible since it is a member of this mlass
inst = m.make(c = 0) # here, we make an "instance" of the module with c initialized to 0
assert inst.c == 0
inst.inc(2)
assert inst.c == 2
inst.dec(3)
assert inst.c == -1
assert inst.plus10() == 9
Benefits of ``Module`` over ``function`` in this example:
* There is no need to manipulate the containers directly
* The fact inc and dec share a state is more obvious syntactically.
* ``Method`` does not require the states to be anywhere in the input list.
* The interface of the instance produced by ``m.make()`` is simple and coherent, extremely similar to that of a normal python object. It is directly usable by any user.
Nesting example
===============
The problem now is to create two pairs of ``inc dec`` functions and a function ``sum`` that adds the shared states of the first and second pair.
Using function:
.. code-block:: python
def make_incdec_function():
n, c = T.scalars('nc')
inc = theano.function([n, ((c, c + n), 0)], [])
dec = theano.function([n, ((c, c - n), inc.container[c])], [])#inc and dec share the same state.
return inc,dec
inc1, dec1 = make_incdec_function()
inc2, dec2 = make_incdec_function()
a, b = T.scalars('ab')
sum = theano.function([(a, inc1.container['c']), (b, inc2.container['c'])], a + b)
inc1(2)
dec1(4)
inc2(6)
assert inc1['c'] == -2 and inc2['c'] == 6
assert sum() == 4 # -2 + 6
Using Module:
.. code-block:: python
def make_incdec_module():
m = M.Module()
n = T.scalar('n')
m.c = T.scalar() # state variables
m.inc = M.Method(n, [], updates = {m.c: m.c + n}) # m.c <= m.c + n
m.dec = M.Method(n, [], updates = {m.c: m.c - n}) # m.c <= m.c - n
return m
m = M.Module()
m.incdec1 = make_incdec_module()
m.incdec2 = make_incdec_module()
m.sum = M.Method([], m.incdec1.c + m.incdec2.c)
inst = m.make(incdec1 = dict(c=0), incdec2 = dict(c=0))
inst.incdec1.inc(2)
inst.incdec1.dec(4)
inst.incdec2.inc(6)
assert inst.incdec1.c == -2 and inst.incdec2.c == 6
assert inst.sum() == 4 # -2 + 6
Here, we make a new ``Module`` and we give it two inner ``Modules`` like
the one defined in the basic example. Each inner module has methods inc
and dec as well as a state c and their state is directly accessible from
the outer module, which means that it can define methods using them. The
instance (inst) we make from the ``Module`` (m) reflects the hierarchy
that we created. Unlike the method using function, there is no need to
manipulate any containers directly.
Advanced example
================
Complex models can be implemented by subclassing ``Module`` (though that is not mandatory). Here is a complete, extensible (and working) regression model implemented using this system:
.. literalinclude:: ../../benchmark/regression/regression.py
Here is how we use the model:
.. code-block:: python
data_x = N.random.randn(4, 10)
data_y = [ [int(x)] for x in N.random.randn(4) > 0]
model = SoftmaxXERegression(regularize = False).make(input_size = 10,
target_size = 1,
stepsize = 0.1)
for i in xrange(1000):
xe = model.update(data_x, data_y)
if i % 100 == 0:
print i, xe
pass
#for inputs, targets in my_training_set():
#print "cost:", model.update(inputs, targets)
print "final weights:", model.w
print "final biases:", model.b
Extending ``Methods``
=======================
``Methods`` can be extended to update more parameters. For example, if we wanted to add a variable holding the sum of all costs encountered so far to ``SoftmaxXERegression``, we could proceed like this:
.. code-block:: python
model_module = SoftmaxXERegression(regularize = False)
model_module.sum = T.scalar() # we add a module member to hold the sum
model_module.update.updates.update(sum = model_module.sum + model_module.cost) # now update will also update sum!
model = model_module.make(input_size = 4,
target_size = 2,
stepsize = 0.1,
sum = 0) # we mustn't forget to initialize the sum
test = model.update([[0,0,1,0]], [[0,1]]) + model.update([[0,1,0,0]], [[1,0]])
assert model.sum == test
The inputs and outputs list of a ``Method`` can be doctored as well, but it is trickier, arguably less useful and not fully supported at the moment.
.. _module_vs_op:
================================
When should I use Module vs. Op?
================================
An Op can:
- compute some stuff from multiple inputs
- produce multiple outputs
- resize them as necessary (matrices are generally resizable in theano runtime. The only exception is when a vector of integers is used as the new *shape* of some tensor. Since the rank of a tensor is fixed, that vector of integers must have a fixed length.)
Python expressions provide the nice syntax for sticking Ops together as if they were more like PLearn Variables.
But all the links that you have in PLearn modules are still present with Ops, and they can be manipulated explicitly. Theano's optimizations do this. They look at small sections of the graph (so you can handle the case where your inputs come from certain kinds of Ops differently) and re-wire the graph.
So that's the Op for you. I think that if you only ever wanted to compile one theano function per program execution, the Ops would be enough, and there would be no need for Modules. The Modules exist to make it syntactically easier for multiple theano compiled functions to collaborate by sharing physical variables.
When you compile a Method in a Module, it *automatically* gets access to all of the Module's Member [symbolic] variables, and when that Method is compiled to a function, then the function gets access to all of the ModuleInstance's [physical] variables.
So I don't think that there is an analog of Modules in PLearn, because PLearn doesn't make a distinction between the symbolic and instantiated functions.
Modules can also be arranged into graphs. Modules can contain Modules. The meaning of this though is not computational... it's still about sharing variables. Variables are shared throughout the entire Module graph: when you add a DAA to a parent Module for example, the parent Module's Methods gain access to the variables in the DAA. This makes it possible to identify each Module with one particular USE of member variables. Complex behaviour can be built up by adding a few Modules that each do something (bring new skills??) with common variables.
For example, you could have one Module that has weight and bias members, and comes with some [symbolic] methods for using these members to compute the hidden-unit activation of a single layer, given some input.
Then, you could add a second module that handles pre-training by RBM. You would tell the second Module to use the weight matrix and bias of the first Module, and it would allocate its own member for the visible-unit bias. This module would come with [symbolic] methods for doing CD.
Then, you could add a third module that handles pre-training by DAA! You would tell this module about the original weights (maybe the bias too, maybe not) and it would allocate the downward weights, and yet another visible-bias, and would add [symbolic] methods for pre-training that way.
When you compile the parent module, all of the methods associated with each algorithm will be compiled so that they update the same weight matrix that the first module uses to compute it's hidden-unit activation.
This ability for Modules to bring algorithms to work on existing member variables is what lets the minimization algorithm be separated from the layer and regression Modules. There is thus a stochastic gradient descent module, that has one little learning-rate Member, and basically just works with the parameter members of other modules.
The module system would make it possible to include several minimization algorithms at once too, so you could start off by using SGD, and then maybe later you could switch to conjugate gradient for really fine tuning.
So, Ops are for computations and Modules are for sharing variables between Theano functions.
......@@ -142,12 +142,6 @@ How to use the PrintOp
** This is also useful in the How to write an Op tutorial. **
=======================================================
Modules
=======================================================
* What is the correct way to tie weights?
=======================================================
Mammouth
=======================================================
......
......@@ -223,8 +223,8 @@ The ``compute_test_value`` mechanism works as follows:
which do not implement a ``perform`` method.
"How do I Print an Intermediate Value in a Function/Method?"
------------------------------------------------------------
"How do I Print an Intermediate Value in a Function?"
-----------------------------------------------------
Theano provides a 'Print' op to do this.
......
......@@ -179,7 +179,6 @@ c|py [#cpy1]_ yes yes "+++" Try C code. If none exis
c|py_nogc no yes "++" As c|py, but without gc
c no yes "+" Use only C code (if none available for an op, raise an error)
py yes yes "+++" Use only Python code
c&py [#cpy2]_ no yes "+++++" Use C and Python code
ProfileMode no no "++++" (Deprecated) Compute some extra profiling info
DebugMode no yes VERY HIGH Make many checks on what Theano computes
============= ========= ================= ========= ===
......@@ -190,7 +189,6 @@ DebugMode no yes VERY HIGH Make many checks on what
Theano function calls, in order not to
reallocate memory, and lower the overhead (make it faster...).
.. [#cpy1] Default
.. [#cpy2] Deprecated
For more detail, see :ref:`Mode<libdoc_compile_mode>` in the library.
......@@ -300,9 +298,6 @@ would normally, by specifying the mode parameter.
>>> # with functions
>>> f = theano.function([input1,input2],[output1], mode=profmode)
>>> # with modules
>>> m = theano.Module()
>>> minst = m.make(mode=profmode)
Retrieving Timing Information
-----------------------------
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论