提交 5ea40ae1 authored 作者: James Bergstra's avatar James Bergstra

giant commit: moving pfunc & shared out of sandbox

上级 cf7f9f7e
...@@ -39,14 +39,15 @@ from gof import \ ...@@ -39,14 +39,15 @@ from gof import \
set_compiledir, get_compiledir, clear_compiledir set_compiledir, get_compiledir, clear_compiledir
from compile import \ from compile import \
SymbolicInput, SymbolicInputKit, In, \ SymbolicInput, In, \
SymbolicOutput, Out, \ SymbolicOutput, Out, \
Mode, \ Mode, \
predefined_modes, predefined_linkers, predefined_optimizers, \ predefined_modes, predefined_linkers, predefined_optimizers, \
FunctionMaker, function, OpFromGraph, \ FunctionMaker, function, OpFromGraph, \
Component, External, Member, Method, \ Component, External, Member, Method, \
Composite, ComponentList, ComponentDict, Module, \ Composite, ComponentList, ComponentDict, Module, \
ProfileMode ProfileMode, \
Param, shared
FancyModule = Module FancyModule = Module
......
...@@ -19,3 +19,8 @@ from debugmode import DebugMode ...@@ -19,3 +19,8 @@ from debugmode import DebugMode
from profilemode import ProfileMode from profilemode import ProfileMode
from theano.compile.sharedvalue import shared, shared_constructor, SharedVariable
from theano.compile.pfunc import pfunc, Param
from function import function
from theano import gof from theano import gof
from theano import gradient as G from theano import gradient as G
from function_module import function from function_module import orig_function
class OpFromGraph(gof.Op): class OpFromGraph(gof.Op):
...@@ -44,7 +44,7 @@ class OpFromGraph(gof.Op): ...@@ -44,7 +44,7 @@ class OpFromGraph(gof.Op):
raise TypeError('updates are not allowed in kwargs') raise TypeError('updates are not allowed in kwargs')
# TODO: the graph may have implicit inputs like Value and SharedVariable instances. # TODO: the graph may have implicit inputs like Value and SharedVariable instances.
# what impact to they have on the validity of this Op? # what impact to they have on the validity of this Op?
self.fn = function(inputs, outputs, **kwargs) self.fn = orig_function(inputs, outputs, **kwargs)
self.inputs = inputs self.inputs = inputs
self.outputs = outputs self.outputs = outputs
self.input_types = [input.type for input in inputs] self.input_types = [input.type for input in inputs]
......
...@@ -830,10 +830,7 @@ def check_equal(x, y): ...@@ -830,10 +830,7 @@ def check_equal(x, y):
def register_checker(checker): def register_checker(checker):
__checkers.insert(0, checker) __checkers.insert(0, checker)
def orig_function(inputs, outputs, mode=None, accept_inplace = False):
def function(inputs, outputs, mode=None, accept_inplace = False):
""" """
Return a Function that will calculate the outputs from the inputs. Return a Function that will calculate the outputs from the inputs.
......
...@@ -479,7 +479,7 @@ class Method(Component): ...@@ -479,7 +479,7 @@ class Method(Component):
#backport #backport
#effective_mode = mode if self.mode is None else self.mode #effective_mode = mode if self.mode is None else self.mode
rval = F.function(inputs, outputs, effective_mode) rval = F.orig_function(inputs, outputs, effective_mode)
memo[self] = rval memo[self] = rval
return rval return rval
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from theano.gof import Container, Variable, generic, graph, Constant, Value from theano.gof import Container, Variable, generic, graph, Constant, Value
from theano.compile import function, In from theano.compile import orig_function, In, Out
from theano.compile.sandbox.sharedvalue import SharedVariable, shared from theano.compile.sharedvalue import SharedVariable, shared
import numpy # for backport to 2.4, to get any(). import numpy # for backport to 2.4, to get any().
class Param(object): class Param(object):
...@@ -33,7 +33,7 @@ class Param(object): ...@@ -33,7 +33,7 @@ class Param(object):
self.strict = strict self.strict = strict
self.implicit = implicit self.implicit = implicit
def pfunc(params, outputs=None, mode=None, updates=[], givens=[]): def pfunc(params, outputs=None, mode=None, updates=[], givens=[], accept_inplace=False):
"""Function-constructor for graphs with shared variables. """Function-constructor for graphs with shared variables.
:type params: list of either Variable or Param instances. :type params: list of either Variable or Param instances.
...@@ -121,19 +121,33 @@ def pfunc(params, outputs=None, mode=None, updates=[], givens=[]): ...@@ -121,19 +121,33 @@ def pfunc(params, outputs=None, mode=None, updates=[], givens=[]):
raise TypeError('Cannot use a shared variable (%s) as explicit input ' raise TypeError('Cannot use a shared variable (%s) as explicit input '
% v) % v)
# computed_list is a list of output variables # computed_list is a list of output variables (which will be extended later)
computed_list = []
if isinstance(outputs, list): if isinstance(outputs, list):
cloned_outputs = []
for v in outputs: for v in outputs:
if not isinstance(v, Variable): if isinstance(v, Variable):
raise TypeError('outputs must be theano Variable instances', v) cloned_v = v_clone(v)
# Copy list (because it may be extended later). cloned_outputs.append(cloned_v)
computed_list = [v_clone(o) for o in outputs] elif isinstance(v, Out):
cloned_outputs = list(computed_list) cloned_v = v_clone(v.variable)
cloned_outputs.append(Out(cloned_v, borrow=v.borrow))
else: else:
if not isinstance(outputs, Variable): raise TypeError('outputs must be theano Variable or Out instances', v)
raise TypeError('output must be a theano Variable instance', outputs) computed_list.append(cloned_v)
cloned_outputs = v_clone(outputs) else:
computed_list = [cloned_outputs] if isinstance(outputs, Variable):
cloned_v = v_clone(outputs)
cloned_outputs = cloned_v
computed_list.append(cloned_v)
elif isinstance(outputs, Out):
cloned_v = v_clone(outputs.variable)
cloned_outputs = Out(cloned_v, borrow=outputs.borrow)
computed_list.append(cloned_v)
elif outputs is None:
cloned_outputs = [] # TODO: return None
else:
raise TypeError('output must be a theano Variable or Out instance', outputs)
# Add update values as quantities that must be computed. # Add update values as quantities that must be computed.
# Here, we # Here, we
...@@ -187,14 +201,15 @@ def pfunc(params, outputs=None, mode=None, updates=[], givens=[]): ...@@ -187,14 +201,15 @@ def pfunc(params, outputs=None, mode=None, updates=[], givens=[]):
in_sv.update = new_val in_sv.update = new_val
in_sv.mutable = True in_sv.mutable = True
return function(inputs, cloned_outputs, mode, accept_inplace=False) return orig_function(inputs, cloned_outputs, mode, accept_inplace=accept_inplace)
def _pfunc_param_to_in(param): def _pfunc_param_to_in(param):
if isinstance(param, Constant): if isinstance(param, Constant):
raise TypeError('Constants not allowed in param list', param) raise TypeError('Constants not allowed in param list', param)
if isinstance(param, Value): #if isinstance(param, Value):
raise NotImplementedError() #return In(variable=param)
if isinstance(param, Variable): #includes SharedVariable #raise NotImplementedError()
if isinstance(param, Variable): #N.B. includes Value and SharedVariable
return In(variable=param) return In(variable=param)
elif isinstance(param, Param): elif isinstance(param, Param):
return In( return In(
...@@ -204,7 +219,7 @@ def _pfunc_param_to_in(param): ...@@ -204,7 +219,7 @@ def _pfunc_param_to_in(param):
mutable=param.mutable, mutable=param.mutable,
strict=param.strict, strict=param.strict,
implicit = param.implicit) implicit = param.implicit)
raise NotImplementedError('Unknown parameter type: %s' % type(param)) raise TypeError('Unknown parameter type: %s' % type(param))
def iter_over_pairs(pairs): def iter_over_pairs(pairs):
......
from theano.compile.sandbox.sharedvalue import shared, shared_constructor import sys
from theano.compile.sandbox.pfunc import pfunc print >> sys.stderr, "DEPRECATION: theano.compile.sandbox no longer provides shared, shared_constructor, and pfunc. They have been moved to theano.compile."
from theano.compile.sharedvalue import shared, shared_constructor
from theano.compile.pfunc import pfunc
...@@ -3,13 +3,7 @@ __docformat__ = 'restructuredtext en' ...@@ -3,13 +3,7 @@ __docformat__ = 'restructuredtext en'
import traceback import traceback
import copy import copy
import numpy
import theano.tensor.basic
from theano.gof import Container, Variable, generic from theano.gof import Container, Variable, generic
from theano.tensor import TensorType
from theano.scalar import Scalar
from theano.compile import function
import logging import logging
_logger = logging.getLogger('theano.compile.sandbox.sharedvalue') _logger = logging.getLogger('theano.compile.sandbox.sharedvalue')
...@@ -146,59 +140,3 @@ def generic_constructor(value, name=None, strict=False): ...@@ -146,59 +140,3 @@ def generic_constructor(value, name=None, strict=False):
"""SharedVariable Constructor""" """SharedVariable Constructor"""
return SharedVariable(type=generic, value=value, name=name, strict=strict) return SharedVariable(type=generic, value=value, name=name, strict=strict)
class TensorSharedVariable(SharedVariable, theano.tensor.basic._tensor_py_operators):
pass
@shared_constructor
def tensor_constructor(value, name=None, strict=False, broadcastable=None):
"""SharedVariable Constructor for TensorType
:note: Regarding the inference of the broadcastable pattern...
The default is to assume that the value might be resized in any dimension, so the default
broadcastable is ``(False,)*len(value.shape)``. The optional `broadcastable` argument will
override this default.
"""
if not isinstance(value, numpy.ndarray):
raise TypeError()
# if no broadcastable is given, then the default is to assume that the value might be
# resized in any dimension in the future.
#
if broadcastable is None:
broadcastable = (False,)*len(value.shape)
type = TensorType(value.dtype, broadcastable=broadcastable)
return TensorSharedVariable(type=type, value=value, name=name, strict=strict)
# TensorSharedVariable brings in the tensor operators, is not ideal, but works as long as we
# dont do purely scalar-scalar operations
class ScalarSharedVariable(SharedVariable, theano.tensor.basic._tensor_py_operators):
pass
@shared_constructor
def scalar_constructor(value, name=None, strict=False, dtype=None):
"""SharedVariable constructor for scalar values. Defaults to int64 or float64.
:note: We implement this using 0-d tensors for now.
"""
if not isinstance (value, (numpy.number, float, int)):
raise TypeError()
if dtype is None:
if isinstance(value, float):
dtype = 'float64'
elif isinstance(value, int):
dtype = 'int64'
else:
dtype = type(value).__name__
type = TensorType(dtype=dtype, broadcastable=[])
try:
# don't pass the dtype to asarray because we want this to fail if strict is True and the
# types do not match
rval = ScalarSharedVariable(type=type, value=numpy.asarray(value), name=name, strict=strict)
return rval
except:
traceback.print_exc()
raise
...@@ -4,6 +4,7 @@ from theano import gof ...@@ -4,6 +4,7 @@ from theano import gof
from theano import compile from theano import compile
from theano.compile.function_module import * from theano.compile.function_module import *
from theano.compile import function
from theano.scalar import * from theano.scalar import *
from theano import tensor from theano import tensor
......
...@@ -4,6 +4,7 @@ from theano import gof ...@@ -4,6 +4,7 @@ from theano import gof
from theano import compile from theano import compile
from theano.scalar import * from theano.scalar import *
from theano.compile.function_module import * from theano.compile.function_module import *
from theano.compile import function
from theano import tensor from theano import tensor
from theano import tensor as T from theano import tensor as T
......
import numpy, theano, unittest import numpy, theano, unittest
from theano.compile.sandbox.pfunc import pfunc from theano.compile.pfunc import pfunc
from theano.compile.sandbox.sharedvalue import shared from theano.compile.sharedvalue import shared
from theano import tensor from theano import tensor
from theano.tensor.nnet import sigmoid from theano.tensor.nnet import sigmoid
......
...@@ -5,8 +5,8 @@ import theano ...@@ -5,8 +5,8 @@ import theano
from theano.tensor import Tensor, dmatrix, dvector, lscalar from theano.tensor import Tensor, dmatrix, dvector, lscalar
from theano import tensor from theano import tensor
from theano.compile.sandbox.sharedvalue import * from theano.compile.sharedvalue import *
from theano.compile.sandbox.pfunc import * from theano.compile.pfunc import *
class Test_pfunc(unittest.TestCase): class Test_pfunc(unittest.TestCase):
......
...@@ -2,9 +2,9 @@ import numpy ...@@ -2,9 +2,9 @@ import numpy
import unittest import unittest
import copy import copy
import theano import theano
from theano.tensor import Tensor from theano.tensor import Tensor, TensorType
from theano.compile.sandbox.sharedvalue import * from theano.compile.sharedvalue import *
class Test_SharedVariable(unittest.TestCase): class Test_SharedVariable(unittest.TestCase):
......
...@@ -17,6 +17,7 @@ random = RandomStreams(seed=0xBAD5EED) ...@@ -17,6 +17,7 @@ random = RandomStreams(seed=0xBAD5EED)
from elemwise import \ from elemwise import \
DimShuffle, Elemwise, CAReduce DimShuffle, Elemwise, CAReduce
import sharedvar # adds shared-variable constructors
......
...@@ -4,10 +4,9 @@ __docformat__ = "restructuredtext en" ...@@ -4,10 +4,9 @@ __docformat__ = "restructuredtext en"
import sys import sys
import numpy import numpy
from ...gof import Container from ..gof import Container
from ...tensor import raw_random from ..compile.sharedvalue import SharedVariable, shared_constructor, shared
import raw_random
from sharedvalue import SharedVariable, shared_constructor, shared
class RandomStateSharedVariable(SharedVariable): class RandomStateSharedVariable(SharedVariable):
pass pass
......
...@@ -9,9 +9,9 @@ from unittest import TestCase ...@@ -9,9 +9,9 @@ from unittest import TestCase
from theano.tests import unittest_tools from theano.tests import unittest_tools
from copy import copy from copy import copy
from theano import In, Out from theano import Param, shared
from test_basic import (_approx_eq, as_tensor_variable, inplace_func, from test_basic import (_approx_eq, as_tensor_variable, inplace_func,
compile, value, constant, inplace, eval_outputs) compile, constant, inplace, eval_outputs)
class t_gemm(TestCase): class t_gemm(TestCase):
"""This test suite is supposed to establish that gemm works as it is supposed to.""" """This test suite is supposed to establish that gemm works as it is supposed to."""
...@@ -138,12 +138,12 @@ class t_gemm(TestCase): ...@@ -138,12 +138,12 @@ class t_gemm(TestCase):
def test_destroy_map4(self): def test_destroy_map4(self):
"""test that dot args can be aliased""" """test that dot args can be aliased"""
Z = value(self.rand(2,2)) Z = shared(self.rand(2,2))
A = value(self.rand(2,2)) A = shared(self.rand(2,2))
f = inplace_func([A,Z], gemm(Z, 1.0, A, A, 1.0)) f = inplace_func([], gemm(Z, 1.0, A, A, 1.0))
f(A.data, Z.data) f()
f = inplace_func([A,Z], gemm(Z, 1.0, A, A.T, 1.0)) f = inplace_func([], gemm(Z, 1.0, A, A.T, 1.0))
f(A.data, Z.data) f()
def test_transposes(self): def test_transposes(self):
# three square matrices which are not contiguous # three square matrices which are not contiguous
...@@ -156,14 +156,27 @@ class t_gemm(TestCase): ...@@ -156,14 +156,27 @@ class t_gemm(TestCase):
z_orig = z.copy() z_orig = z.copy()
z_after = self._gemm(z, a, x, y, b) z_after = self._gemm(z, a, x, y, b)
tz,ta,tx,ty,tb = [value(p) for p in z,a,x,y,b] tz,ta,tx,ty,tb = [shared(p) for p in z,a,x,y,b]
f = inplace_func([tz,ta,tx,ty,tb], gemm(tz,ta,tx,ty,tb), mode = compile.Mode(optimizer = None, linker=l)) #f = inplace_func([tz,ta,tx,ty,tb], gemm(tz,ta,tx,ty,tb), mode = compile.Mode(optimizer = None, linker=l))
f(z, a, x, y, b) #f(z, a, x, y, b)
f = inplace_func([], gemm(tz,ta,tx,ty,tb), mode = compile.Mode(optimizer = None, linker=l))
f()
self.failUnless(_approx_eq(z_after, z), (z_orig, z_after, z, z_after - z))
f()
self.failUnless(_approx_eq(z_after, z), (z_orig, z_after, z, z_after - z))
f()
self.failUnless(_approx_eq(z_after, z), (z_orig, z_after, z, z_after - z)) self.failUnless(_approx_eq(z_after, z), (z_orig, z_after, z, z_after - z))
f(z.T, a, y.T, x.T, b) #tz.value *= 0 # clear z's value
self.failUnless(_approx_eq(z_after, z)) y_T = ty.value.T
ty.value = tx.value.T
tx.value = y_T
f()
assert numpy.all(tz.value == z) # should be aliased still
# test that the transposed version of multiplication gives same answer
self.failUnless(_approx_eq(z_after, z.T))
t(C,A,B) t(C,A,B)
t(C.T, A, B) t(C.T, A, B)
...@@ -256,7 +269,7 @@ class Warning(Exception): ...@@ -256,7 +269,7 @@ class Warning(Exception):
def just_gemm(i, o, ishapes = [(4,3), (3,5), (4,5), (), ()]): def just_gemm(i, o, ishapes = [(4,3), (3,5), (4,5), (), ()]):
try: try:
f = inplace_func([In(ii, mutable=True) for ii in i],o, mode='FAST_RUN') f = inplace_func([Param(ii, mutable=True) for ii in i],o, mode='FAST_RUN')
for node in f.maker.env.nodes: for node in f.maker.env.nodes:
if node.op == T.dot: raise Warning('dot not changed to gemm in graph') if node.op == T.dot: raise Warning('dot not changed to gemm in graph')
if node.op == _dot22: raise Warning('_dot22 not changed to gemm in graph') if node.op == _dot22: raise Warning('_dot22 not changed to gemm in graph')
...@@ -320,7 +333,7 @@ def test_gemm_opt_double_gemm(): ...@@ -320,7 +333,7 @@ def test_gemm_opt_double_gemm():
i = [X,Y,Z,a,b, R, S, c] i = [X,Y,Z,a,b, R, S, c]
o = [a * T.dot(X,Y) + gemm(Z, b, S.T, R.T, 1.0)] o = [a * T.dot(X,Y) + gemm(Z, b, S.T, R.T, 1.0)]
try: try:
f = inplace_func([In(ii, mutable=True) for ii in i],o, mode='FAST_RUN') f = inplace_func([Param(ii, mutable=True) for ii in i],o, mode='FAST_RUN')
for node in f.maker.env.nodes: for node in f.maker.env.nodes:
if node.op == T.dot: raise Failure('dot in graph') if node.op == T.dot: raise Failure('dot in graph')
if node.op == _dot22: raise Failure('_dot22 in graph') if node.op == _dot22: raise Failure('_dot22 in graph')
......
## PENDING REWRITE OF tensor_opt.py ## PENDING REWRITE OF tensor_opt.py
import numpy
import theano
from theano import gof from theano import gof
from theano.tensor.opt import * from theano.tensor.opt import *
from theano import tensor from theano import tensor
from theano.tensor import TensorType from theano.tensor import TensorType
from theano.gof import Env from theano.gof import Env
from theano.tensor.elemwise import DimShuffle from theano.tensor.elemwise import DimShuffle
from theano import pprint from theano import pprint, shared
import numpy
#import scalar_opt #import scalar_opt
from theano import function, compile from theano import function, compile
...@@ -809,10 +811,6 @@ def test_const_type_in_mul_canonizer(): ...@@ -809,10 +811,6 @@ def test_const_type_in_mul_canonizer():
f2(ival, wval, visbval, hidbval, betaval, aval), f2(ival, wval, visbval, hidbval, betaval, aval),
f1(ival, wval, visbval, hidbval, betaval, aval)) f1(ival, wval, visbval, hidbval, betaval, aval))
from theano.compile.sandbox.pfunc import pfunc
from theano.compile.sandbox.sharedvalue import shared
import theano
class test_fusion(unittest.TestCase): class test_fusion(unittest.TestCase):
def do(self, mode, shared_fn, shp, gpu=False, nb_repeat=1, assert_len_topo=True, slice=None): def do(self, mode, shared_fn, shp, gpu=False, nb_repeat=1, assert_len_topo=True, slice=None):
...@@ -951,7 +949,7 @@ class test_fusion(unittest.TestCase): ...@@ -951,7 +949,7 @@ class test_fusion(unittest.TestCase):
nb_repeat=1 nb_repeat=1
else: else:
out=shared_fn(numpy.zeros(shp, dtype=out_dtype),'out') out=shared_fn(numpy.zeros(shp, dtype=out_dtype),'out')
f = pfunc(sym_inputs,[],updates=[(out,out+g)],mode=mode) f = function(sym_inputs,[],updates=[(out,out+g)],mode=mode)
#pre-call to have the data in cache if it fit to don't penalise the first iteration #pre-call to have the data in cache if it fit to don't penalise the first iteration
# if id==0: # if id==0:
# f(*val_inputs) # f(*val_inputs)
...@@ -1084,9 +1082,9 @@ class test_fusion(unittest.TestCase): ...@@ -1084,9 +1082,9 @@ class test_fusion(unittest.TestCase):
# v1=weakref.ref(v) # v1=weakref.ref(v)
out=shared_fn(v,'out') out=shared_fn(v,'out')
pdb.set_trace() pdb.set_trace()
# f = pfunc(sym_inputs,[],updates=[(out,out+g)],mode=mode) # f = function(sym_inputs,[],updates=[(out,out+g)],mode=mode)
# f = pfunc([fx],[],updates=[(out,out+fx)],mode=mode) # f = function([fx],[],updates=[(out,out+fx)],mode=mode)
# f = pfunc([fx],out+fx,mode=mode) # f = function([fx],out+fx,mode=mode)
# f = compile.function([fx,out],[out+fx],mode=mode)#no memory leak. # f = compile.function([fx,out],[out+fx],mode=mode)#no memory leak.
f = compile.function([fx,compile.In(variable=out, value=out.container, mutable=None)], f = compile.function([fx,compile.In(variable=out, value=out.container, mutable=None)],
[out+fx],mode=mode)#if mutable is True or False, their is a memory leak [out+fx],mode=mode)#if mutable is True or False, their is a memory leak
......
...@@ -5,8 +5,8 @@ import unittest ...@@ -5,8 +5,8 @@ import unittest
import numpy import numpy
from theano.tensor import raw_random from theano.tensor import raw_random
from theano.compile.sandbox.shared_randomstreams import RandomStreams from theano.tensor.shared_randomstreams import RandomStreams
from theano.compile.sandbox.pfunc import pfunc from theano.compile.pfunc import pfunc
from theano import tensor from theano import tensor
from theano import compile, gof from theano import compile, gof
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论