diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 5938f14c..c432d775 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -4,9 +4,9 @@ build: - pip install -r req-scrutinizer.txt tests: override: - - flake8 --filename=* bin + - flake8 --filename='blocks-continue' bin - flake8 blocks doctests tests - - pep257 bin --numpy --ignore=D100,D101,D102,D103 --match='.*' + - pep257 bin --numpy --ignore=D100,D101,D102,D103 --match='blocks-continue' - pep257 blocks --numpy --ignore=D100,D101,D102,D103 - pep257 doctests tests --numpy --ignore=D100,D101,D102,D103 --match='.*\.py' checks: @@ -157,4 +157,4 @@ checks: filter: paths: - blocks/* - - bin/* + - bin/blocks-continue diff --git a/.travis.yml b/.travis.yml index 20ed1828..3afd1d00 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,17 +13,17 @@ matrix: env: TESTS=blocks FLOATX=float32 - python: 2.7 env: TESTS=blocks FLOATX=float32 DB=sqlite - - python: 3.4 + - python: 3.5 env: TESTS=blocks FLOATX=float64 - python: 2.7 env: TESTS=blocks-examples FLOATX=float32 - python: 2.7 env: TESTS=blocks-examples FLOATX=float32 DB=sqlite - - python: 3.4 + - python: 3.5 env: TESTS=blocks-examples FLOATX=float64 - python: 2.7 env: TESTS=documentation FLOATX=float32 - - python: 3.4 + - python: 3.5 env: TESTS=documentation FLOATX=float64 before_install: - # Setup Python environment with BLAS libraries @@ -38,6 +38,7 @@ before_install: - export PATH=$HOME/miniconda/bin:$PATH - conda update -q --yes conda - export FUEL_DATA_PATH=$TRAVIS_BUILD_DIR/data + - export MKL_THREADING_LAYER=GNU # For Theano install: # Install all Python dependencies - conda install -q --yes python=$TRAVIS_PYTHON_VERSION --file req-travis-conda.txt diff --git a/blocks/bricks/__init__.py b/blocks/bricks/__init__.py index d8d9b170..d8d98f95 100644 --- a/blocks/bricks/__init__.py +++ b/blocks/bricks/__init__.py @@ -7,8 +7,8 @@ from .interfaces import (Activation, Feedforward, Initializable, LinearLike, Random) from .recurrent import (BaseRecurrent, SimpleRecurrent, LSTM, GatedRecurrent, - Bidirectional, RecurrentStack, RECURRENTSTACK_SEPARATOR, - recurrent) + Bidirectional, RecurrentStack, + RECURRENTSTACK_SEPARATOR, recurrent) from .simple import (Linear, Bias, Maxout, LinearMaxout, Identity, Tanh, Logistic, Softplus, Rectifier, LeakyRectifier, Softmax, NDimensionalSoftmax) diff --git a/blocks/bricks/base.py b/blocks/bricks/base.py index eb470c96..a7a41908 100644 --- a/blocks/bricks/base.py +++ b/blocks/bricks/base.py @@ -32,6 +32,7 @@ def create_unbound_method(func, cls): if six.PY3: return func + # Rename built-in property to avoid conflict with Application.property property_ = property @@ -806,6 +807,7 @@ def __bool__(self): __nonzero__ = __bool__ + NoneAllocation = LazyNone('NoneAllocation') NoneInitialization = LazyNone('NoneInitialization') diff --git a/blocks/bricks/recurrent/__init__.py b/blocks/bricks/recurrent/__init__.py index 08894a7f..d215ec26 100644 --- a/blocks/bricks/recurrent/__init__.py +++ b/blocks/bricks/recurrent/__init__.py @@ -1,3 +1,8 @@ from .base import BaseRecurrent, recurrent from .architectures import SimpleRecurrent, LSTM, GatedRecurrent from .misc import Bidirectional, RecurrentStack, RECURRENTSTACK_SEPARATOR + + +__all__ = ("BaseRecurrent", "recurrent", "SimpleRecurrent", "LSTM", + "GatedRecurrent", "Bidirectional", "RecurrentStack", + "RECURRENTSTACK_SEPARATOR") diff --git a/blocks/bricks/recurrent/misc.py b/blocks/bricks/recurrent/misc.py index c9a53944..b41e44e6 100644 --- a/blocks/bricks/recurrent/misc.py +++ b/blocks/bricks/recurrent/misc.py @@ -58,6 +58,7 @@ def get_dim(self, name): return self.prototype.get_dim(name) * 2 return self.prototype.get_dim(name) + RECURRENTSTACK_SEPARATOR = '#' diff --git a/blocks/bricks/simple.py b/blocks/bricks/simple.py index 1243d3ea..8c8ea8bd 100644 --- a/blocks/bricks/simple.py +++ b/blocks/bricks/simple.py @@ -286,7 +286,7 @@ def apply(self, input_): class LeakyRectifier(Activation): - r"""Leaky ReLU + r"""Leaky ReLU. Like Rectifier, but inputs are scaled by small constant for negative inputs. diff --git a/blocks/filter.py b/blocks/filter.py index cfda8068..9d0f5aa1 100644 --- a/blocks/filter.py +++ b/blocks/filter.py @@ -66,8 +66,8 @@ class VariableFilter(object): A regular expression for the variable name. The Theano name (i.e. `x.name`) is used. call_id : str, optional - The call identifier as written in :class:`.ApplicationCall` metadata - attribute. + The call identifier as written in :class:`.ApplicationCall` + metadata attribute. applications : list of :class:`.Application` or :class:`.BoundApplication`, optional Matches a variable that was produced by any of the applications diff --git a/blocks/monitoring/aggregation.py b/blocks/monitoring/aggregation.py index b2176f39..68874c72 100644 --- a/blocks/monitoring/aggregation.py +++ b/blocks/monitoring/aggregation.py @@ -217,6 +217,7 @@ def get_aggregator(self): return self._build_aggregator(tensor.minimum(self.storage, self.variable)) + minimum = partial(_simple_aggregation, Minimum) @@ -227,6 +228,7 @@ def get_aggregator(self): return self._build_aggregator(tensor.maximum(self.storage, self.variable)) + maximum = partial(_simple_aggregation, Maximum) @@ -251,6 +253,7 @@ def get_aggregator(self): return self._build_aggregator(tensor.concatenate([self.storage, self.variable])) + concatenate = partial(_simple_aggregation, Concatenate) diff --git a/blocks/roles.py b/blocks/roles.py index e7facca7..85e5c858 100644 --- a/blocks/roles.py +++ b/blocks/roles.py @@ -75,6 +75,7 @@ def __repr__(self): class InputRole(VariableRole): pass + #: The input of a :class:`~.bricks.Brick` INPUT = InputRole() @@ -82,6 +83,7 @@ class InputRole(VariableRole): class OutputRole(VariableRole): pass + #: The output of a :class:`~.bricks.Brick` OUTPUT = OutputRole() @@ -89,6 +91,7 @@ class OutputRole(VariableRole): class CostRole(VariableRole): pass + #: A scalar cost that can be used to train or regularize COST = CostRole() @@ -96,6 +99,7 @@ class CostRole(VariableRole): class PersistentRole(VariableRole): pass + # Any persistent quantity that should be saved as part of the model PERSISTENT = PersistentRole() @@ -103,6 +107,7 @@ class PersistentRole(VariableRole): class ParameterRole(PersistentRole): pass + #: A parameter of the model PARAMETER = ParameterRole() @@ -110,6 +115,7 @@ class ParameterRole(PersistentRole): class AuxiliaryRole(VariableRole): pass + #: Variables added to the graph as annotations AUXILIARY = AuxiliaryRole() @@ -117,6 +123,7 @@ class AuxiliaryRole(VariableRole): class WeightRole(ParameterRole): pass + #: The weight matrices of linear transformations WEIGHT = WeightRole() @@ -124,6 +131,7 @@ class WeightRole(ParameterRole): class BiasRole(ParameterRole): pass + #: Biases of linear transformations BIAS = BiasRole() @@ -131,6 +139,7 @@ class BiasRole(ParameterRole): class InitialStateRole(ParameterRole): pass + #: Initial state of a recurrent network INITIAL_STATE = InitialStateRole() @@ -138,6 +147,7 @@ class InitialStateRole(ParameterRole): class FilterRole(WeightRole): pass + #: The filters (kernels) of a convolution operation FILTER = FilterRole() @@ -145,6 +155,7 @@ class FilterRole(WeightRole): class DropoutRole(VariableRole): pass + #: Inputs with applied dropout DROPOUT = DropoutRole() @@ -152,6 +163,7 @@ class DropoutRole(VariableRole): class CollectedRole(VariableRole): pass + #: The replacement of a variable collected into a single shared variable COLLECTED = CollectedRole() @@ -159,6 +171,7 @@ class CollectedRole(VariableRole): class CollectorRole(ParameterRole): pass + #: A collection of parameters combined into a single shared variable COLLECTOR = CollectorRole() @@ -166,6 +179,7 @@ class CollectorRole(ParameterRole): class AlgorithmStateRole(VariableRole): pass + #: Shared variables used in algorithms updates ALGORITHM_STATE = AlgorithmStateRole() @@ -173,6 +187,7 @@ class AlgorithmStateRole(VariableRole): class AlgorithmHyperparameterRole(AlgorithmStateRole): pass + #: hyperparameters accociated with algorithms ALGORITHM_HYPERPARAMETER = AlgorithmHyperparameterRole() @@ -180,6 +195,7 @@ class AlgorithmHyperparameterRole(AlgorithmStateRole): class AlgorithmBufferRole(AlgorithmStateRole): pass + #: buffers accociated with algorithms ALGORITHM_BUFFER = AlgorithmBufferRole() @@ -187,6 +203,7 @@ class AlgorithmBufferRole(AlgorithmStateRole): class BatchNormPopulationStatisticsRole(PersistentRole): pass + #: base role for batch normalization population statistics BATCH_NORM_POPULATION_STATISTICS = BatchNormPopulationStatisticsRole() @@ -194,6 +211,7 @@ class BatchNormPopulationStatisticsRole(PersistentRole): class BatchNormPopulationMeanRole(BatchNormPopulationStatisticsRole): pass + #: mean activations accumulated over the dataset BATCH_NORM_POPULATION_MEAN = BatchNormPopulationMeanRole() @@ -201,6 +219,7 @@ class BatchNormPopulationMeanRole(BatchNormPopulationStatisticsRole): class BatchNormPopulationStdevRole(BatchNormPopulationStatisticsRole): pass + #: standard deviations of activations accumulated over the dataset BATCH_NORM_POPULATION_STDEV = BatchNormPopulationStdevRole() @@ -208,6 +227,7 @@ class BatchNormPopulationStdevRole(BatchNormPopulationStatisticsRole): class BatchNormGraphVariableRole(VariableRole): pass + #: base for roles used for within-graph batch normalization replacement BATCH_NORM_GRAPH_VARIABLE = BatchNormGraphVariableRole() @@ -215,6 +235,7 @@ class BatchNormGraphVariableRole(VariableRole): class BatchNormOffsetRole(BatchNormGraphVariableRole): pass + #: offset applied in a BatchNormalization application (or its # batch-normalized replacement) BATCH_NORM_OFFSET = BatchNormOffsetRole() @@ -223,6 +244,7 @@ class BatchNormOffsetRole(BatchNormGraphVariableRole): class BatchNormDivisorRole(BatchNormGraphVariableRole): pass + #: divisor applied in a BatchNormalization application (or its # batch-normalized replacement) BATCH_NORM_DIVISOR = BatchNormDivisorRole() @@ -231,6 +253,7 @@ class BatchNormDivisorRole(BatchNormGraphVariableRole): class BatchNormMinibatchEstimateRole(BatchNormGraphVariableRole): pass + #: role added to variables that are the result of a batch normalization # replacement, rather than the original population statistics variables. BATCH_NORM_MINIBATCH_ESTIMATE = BatchNormMinibatchEstimateRole() @@ -239,6 +262,7 @@ class BatchNormMinibatchEstimateRole(BatchNormGraphVariableRole): class BatchNormScaleParameterRole(ParameterRole): pass + #: role given to the scale parameter, referred to as "scale" in the # batch normalization manuscript, applied after normalizing. BATCH_NORM_SCALE_PARAMETER = BatchNormScaleParameterRole() @@ -247,6 +271,7 @@ class BatchNormScaleParameterRole(ParameterRole): class BatchNormShiftParameterRole(BiasRole): pass + #: role given to the shift parameter, referred to as "beta" in the # batch normalization manuscript, applied after normalizing and scaling. # Inherits from BIAS, because there really is no functional difference diff --git a/blocks/serialization.py b/blocks/serialization.py index bd948b1f..2113ab48 100644 --- a/blocks/serialization.py +++ b/blocks/serialization.py @@ -229,7 +229,7 @@ def secure_dump(object_, path, dump_function=dump, **kwargs): logger.debug("Moving the temporary file") shutil.move(temp.name, path) logger.debug("Dump finished") - except: + except: # noqa: E722 if "temp" in locals(): os.remove(temp.name) raise @@ -564,6 +564,7 @@ def _recreate_pygpu_array(context_name, content): context = theano.gpuarray.get_context(context_name) return pygpu.gpuarray.array(content, context=context) + _ARRAY_TYPE_MAP = {numpy.ndarray: 'numpy_ndarray'} _INVERSE_ARRAY_TYPE_MAP = {'numpy_ndarray': _recreate_numpy_ndarray} if cuda_ndarray: diff --git a/blocks/utils/__init__.py b/blocks/utils/__init__.py index a9f28ae0..b85ecf54 100644 --- a/blocks/utils/__init__.py +++ b/blocks/utils/__init__.py @@ -10,13 +10,15 @@ class UtilsModule(ModuleType): - utils_attrs = ("pack", "unpack", "reraise_as", "dict_subset", "dict_union", - "repr_attrs", "ipdb_breakpoint", "print_sum", "print_shape", - "change_recursion_limit", "extract_args", "find_bricks") - theano_utils_attrs = ("shared_floatx_zeros_matching", "shared_floatx_zeros", - "shared_floatx_nans", "shared_floatx", "shared_like", - "check_theano_variable", "is_graph_input", - "is_shared_variable", "put_hook") + utils_attrs = ( + "pack", "unpack", "reraise_as", "dict_subset", "dict_union", + "repr_attrs", "ipdb_breakpoint", "print_sum", "print_shape", + "change_recursion_limit", "extract_args", "find_bricks") + theano_utils_attrs = ( + "shared_floatx_zeros_matching", "shared_floatx_zeros", + "shared_floatx_nans", "shared_floatx", "shared_like", + "check_theano_variable", "is_graph_input", + "is_shared_variable", "put_hook") __all__ = utils_attrs + theano_utils_attrs __doc__ = __doc__ __file__ = __file__ diff --git a/blocks/utils/utils.py b/blocks/utils/utils.py index b6687101..41343c22 100644 --- a/blocks/utils/utils.py +++ b/blocks/utils/utils.py @@ -4,7 +4,8 @@ import contextlib from collections import OrderedDict, deque -import numpy +# for documentation +import numpy # noqa: F401 def pack(arg): @@ -362,4 +363,3 @@ def find_bricks(top_bricks, predicate): found.append(current) to_visit.extend(current.children) return found - diff --git a/docs/conf.py b/docs/conf.py index b75f074e..9fea5665 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -63,11 +63,13 @@ 'python': ('http://docs.python.org/3.4', None) } + class Mock(MagicMock): @classmethod def __getattr__(cls, name): return Mock() + MOCK_MODULES = ['fuel'] sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES) diff --git a/doctests/__init__.py b/doctests/__init__.py index fd4c8a70..8621f817 100644 --- a/doctests/__init__.py +++ b/doctests/__init__.py @@ -29,7 +29,7 @@ def load_tests(loader, tests, ignore): tests.addTests(doctest.DocTestSuite( module=importlib.import_module(module), setUp=setup, optionflags=doctest.IGNORE_EXCEPTION_DETAIL)) - except: + except: # noqa: E722 pass # This part loads the doctests from the documentation diff --git a/req-rtd.txt b/req-rtd.txt index fad70ead..86886e5a 100644 --- a/req-rtd.txt +++ b/req-rtd.txt @@ -3,7 +3,4 @@ progressbar2==3.10.0 pyyaml==3.11 six==1.10.0 toolz==0.8.0 - ---allow-external theano ---allow-unverified theano git+https://github.com/Theano/Theano.git#egg=theano diff --git a/req-scrutinizer.txt b/req-scrutinizer.txt index ddbc40c8..fdc9baa0 100644 --- a/req-scrutinizer.txt +++ b/req-scrutinizer.txt @@ -1,5 +1,2 @@ flake8==2.3.0 # rq.filter: <2.4.0 - ---allow-external pep257 ---allow-unverified pep257 git+https://github.com/bartvm/pep257.git@numpy#egg=pep257 diff --git a/req-travis-pip.txt b/req-travis-pip.txt index 75de0262..c7cf3f80 100644 --- a/req-travis-pip.txt +++ b/req-travis-pip.txt @@ -2,11 +2,5 @@ coveralls==1.1 nose2[coverage_plugin]==0.6.5 picklable-itertools==0.1.1 progressbar2==3.10.0 - ---allow-external theano ---allow-unverified theano git+https://github.com/Theano/Theano.git#egg=theano - ---allow-external fuel ---allow-unverified fuel git+https://github.com/mila-udem/fuel#egg=fuel diff --git a/requirements.txt b/requirements.txt index b369b5cc..95b1f2ad 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,11 +4,5 @@ progressbar2==3.10.0 pyyaml==3.11 six==1.10.0 toolz==0.8.0 - ---allow-external theano ---allow-unverified theano git+https://github.com/Theano/Theano.git#egg=theano - ---allow-external fuel ---allow-unverified fuel git+https://github.com/mila-udem/fuel#egg=fuel diff --git a/tests/algorithms/test_algorithms.py b/tests/algorithms/test_algorithms.py index 3764a370..d898294d 100644 --- a/tests/algorithms/test_algorithms.py +++ b/tests/algorithms/test_algorithms.py @@ -186,8 +186,8 @@ def test_gradient_descent_spurious_sources(): algorithm = GradientDescent(cost=cost, parameters=[W]) algorithm.step_rule.learning_rate.set_value(0.75) algorithm.initialize() - assert_raises(lambda: - algorithm.process_batch(dict(example_id='test'))) + with assert_raises(ValueError): + algorithm.process_batch(dict(example_id='test')) algorithm = GradientDescent(cost=cost, parameters=[W], on_unused_sources='ignore') diff --git a/tests/bricks/test_recurrent.py b/tests/bricks/test_recurrent.py index 0cf3f4ad..c15d18f8 100644 --- a/tests/bricks/test_recurrent.py +++ b/tests/bricks/test_recurrent.py @@ -435,6 +435,7 @@ def test_many_steps(self): self.do_many_steps(self.stack2, skip_connections=True) self.do_many_steps(self.stack2, skip_connections=True, low_memory=True) + class TestRecurrentStackHelperMethodes(unittest.TestCase): # Separated from TestRecurrentStack because it doesn't depend on setUp # and covers a different area then the other tests in TestRecurrentStack @@ -452,14 +453,16 @@ def test_suffix(self): ] for _name, level, _expected_result in test_cases: - name = _name.format(name=name1, level=level1, sep=RECURRENTSTACK_SEPARATOR) - expected_result = _expected_result.format(name=name1, level=level1, sep=RECURRENTSTACK_SEPARATOR) + name = _name.format( + name=name1, level=level1, sep=RECURRENTSTACK_SEPARATOR) + expected_result = _expected_result.format( + name=name1, level=level1, sep=RECURRENTSTACK_SEPARATOR) resut = RecurrentStack.suffix(name, level) - assert resut == expected_result, "expected suffix(\"{}\",{}) -> \"{}\" got \"{}\"".format(name, level, - expected_result, - resut) + assert resut == expected_result, \ + "expected suffix(\"{}\",{}) -> \"{}\" got \"{}\"".format( + name, level, expected_result, resut) def test_split_suffix(self): # generate some numbers @@ -474,28 +477,37 @@ def test_split_suffix(self): # case empty name part ("{sep}{level}", "", level1), # normal case - ("{name}{sep}{level}","{name}",level1), + ("{name}{sep}{level}", "{name}", level1), # case nested recurrent stacks - ("{name}{sep}{level}{sep}{level2}","{name}{sep}{level}", level2), + ("{name}{sep}{level}{sep}{level2}", "{name}{sep}{level}", level2), # some more edge cases... ("{sep}{name}{sep}{level}", "{sep}{name}", level1), - ("{name}{sep}","{name}{sep}", 0), - ("{name}{sep}{name}","{name}{sep}{name}", 0), - ("{name}{sep}{level}{sep}{name}", "{name}{sep}{level}{sep}{name}", 0) + ("{name}{sep}", "{name}{sep}", 0), + ("{name}{sep}{name}", "{name}{sep}{name}", 0), + ("{name}{sep}{level}{sep}{name}", + "{name}{sep}{level}{sep}{name}", 0) ] # check all test cases for _name, _expected_name_part, expected_level in test_cases: # fill in aktual details like the currend RECURRENTSTACK_SEPARATOR - name = _name.format(name=name1, level=level1, level2=level2, sep=RECURRENTSTACK_SEPARATOR) - expected_name_part = _expected_name_part.format(name=name1, level=level1, level2=level2, - sep=RECURRENTSTACK_SEPARATOR) + name = _name.format( + name=name1, level=level1, level2=level2, + sep=RECURRENTSTACK_SEPARATOR) + expected_name_part = _expected_name_part.format( + name=name1, level=level1, level2=level2, + sep=RECURRENTSTACK_SEPARATOR) name_part, level = RecurrentStack.split_suffix(name) - assert name_part == expected_name_part and level == expected_level, \ - "expected split_suffex(\"{}\") -> name(\"{}\"), level({}) got name(\"{}\"), level({})".format( - name, expected_name_part, expected_level, name_part, level) + condition = (name_part == expected_name_part and + level == expected_level) + assert condition, "expected split_suffex(\"{}\") " \ + "-> name(\"{}\"), level({}) got " \ + "name(\"{}\"), level({})".format( + name, expected_name_part, + expected_level, + name_part, level) class TestGatedRecurrent(unittest.TestCase): diff --git a/tests/monitoring/test_aggregation.py b/tests/monitoring/test_aggregation.py index 013efba0..faa2ad78 100644 --- a/tests/monitoring/test_aggregation.py +++ b/tests/monitoring/test_aggregation.py @@ -63,7 +63,7 @@ def test_parameter_monitor(): def _test_mean_like_aggregator(scheme, func): - """Common test function for both Mean and Perplexity""" + """Common test function for both Mean and Perplexity.""" features = numpy.array( [[0, 3], [2, 9], diff --git a/tests/utils/test_containers.py b/tests/utils/test_containers.py index de69c68c..724c695c 100644 --- a/tests/utils/test_containers.py +++ b/tests/utils/test_containers.py @@ -2,12 +2,12 @@ def test_annotating_list(): - l = AnnotatingList(range(10)) - assert repr(l) == repr(list(range(10))) - assert l == list(range(10)) - assert l != list(range(9)) - assert l[0] == 0 - l[0] = 10 - del l[0] - l.insert(0, 0) - assert l == list(range(10)) + lst = AnnotatingList(range(10)) + assert repr(lst) == repr(list(range(10))) + assert lst == list(range(10)) + assert lst != list(range(9)) + assert lst[0] == 0 + lst[0] = 10 + del lst[0] + lst.insert(0, 0) + assert lst == list(range(10)) diff --git a/tests/utils/test_imports.py b/tests/utils/test_imports.py index 4054f2ee..6ac60a66 100644 --- a/tests/utils/test_imports.py +++ b/tests/utils/test_imports.py @@ -3,14 +3,14 @@ def test_no_theano_import(): del sys.modules['theano'] - import blocks.utils + import blocks.utils # noqa: F401 assert 'theano' not in sys.modules - from blocks.utils import dict_union + from blocks.utils import dict_union # noqa: F401 assert 'theano' not in sys.modules def test_imports(): from blocks.utils import dict_union - from blocks.utils import check_theano_variable - from blocks.utils.utils import dict_union - from blocks.utils.theano_utils import check_theano_variable + from blocks.utils import check_theano_variable # noqa: F401 + from blocks.utils.utils import dict_union # noqa: F811,F401 + from blocks.utils.theano_utils import check_theano_variable # noqa: F811,F401,E501