提交 7a49c0da authored 作者: james@X40's avatar james@X40

deprecated RModule, added comments to RandomStreams

上级 0786f2af
...@@ -6,11 +6,11 @@ from basic import * ...@@ -6,11 +6,11 @@ from basic import *
import opt import opt
import blas import blas
import raw_random, rmodule import raw_random, randomstreams
from rmodule import \ from randomstreams import \
RandomKit, RModule RandomStreams
random = RandomKit('random') random = RandomStreams(seed=0xBAD5EED)
"""Imitate the numpy.random symbol with a tensor.random one""" """Imitate the numpy.random symbol with a tensor.random one"""
from elemwise import \ from elemwise import \
......
"""Define RModule, a Module providing random number streams in Theano graphs."""
__docformat__ = "restructuredtext en"
import sys
import functools
from functools import partial
from collections import deque
import numpy
from ...compile import (SymbolicInputKit, SymbolicInput,
Module, KitComponent, module, Method, Member, In, Component)
from ...gof import Container
from ...tensor import raw_random
class RandomKit(SymbolicInputKit):
def __init__(self, name, value = None):
super(RandomKit, self).__init__(name)
self.value = value
def gen(self, op, *args, **kwargs):
random_state_result = raw_random.random_state_type()
new_r, out = op(random_state_result, *args, **kwargs)
self.add_input(SymbolicInput(random_state_result, update = new_r))
out.rng = new_r
out.auto = self
return out
def distribute(self, value, indices, containers):
rg = partial(numpy.random.RandomState(int(value)).randint, 2**30)
elems = deque(zip(indices, containers))
i = 0
while elems:
index, container = elems.popleft()
while i <= index:
curr = rg()
i += 1
rs = numpy.random.RandomState(int(curr))
container.data = rs
def binomial(self, *args, **kwargs):
return self.gen(raw_random.binomial, *args, **kwargs)
def uniform(self, *args, **kwargs):
return self.gen(raw_random.uniform, *args, **kwargs)
def normal(self, *args, **kwargs):
return self.gen(raw_random.normal, *args, **kwargs)
def random_integers(self, *args, **kwargs):
return self.gen(raw_random.random_integers, *args, **kwargs)
rk = RandomKit('rk', 0xBAD5EED)
class RModule(Module):
"""Module providing random number streams in Theano graphs."""
def __init__(self, components = {}, **kwcomponents):
super(RModule, self).__init__(components, **kwcomponents)
self.random = RandomKit('rkit')
self._rkit = KitComponent(self.random)
def __wrapper__(self, x):
x = module.wrap(x)
if isinstance(x, Method):
x.kits += [self.random]
return x
def _instance_seed(self, inst, seed, recursive = True):
seedgen = numpy.random.RandomState(seed)
if recursive:
#Here, we recurse through all the components (inst2) contained in (inst)
#and seeds each subcomponent that is an RModule
for path, c in self.flat_components_map(True):
if isinstance(c, RModule):
inst2 = inst
for name in path:
inst2 = inst2[name]
# A Kit (c._rkit.kit) contains a list of io.SymbolicIn instances
# and the distribute method takes a value (seed), a list of indices
# and a list of corresponding Container instances. In this
# situation it will reseed all the rngs using the containers
# associated to them.
c._rkit.kit.distribute(seedgen.random_integers(2**30),
xrange(len(inst2._rkit)), inst2._rkit)
else:
self._rkit.kit.distribute(seedgen.random_integers(2**30), xrange(len(inst._rkit)), inst._rkit)
"""Define RModule, a Module providing random number streams in Theano graphs.""" """Define RandomStreams, providing random number variables for Theano graphs."""
__docformat__ = "restructuredtext en" __docformat__ = "restructuredtext en"
import sys
import functools
from functools import partial
from collections import deque
import sys
import numpy import numpy
from ..compile import (SymbolicInputKit, SymbolicInput, from ..compile import module, In, Component
Module, KitComponent, module, Method, Member, In, Component)
from ..gof import Container from ..gof import Container
from ..tensor import raw_random from ..tensor import raw_random
class RandomKit(SymbolicInputKit):
def __init__(self, name, value = None):
super(RandomKit, self).__init__(name)
self.value = value
def gen(self, op, *args, **kwargs):
random_state_result = raw_random.random_state_type()
new_r, out = op(random_state_result, *args, **kwargs)
self.add_input(SymbolicInput(random_state_result, update = new_r))
out.rng = new_r
out.auto = self
return out
def distribute(self, value, indices, containers):
rg = partial(numpy.random.RandomState(int(value)).randint, 2**30)
elems = deque(zip(indices, containers))
i = 0
while elems:
index, container = elems.popleft()
while i <= index:
curr = rg()
i += 1
rs = numpy.random.RandomState(int(curr))
container.data = rs
def binomial(self, *args, **kwargs):
return self.gen(raw_random.binomial, *args, **kwargs)
def uniform(self, *args, **kwargs):
return self.gen(raw_random.uniform, *args, **kwargs)
def normal(self, *args, **kwargs):
return self.gen(raw_random.normal, *args, **kwargs)
def random_integers(self, *args, **kwargs):
return self.gen(raw_random.random_integers, *args, **kwargs)
rk = RandomKit('rk', 0xBAD5EED)
class RModule(Module):
"""Module providing random number streams in Theano graphs."""
def __init__(self, components = {}, **kwcomponents):
super(RModule, self).__init__(components, **kwcomponents)
self.random = RandomKit('rkit')
self._rkit = KitComponent(self.random)
def __wrapper__(self, x):
x = module.wrap(x)
if isinstance(x, Method):
x.kits += [self.random]
return x
def _instance_seed(self, inst, seed, recursive = True):
seedgen = numpy.random.RandomState(seed)
if recursive:
#Here, we recurse through all the components (inst2) contained in (inst)
#and seeds each subcomponent that is an RModule
for path, c in self.flat_components_map(True):
if isinstance(c, RModule):
inst2 = inst
for name in path:
inst2 = inst2[name]
# A Kit (c._rkit.kit) contains a list of io.SymbolicIn instances
# and the distribute method takes a value (seed), a list of indices
# and a list of corresponding Container instances. In this
# situation it will reseed all the rngs using the containers
# associated to them.
c._rkit.kit.distribute(seedgen.random_integers(2**30),
xrange(len(inst2._rkit)), inst2._rkit)
else:
self._rkit.kit.distribute(seedgen.random_integers(2**30), xrange(len(inst._rkit)), inst._rkit)
class RandomStreamsInstance(object): class RandomStreamsInstance(object):
"""RandomStreamsInstance""" """RandomStreamsInstance"""
def __init__(self, random_streams, memo, default_seed): def __init__(self, random_streams, memo, default_seed):
...@@ -168,10 +83,8 @@ class RandomStreamsInstance(object): ...@@ -168,10 +83,8 @@ class RandomStreamsInstance(object):
return return
raise KeyError(item) raise KeyError(item)
class RandomStreams(Component): class RandomStreams(Component):
"""Module with similar interface to numpy.random (numpy.random.RandomState)""" """Module component with similar interface to numpy.random (numpy.random.RandomState)"""
random_state_results = [] random_state_results = []
"""A list of pairs of the form (input_r, output_r). This will be over-ridden by the module """A list of pairs of the form (input_r, output_r). This will be over-ridden by the module
...@@ -183,11 +96,18 @@ class RandomStreams(Component): ...@@ -183,11 +96,18 @@ class RandomStreams(Component):
generator that provides seeds for member streams""" generator that provides seeds for member streams"""
def __init__(self, seed=None): def __init__(self, seed=None):
"""
:type seed: None or int
:param seed: a default seed to initialize the RandomState instances after build. See
`RandomStreamsInstance.__init__` for more details.
"""
super(RandomStreams, self).__init__() super(RandomStreams, self).__init__()
self.random_state_results = [] self.random_state_results = []
self.default_instance_seed = seed self.default_instance_seed = seed
def allocate(self, memo): def allocate(self, memo):
"""override `Component.allocate` """
for old_r, new_r in self.random_state_results: for old_r, new_r in self.random_state_results:
assert old_r not in memo assert old_r not in memo
memo[old_r] = In(old_r, memo[old_r] = In(old_r,
...@@ -196,11 +116,23 @@ class RandomStreams(Component): ...@@ -196,11 +116,23 @@ class RandomStreams(Component):
mutable=True) mutable=True)
def build(self, mode, memo): def build(self, mode, memo):
#print 'MODE', mode """override `Component.build` """
#returns a list of containers
return RandomStreamsInstance(self, memo, self.default_instance_seed) return RandomStreamsInstance(self, memo, self.default_instance_seed)
def gen(self, op, *args, **kwargs): def gen(self, op, *args, **kwargs):
"""Create a new random stream in this container.
:param op: a RandomFunction instance to
:param args: interpreted by `op`
:param kwargs: interpreted by `op`
:returns: The symbolic random draw part of op()'s return value. This function stores
the updated RandomStateType Result for use at `build` time.
:rtype: TensorResult
"""
random_state_result = raw_random.random_state_type() random_state_result = raw_random.random_state_type()
new_r, out = op(random_state_result, *args, **kwargs) new_r, out = op(random_state_result, *args, **kwargs)
out.rng = random_state_result out.rng = random_state_result
...@@ -210,15 +142,28 @@ class RandomStreams(Component): ...@@ -210,15 +142,28 @@ class RandomStreams(Component):
def binomial(self, *args, **kwargs): def binomial(self, *args, **kwargs):
"""Return a symbolic binomial sample """Return a symbolic binomial sample
This is a shortcut for a call to `self.gen`
""" """
return self.gen(raw_random.binomial, *args, **kwargs) return self.gen(raw_random.binomial, *args, **kwargs)
def uniform(self, *args, **kwargs): def uniform(self, *args, **kwargs):
"""Return a symbolic uniform sample
This is a shortcut for a call to `self.gen`
"""
return self.gen(raw_random.uniform, *args, **kwargs) return self.gen(raw_random.uniform, *args, **kwargs)
def normal(self, *args, **kwargs): def normal(self, *args, **kwargs):
"""Return a symbolic normal sample
This is a shortcut for a call to `self.gen`
"""
return self.gen(raw_random.normal, *args, **kwargs) return self.gen(raw_random.normal, *args, **kwargs)
def random_integers(self, *args, **kwargs): def random_integers(self, *args, **kwargs):
"""Return a symbolic random integer sample
This is a shortcut for a call to `self.gen`
"""
return self.gen(raw_random.random_integers, *args, **kwargs) return self.gen(raw_random.random_integers, *args, **kwargs)
...@@ -18,7 +18,7 @@ def cross_entropy(target, output, axis=1): ...@@ -18,7 +18,7 @@ def cross_entropy(target, output, axis=1):
""" """
return -T.mean(target * T.log(output) + (1 - target) * T.log(1 - output), axis=axis) return -T.mean(target * T.log(output) + (1 - target) * T.log(1 - output), axis=axis)
class QuadraticDenoisingAA(T.RModule): class QuadraticDenoisingAA(module.Module):
"""Quadratic de-noising Auto-encoder """Quadratic de-noising Auto-encoder
WRITEME WRITEME
...@@ -59,6 +59,8 @@ class QuadraticDenoisingAA(T.RModule): ...@@ -59,6 +59,8 @@ class QuadraticDenoisingAA(T.RModule):
""" """
super(QuadraticDenoisingAA, self).__init__() super(QuadraticDenoisingAA, self).__init__()
self.random = T.RandomStreams()
# MODEL CONFIGURATION # MODEL CONFIGURATION
# self.regularize = regularize # self.regularize = regularize
self.tie_weights = tie_weights self.tie_weights = tie_weights
...@@ -75,11 +77,11 @@ class QuadraticDenoisingAA(T.RModule): ...@@ -75,11 +77,11 @@ class QuadraticDenoisingAA(T.RModule):
# PARAMETERS # PARAMETERS
if _qfilters is None: if _qfilters is None:
self.qfilters = [theano.Member(T.dmatrix()) for i in xrange(n_quadratic_filters)] self.qfilters = [theano.Member(T.dmatrix('q%i'%i)) for i in xrange(n_quadratic_filters)]
else: else:
self.qfilters = [theano.Member(q) for q in _qfilters] self.qfilters = [theano.Member(q) for q in _qfilters]
self.w1 = theano.Member(T.matrix()) if _w1 is None else theano.Member(_w1) self.w1 = theano.Member(T.matrix('w1')) if _w1 is None else theano.Member(_w1)
if _w2 is None: if _w2 is None:
if not tie_weights: if not tie_weights:
self.w2 = theano.Member(T.matrix()) self.w2 = theano.Member(T.matrix())
...@@ -87,8 +89,8 @@ class QuadraticDenoisingAA(T.RModule): ...@@ -87,8 +89,8 @@ class QuadraticDenoisingAA(T.RModule):
self.w2 = self.w1.T self.w2 = self.w1.T
else: else:
self.w2 = theano.Member(_w2) self.w2 = theano.Member(_w2)
self.b1 = theano.Member(T.vector()) if _b1 is None else theano.Member(_b1) self.b1 = theano.Member(T.vector('b1')) if _b1 is None else theano.Member(_b1)
self.b2 = theano.Member(T.vector()) if _b2 is None else theano.Member(_b2) self.b2 = theano.Member(T.vector('b2')) if _b2 is None else theano.Member(_b2)
# # REGULARIZATION COST # # REGULARIZATION COST
# self.regularization = self.build_regularization() # self.regularization = self.build_regularization()
...@@ -173,6 +175,7 @@ class QuadraticDenoisingAA(T.RModule): ...@@ -173,6 +175,7 @@ class QuadraticDenoisingAA(T.RModule):
if (input_size is None) ^ (hidden_size is None): if (input_size is None) ^ (hidden_size is None):
raise ValueError("Must specify input_size and hidden_size or neither.") raise ValueError("Must specify input_size and hidden_size or neither.")
super(QuadraticDenoisingAA, self)._instance_initialize(obj, {}) super(QuadraticDenoisingAA, self)._instance_initialize(obj, {})
obj.random.initialize()
if seed is not None: if seed is not None:
R = N.random.RandomState(seed) R = N.random.RandomState(seed)
else: else:
...@@ -189,7 +192,7 @@ class QuadraticDenoisingAA(T.RModule): ...@@ -189,7 +192,7 @@ class QuadraticDenoisingAA(T.RModule):
obj.qfilters = [R.uniform(size = sz, low = -inf, high = inf) * qfilter_relscale \ obj.qfilters = [R.uniform(size = sz, low = -inf, high = inf) * qfilter_relscale \
for qf in self.qfilters] for qf in self.qfilters]
if seed is not None: if seed is not None:
obj.seed(seed, recursive=True) obj.random.seed(seed)
obj.lr = lr obj.lr = lr
......
__docformat__ = "restructuredtext en"
import sys
import unittest
import numpy
from theano.tensor.randomstreams import RandomStreams, raw_random
from theano.compile import Module, Method, Member
from theano import tensor
from theano import compile, gof
class T_RandomStreams(unittest.TestCase):
def test_basics(self):
m = Module()
m.random = RandomStreams(234)
m.fn = Method([], m.random.uniform((2,2)))
m.gn = Method([], m.random.normal((2,2)))
made = m.make()
made.random.initialize()
fn_val0 = made.fn()
fn_val1 = made.fn()
gn_val0 = made.gn()
rng_seed = numpy.random.RandomState(234).randint(2**30)
rng = numpy.random.RandomState(int(rng_seed)) #int() is for 32bit
#print fn_val0
numpy_val0 = rng.uniform(size=(2,2))
numpy_val1 = rng.uniform(size=(2,2))
#print numpy_val0
assert numpy.all(fn_val0 == numpy_val0)
assert numpy.all(fn_val1 == numpy_val1)
def test_seed_in_initialize(self):
m = Module()
m.random = RandomStreams(234)
m.fn = Method([], m.random.uniform((2,2)))
made = m.make()
made.random.initialize(seed=888)
fn_val0 = made.fn()
fn_val1 = made.fn()
rng_seed = numpy.random.RandomState(888).randint(2**30)
rng = numpy.random.RandomState(int(rng_seed)) #int() is for 32bit
#print fn_val0
numpy_val0 = rng.uniform(size=(2,2))
numpy_val1 = rng.uniform(size=(2,2))
#print numpy_val0
assert numpy.all(fn_val0 == numpy_val0)
assert numpy.all(fn_val1 == numpy_val1)
def test_seed_fn(self):
m = Module()
m.random = RandomStreams(234)
m.fn = Method([], m.random.uniform((2,2)))
made = m.make()
made.random.initialize(seed=789)
made.random.seed(888)
fn_val0 = made.fn()
fn_val1 = made.fn()
rng_seed = numpy.random.RandomState(888).randint(2**30)
rng = numpy.random.RandomState(int(rng_seed)) #int() is for 32bit
#print fn_val0
numpy_val0 = rng.uniform(size=(2,2))
numpy_val1 = rng.uniform(size=(2,2))
#print numpy_val0
assert numpy.all(fn_val0 == numpy_val0)
assert numpy.all(fn_val1 == numpy_val1)
def test_getitem(self):
m = Module()
m.random = RandomStreams(234)
out = m.random.uniform((2,2))
m.fn = Method([], out)
made = m.make()
made.random.initialize(seed=789)
made.random.seed(888)
rng = numpy.random.RandomState()
rng.set_state(made.random[out.rng].get_state())
fn_val0 = made.fn()
fn_val1 = made.fn()
numpy_val0 = rng.uniform(size=(2,2))
numpy_val1 = rng.uniform(size=(2,2))
assert numpy.all(fn_val0 == numpy_val0)
assert numpy.all(fn_val1 == numpy_val1)
def test_setitem(self):
m = Module()
m.random = RandomStreams(234)
out = m.random.uniform((2,2))
m.fn = Method([], out)
made = m.make()
made.random.initialize(seed=789)
made.random.seed(888)
rng = numpy.random.RandomState(823874)
made.random[out.rng] = numpy.random.RandomState(823874)
fn_val0 = made.fn()
fn_val1 = made.fn()
numpy_val0 = rng.uniform(size=(2,2))
numpy_val1 = rng.uniform(size=(2,2))
assert numpy.all(fn_val0 == numpy_val0)
assert numpy.all(fn_val1 == numpy_val1)
if __name__ == '__main__':
from theano.tests import main
main("test_randomstreams")
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论