提交 626104a8 authored 作者: Frédéric Bastien's avatar Frédéric Bastien

Merge pull request #2744 from mohammadpz/pep8

Pep8
......@@ -24,7 +24,7 @@ def floatX_convert(s):
AddConfigVar('floatX',
"Default floating-point precision for python casts",
EnumStr('float64', 'float32', convert=floatX_convert,),
)
)
AddConfigVar('warn_float64',
"Do an action when a tensor variable with float64 dtype is"
......@@ -32,20 +32,20 @@ AddConfigVar('warn_float64',
" gpu back-end and are slow with gamer GPUs.",
EnumStr('ignore', 'warn', 'raise', 'pdb'),
in_c_key=False,
)
)
AddConfigVar('cast_policy',
"Rules for implicit type casting",
EnumStr('custom', 'numpy+floatX',
# The 'numpy' policy was originally planned to provide a smooth
# transition from numpy. It was meant to behave the same as
# numpy+floatX, but keeping float64 when numpy would. However
# the current implementation of some cast mechanisms makes it
# a bit more complex to add than what was expected, so it is
# currently not available.
# numpy,
),
)
'Rules for implicit type casting',
EnumStr('custom', 'numpy+floatX',
# The 'numpy' policy was originally planned to provide a
# smooth transition from numpy. It was meant to behave the
# same asnumpy+floatX, but keeping float64 when numpy
# would. However the current implementation of some cast
# mechanisms makes it a bit more complex to add than what
# was expected, so it is currently not available.
# numpy,
),
)
# python 2.* define int / int to return int and int // int to return int.
# python 3* define int / int to return float and int // int to return int.
......@@ -53,10 +53,10 @@ AddConfigVar('cast_policy',
# than numpy. When we will do the transition, we should create an int_warn
# and floatX_warn option.
AddConfigVar('int_division',
"What to do when one computes x / y, where both x and y are of "
"integer types",
EnumStr('int', 'raise', 'floatX'),
in_c_key=False)
"What to do when one computes x / y, where both x and y are of "
"integer types",
EnumStr('int', 'raise', 'floatX'),
in_c_key=False)
# gpu means let the driver select the gpu. Needed in case of gpu in
# exclusive mode.
......@@ -82,14 +82,14 @@ class DeviceParam(ConfigParam):
def __str__(self):
return '%s (cpu, gpu*, opencl*, cuda*) ' % (self.fullname,)
AddConfigVar('device',
("Default device for computations. If gpu*, change the default to try "
"to move computation to it and to put shared variable of float32 "
"on it. Do not use upper case letters, only lower case even if "
"NVIDIA use capital letters."),
DeviceParam('cpu', allow_override=False),
in_c_key=False,
)
AddConfigVar(
'device',
("Default device for computations. If gpu*, change the default to try "
"to move computation to it and to put shared variable of float32 "
"on it. Do not use upper case letters, only lower case even if "
"NVIDIA use capital letters."),
DeviceParam('cpu', allow_override=False),
in_c_key=False,)
AddConfigVar('gpuarray.init_device',
"""
......@@ -99,28 +99,31 @@ AddConfigVar('gpuarray.init_device',
StrParam(''),
in_c_key=False)
AddConfigVar('init_gpu_device',
("Initialize the gpu device to use, works only if device=cpu. "
"Unlike 'device', setting this option will NOT move computations, "
"nor shared variables, to the specified GPU. "
"It can be used to run GPU-specific tests on a particular GPU."),
EnumStr('', 'gpu',
AddConfigVar(
'init_gpu_device',
("Initialize the gpu device to use, works only if device=cpu. "
"Unlike 'device', setting this option will NOT move computations, "
"nor shared variables, to the specified GPU. "
"It can be used to run GPU-specific tests on a particular GPU."),
EnumStr('', 'gpu',
'gpu0', 'gpu1', 'gpu2', 'gpu3',
'gpu4', 'gpu5', 'gpu6', 'gpu7',
'gpu8', 'gpu9', 'gpu10', 'gpu11',
'gpu12', 'gpu13', 'gpu14', 'gpu15',
allow_override=False),
in_c_key=False)
allow_override=False),
in_c_key=False)
AddConfigVar('force_device',
"Raise an error if we can't use the specified device",
BoolParam(False, allow_override=False),
in_c_key=False)
AddConfigVar(
'force_device',
"Raise an error if we can't use the specified device",
BoolParam(False, allow_override=False),
in_c_key=False)
AddConfigVar('print_active_device',
"Print active device at when the GPU device is initialized.",
BoolParam(True, allow_override=False),
in_c_key=False)
AddConfigVar(
'print_active_device',
"Print active device at when the GPU device is initialized.",
BoolParam(True, allow_override=False),
in_c_key=False)
# Do not add FAST_RUN_NOGC to this list (nor any other ALL CAPS shortcut).
......@@ -129,11 +132,12 @@ AddConfigVar('print_active_device',
# scalable.
# Also, please be careful not to modify the first item in the enum when adding
# new modes, since it is the default mode.
AddConfigVar('mode',
"Default compilation mode",
EnumStr('Mode', 'ProfileMode', 'DebugMode', 'FAST_RUN',
'FAST_COMPILE', 'PROFILE_MODE', 'DEBUG_MODE'),
in_c_key=False)
AddConfigVar(
'mode',
"Default compilation mode",
EnumStr('Mode', 'ProfileMode', 'DebugMode', 'FAST_RUN',
'FAST_COMPILE', 'PROFILE_MODE', 'DEBUG_MODE'),
in_c_key=False)
param = "g++"
......@@ -209,22 +213,24 @@ AddConfigVar('allow_gc',
in_c_key=False)
# Keep the default optimizer the same as the one for the mode FAST_RUN
AddConfigVar('optimizer',
("Default optimizer. If not None, will use this linker with the Mode "
"object (not ProfileMode(deprecated) or DebugMode)"),
EnumStr('fast_run', 'merge', 'fast_compile', 'None'),
in_c_key=False)
AddConfigVar(
'optimizer',
("Default optimizer. If not None, will use this linker with the Mode "
"object (not ProfileMode(deprecated) or DebugMode)"),
EnumStr('fast_run', 'merge', 'fast_compile', 'None'),
in_c_key=False)
AddConfigVar('optimizer_verbose',
"If True, we print all optimization being applied",
BoolParam(False),
in_c_key=False)
AddConfigVar('on_opt_error',
("What to do when an optimization crashes: warn and skip it, raise "
"the exception, or fall into the pdb debugger."),
EnumStr('warn', 'raise', 'pdb'),
in_c_key=False)
AddConfigVar(
'on_opt_error',
("What to do when an optimization crashes: warn and skip it, raise "
"the exception, or fall into the pdb debugger."),
EnumStr('warn', 'raise', 'pdb'),
in_c_key=False)
def safe_no_home(home):
......@@ -239,23 +245,25 @@ def safe_no_home(home):
"""
if home:
raise RuntimeError(
'The `config.home` option has been removed and should not be '
'used anymore. Please set the `config.base_compiledir` option '
'instead (for instance to: %s)' %
os.path.join(home, '.theano'))
'The `config.home` option has been removed and should not be '
'used anymore. Please set the `config.base_compiledir` option '
'instead (for instance to: %s)' %
os.path.join(home, '.theano'))
return True
AddConfigVar('home',
"This config option was removed in 0.5: do not use it!",
ConfigParam('', allow_override=False, filter=safe_no_home),
in_c_key=False)
AddConfigVar(
'home',
"This config option was removed in 0.5: do not use it!",
ConfigParam('', allow_override=False, filter=safe_no_home),
in_c_key=False)
AddConfigVar('nocleanup',
"Suppress the deletion of code files that did not compile cleanly",
BoolParam(False),
in_c_key=False)
AddConfigVar(
'nocleanup',
"Suppress the deletion of code files that did not compile cleanly",
BoolParam(False),
in_c_key=False)
AddConfigVar('on_unused_input',
"What to do if a variable in the 'inputs' list of "
......@@ -267,40 +275,46 @@ AddConfigVar('on_unused_input',
# So changing it after import will not modify these global variables.
# This could be done differently... but for now we simply prevent it from being
# changed at runtime.
AddConfigVar('tensor.cmp_sloppy',
"Relax tensor._allclose (0) not at all, (1) a bit, (2) more",
IntParam(0, lambda i: i in (0, 1, 2), allow_override=False),
in_c_key=False)
AddConfigVar('tensor.local_elemwise_fusion',
("Enable or not in fast_run mode(fast_run optimization) the elemwise "
"fusion optimization"),
BoolParam(True),
in_c_key=False)
AddConfigVar('gpu.local_elemwise_fusion',
("Enable or not in fast_run mode(fast_run optimization) the gpu "
"elemwise fusion optimization"),
BoolParam(True),
in_c_key=False)
AddConfigVar(
'tensor.cmp_sloppy',
"Relax tensor._allclose (0) not at all, (1) a bit, (2) more",
IntParam(0, lambda i: i in (0, 1, 2), allow_override=False),
in_c_key=False)
AddConfigVar(
'tensor.local_elemwise_fusion',
("Enable or not in fast_run mode(fast_run optimization) the elemwise "
"fusion optimization"),
BoolParam(True),
in_c_key=False)
AddConfigVar(
'gpu.local_elemwise_fusion',
("Enable or not in fast_run mode(fast_run optimization) the gpu "
"elemwise fusion optimization"),
BoolParam(True),
in_c_key=False)
# http://developer.amd.com/CPU/LIBRARIES/LIBM/Pages/default.aspx
AddConfigVar('lib.amdlibm',
"Use amd's amdlibm numerical library",
BoolParam(False))
AddConfigVar('gpuelemwise.sync',
"when true, wait that the gpu fct finished and check it error code.",
BoolParam(True),
in_c_key=False)
AddConfigVar('traceback.limit',
"The number of stack to trace. -1 mean all.",
# We default to 6 to be able to know where v1 + v2 is created in the
# user script. The bigger this number is, the more run time it takes.
# We need to default to 7 to support theano.tensor.tensor(...).
IntParam(7),
in_c_key=False)
AddConfigVar(
'lib.amdlibm',
"Use amd's amdlibm numerical library",
BoolParam(False))
AddConfigVar(
'gpuelemwise.sync',
"when true, wait that the gpu fct finished and check it error code.",
BoolParam(True),
in_c_key=False)
AddConfigVar(
'traceback.limit',
"The number of stack to trace. -1 mean all.",
# We default to 6 to be able to know where v1 + v2 is created in the
# user script. The bigger this number is, the more run time it takes.
# We need to default to 7 to support theano.tensor.tensor(...).
IntParam(7),
in_c_key=False)
AddConfigVar('experimental.mrg',
"Another random number generator that work on the gpu",
......@@ -329,14 +343,14 @@ AddConfigVar('numpy.seterr_all',
"by the following flags: seterr_divide, seterr_over, "
"seterr_under and seterr_invalid."),
EnumStr('ignore', 'warn', 'raise', 'call', 'print', 'log', 'None',
allow_override=False),
allow_override=False),
in_c_key=False)
AddConfigVar('numpy.seterr_divide',
("Sets numpy's behavior for division by zero, see numpy.seterr. "
"'None' means using the default, defined by numpy.seterr_all."),
EnumStr('None', 'ignore', 'warn', 'raise', 'call', 'print', 'log',
allow_override=False),
allow_override=False),
in_c_key=False)
AddConfigVar('numpy.seterr_over',
......@@ -344,7 +358,7 @@ AddConfigVar('numpy.seterr_over',
"see numpy.seterr. "
"'None' means using the default, defined by numpy.seterr_all."),
EnumStr('None', 'ignore', 'warn', 'raise', 'call', 'print', 'log',
allow_override=False),
allow_override=False),
in_c_key=False)
AddConfigVar('numpy.seterr_under',
......@@ -352,7 +366,7 @@ AddConfigVar('numpy.seterr_under',
"see numpy.seterr. "
"'None' means using the default, defined by numpy.seterr_all."),
EnumStr('None', 'ignore', 'warn', 'raise', 'call', 'print', 'log',
allow_override=False),
allow_override=False),
in_c_key=False)
AddConfigVar('numpy.seterr_invalid',
......@@ -360,7 +374,7 @@ AddConfigVar('numpy.seterr_invalid',
"see numpy.seterr. "
"'None' means using the default, defined by numpy.seterr_all."),
EnumStr('None', 'ignore', 'warn', 'raise', 'call', 'print', 'log',
allow_override=False),
allow_override=False),
in_c_key=False)
###
......@@ -422,30 +436,33 @@ AddConfigVar('warn.sum_div_dimshuffle_bug',
BoolParam(warn_default('0.3')),
in_c_key=False)
AddConfigVar('warn.subtensor_merge_bug',
"Warn if previous versions of Theano (before 0.5rc2) could have given "
"incorrect results when indexing into a subtensor with negative "
"stride (for instance, for instance, x[a:b:-1][c]).",
BoolParam(warn_default('0.5')),
in_c_key=False)
AddConfigVar('warn.gpu_set_subtensor1',
"Warn if previous versions of Theano (before 0.6) could have given "
"incorrect results when moving to the gpu "
"set_subtensor(x[int vector], new_value)",
BoolParam(warn_default('0.6')),
in_c_key=False)
AddConfigVar('warn.vm_gc_bug',
"There was a bug that existed in the default Theano configuration,"
" only in the development version between July 5th 2012"
" and July 30th 2012. This was not in a released version."
" If your code was affected by this bug, a warning"
" will be printed during the code execution if you use the"
" `linker=vm,vm.lazy=True,warn.vm_gc_bug=True` Theano flags."
" This warning is disabled by default as the bug was not released.",
BoolParam(False),
in_c_key=False)
AddConfigVar(
'warn.subtensor_merge_bug',
"Warn if previous versions of Theano (before 0.5rc2) could have given "
"incorrect results when indexing into a subtensor with negative "
"stride (for instance, for instance, x[a:b:-1][c]).",
BoolParam(warn_default('0.5')),
in_c_key=False)
AddConfigVar(
'warn.gpu_set_subtensor1',
"Warn if previous versions of Theano (before 0.6) could have given "
"incorrect results when moving to the gpu "
"set_subtensor(x[int vector], new_value)",
BoolParam(warn_default('0.6')),
in_c_key=False)
AddConfigVar(
'warn.vm_gc_bug',
"There was a bug that existed in the default Theano configuration,"
" only in the development version between July 5th 2012"
" and July 30th 2012. This was not in a released version."
" If your code was affected by this bug, a warning"
" will be printed during the code execution if you use the"
" `linker=vm,vm.lazy=True,warn.vm_gc_bug=True` Theano flags."
" This warning is disabled by default as the bug was not released.",
BoolParam(False),
in_c_key=False)
AddConfigVar('warn.signal_conv2d_interface',
("Warn we use the new signal.conv2d() when its interface"
......@@ -474,13 +491,14 @@ AddConfigVar('warn.inc_set_subtensor1',
BoolParam(warn_default('0.7')),
in_c_key=False)
AddConfigVar('compute_test_value',
("If 'True', Theano will run each op at graph build time, using "
"Constants, SharedVariables and the tag 'test_value' as inputs "
"to the function. This helps the user track down problems in the "
"graph before it gets optimized."),
EnumStr('off', 'ignore', 'warn', 'raise', 'pdb'),
in_c_key=False)
AddConfigVar(
'compute_test_value',
("If 'True', Theano will run each op at graph build time, using "
"Constants, SharedVariables and the tag 'test_value' as inputs "
"to the function. This helps the user track down problems in the "
"graph before it gets optimized."),
EnumStr('off', 'ignore', 'warn', 'raise', 'pdb'),
in_c_key=False)
AddConfigVar('compute_test_value_opt',
......@@ -497,10 +515,11 @@ AddConfigVar('unpickle_function',
BoolParam(True),
in_c_key=False)
AddConfigVar('reoptimize_unpickled_function',
"Re-optimize the graph when a theano function is unpickled from the disk.",
BoolParam(True, allow_override=True),
in_c_key=False)
AddConfigVar(
'reoptimize_unpickled_function',
"Re-optimize the graph when a theano function is unpickled from the disk.",
BoolParam(True, allow_override=True),
in_c_key=False)
"""Note to developers:
......@@ -509,17 +528,18 @@ AddConfigVar('reoptimize_unpickled_function',
== 'high', you should include a call to printing.min_informative_str
on all important apply nodes.
"""
AddConfigVar('exception_verbosity',
"If 'low', the text of exceptions will generally refer " \
+ "to apply nodes with short names such as " \
+ "Elemwise{add_no_inplace}. If 'high', some exceptions " \
+ "will also refer to apply nodes with long descriptions " \
+ """ like:
A. Elemwise{add_no_inplace}
B. log_likelihood_v_given_h
C. log_likelihood_h""",
EnumStr('low', 'high'),
in_c_key=False)
AddConfigVar(
'exception_verbosity',
"If 'low', the text of exceptions will generally refer "
"to apply nodes with short names such as "
"Elemwise{add_no_inplace}. If 'high', some exceptions "
"will also refer to apply nodes with long descriptions "
""" like:
A. Elemwise{add_no_inplace}
B. log_likelihood_v_given_h
C. log_likelihood_h""",
EnumStr('low', 'high'),
in_c_key=False)
# Test if the env variable is set
var = os.getenv('OMP_NUM_THREADS', None)
......@@ -560,7 +580,7 @@ AddConfigVar('openmp',
" If it is set to 1, we disable openmp in Theano by default.",
BoolParam(default_openmp),
in_c_key=False,
)
)
AddConfigVar('openmp_elemwise_minsize',
"If OpenMP is enabled, this is the minimum size of vectors "
......@@ -568,19 +588,21 @@ AddConfigVar('openmp_elemwise_minsize',
"in element wise ops.",
IntParam(200000),
in_c_key=False,
)
AddConfigVar('check_input',
"Specify if types should check their input in their C code. "
"It can be used to speed up compilation, reduce overhead "
"(particularly for scalars) and reduce the number of generated C "
"files.",
BoolParam(True))
AddConfigVar('cache_optimizations',
"WARNING: work in progress, does not work yet. "
"Specify if the optimization cache should be used. This cache will "
"any optimized graph and its optimization. Actually slow downs a lot "
"the first optimization, and could possibly still contains some bugs. "
"Use at your own risks.",
BoolParam(False))
)
AddConfigVar(
'check_input',
"Specify if types should check their input in their C code. "
"It can be used to speed up compilation, reduce overhead "
"(particularly for scalars) and reduce the number of generated C "
"files.",
BoolParam(True))
AddConfigVar(
'cache_optimizations',
"WARNING: work in progress, does not work yet. "
"Specify if the optimization cache should be used. This cache will "
"any optimized graph and its optimization. Actually slow downs a lot "
"the first optimization, and could possibly still contains some bugs. "
"Use at your own risks.",
BoolParam(False))
......@@ -44,9 +44,9 @@ def parse_config_string(config_string, issue_warnings=True):
if len(kv_tuple) == 1:
if issue_warnings:
TheanoConfigWarning.warn(
("Config key '%s' has no value, ignoring it"
% kv_tuple[0]),
stacklevel=1)
("Config key '%s' has no value, ignoring it"
% kv_tuple[0]),
stacklevel=1)
else:
k, v = kv_tuple
# subsequent values for k will override earlier ones
......@@ -77,7 +77,7 @@ theano_cfg = ConfigParser.SafeConfigParser(
'TEMP': os.getenv("TEMP", ""),
'TMP': os.getenv("TMP", ""),
'PID': str(os.getpid()),
}
}
)
theano_cfg.read(config_files)
# Having a raw version of the config around as well enables us to pass
......@@ -145,7 +145,7 @@ def get_config_md5():
all_opts = sorted([c for c in _config_var_list if c.in_c_key],
key=lambda cv: cv.fullname)
return theano.gof.cc.hash_from_code('\n'.join(
['%s = %s' % (cv.fullname, cv.__get__()) for cv in all_opts]))
['%s = %s' % (cv.fullname, cv.__get__()) for cv in all_opts]))
class TheanoConfigParser(object):
......@@ -217,11 +217,11 @@ def AddConfigVar(name, doc, configparam, root=config, in_c_key=True):
_i_am_a_config_class = True
setattr(root.__class__, sections[0], SubObj())
newroot = getattr(root, sections[0])
if (not getattr(newroot, '_i_am_a_config_class', False)
or isinstance(newroot, type)):
if (not getattr(newroot, '_i_am_a_config_class', False) or
isinstance(newroot, type)):
raise TypeError(
'Internal config nodes must be config class instances',
newroot)
'Internal config nodes must be config class instances',
newroot)
return AddConfigVar('.'.join(sections[1:]), doc, configparam,
root=newroot, in_c_key=in_c_key)
else:
......@@ -235,7 +235,8 @@ def AddConfigVar(name, doc, configparam, root=config, in_c_key=True):
if not callable(configparam.default):
configparam.__get__()
else:
# We do not want to evaluate now the default value when it is a callable.
# We do not want to evaluate now the default value
# when it is a callable.
try:
fetch_val_for_key(configparam.fullname)
# The user provided a value, filter it now.
......@@ -282,8 +283,8 @@ class ConfigParam(object):
def __set__(self, cls, val):
if not self.allow_override and hasattr(self, 'val'):
raise Exception(
"Can't change the value of this config parameter "
"after initialization!")
"Can't change the value of this config parameter "
"after initialization!")
# print "SETTING PARAM", self.fullname,(cls), val
if self.filter:
self.val = self.filter(val)
......@@ -300,7 +301,7 @@ class EnumStr(ConfigParam):
for val in self.all:
if not isinstance(val, basestring):
raise ValueError('Valid values for an EnumStr parameter '
'should be strings', val, type(val))
'should be strings', val, type(val))
convert = kwargs.get("convert", None)
......@@ -332,13 +333,13 @@ class TypedParam(ConfigParam):
return cast_val
else:
raise ValueError(
'Invalid value (%s) for configuration variable '
'"%s".'
% (val, self.fullname), val)
'Invalid value (%s) for configuration variable '
'"%s".'
% (val, self.fullname), val)
return cast_val
super(TypedParam, self).__init__(default, filter,
allow_override=allow_override)
allow_override=allow_override)
def __str__(self):
return '%s (%s) ' % (self.fullname, self.mytype)
......@@ -375,4 +376,4 @@ def BoolParam(default, is_valid=None, allow_override=True):
is_valid = is_valid_bool
return TypedParam(default, booltype, is_valid,
allow_override=allow_override)
allow_override=allow_override)
"""Driver for gradient calculations."""
__authors__ = "James Bergstra, Razvan Pascanu, Arnaud Bergeron, Ian Goodfellow"
__copyright__ = "(c) 2011, Universite de Montreal"
__license__ = "3-clause BSD License"
__contact__ = "theano-dev <theano-dev@googlegroups.com>"
__docformat__ = "restructuredtext en"
import __builtin__
from itertools import izip
import logging
import time
import warnings
_logger = logging.getLogger('theano.gradient')
import numpy # for numeric_grad
np = numpy
import theano
......@@ -26,6 +16,15 @@ from theano.gof.null_type import NullType, null_type
from theano.gof.op import get_debug_values
from theano.compile import ViewOp
np = numpy
__authors__ = "James Bergstra, Razvan Pascanu, Arnaud Bergeron, Ian Goodfellow"
__copyright__ = "(c) 2011, Universite de Montreal"
__license__ = "3-clause BSD License"
__contact__ = "theano-dev <theano-dev@googlegroups.com>"
__docformat__ = "restructuredtext en"
_logger = logging.getLogger('theano.gradient')
# we can't do "import theano.tensor"
# tensor depends on theano.compile
# theano.compile depends on theano.gradient (this file)
......@@ -86,7 +85,7 @@ def grad_not_implemented(op, x_pos, x, comment=""):
return (NullType((
"This variable is Null because the grad method for "
"input %s (%s) of the %s op is not implemented. %s"
) % (x_pos, x, op, comment)))()
) % (x_pos, x, op, comment)))()
def grad_undefined(op, x_pos, x, comment=""):
......@@ -467,16 +466,17 @@ def grad(cost, wrt, consider_constant=None,
g_cost = known_grads[cost]
else:
g_cost = _float_ones_like(cost)
# g_cost may be Disconnected or NullType. A creative use of the function,
# sure, but nonetheless one we can and should support. So before we try
# to cast it make sure it even has a dtype
# g_cost may be Disconnected or NullType. A creative use of the
# function, sure, but nonetheless one we can and should support.
# So before we try to cast it make sure it even has a dtype
if (hasattr(g_cost.type, 'dtype') and
cost.type.dtype not in tensor.discrete_dtypes):
# Here we enforce the constraint that floating point variables have
# the same dtype as their gradient.
g_cost = g_cost.astype(cost.type.dtype)
cost.type.dtype not in tensor.discrete_dtypes):
# Here we enforce the constraint that floating point variables
# have the same dtype as their gradient.
g_cost = g_cost.astype(cost.type.dtype)
# DO NOT enforce g_cost to be 0 if cost is an integer.
# This is to be enforced by the Op.grad method for the Op that outputs cost.
# This is to be enforced by the Op.grad method for the
# Op that outputs cost.
if hasattr(g_cost.type, 'dtype'):
assert g_cost.type.dtype not in tensor.discrete_dtypes
......@@ -491,10 +491,10 @@ def grad(cost, wrt, consider_constant=None,
' or sparse theano variable' % str(type(g_var)))
if (not isinstance(g_var.type, (NullType, DisconnectedType)) and
'float' not in str(g_var.type.dtype)):
'float' not in str(g_var.type.dtype)):
raise TypeError("Gradients must always be NullType, "
"DisconnectedType, or continuous, but grad was "
"given a known_grad of type "+str(g_var.type))
"given a known_grad of type " + str(g_var.type))
# DO NOT check that these gradients are equal to 0 if var is int
# The gradient is allowed to be non-zero on var in that case
......@@ -734,9 +734,9 @@ def _node_to_pattern(node):
if not isinstance(output_pattern, list):
raise TypeError(
'%s.connection_pattern should return' %
node.op + ' a list of lists, but element %d' % ii
+ 'is %s of type %s.' % (output_pattern,
type(output_pattern)))
node.op + ' a list of lists, but element %d' % ii +
'is %s of type %s.' % (output_pattern,
type(output_pattern)))
else:
connection_pattern = [[True for output in node.outputs]
for ipt in node.inputs]
......@@ -846,10 +846,10 @@ def _populate_var_to_app_to_idx(outputs, wrt, consider_constant):
if ipt not in var_to_app_to_idx:
# This object here *must* be an OrderedDict, because
# we iterate over its keys when adding up the terms of
# the gradient on ipt. If it is a regular dict, the grad
# method will return something that is analytically correct,
# but whose order of doing additions depends on the memory
# we iterate over its keys when adding up the terms of the
# gradient on ipt. If it is a regular dict, the grad method
# will return something that is analytically correct, but
# whose order of doing additions depends on the memory
# location of the apply nodes.
var_to_app_to_idx[ipt] = OrderedDict()
app_to_idx = var_to_app_to_idx[ipt]
......@@ -923,8 +923,8 @@ def _populate_grad_dict(var_to_app_to_idx,
grad_dict: A dictionary mapping variables to their gradients.
Should be populated by grad function, which should:
-Set the gradient with respect to the cost to 1
-Load all gradients from known_grads, possibly overriding
the cost
-Load all gradients from known_grads, possibly
overriding the cost
-Set the gradient for disconnected
inputs to a variable with type DisconnectedType()
......@@ -1004,10 +1004,10 @@ def _populate_grad_dict(var_to_app_to_idx,
# call the op's grad method
# Each Op's grad function requires inputs and output_grads
# If the Op destroys any input, but the grad expression uses it,
# then chances are the resulting graph will have a dependency
# cycle. We avoid this cycle by passing (symbolic) copies of
# each destroyed input.
# If the Op destroys any input, but the grad expression uses
# it, then chances are the resulting graph will have a
# dependency cycle. We avoid this cycle by passing (symbolic)
# copies of each destroyed input.
try:
dinputs = [node.inputs[x[0]] for x in
node.op.destroy_map.values()]
......@@ -1030,15 +1030,16 @@ def _populate_grad_dict(var_to_app_to_idx,
# If an output is of an integer dtype, then we just leave it
# alone.
# DO NOT force integer variables to have zero grad. This causes
# bugs where we fail to detect disconnected or undefined gradients.
# DO NOT force integer variables to have integer dtype. This is
# a violation of the op contract.
# bugs where we fail to detect disconnected or undefined
# gradients.
# DO NOT force integer variables to have integer dtype.
# This is a violation of the op contract.
new_output_grads = []
for o, og in zip(node.outputs, output_grads):
o_dt = getattr(o.type, 'dtype', None)
og_dt = getattr(og.type, 'dtype', None)
if (o_dt not in theano.tensor.discrete_dtypes and
og_dt and o_dt != og_dt):
og_dt and o_dt != og_dt):
new_output_grads.append(og.astype(o_dt))
else:
new_output_grads.append(og)
......@@ -1049,7 +1050,7 @@ def _populate_grad_dict(var_to_app_to_idx,
o_dt = getattr(o.type, 'dtype', None)
ng_dt = getattr(ng.type, 'dtype', None)
if (ng_dt is not None and
o_dt not in theano.tensor.discrete_dtypes):
o_dt not in theano.tensor.discrete_dtypes):
assert ng_dt == o_dt
# Someone who had obviously not read the Op contract tried
......@@ -1063,14 +1064,15 @@ def _populate_grad_dict(var_to_app_to_idx,
assert (getattr(ng.type, 'dtype', None)
not in theano.tensor.discrete_dtypes)
# If config.compute_test_value is turned on, check that the gradients
# on the outputs of this node have the right shape.
# We also check the gradient on the inputs later--both checks are needed,
# because some gradients are only ever specified by the user, not computed
# by Op.grad, and some gradients are only computed and returned, but never
# passed as another node's output grads.
# If config.compute_test_value is turned on, check that the
# gradients on the outputs of this node have the right shape.
# We also check the gradient on the inputs later--both checks
# are needed, because some gradients are only ever specified
# by the user, not computed by Op.grad, and some gradients are
# only computed and returned, but never passed as another
# node's output grads.
for idx, packed in enumerate(izip(node.outputs,
new_output_grads)):
new_output_grads)):
orig_output, new_output_grad = packed
if not hasattr(orig_output, 'shape'):
continue
......@@ -1098,14 +1100,14 @@ def _populate_grad_dict(var_to_app_to_idx,
# We can not enforce this, as AdvancedSubtensor1 has an option to
# return the sparse grad for optimization reason.
# for ig, i in zip(input_grads, inputs):
# if (not isinstance(ig.type, (DisconnectedType, NullType)) and
# type(ig.type) != type(i.type)):
# raise ValueError(
# "%s returned the wrong type for gradient terms."
# " Sparse inputs must have sparse grads and dense"
# " inputs must have dense grad. Got %s, expected %s" % (
# str(node.op), ig.type, i.type))
# for ig, i in zip(input_grads, inputs):
# if (not isinstance(ig.type, (DisconnectedType, NullType)) and
# type(ig.type) != type(i.type)):
# raise ValueError(
# "%s returned the wrong type for gradient terms."
# " Sparse inputs must have sparse grads and dense"
# " inputs must have dense grad. Got %s, expected %s" %(
# str(node.op), ig.type, i.type))
# must convert to list in case the op returns a tuple
# we won't be able to post-process out the Nones if it does that
......@@ -1138,7 +1140,8 @@ def _populate_grad_dict(var_to_app_to_idx,
'the grad_undefined or grad_unimplemented helper '
'functions.') % node.op)
# Check that the gradient term for this input has the right shape
# Check that the gradient term for this input
# has the right shape
if hasattr(term, 'shape'):
orig_ipt = inputs[i]
for orig_ipt_v, term_v in get_debug_values(orig_ipt, term):
......@@ -1384,12 +1387,13 @@ class numeric_grad(object):
total_size = __builtin__.sum(prod(sh) for sh in shapes)
working_dtype = __builtin__.min((self.type_eps[dt], dt)
for dt in dtypes)[1]
working_dtype = __builtin__.min(
(self.type_eps[dt], dt) for dt in dtypes)[1]
# create un-initialized memory
x = numpy.ndarray((total_size,), dtype=working_dtype)
if (not out_type is None) and (out_type.startswith('complex')):
# (not out_type is None) --> (out_type is not None) ???
if (out_type is not None) and (out_type.startswith('complex')):
gx = numpy.ndarray((total_size,), dtype=out_type)
else:
gx = numpy.ndarray((total_size,), dtype=working_dtype)
......@@ -1734,10 +1738,10 @@ def jacobian(expression, wrt, consider_constant=None,
from theano.tensor import arange
# Check inputs have the right format
assert isinstance(expression, Variable), \
"tensor.jacobian expects a Variable as `expression`"
"tensor.jacobian expects a Variable as `expression`"
assert expression.ndim < 2, \
("tensor.jacobian expects a 1 dimensional variable as "
"`expression`. If not use flatten to make it a vector")
("tensor.jacobian expects a 1 dimensional variable as "
"`expression`. If not use flatten to make it a vector")
using_list = isinstance(wrt, list)
using_tuple = isinstance(wrt, tuple)
......@@ -1774,9 +1778,9 @@ def jacobian(expression, wrt, consider_constant=None,
sequences=arange(expression.shape[0]),
non_sequences=[expression] + wrt)
assert not updates, \
("Scan has returned a list of updates. This should not "
"happen! Report this to theano-users (also include the "
"script that generated the error)")
("Scan has returned a list of updates. This should not "
"happen! Report this to theano-users (also include the "
"script that generated the error)")
return format_as(using_list, using_tuple, jacobs)
......@@ -1808,9 +1812,9 @@ def hessian(cost, wrt, consider_constant=None,
from theano.tensor import arange
# Check inputs have the right format
assert isinstance(cost, Variable), \
"tensor.hessian expects a Variable as `cost`"
"tensor.hessian expects a Variable as `cost`"
assert cost.ndim == 0, \
"tensor.hessian expects a 0 dimensional variable as `cost`"
"tensor.hessian expects a 0 dimensional variable as `cost`"
using_list = isinstance(wrt, list)
using_tuple = isinstance(wrt, tuple)
......@@ -1823,10 +1827,10 @@ def hessian(cost, wrt, consider_constant=None,
hessians = []
for input in wrt:
assert isinstance(input, Variable), \
"tensor.hessian expects a (list of) Variable as `wrt`"
"tensor.hessian expects a (list of) Variable as `wrt`"
assert input.ndim == 1, \
"tensor.hessian expects a (list of) 1 dimensional variable "\
"as `wrt`"
"tensor.hessian expects a (list of) 1 dimensional variable "\
"as `wrt`"
expr = grad(cost, input, consider_constant=consider_constant,
disconnected_inputs=disconnected_inputs)
......@@ -1834,16 +1838,16 @@ def hessian(cost, wrt, consider_constant=None,
# even if they are connected to cost.
# This should not be an error.
hess, updates = theano.scan(lambda i, y, x: grad(
y[i],
x,
consider_constant=consider_constant,
disconnected_inputs='ignore'),
sequences=arange(expr.shape[0]),
non_sequences=[expr, input])
y[i],
x,
consider_constant=consider_constant,
disconnected_inputs='ignore'),
sequences=arange(expr.shape[0]),
non_sequences=[expr, input])
assert not updates, \
("Scan has returned a list of updates. This should not "
"happen! Report this to theano-users (also include the "
"script that generated the error)")
("Scan has returned a list of updates. This should not "
"happen! Report this to theano-users (also include the "
"script that generated the error)")
hessians.append(hess)
return format_as(using_list, using_tuple, hessians)
......@@ -1974,6 +1978,7 @@ def disconnected_grad(x):
class GradClip(ViewOp):
# See doc in user fct grad_clip
__props__ = ()
def __init__(self, clip_lower_bound, clip_upper_bound):
# We do not put those member in __eq__ or __hash__
# as they do not influence the perform of this op.
......@@ -1996,7 +2001,7 @@ def grad_clip(x, lower_bound, upper_bound):
:param x: the variable we want its gradient inputs clipped
:param lower_bound: The lower bound of the gradient value
:param upper_bound: The upper bound of the gradient value.
:examples:
x = theano.tensor.scalar()
......
......@@ -10,15 +10,6 @@ which value to report. Note also that `switch` is an elemwise operation (so
it picks each entry of a matrix according to the condition) while `ifelse`
is a global operation with a scalar condition.
"""
__docformat__ = 'restructedtext en'
__authors__ = ("Razvan Pascanu "
"James Bergstra "
"Dumitru Erhan "
"David Warde-Farley")
__copyright__ = "(c) 2010, Universite de Montreal"
__contact__ = "Razvan Pascanu <r.pascanu@gmail>"
from copy import deepcopy
from itertools import izip
import logging
......@@ -34,6 +25,15 @@ from theano.tensor import opt
from theano.scan_module.scan_utils import find_up
from theano.scan_module.scan_utils import clone
__docformat__ = 'restructedtext en'
__authors__ = ("Razvan Pascanu "
"James Bergstra "
"Dumitru Erhan "
"David Warde-Farley")
__copyright__ = "(c) 2010, Universite de Montreal"
__contact__ = "Razvan Pascanu <r.pascanu@gmail>"
_logger = logging.getLogger('theano.ifelse')
......@@ -142,8 +142,8 @@ class IfElse(PureOp):
gpu=False,
name='_'.join(name_tokens))
new_outs = new_ifelse(node.inputs[0],
*(new_ts_inputs + new_fs_inputs),
**dict(return_list=True))
*(new_ts_inputs + new_fs_inputs),
**dict(return_list=True))
else:
new_outs = []
......@@ -160,8 +160,8 @@ class IfElse(PureOp):
def make_node(self, c, *args):
assert len(args) == 2 * self.n_outs, (
"Wrong number of arguments to make_node: "
"expected %d, got %d" % (2 * self.n_outs, len(args))
"Wrong number of arguments to make_node: "
"expected %d, got %d" % (2 * self.n_outs, len(args))
)
if not self.gpu:
# When gpu is true, we are given only cuda ndarrays, and we want
......@@ -328,35 +328,35 @@ def ifelse(condition, then_branch, else_branch, name=None):
for then_branch_elem, else_branch_elem in izip(then_branch, else_branch):
if not isinstance(then_branch_elem, theano.Variable):
then_branch_elem = theano.tensor.as_tensor_variable(
then_branch_elem)
then_branch_elem)
if not isinstance(else_branch_elem, theano.Variable):
else_branch_elem = theano.tensor.as_tensor_variable(
else_branch_elem)
else_branch_elem)
if then_branch_elem.type != else_branch_elem.type:
# If one of them is a TensorType, and the other one can be
# converted into one, then we try to do that.
# This case happens when one of the elements has a GPU type,
# for instance a shared variable that was silently moved to GPU.
if (isinstance(then_branch_elem.type, TensorType)
and not isinstance(else_branch_elem.type, TensorType)):
if (isinstance(then_branch_elem.type, TensorType) and not
isinstance(else_branch_elem.type, TensorType)):
else_branch_elem = then_branch_elem.type.filter_variable(
else_branch_elem)
else_branch_elem)
elif (isinstance(else_branch_elem.type, TensorType)
and not isinstance(then_branch_elem.type, TensorType)):
elif (isinstance(else_branch_elem.type, TensorType) and not
isinstance(then_branch_elem.type, TensorType)):
then_branch_elem = else_branch_elem.type.filter_variable(
then_branch_elem)
then_branch_elem)
if then_branch_elem.type != else_branch_elem.type:
# If the types still don't match, there is a problem.
raise TypeError(
'The two branches should have identical types, but '
'they are %s and %s respectively. This error could be '
'raised if for example you provided a one element '
'list on the `then` branch but a tensor on the `else` '
'branch.' %
(then_branch_elem.type, else_branch_elem.type))
'The two branches should have identical types, but '
'they are %s and %s respectively. This error could be '
'raised if for example you provided a one element '
'list on the `then` branch but a tensor on the `else` '
'branch.' %
(then_branch_elem.type, else_branch_elem.type))
new_then_branch.append(then_branch_elem)
new_else_branch.append(else_branch_elem)
......@@ -396,7 +396,7 @@ def cond_make_inplace(node):
optdb.register('cond_make_inplace', opt.in2out(cond_make_inplace,
ignore_newtrees=True), 95, 'fast_run', 'inplace')
ignore_newtrees=True), 95, 'fast_run', 'inplace')
# XXX: Optimizations commented pending further debugging (certain optimizations
# make computation less lazy than it should be currently).
......@@ -460,7 +460,7 @@ def ifelse_lift_single_if_through_acceptable_ops(main_node):
for inp in main_node.inputs:
all_inp_nodes.add(inp.owner)
ifnodes = [x for x in list(all_inp_nodes)
if x and isinstance(x.op, IfElse)]
if x and isinstance(x.op, IfElse)]
# if we have multiple ifs as inputs .. it all becomes quite complicated
# :)
if len(ifnodes) != 1:
......@@ -471,7 +471,7 @@ def ifelse_lift_single_if_through_acceptable_ops(main_node):
ts = node.inputs[1:][:op.n_outs]
fs = node.inputs[1:][op.n_outs:]
outs = main_node.outputs
# outs = main_node.outputs
mop = main_node.op
true_ins = []
false_ins = []
......@@ -486,8 +486,8 @@ def ifelse_lift_single_if_through_acceptable_ops(main_node):
false_ins.append(x)
true_eval = mop(*true_ins, **dict(return_list=True))
false_eval = mop(*false_ins, **dict(return_list=True))
#true_eval = clone(outs, replace = dict(zip(node.outputs, ts)))
#false_eval = clone(outs, replace = dict(zip(node.outputs, fs)))
# true_eval = clone(outs, replace = dict(zip(node.outputs, ts)))
# false_eval = clone(outs, replace = dict(zip(node.outputs, fs)))
nw_outs = ifelse(node.inputs[0], true_eval, false_eval, return_list=True)
return nw_outs
......@@ -503,10 +503,10 @@ def cond_merge_ifs_true(node):
replace = {}
for idx, tval in enumerate(t_ins):
if (tval.owner and isinstance(tval.owner.op, IfElse) and
tval.owner.inputs[0] == node.inputs[0]):
ins_op = tval.owner.op
ins_t = tval.owner.inputs[1:][:ins_op.n_outs]
replace[idx + 1] = ins_t[tval.owner.outputs.index(tval)]
tval.owner.inputs[0] == node.inputs[0]):
ins_op = tval.owner.op
ins_t = tval.owner.inputs[1:][:ins_op.n_outs]
replace[idx + 1] = ins_t[tval.owner.outputs.index(tval)]
if len(replace.items()) == 0:
return False
......@@ -527,10 +527,10 @@ def cond_merge_ifs_false(node):
replace = {}
for idx, fval in enumerate(f_ins):
if (fval.owner and isinstance(fval.owner.op, IfElse) and
fval.owner.inputs[0] == node.inputs[0]):
ins_op = fval.owner.op
ins_t = fval.owner.inputs[1:][ins_op.n_outs:]
replace[idx + 1 + op.n_outs] = \
fval.owner.inputs[0] == node.inputs[0]):
ins_op = fval.owner.op
ins_t = fval.owner.inputs[1:][ins_op.n_outs:]
replace[idx + 1 + op.n_outs] = \
ins_t[fval.owner.outputs.index(fval)]
if len(replace.items()) == 0:
......@@ -555,7 +555,7 @@ class CondMerge(gof.Optimizer):
merging_node = cond_nodes[0]
for proposal in cond_nodes[1:]:
if (proposal.inputs[0] == merging_node.inputs[0] and
not find_up(proposal, merging_node)):
not find_up(proposal, merging_node)):
# Create a list of replacements for proposal
mn_ts = merging_node.inputs[1:][:merging_node.op.n_outs]
mn_fs = merging_node.inputs[1:][merging_node.op.n_outs:]
......@@ -567,8 +567,8 @@ class CondMerge(gof.Optimizer):
if merging_node.op.name:
mn_name = merging_node.op.name
pl_name = '?'
mn_n_ts = len(mn_ts)
mn_n_fs = len(mn_fs)
# mn_n_ts = len(mn_ts)
# mn_n_fs = len(mn_fs)
if proposal.op.name:
pl_name = proposal.op.name
new_ifelse = IfElse(
......@@ -607,8 +607,8 @@ def cond_remove_identical(node):
if idx not in out_map:
for jdx in xrange(idx + 1, len(node.outputs)):
if (ts[idx] == ts[jdx] and
fs[idx] == fs[jdx] and
jdx not in out_map):
fs[idx] == fs[jdx] and
jdx not in out_map):
out_map[jdx] = idx
if len(out_map.keys()) == 0:
......@@ -652,7 +652,7 @@ def cond_merge_random_op(main_node):
for inp in main_node.inputs:
all_inp_nodes.add(inp.owner)
cond_nodes = [x for x in list(all_inp_nodes)
if x and isinstance(x.op, IfElse)]
if x and isinstance(x.op, IfElse)]
if len(cond_nodes) < 2:
return False
......@@ -660,8 +660,8 @@ def cond_merge_random_op(main_node):
merging_node = cond_nodes[0]
for proposal in cond_nodes[1:]:
if (proposal.inputs[0] == merging_node.inputs[0] and
not find_up(proposal, merging_node) and
not find_up(merging_node, proposal)):
not find_up(proposal, merging_node) and
not find_up(merging_node, proposal)):
# Create a list of replacements for proposal
mn_ts = merging_node.inputs[1:][:merging_node.op.n_outs]
mn_fs = merging_node.inputs[1:][merging_node.op.n_outs:]
......@@ -673,8 +673,8 @@ def cond_merge_random_op(main_node):
if merging_node.op.name:
mn_name = merging_node.op.name
pl_name = '?'
mn_n_ts = len(mn_ts)
mn_n_fs = len(mn_fs)
# mn_n_ts = len(mn_ts)
# mn_n_fs = len(mn_fs)
if proposal.op.name:
pl_name = proposal.op.name
new_ifelse = IfElse(
......
......@@ -17,13 +17,8 @@ except ImportError:
flake8_available = False
whitelist_flake8 = [
"updates.py",
"__init__.py",
"configparser.py",
"ifelse.py",
"version.py",
"configdefaults.py",
"gradient.py",
"compat/python2x.py",
"compat/six.py",
"compat/__init__.py",
......
"""Defines Updates object for storing a (SharedVariable, new_value) mapping.
"""
from theano.compat.python2x import OrderedDict
from theano.compile.sharedvalue import SharedVariable
import logging
import warnings
__authors__ = "theano-dev"
__copyright__ = "(c) 2010, Universite de Montreal"
__license__ = "3-clause BSD License"
......@@ -8,12 +15,7 @@ __contact__ = "theano-dev <theano-dev@googlegroups.com>"
__docformat__ = "restructuredtext en"
from theano.compat.python2x import OrderedDict
from theano.compile.sharedvalue import SharedVariable
import logging
logger = logging.getLogger('theano.updates')
import warnings
# Must be an OrderedDict or updates will be applied in a non-deterministic
......@@ -26,9 +28,9 @@ class OrderedUpdates(OrderedDict):
"""
def __init__(self, *key, **kwargs):
if (len(key) >= 1 and
isinstance(key[0], dict) and
len(key[0]) > 1 and
not isinstance(key[0], OrderedDict)):
isinstance(key[0], dict) and
len(key[0]) > 1 and
not isinstance(key[0], OrderedDict)):
# Warn when using as input a non-ordered dictionary.
warnings.warn('Initializing an `OrderedUpdates` from a '
'non-ordered dictionary with 2+ elements could '
......@@ -62,8 +64,8 @@ class OrderedUpdates(OrderedDict):
if other is None:
return
if (isinstance(other, dict) and
len(other) > 1 and
not isinstance(other, OrderedDict)):
len(other) > 1 and
not isinstance(other, OrderedDict)):
# Warn about non-determinism.
warnings.warn('Updating an `OrderedUpdates` with a '
'non-ordered dictionary with 2+ elements could '
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论