1from __future__ import absolute_import, print_function, division 2 3from copy import copy, deepcopy 4from functools import partial 5import itertools 6import logging 7from nose.plugins.skip import SkipTest 8from nose.tools import assert_raises 9import operator 10import os 11import sys 12from tempfile import mkstemp 13import unittest 14import warnings 15 16from six import iteritems 17from six.moves import StringIO, reduce 18from six.moves import xrange 19# Import builtin min to be able to use it after importing the tensor version. 20from six.moves.builtins import min as builtin_min 21 22import numpy as np 23from numpy.testing import dec, assert_array_equal, assert_allclose 24 25import theano 26from theano.compat import izip 27from theano.compat import PY3, exc_message, operator_div 28from theano import compile, config, function, gof, tensor, shared 29from theano.compile import DeepCopyOp 30from theano.compile.mode import get_default_mode 31from theano.scalar import autocast_float_as, autocast_float 32from theano.tensor import ( 33 wvector, bvector, 34 argmin, max_and_argmax, cscalar, join, 35 horizontal_stack, vertical_stack, argmax, get_vector_length, 36 fscalar, sum, tensor3, vector, add, addbroadcast, 37 alloc, as_tensor_variable, tensor_from_scalar, ARange, 38 clip, constant, default, diag, dot, batched_dot, 39 dmatrix, dscalar, dvector, eq, eye, fill, flatten, inverse_permutation, 40 tensor4, permute_row_elements, fmatrix, fscalars, grad, 41 inplace, iscalar, matrix, minimum, matrices, maximum, mul, neq, 42 Reshape, row, scalar, scalars, second, smallest, stack, sub, Tensor, 43 tensor_copy, tensordot, TensorType, Tri, tri, tril, triu, unbroadcast, 44 var, Argmax, Join, shape, MaxAndArgmax, lscalar, zvector, exp, 45 get_scalar_constant_value, ivector, reshape, scalar_from_tensor, scal, 46 iscalars, arange, dscalars, fvector, imatrix, numeric_grad, 47 opt, lvector, true_div, max, min, Split, roll, 48 tile, patternbroadcast, Eye, Shape, Dot, PermuteRowElements, 49 ScalarFromTensor, TensorFromScalar, dtensor4, Rebroadcast, Alloc, 50 dtensor3, SpecifyShape, Mean, 51 itensor3, Tile, switch, ExtractDiag, AllocDiag, 52 nonzero, flatnonzero, nonzero_values, 53 stacklists, DimShuffle, hessian, ptp, power, 54 swapaxes, choose, Choose, NoneConst, AllocEmpty, 55 isclose, allclose, mgrid, ogrid, extract_constant, 56 ) 57 58from theano.tests import unittest_tools as utt 59from theano.tests.unittest_tools import attr 60from theano import change_flags 61 62imported_scipy_special = False 63mode_no_scipy = get_default_mode() 64try: 65 import scipy.special 66 import scipy.stats 67 imported_scipy_special = True 68except ImportError: 69 if config.mode == "FAST_COMPILE": 70 mode_no_scipy = "FAST_RUN" 71floatX = config.floatX 72 73if config.mode == "FAST_COMPILE": 74 mode_opt = "FAST_RUN" 75else: 76 mode_opt = get_default_mode() 77 78 79# Use a seeded random number generator so that unittests are deterministic 80utt.seed_rng() 81test_rng = np.random.RandomState(seed=utt.fetch_seed()) 82# In order to check random values close to the boundaries when designing 83# new tests, you can use utt.MockRandomState, for instance: 84# test_rng = MockRandomState(0) 85# test_rng = MockRandomState(0.99999982) 86# test_rng = MockRandomState(1) 87 88 89if PY3: 90 def L(i): 91 return i 92else: 93 def L(i): 94 return long(i) # noqa for Python 3 95 96 97def inplace_func(inputs, outputs, mode=None, allow_input_downcast=False, 98 on_unused_input='raise', name=None): 99 if mode is None: 100 mode = get_default_mode() 101 return function(inputs, outputs, 102 mode=mode, 103 allow_input_downcast=allow_input_downcast, 104 accept_inplace=True, 105 on_unused_input=on_unused_input, 106 name=name) 107 108 109def eval_outputs(outputs, ops=(), mode=None): 110 f = inplace_func([], outputs, mode=mode) 111 variables = f() 112 if ops: 113 assert any(isinstance(node.op, ops) for node in f.maker.fgraph.apply_nodes) 114 if isinstance(variables, (tuple, list)) and len(variables) == 1: 115 return variables[0] 116 return variables 117 118 119def get_numeric_subclasses(cls=np.number, ignore=None): 120 # Return subclasses of `cls` in the numpy scalar hierarchy. 121 # 122 # We only return subclasses that correspond to unique data types. 123 # The hierarchy can be seen here: 124 # http://docs.scipy.org/doc/numpy/reference/arrays.scalars.html 125 if ignore is None: 126 ignore = [] 127 rval = [] 128 dtype = np.dtype(cls) 129 dtype_num = dtype.num 130 if dtype_num not in ignore: 131 # Safety check: we should be able to represent 0 with this data type. 132 np.array(0, dtype=dtype) 133 rval.append(cls) 134 ignore.append(dtype_num) 135 for sub_ in cls.__subclasses__(): 136 rval += [c for c in get_numeric_subclasses(sub_, ignore=ignore)] 137 return rval 138 139 140def get_numeric_types(with_int=True, with_float=True, with_complex=False, 141 only_theano_types=True): 142 # Return numpy numeric data types. 143 # 144 # :param with_int: Whether to include integer types. 145 # 146 # :param with_float: Whether to include floating point types. 147 # 148 # :param with_complex: Whether to include complex types. 149 # 150 # :param only_theano_types: If True, then numpy numeric data types that are 151 # not supported by Theano are ignored (i.e. those that are not declared in 152 # scalar/basic.py). 153 # 154 # :returns: A list of unique data type objects. Note that multiple data types 155 # may share the same string representation, but can be differentiated through 156 # their `num` attribute. 157 # 158 # Note that when `only_theano_types` is True we could simply return the list 159 # of types defined in the `scalar` module. However with this function we can 160 # test more unique dtype objects, and in the future we may use it to 161 # automatically detect new data types introduced in numpy. 162 if only_theano_types: 163 theano_types = [d.dtype for d in theano.scalar.all_types] 164 rval = [] 165 166 def is_within(cls1, cls2): 167 # Return True if scalars defined from `cls1` are within the hierarchy 168 # starting from `cls2`. 169 # The third test below is to catch for instance the fact that 170 # one can use ``dtype=numpy.number`` and obtain a float64 scalar, even 171 # though `numpy.number` is not under `numpy.floating` in the class 172 # hierarchy. 173 return (cls1 is cls2 or 174 issubclass(cls1, cls2) or 175 isinstance(np.array([0], dtype=cls1)[0], cls2)) 176 177 for cls in get_numeric_subclasses(): 178 dtype = np.dtype(cls) 179 if ((not with_complex and is_within(cls, np.complexfloating)) or 180 (not with_int and is_within(cls, np.integer)) or 181 (not with_float and is_within(cls, np.floating)) or 182 (only_theano_types and dtype not in theano_types)): 183 # Ignore this class. 184 continue 185 rval.append([str(dtype), dtype, dtype.num]) 186 # We sort it to be deterministic, then remove the string and num elements. 187 return [x[1] for x in sorted(rval, key=str)] 188 189 190def _numpy_checker(x, y): 191 # Checks if x.data and y.data have the same contents. 192 # Used in DualLinker to compare C version with Python version. 193 x, y = x[0], y[0] 194 if (x.dtype != y.dtype or x.shape != y.shape or 195 np.any(np.abs(x - y) > 1e-10)): 196 raise Exception("Output mismatch.", {'performlinker': x, 'clinker': y}) 197 198 199def safe_make_node(op, *inputs): 200 # Emulate the behaviour of make_node when op is a function. 201 # 202 # Normally op in an instead of the Op class. 203 node = op(*inputs) 204 if isinstance(node, list): 205 return node[0].owner 206 else: 207 return node.owner 208 209 210def upcast_float16_ufunc(fn): 211 # Decorator that enforces computation is not done in float16 by NumPy. 212 # 213 # Some ufuncs in NumPy will compute float values on int8 and uint8 214 # in half-precision (float16), which is not enough, and not compatible 215 # with the C code. 216 # 217 # :param fn: numpy ufunc 218 # :returns: function similar to fn.__call__, computing the same 219 # value with a minimum floating-point precision of float32 220 def ret(*args, **kwargs): 221 out_dtype = np.find_common_type( 222 [a.dtype for a in args], [np.float16]) 223 if out_dtype == 'float16': 224 # Force everything to float32 225 sig = 'f' * fn.nin + '->' + 'f' * fn.nout 226 kwargs.update(sig=sig) 227 return fn(*args, **kwargs) 228 229 return ret 230 231 232def upcast_int8_nfunc(fn): 233 # Decorator that upcasts input of dtype int8 to float32. 234 # 235 # This is so that floating-point computation is not carried using 236 # half-precision (float16), as some NumPy functions do. 237 # 238 # :param fn: function computing a floating-point value from inputs 239 # :returns: function similar to fn, but upcasting its uint8 and int8 240 # inputs before carrying out the computation. 241 def ret(*args, **kwargs): 242 args = list(args) 243 for i, a in enumerate(args): 244 if getattr(a, 'dtype', None) in ('int8', 'uint8'): 245 args[i] = a.astype('float32') 246 247 return fn(*args, **kwargs) 248 249 return ret 250 251 252def makeTester(name, op, expected, checks=None, good=None, bad_build=None, 253 bad_runtime=None, grad=None, mode=None, grad_rtol=None, 254 eps=1e-10, skip=False, test_memmap=True, check_name=True, 255 grad_eps=None): 256 # :param check_name: 257 # Use only for tester that aren't in Theano. 258 if checks is None: 259 checks = {} 260 if good is None: 261 good = {} 262 if bad_build is None: 263 bad_build = {} 264 if bad_runtime is None: 265 bad_runtime = {} 266 if grad is None: 267 grad = {} 268 if grad is True: 269 grad = good 270 271 _op, _expected, _checks, _good = op, expected, checks, good 272 _bad_build, _bad_runtime, _grad = bad_build, bad_runtime, grad 273 _mode, _grad_rtol, _eps, skip_ = mode, grad_rtol, eps, skip 274 _test_memmap = test_memmap 275 _check_name = check_name 276 _grad_eps = grad_eps 277 278 class Checker(unittest.TestCase): 279 280 op = staticmethod(_op) 281 expected = staticmethod(_expected) 282 checks = _checks 283 check_name = _check_name 284 good = _good 285 bad_build = _bad_build 286 bad_runtime = _bad_runtime 287 grad = _grad 288 mode = _mode 289 skip = skip_ 290 test_memmap = _test_memmap 291 292 def setUp(self): 293 # Verify that the test's name is correctly set. 294 # Some tests reuse it outside this module. 295 if self.check_name: 296 eval(self.__class__.__module__ + '.' + self.__class__.__name__) 297 298 # We keep a list of temporary files created in add_memmap_values, 299 # to remove them at the end of the test. 300 self.tmp_files = [] 301 302 def add_memmap_values(self, val_dict): 303 # If test_memmap is True, we create a temporary file 304 # containing a copy of the data passed in the "val_dict" dict, 305 # then open it as a memmapped array, and we can use the result as a 306 # new test value. 307 if not self.test_memmap: 308 return val_dict 309 310 # Copy dict before modifying them 311 val_dict = val_dict.copy() 312 313 # Note that we sort items in the dictionary to ensure tests are 314 # deterministic (since the loop below will break on the first valid 315 # item that can be memmapped). 316 for k, v in sorted(val_dict.items()): 317 new_k = '_'.join((k, 'memmap')) 318 if new_k in val_dict: 319 # A corresponding key was already provided 320 break 321 322 new_v = [] 323 for inp in v: 324 if type(inp) is np.ndarray and inp.size > 0: 325 f, fname = mkstemp() 326 self.tmp_files.append((f, fname)) 327 new_inp = np.memmap(fname, dtype=inp.dtype, 328 mode='w+', shape=inp.shape) 329 new_inp[...] = inp[...] 330 new_v.append(new_inp) 331 else: 332 new_v.append(inp) 333 val_dict[new_k] = new_v 334 335 # We only need one value, no need to copy all of them 336 break 337 return val_dict 338 339 def tearDown(self): 340 # This is to avoid a problem with deleting memmap files on windows. 341 import gc 342 gc.collect() 343 for f, fname in self.tmp_files: 344 os.close(f) 345 os.remove(fname) 346 347 def test_good(self): 348 if skip: 349 raise SkipTest(skip) 350 351 good = self.add_memmap_values(self.good) 352 353 for testname, inputs in iteritems(good): 354 inputs = [copy(input) for input in inputs] 355 inputrs = [TensorType( 356 dtype=input.dtype, 357 broadcastable=[shape_elem == 1 358 for shape_elem in input.shape] 359 )() for input in inputs] 360 try: 361 node = safe_make_node(self.op, *inputrs) 362 except Exception as exc: 363 err_msg = ("Test %s::%s: Error occurred while" 364 " making a node with inputs %s") % ( 365 self.op, testname, inputs) 366 exc.args += (err_msg,) 367 raise 368 369 try: 370 f = inplace_func(inputrs, node.outputs, mode=mode, name='test_good') 371 except Exception as exc: 372 err_msg = ("Test %s::%s: Error occurred while" 373 " trying to make a Function") % (self.op, testname) 374 exc.args += (err_msg,) 375 raise 376 if (isinstance(self.expected, dict) and 377 testname in self.expected): 378 expecteds = self.expected[testname] 379 # with numpy version, when we print a number and read it 380 # back, we don't get exactly the same result, so we accept 381 # rounding error in that case. 382 eps = 5e-9 383 else: 384 expecteds = self.expected(*inputs) 385 eps = 1e-10 386 387 if any([i.dtype in ('float32', 'int8', 'uint8', 'uint16') 388 for i in inputs]): 389 eps = 1e-6 390 eps = np.max([eps, _eps]) 391 392 try: 393 variables = f(*inputs) 394 except Exception as exc: 395 err_msg = ("Test %s::%s: Error occurred while calling" 396 " the Function on the inputs %s") % ( 397 self.op, testname, inputs) 398 exc.args += (err_msg,) 399 raise 400 401 if not isinstance(expecteds, (list, tuple)): 402 expecteds = (expecteds, ) 403 404 for i, (variable, expected) in enumerate( 405 izip(variables, expecteds)): 406 if (variable.dtype != expected.dtype or 407 variable.shape != expected.shape or 408 not np.allclose(variable, expected, 409 atol=eps, rtol=eps)): 410 self.fail(("Test %s::%s: Output %s gave the wrong" 411 " value. With inputs %s, expected %s (dtype %s)," 412 " got %s (dtype %s). eps=%f" 413 " np.allclose returns %s %s") % ( 414 self.op, 415 testname, 416 i, 417 inputs, 418 expected, 419 expected.dtype, 420 variable, 421 variable.dtype, 422 eps, 423 np.allclose(variable, expected, 424 atol=eps, rtol=eps), 425 np.allclose(variable, expected))) 426 427 for description, check in iteritems(self.checks): 428 if not check(inputs, variables): 429 self.fail(("Test %s::%s: Failed check: %s (inputs" 430 " were %s, outputs were %s)") % ( 431 self.op, testname, description, 432 inputs, variables)) 433 434 def test_bad_build(self): 435 if skip: 436 raise SkipTest(skip) 437 for testname, inputs in iteritems(self.bad_build): 438 inputs = [copy(input) for input in inputs] 439 inputrs = [shared(input) for input in inputs] 440 self.assertRaises(Exception, 441 safe_make_node, self.op, *inputrs) 442 # The old error string was ("Test %s::%s: %s was successfully 443 # instantiated on the following bad inputs: %s" 444 # % (self.op, testname, node, inputs)) 445 446 @change_flags(compute_test_value='off') 447 def test_bad_runtime(self): 448 if skip: 449 raise SkipTest(skip) 450 for testname, inputs in iteritems(self.bad_runtime): 451 inputrs = [shared(input) for input in inputs] 452 try: 453 node = safe_make_node(self.op, *inputrs) 454 except Exception as exc: 455 err_msg = ("Test %s::%s: Error occurred while trying" 456 " to make a node with inputs %s") % ( 457 self.op, testname, inputs) 458 exc.args += (err_msg,) 459 raise 460 461 try: 462 f = inplace_func([], node.outputs, mode=mode, name="test_bad_runtime") 463 except Exception as exc: 464 err_msg = ("Test %s::%s: Error occurred while trying" 465 " to make a Function") % (self.op, testname) 466 exc.args += (err_msg,) 467 raise 468 469 # Add tester return a ValueError. Should we catch only this 470 # one? 471 # TODO: test that only this one is raised and catch only this 472 # one or the subset that get raised. 473 self.assertRaises(Exception, f, []) 474 475 def test_grad(self): 476 if skip: 477 raise SkipTest(skip) 478 # Disable old warning that may be triggered by this test. 479 backup = config.warn.sum_div_dimshuffle_bug 480 config.warn.sum_div_dimshuffle_bug = False 481 try: 482 for testname, inputs in iteritems(self.grad): 483 inputs = [copy(input) for input in inputs] 484 try: 485 utt.verify_grad(self.op, inputs, 486 mode=self.mode, 487 rel_tol=_grad_rtol, 488 eps=_grad_eps) 489 except Exception as exc: 490 err_msg = ("Test %s::%s: Error occurred while" 491 " computing the gradient on the following" 492 " inputs: %s") % (self.op, testname, inputs) 493 exc.args += (err_msg,) 494 raise 495 finally: 496 config.warn.sum_div_dimshuffle_bug = backup 497 498 def test_grad_none(self): 499 # Check that None is never returned as input gradient 500 # when calling self.op.grad 501 # We use all values in self.good because this has to be true 502 # whether or not the values work for utt.verify_grad. 503 if skip: 504 raise SkipTest(skip) 505 506 if not hasattr(self.op, 'grad'): 507 # This is not actually an Op 508 return 509 510 for testname, inputs in iteritems(self.good): 511 inputs = [copy(input) for input in inputs] 512 inputrs = [TensorType( 513 dtype=input.dtype, 514 broadcastable=[shape_elem == 1 515 for shape_elem in input.shape] 516 )() for input in inputs] 517 518 if (isinstance(self.expected, dict) and 519 testname in self.expected): 520 expecteds = self.expected[testname] 521 # with numpy version, when we print a number and read it 522 # back, we don't get exactly the same result, so we accept 523 # rounding error in that case. 524 else: 525 expecteds = self.expected(*inputs) 526 if not isinstance(expecteds, (list, tuple)): 527 expecteds = (expecteds, ) 528 529 out_grad_vars = [] 530 for out in expecteds: 531 if str(out.dtype) in tensor.discrete_dtypes: 532 dtype = floatX 533 else: 534 dtype = str(out.dtype) 535 bcast = [shape_elem == 1 for shape_elem in out.shape] 536 var = TensorType(dtype=dtype, broadcastable=bcast)() 537 out_grad_vars.append(var) 538 539 try: 540 in_grad_vars = self.op.grad(inputrs, out_grad_vars) 541 except (gof.utils.MethodNotDefined, NotImplementedError): 542 pass 543 else: 544 assert None not in in_grad_vars 545 546 Checker.__name__ = name 547 if hasattr(Checker, '__qualname__'): 548 Checker.__qualname__ = name 549 return Checker 550 551 552def rand(*shape): 553 r = test_rng.rand(*shape) * 2 - 1 554 return np.asarray(r, dtype=config.floatX) 555 556 557def rand_nonzero(shape, eps=3e-4): 558 # Like rand, but the absolute value has to be at least eps 559 # covers [0, 1) 560 r = np.asarray(test_rng.rand(*shape), dtype=config.floatX) 561 # covers [0, (1 - eps) / 2) U [(1 + eps) / 2, 1) 562 r = r * (1 - eps) + eps * (r >= 0.5) 563 # covers [-1, -eps) U [eps, 1) 564 r = r * 2 - 1 565 return r 566 567 568def randint(*shape): 569 return test_rng.randint(-5, 6, shape) 570 571 572def randuint32(*shape): 573 return np.array(test_rng.randint(5, size=shape), dtype=np.uint32) 574 575 576def randuint16(*shape): 577 return np.array(test_rng.randint(5, size=shape), dtype=np.uint16) 578 579 580# XXX: this so-called complex random array as all-zero imaginary parts 581def randcomplex(*shape): 582 r = np.asarray(test_rng.rand(*shape), dtype=config.floatX) 583 return np.complex128(2 * r - 1) 584 585 586def randcomplex_nonzero(shape, eps=1e-4): 587 return np.complex128(rand_nonzero(shape, eps)) 588 589 590def randint_nonzero(*shape): 591 r = test_rng.randint(-5, 5, shape) 592 return r + (r == 0) * 5 593 594 595def rand_ranged(min, max, shape): 596 return np.asarray(test_rng.rand(*shape) * (max - min) + min, 597 dtype=config.floatX) 598 599 600def randint_ranged(min, max, shape): 601 return test_rng.randint(min, max + 1, shape) 602 603 604def randc128_ranged(min, max, shape): 605 return np.asarray(test_rng.rand(*shape) * (max - min) + min, 606 dtype='complex128') 607 608 609def rand_of_dtype(shape, dtype): 610 if dtype in tensor.discrete_dtypes: 611 return randint(*shape).astype(dtype) 612 elif dtype in tensor.float_dtypes: 613 return rand(*shape).astype(dtype) 614 elif dtype in tensor.complex_dtypes: 615 return randcomplex(*shape).astype(dtype) 616 else: 617 raise TypeError() 618 619# Used to exclude random numbers too close to certain values 620_eps = 1e-2 621 622 623def makeBroadcastTester(op, expected, checks=None, name=None, **kwargs): 624 if checks is None: 625 checks = {} 626 if name is None: 627 name = str(op) 628 # Here we ensure the test name matches the name of the variable defined in 629 # this script. This is needed to properly identify the test e.g. with the 630 # --with-id option of nosetests, or simply to rerun a specific test that 631 # failed. 632 capitalize = False 633 if name.startswith('Elemwise{') and name.endswith(',no_inplace}'): 634 # For instance: Elemwise{add,no_inplace} -> Add 635 name = name[9:-12] 636 capitalize = True 637 elif name.endswith('_inplace'): 638 # For instance: sub_inplace -> SubInplace 639 capitalize = True 640 if capitalize: 641 name = ''.join([x.capitalize() for x in name.split('_')]) 642 # Some tests specify a name that already ends with 'Tester', while in other 643 # cases we need to add it manually. 644 if not name.endswith('Tester'): 645 name += "Tester" 646 if 'inplace' in kwargs: 647 if kwargs['inplace']: 648 _expected = expected 649 if not isinstance(_expected, dict): 650 def expected(*inputs): 651 return np.array(_expected(*inputs), dtype=inputs[0].dtype) 652 653 def inplace_check(inputs, outputs): 654 # this used to be inputs[0] is output[0] 655 # I changed it so that it was easier to satisfy by the 656 # DebugMode 657 return np.all(inputs[0] == outputs[0]) 658 659 checks = dict(checks, inplace_check=inplace_check) 660 del kwargs['inplace'] 661 return makeTester(name, op, expected, checks, **kwargs) 662 663 664_good_broadcast_binary_normal = dict( 665 same_shapes=(rand(2, 3), rand(2, 3)), 666 not_same_dimensions=(rand(2, 2), rand(2)), 667 scalar=(rand(2, 3), rand(1, 1)), 668 row=(rand(2, 3), rand(1, 3)), 669 column=(rand(2, 3), rand(2, 1)), 670 integers=(randint(2, 3), randint(2, 3)), 671 uint32=(randuint32(2, 3), randuint32(2, 3)), 672 uint16=(randuint16(2, 3), randuint16(2, 3)), 673 dtype_mixup_1=(rand(2, 3), randint(2, 3)), 674 dtype_mixup_2=(randint(2, 3), rand(2, 3)), 675 complex1=(randcomplex(2, 3), randcomplex(2, 3)), 676 complex2=(randcomplex(2, 3), rand(2, 3)), 677 # Disabled as we test the case where we reuse the same output as the 678 # first inputs. 679 # complex3=(rand(2,3),randcomplex(2,3)), 680 empty=(np.asarray([], dtype=config.floatX), 681 np.asarray([1], dtype=config.floatX)), 682 ) 683 684_bad_build_broadcast_binary_normal = dict() 685 686_bad_runtime_broadcast_binary_normal = dict( 687 bad_shapes=(rand(2, 3), rand(3, 2)), 688 bad_row=(rand(2, 3), rand(1, 2))) 689 690_grad_broadcast_binary_normal = dict( 691 same_shapes=(rand(2, 3), rand(2, 3)), 692 scalar=(rand(2, 3), rand(1, 1)), 693 row=(rand(2, 3), rand(1, 3)), 694 column=(rand(2, 3), rand(2, 1)), 695 # This don't work as verify grad don't support that 696 # empty=(np.asarray([]), np.asarray([1])) 697 # complex1=(randcomplex(2,3),randcomplex(2,3)), 698 # complex2=(randcomplex(2,3),rand(2,3)), 699 # Disabled as we test the case where we reuse the same output as the 700 # first inputs. 701 # complex3=(rand(2,3),randcomplex(2,3)), 702 ) 703 704 705def check_floatX(inputs, rval): 706 # :param inputs: Inputs to a function that returned `rval` with these inputs. 707 # 708 # :param rval: Value returned by a function with inputs set to `inputs`. 709 # 710 # :returns: Either `rval` unchanged, or `rval` cast in float32. The idea is 711 # that when a numpy function would have returned a float64, Theano may prefer 712 # to return a float32 instead when `config.cast_policy` is set to 713 # 'numpy+floatX' and config.floatX to 'float32', and there was no float64 714 # input. 715 if (isinstance(rval, np.ndarray) and 716 rval.dtype == 'float64' and 717 config.cast_policy == 'numpy+floatX' and 718 config.floatX == 'float32' and 719 all(x.dtype != 'float64' for x in inputs)): 720 # Then we expect float32 instead of float64. 721 return rval.astype('float32') 722 else: 723 return rval 724 725 726AddTester = makeBroadcastTester( 727 op=add, 728 expected=lambda *inputs: check_floatX( 729 inputs, reduce(lambda x, y: x + y, inputs)), 730 good=dict( 731 three_inputs_same_shapes=(rand(2, 3), 732 rand(2, 3), 733 rand(2, 3)), 734 three_inputs_same_shapes_uint=(randuint32(2, 3), 735 randuint32(2, 3), 736 randuint32(2, 3)), 737 four_inputs_broadcast=(rand(2, 3), 738 rand(1, 3), 739 rand(2, 1), 740 rand(1, 1)), 741 **_good_broadcast_binary_normal), 742 bad_build=_bad_build_broadcast_binary_normal, 743 bad_runtime=_bad_runtime_broadcast_binary_normal) 744 745 746AddInplaceTester = makeBroadcastTester( 747 op=inplace.add_inplace, 748 expected=lambda x, y: x + y, 749 good=_good_broadcast_binary_normal, 750 bad_build=_bad_build_broadcast_binary_normal, 751 bad_runtime=_bad_runtime_broadcast_binary_normal, 752 inplace=True) 753 754SubTester = makeBroadcastTester( 755 op=sub, 756 expected=lambda x, y: check_floatX((x, y), x - y), 757 good=_good_broadcast_binary_normal, 758 bad_build=_bad_build_broadcast_binary_normal, 759 bad_runtime=_bad_runtime_broadcast_binary_normal, 760 grad=_grad_broadcast_binary_normal) 761 762SubInplaceTester = makeBroadcastTester(op=inplace.sub_inplace, 763 expected=lambda x, y: x - y, 764 good=_good_broadcast_binary_normal, 765 bad_build=_bad_build_broadcast_binary_normal, 766 bad_runtime=_bad_runtime_broadcast_binary_normal, 767 inplace=True) 768 769 770SwitchTester = makeBroadcastTester( 771 op=switch, 772 expected=np.where, 773 good=dict(all_true=(np.asarray(1, dtype=config.floatX), 774 rand(4, 5), rand(4, 5)), 775 false_true=(np.asarray(0, dtype=config.floatX), 776 rand(4, 5), rand(4, 5)), 777 mixed=(randint_ranged(0, 1, (4, 5)), 778 rand(4, 5), rand(4, 5)) 779 ), 780 bad_build=dict(all_true=(np.asarray(1, dtype=config.floatX), 781 rand(4, 5))), 782 bad_runtime=dict(all_true=(np.asarray(1, dtype=config.floatX), 783 rand(3, 5), rand(4, 5)), 784 false_true=(np.asarray(0, dtype=config.floatX), 785 rand(4, 6), rand(4, 5)), 786 ), 787 # We suppose that cond+eps do not switch branch in switch.grad() 788 # So we can't call verify_grad with cond 0. 789 grad=dict(all_true=(np.asarray(1, dtype=config.floatX), 790 rand(4, 5), rand(4, 5)), 791 # false_true=(np.asarray(0, dtype=config.floatX), 792 # rand(4, 5), rand(4, 5)), 793 # mixed=(randint_ranged(0, 1, (4, 5)).astype(config.floatX), 794 # rand(4, 5), rand(4, 5)) 795 ), 796) 797 798 799MaximumTester = makeBroadcastTester( 800 op=maximum, 801 expected=lambda *inputs: check_floatX(inputs, np.maximum(*inputs)), 802 good=_good_broadcast_binary_normal, 803 bad_build=_bad_build_broadcast_binary_normal, 804 bad_runtime=_bad_runtime_broadcast_binary_normal, 805 grad=_grad_broadcast_binary_normal) 806 807MaximumInplaceTester = makeBroadcastTester( 808 op=inplace.maximum_inplace, 809 expected=np.maximum, 810 good=_good_broadcast_binary_normal, 811 bad_build=_bad_build_broadcast_binary_normal, 812 bad_runtime=_bad_runtime_broadcast_binary_normal, 813 inplace=True) 814 815 816def test_maximum_minimum_grad(): 817 # Test the discontinuity point. 818 # We decided that we only pass the gradient to the first input in that case. 819 x, y = tensor.vectors('xy') 820 for op in [tensor.maximum, tensor.minimum]: 821 o = op(x, y) 822 g = theano.grad(o.sum(), [x, y]) 823 824 f = theano.function([x, y], g) 825 assert np.allclose(f([1], [1]), [[1], [0]]) 826 827 828MinimumTester = makeBroadcastTester( 829 op=minimum, 830 expected=lambda *inputs: check_floatX(inputs, np.minimum(*inputs)), 831 good=_good_broadcast_binary_normal, 832 bad_build=_bad_build_broadcast_binary_normal, 833 bad_runtime=_bad_runtime_broadcast_binary_normal, 834 grad=_grad_broadcast_binary_normal) 835 836MinimumInplaceTester = makeBroadcastTester( 837 op=inplace.minimum_inplace, 838 expected=np.minimum, 839 good=_good_broadcast_binary_normal, 840 bad_build=_bad_build_broadcast_binary_normal, 841 bad_runtime=_bad_runtime_broadcast_binary_normal, 842 inplace=True) 843 844MulTester = makeBroadcastTester( 845 op=mul, 846 expected=lambda *inputs: check_floatX(inputs, reduce(lambda x, y: x * y, inputs)), 847 good=dict(three_inputs_same_shapes=(rand(2, 3), rand(2, 3), rand(2, 3)), 848 four_inputs_broadcast=(rand(2, 3), rand(1, 3), rand(2, 1), rand(1, 1)), 849 **_good_broadcast_binary_normal), 850 bad_build=_bad_build_broadcast_binary_normal, 851 bad_runtime=_bad_runtime_broadcast_binary_normal, 852 grad=dict(three_inputs_same_shapes=(rand(2, 3), rand(2, 3), rand(2, 3)), 853 four_inputs_broadcast=(rand(2, 3), rand(1, 3), rand(2, 1), rand(1, 1)), 854 **_grad_broadcast_binary_normal)) 855 856MulInplaceTester = makeBroadcastTester( 857 op=inplace.mul_inplace, 858 expected=lambda x, y: x * y, 859 good=_good_broadcast_binary_normal, 860 bad_build=_bad_build_broadcast_binary_normal, 861 bad_runtime=_bad_runtime_broadcast_binary_normal, 862 inplace=True) 863 864 865def copymod(dct, without=None, **kwargs): 866 # Return dct but with the keys named by args removed, and with 867 # kwargs added. 868 if without is None: 869 without = [] 870 rval = copy(dct) 871 for a in without: 872 if a in rval: 873 del rval[a] 874 for kw, val in iteritems(kwargs): 875 rval[kw] = val 876 return rval 877 878_good_broadcast_div_mod_normal_float_no_complex = dict( 879 same_shapes=(rand(2, 3), rand_nonzero((2, 3))), 880 scalar=(rand(2, 3), rand_nonzero((1, 1))), 881 row=(rand(2, 3), rand_nonzero((1, 3))), 882 column=(rand(2, 3), rand_nonzero((2, 1))), 883 dtype_mixup_1=(rand(2, 3), randint_nonzero(2, 3)), 884 dtype_mixup_2=(randint_nonzero(2, 3), rand_nonzero((2, 3))), 885 integer=(randint(2, 3), randint_nonzero(2, 3)), 886 uint8=(randint(2, 3).astype("uint8"), 887 randint_nonzero(2, 3).astype("uint8")), 888 uint16=(randint(2, 3).astype("uint16"), 889 randint_nonzero(2, 3).astype("uint16")), 890 int8=[np.tile(np.arange(-127, 128, dtype='int8'), [254, 1]).T, 891 np.tile(np.array(list(range(-127, 0)) + list(range(1, 128)), 892 dtype='int8'), 893 [255, 1])], 894 # This empty2 doesn't work for some tests. I don't remember why 895 # empty2=(np.asarray([0]), np.asarray([])), 896 ) 897 898if PY3: 899 _good_broadcast_div_mod_normal_float_inplace = copymod( 900 _good_broadcast_div_mod_normal_float_no_complex, 901 empty1=(np.asarray([]), np.asarray([1])), 902 # No complex floor division in python 3.x 903 ) 904else: 905 _good_broadcast_div_mod_normal_float_inplace = copymod( 906 _good_broadcast_div_mod_normal_float_no_complex, 907 empty1=(np.asarray([], dtype=config.floatX), 908 np.asarray([1], dtype=config.floatX)), 909 complex1=(randcomplex(2, 3), randcomplex_nonzero((2, 3))), 910 complex2=(randcomplex(2, 3), rand_nonzero((2, 3))), 911 # Inplace on the first element. Must have the same type. 912 # complex3=(rand(2, 3) ,randcomplex(2, 3)), 913 ) 914 915_good_broadcast_div_mod_normal_float = copymod( 916 _good_broadcast_div_mod_normal_float_inplace, 917 empty2=(np.asarray([0], dtype=config.floatX), 918 np.asarray([], dtype=config.floatX)) 919 ) 920 921 922_grad_broadcast_div_mod_normal = dict( 923 same_shapes=(rand(2, 3), rand_nonzero((2, 3))), 924 scalar=(rand(2, 3), rand_nonzero((1, 1))), 925 row=(rand(2, 3), rand_nonzero((1, 3))), 926 column=(rand(2, 3), rand_nonzero((2, 1))), 927 # complex1=(randcomplex(2, 3), randcomplex_nonzero((2, 3))), 928 # complex2=(randcomplex(2, 3), rand_nonzero((2, 3))), 929 # complex3=(rand(2, 3), randcomplex_nonzero((2, 3))), 930 # dtype_mixup_1=(rand(2, 3), randint_nonzero(2, 3)), 931 # dtype_mixup_2=(randint_nonzero(2, 3), rand_nonzero((2, 3))), 932 # empty1=(np.asarray([]), np.asarray([1.])), 933 # empty2=(np.asarray([0]), np.asarray([])), 934 ) 935 936div_grad_rtol = None 937if config.floatX == 'float32': 938 # We raise the relative tolerance for the grad as there can be errors in 939 # float32. 940 # This is probably caused by our way of computing the gradient error. 941 div_grad_rtol = 0.025 942 943 944def _numpy_true_div(x, y): 945 # Performs true division, and cast the result in the type we expect. 946 # 947 # We define that function so we can use it in TrueDivTester.expected, 948 # because simply calling np.true_divide could cause a dtype mismatch. 949 out = np.true_divide(x, y) 950 # Use floatX as the result of int / int 951 if x.dtype in tensor.discrete_dtypes and y.dtype in tensor.discrete_dtypes: 952 out = theano._asarray(out, dtype=config.floatX) 953 return out 954 955TrueDivTester = makeBroadcastTester( 956 op=tensor.true_div, 957 expected=_numpy_true_div, 958 good=_good_broadcast_div_mod_normal_float_no_complex, 959 grad=_grad_broadcast_div_mod_normal, 960 grad_rtol=div_grad_rtol, 961 ) 962 963TrueDivInplaceTester = makeBroadcastTester( 964 op=inplace.true_div_inplace, 965 expected=_numpy_true_div, 966 good=copymod( 967 _good_broadcast_div_mod_normal_float_inplace, 968 # The output is now in float, we cannot work inplace on an int. 969 without=['integer', 'uint8', 'uint16', 'int8']), 970 grad_rtol=div_grad_rtol, 971 inplace=True) 972 973 974_good_inv = dict( 975 normal=[5 * rand_nonzero((2, 3))], 976 integers=[randint_nonzero(2, 3)], 977 int8=[np.array(list(range(-127, 0)) + list(range(1, 127)), dtype='int8')], 978 uint8=[np.array(list(range(0, 255)), dtype='uint8')], 979 uint16=[np.array(list(range(0, 65535)), dtype='uint16')], 980 complex=[randcomplex_nonzero((2, 3))], 981 empty=[np.asarray([], dtype=config.floatX)]) 982 983_good_inv_inplace = copymod(_good_inv, without=['integers', 'int8', 'uint8', 'uint16', 'complex']) 984_grad_inv = copymod(_good_inv, 985 without=['integers', 'int8', 'uint8', 'uint16', 'complex', 'empty']) 986 987_bad_runtime_inv = dict( 988 float=[np.zeros((2, 3))], 989 integers=[np.zeros((2, 3), dtype='int64')], 990 int8=[np.zeros((2, 3), dtype='int8')], 991 complex=[np.zeros((2, 3), dtype='complex128')]) 992 993 994InvTester = makeBroadcastTester( 995 op=tensor.inv, 996 expected=lambda x: upcast_int8_nfunc(np.true_divide)(np.int8(1), x), 997 good=_good_inv, 998 bad_runtime=_bad_runtime_inv, 999 grad=_grad_inv, 1000 grad_rtol=div_grad_rtol) 1001 1002InvInplaceTester = makeBroadcastTester( 1003 op=inplace.inv_inplace, 1004 expected=lambda x: _numpy_true_div(np.int8(1), x), 1005 good=_good_inv_inplace, 1006 bad_runtime=_bad_runtime_inv, 1007 grad_rtol=div_grad_rtol, 1008 inplace=True) 1009 1010 1011CeilIntDivTester = makeBroadcastTester( 1012 op=tensor.ceil_intdiv, 1013 expected=lambda x, y: check_floatX((x, y), (x // y) + ((x % y) != 0)), 1014 good=_good_broadcast_div_mod_normal_float_no_complex, 1015 name='CeilIntDiv', 1016 # As we implement this function with neq, the gradient returned is always 0. 1017 # grad=_grad_broadcast_div_mod_normal, 1018 # grad_rtol=div_grad_rtol, 1019 ) 1020 1021ModTester = makeBroadcastTester( 1022 op=tensor.mod, 1023 expected=lambda x, y: np.asarray( 1024 x % y, dtype=theano.scalar.basic.upcast(x.dtype, y.dtype)), 1025 good=copymod(_good_broadcast_div_mod_normal_float, 1026 ['complex1', 'complex2']), 1027 grad=_grad_broadcast_div_mod_normal, 1028 grad_eps=1e-5, 1029 ) 1030 1031 1032ModInplaceTester = makeBroadcastTester( 1033 op=inplace.mod_inplace, 1034 expected=lambda x, y: np.asarray( 1035 x % y, dtype=theano.scalar.basic.upcast(x.dtype, y.dtype)), 1036 good=copymod(_good_broadcast_div_mod_normal_float_inplace, 1037 ["complex1", "complex2"]), 1038 grad_eps=1e-5, 1039 inplace=True) 1040 1041_good_broadcast_pow_normal_float = dict( 1042 same_shapes=(rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))), 1043 scalar=(rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 1))), 1044 row=(rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 3))), 1045 column=(rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 1))), 1046 dtype_mixup=(rand_ranged(-3, 3, (2, 3)), randint_ranged(-3, 3, (2, 3))), 1047 complex1=(randcomplex(2, 3), randcomplex(2, 3)), 1048 complex2=(randcomplex(2, 3), rand(2, 3)), 1049 # complex3 = (rand(2,3),randcomplex(2,3)), # Inplace on the first element. 1050 empty1=(np.asarray([], dtype=config.floatX), 1051 np.asarray([1], dtype=config.floatX)), 1052 empty2=(np.asarray([0], dtype=config.floatX), 1053 np.asarray([], dtype=config.floatX)), 1054 empty3=(np.asarray([], dtype=config.floatX), 1055 np.asarray([], dtype=config.floatX)), 1056 ) 1057_grad_broadcast_pow_normal = dict( 1058 same_shapes=(rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))), 1059 scalar=(rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 1))), 1060 row=(rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 3))), 1061 column=(rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 1))), 1062 # complex1 = (randcomplex(2,3),randcomplex(2,3)), 1063 # complex2 = (randcomplex(2,3),rand(2,3)), 1064 # complex3 = (rand(2,3),randcomplex(2,3)), 1065 # empty1 = (np.asarray([]), np.asarray([1])), 1066 # empty2 = (np.asarray([0]), np.asarray([])), 1067 x_eq_zero=( 1068 np.asarray([0.], dtype=config.floatX), 1069 np.asarray([2.], dtype=config.floatX) 1070 ), # Test for issue 1780 1071 ) 1072# empty2 case is not supported by numpy. 1073_good_broadcast_pow_normal_float_pow = copy(_good_broadcast_pow_normal_float) 1074del _good_broadcast_pow_normal_float_pow["empty2"] 1075 1076# Disable NAN checking for pow operator per issue #1780 1077m = copy(theano.compile.get_default_mode()) 1078m.check_isfinite = False 1079 1080PowTester = makeBroadcastTester( 1081 op=pow, 1082 expected=lambda x, y: check_floatX((x, y), x ** y), 1083 good=_good_broadcast_pow_normal_float, 1084 grad=_grad_broadcast_pow_normal, 1085 name='Pow', 1086 mode=m 1087) 1088 1089PowInplaceTester = makeBroadcastTester( 1090 op=inplace.pow_inplace, 1091 expected=lambda x, y: x ** y, 1092 good=_good_broadcast_pow_normal_float_pow, 1093 inplace=True, 1094 mode=m 1095) 1096 1097# Those are corner case when rounding. Their is many rounding algo. 1098# c round() fct and numpy round are not the same! 1099corner_case = np.asarray( 1100 [-2.5, -2., -1.5, -1., -0.5, -.51, -.49, 0, 1101 0.49, 0.5, 0.9, 1, 1.5, 2, 2.5], 1102 dtype=floatX) 1103 1104# we remove 0 here as the grad is not always computable numerically. 1105corner_case_grad = np.asarray( 1106 [-2.5, -2., -1.5, -1., -0.5, -.51, -.49, 1107 0.49, 0.5, 0.9, 1, 1.5, 2, 2.5], 1108 dtype=floatX) 1109 1110_good_broadcast_unary_normal_float = dict( 1111 normal=[rand_ranged(-5, 5, (2, 3))], 1112 corner_case=[corner_case], 1113 complex=[randcomplex(2, 3)], 1114 empty=[np.asarray([], dtype=config.floatX)]) 1115 1116_good_broadcast_unary_normal_float_no_empty = copymod( 1117 _good_broadcast_unary_normal_float, 1118 without=['empty']) 1119 1120_good_broadcast_unary_normal_float_no_empty_no_complex = copymod( 1121 _good_broadcast_unary_normal_float_no_empty, 1122 without=['complex']) 1123 1124_good_broadcast_unary_normal_float_no_complex = copymod( 1125 _good_broadcast_unary_normal_float, 1126 without=['complex']) 1127 1128_good_broadcast_unary_normal_float_no_complex_small_neg_range = dict( 1129 normal=[rand_ranged(-2, 5, (2, 3))], 1130 corner_case=[corner_case], 1131 empty=[np.asarray([], dtype=config.floatX)]) 1132 1133_good_broadcast_unary_normal = dict( 1134 normal=[np.asarray(rand_ranged(-5, 5, (2, 3)), 1135 dtype=config.floatX)], 1136 integers=[randint_ranged(-5, 5, (2, 3))], 1137 # not using -128 because np.allclose would return False 1138 int8=[np.arange(-127, 128, dtype='int8')], 1139 uint8=[np.arange(0, 255, dtype='uint8')], 1140 uint16=[np.arange(0, 65535, dtype='uint16')], 1141 corner_case=[corner_case], 1142 complex=[randcomplex(2, 3)], 1143 empty=[np.asarray([], dtype=config.floatX)], 1144 ) 1145 1146_good_broadcast_unary_normal_no_complex = dict( 1147 normal=[np.asarray(rand_ranged(-5, 5, (2, 3)), dtype=floatX)], 1148 integers=[randint_ranged(-5, 5, (2, 3))], 1149 int8=[np.arange(-127, 128, dtype='int8')], 1150 uint8=[np.arange(0, 89, dtype='uint8')], 1151 uint16=[np.arange(0, 89, dtype='uint16')], 1152 corner_case=[corner_case], 1153 empty=[np.asarray([], dtype=config.floatX)], 1154 ) 1155 1156_grad_broadcast_unary_normal_no_complex = dict( 1157 normal=[np.asarray(rand_ranged(-5, 5, (2, 3)), dtype=floatX)], 1158 corner_case=[corner_case_grad]) 1159 1160_grad_broadcast_unary_normal = dict( 1161 normal=[np.asarray(rand_ranged(-5, 5, (2, 3)), dtype=floatX)], 1162 corner_case=[corner_case_grad], 1163 # empty = [np.asarray([])] # XXX: should this be included? 1164 ) 1165 1166# Avoid epsilon around integer values 1167_grad_broadcast_unary_normal_noint = dict( 1168 normal=[(rand_ranged(_eps, 1 - _eps, (2, 3)) + randint(2, 3)) 1169 .astype(floatX)]) 1170 1171_grad_broadcast_unary_normal_small_neg_range = dict( 1172 normal=[np.asarray(rand_ranged(-2, 5, (2, 3)), dtype=floatX)], 1173 corner_case=[corner_case_grad]) 1174 1175_grad_broadcast_unary_normal_no_complex_no_corner_case = copymod( 1176 _grad_broadcast_unary_normal_no_complex, 1177 without=['corner_case']) 1178 1179_grad_broadcast_unary_abs1_no_complex = dict( 1180 normal=[np.asarray(rand_ranged(-1 + _eps, 1 - _eps, (2, 3)), dtype=floatX)], 1181 ) 1182 1183_grad_broadcast_unary_0_2_no_complex = dict( 1184 # Don't go too close to 0 or 2 for tests in float32 1185 normal=[np.asarray(rand_ranged(_eps, 1 - _eps, (2, 3)), dtype=floatX)], 1186 ) 1187 1188# inplace ops when the input is integer and the output is float* 1189# don't have a well defined behavior. We don't test that case. 1190 1191AbsTester = makeBroadcastTester( 1192 op=tensor.abs_, 1193 expected=lambda x: abs(x), 1194 good=_good_broadcast_unary_normal, 1195 grad=_grad_broadcast_unary_normal) 1196_good_broadcast_unary_normal_abs = copy(_good_broadcast_unary_normal) 1197# Can't do inplace on Abs as the input/output are not of the same type! 1198del _good_broadcast_unary_normal_abs['complex'] 1199AbsInplaceTester = makeBroadcastTester( 1200 op=inplace.abs__inplace, 1201 expected=lambda x: np.abs(x), 1202 good=_good_broadcast_unary_normal_abs, 1203 inplace=True) 1204 1205NegTester = makeBroadcastTester( 1206 op=tensor.neg, 1207 expected=lambda x: -x, 1208 good=_good_broadcast_unary_normal, 1209 grad=_grad_broadcast_unary_normal) 1210NegInplaceTester = makeBroadcastTester( 1211 op=inplace.neg_inplace, 1212 expected=lambda x: -x, 1213 good=_good_broadcast_unary_normal, 1214 inplace=True) 1215 1216SgnTester = makeBroadcastTester( 1217 op=tensor.sgn, 1218 expected=np.sign, 1219 good=_good_broadcast_unary_normal_no_complex, 1220 grad=_grad_broadcast_unary_normal,) 1221SgnInplaceTester = makeBroadcastTester( 1222 op=inplace.sgn_inplace, 1223 expected=np.sign, 1224 good=_good_broadcast_unary_normal_no_complex, 1225 inplace=True) 1226 1227IntDivTester = makeBroadcastTester( 1228 op=tensor.int_div, 1229 expected=lambda x, y: check_floatX((x, y), x // y), 1230 good=_good_broadcast_div_mod_normal_float, 1231 # I don't test the grad as the output is always an integer 1232 # (this is not a continuous output). 1233 # grad=_grad_broadcast_div_mod_normal, 1234 ) 1235 1236IntDivInplaceTester = makeBroadcastTester( 1237 op=inplace.int_div_inplace, 1238 expected=lambda x, y: check_floatX((x, y), x // y), 1239 good=_good_broadcast_div_mod_normal_float_inplace, 1240 # I don't test the grad as the output is always an integer 1241 # (this is not a continuous output). 1242 # grad=_grad_broadcast_div_mod_normal, 1243 inplace=True 1244 ) 1245 1246 1247CeilTester = makeBroadcastTester( 1248 op=tensor.ceil, 1249 expected=upcast_float16_ufunc(np.ceil), 1250 good=_good_broadcast_unary_normal_no_complex, 1251 grad=copymod(_grad_broadcast_unary_normal_noint, 1252 extra=[np.asarray([-2.5, -1.5, -1.51, 0.49, .98, 1.02], 1253 dtype=floatX)])) 1254 1255CeilInplaceTester = makeBroadcastTester( 1256 op=inplace.ceil_inplace, 1257 expected=upcast_float16_ufunc(np.ceil), 1258 good=copymod(_good_broadcast_unary_normal_no_complex, 1259 without=['integers', 'int8', 'uint8', 'uint16']), 1260 # corner cases includes a lot of integers: points where Ceil is not 1261 # continuous (not differentiable) 1262 inplace=True) 1263 1264FloorTester = makeBroadcastTester( 1265 op=tensor.floor, 1266 expected=upcast_float16_ufunc(np.floor), 1267 good=_good_broadcast_unary_normal_no_complex, 1268 grad=_grad_broadcast_unary_normal_noint) 1269 1270FloorInplaceTester = makeBroadcastTester( 1271 op=inplace.floor_inplace, 1272 expected=upcast_float16_ufunc(np.floor), 1273 good=copymod(_good_broadcast_unary_normal_no_complex, 1274 without=["integers", "int8", "uint8", "uint16"]), 1275 inplace=True) 1276 1277TruncInplaceTester = makeBroadcastTester( 1278 op=inplace.trunc_inplace, 1279 expected=upcast_float16_ufunc(np.trunc), 1280 good=_good_broadcast_unary_normal_no_complex, 1281 inplace=True) 1282 1283TruncTester = makeBroadcastTester( 1284 op=tensor.trunc, 1285 expected=upcast_float16_ufunc(np.trunc), 1286 good=_good_broadcast_unary_normal_no_complex) 1287 1288RoundHalfToEvenTester = makeBroadcastTester( 1289 op=tensor.round_half_to_even, 1290 expected=np.round, 1291 good=_good_broadcast_unary_normal_float_no_complex, 1292 grad=_grad_broadcast_unary_normal_no_complex_no_corner_case) 1293 1294RoundHalfToEvenInplaceTester = makeBroadcastTester( 1295 op=inplace.round_half_to_even_inplace, 1296 expected=np.round, 1297 good=_good_broadcast_unary_normal_float_no_complex, 1298 inplace=True) 1299 1300# np.vectorize don't handle correctly empty ndarray. 1301# see in their file numpy/lib/function_base.py in class vectorize.__call__ 1302# This happen in float32 mode. 1303RoundHalfAwayFromZeroTester = makeBroadcastTester( 1304 op=tensor.round_half_away_from_zero, 1305 expected=lambda a: theano.scalar.basic.round_half_away_from_zero_vec(a), 1306 good=_good_broadcast_unary_normal_float_no_empty_no_complex, 1307 grad=_grad_broadcast_unary_normal_no_complex_no_corner_case) 1308 1309RoundHalfAwayFromZeroInplaceTester = makeBroadcastTester( 1310 op=inplace.round_half_away_from_zero_inplace, 1311 expected=lambda a: theano.scalar.basic.round_half_away_from_zero_vec(a), 1312 good=_good_broadcast_unary_normal_float_no_empty_no_complex, 1313 inplace=True) 1314 1315SqrTester = makeBroadcastTester( 1316 op=tensor.sqr, 1317 expected=np.square, 1318 good=_good_broadcast_unary_normal, 1319 grad=_grad_broadcast_unary_normal) 1320 1321SqrInplaceTester = makeBroadcastTester( 1322 op=inplace.sqr_inplace, 1323 expected=np.square, 1324 good=_good_broadcast_unary_normal, 1325 inplace=True) 1326 1327ExpTester = makeBroadcastTester( 1328 op=tensor.exp, 1329 expected=upcast_float16_ufunc(np.exp), 1330 good=dict(_good_broadcast_unary_normal, 1331 int8=[np.arange(-127, 89, dtype='int8')], 1332 uint8=[np.arange(0, 89, dtype='uint8')], 1333 uint16=[np.arange(0, 89, dtype='uint16')]), 1334 grad=_grad_broadcast_unary_normal) 1335ExpInplaceTester = makeBroadcastTester( 1336 op=inplace.exp_inplace, 1337 expected=np.exp, 1338 good=_good_broadcast_unary_normal_float, 1339 inplace=True) 1340 1341Exp2Tester = makeBroadcastTester( 1342 op=tensor.exp2, 1343 expected=upcast_float16_ufunc(np.exp2), 1344 good=_good_broadcast_unary_normal, 1345 grad=_grad_broadcast_unary_normal) 1346Exp2InplaceTester = makeBroadcastTester( 1347 op=inplace.exp2_inplace, 1348 expected=np.exp2, 1349 good=_good_broadcast_unary_normal_float, 1350 inplace=True) 1351 1352 1353Expm1Tester = makeBroadcastTester( 1354 op=tensor.expm1, 1355 expected=upcast_float16_ufunc(np.expm1), 1356 good=dict(_good_broadcast_unary_normal, 1357 int8=[np.arange(-127, 89, dtype='int8')], 1358 uint8=[np.arange(0, 89, dtype='uint8')], 1359 uint16=[np.arange(0, 89, dtype='uint16')]), 1360 grad=_grad_broadcast_unary_normal) 1361Expm1InplaceTester = makeBroadcastTester( 1362 op=inplace.expm1_inplace, 1363 expected=np.expm1, 1364 good=_good_broadcast_unary_normal_float, 1365 inplace=True) 1366 1367 1368_good_broadcast_unary_positive = dict( 1369 normal=(rand_ranged(0.001, 5, (2, 3)),), 1370 integers=(randint_ranged(1, 5, (2, 3)),), 1371 uint8=[np.arange(1, 256, dtype='uint8')], 1372 complex=(randc128_ranged(1, 5, (2, 3)),), 1373 empty=(np.asarray([], dtype=config.floatX),), 1374 ) 1375 1376_good_broadcast_unary_positive_float = copymod( 1377 _good_broadcast_unary_positive, 1378 without=['integers', 'uint8']) 1379 1380_grad_broadcast_unary_positive = dict(normal=(rand_ranged(_eps, 5, (2, 3)),),) 1381 1382LogTester = makeBroadcastTester( 1383 op=tensor.log, 1384 expected=upcast_float16_ufunc(np.log), 1385 good=_good_broadcast_unary_positive, 1386 grad=_grad_broadcast_unary_positive) 1387LogInplaceTester = makeBroadcastTester( 1388 op=inplace.log_inplace, 1389 expected=np.log, 1390 good=_good_broadcast_unary_positive_float, 1391 inplace=True) 1392 1393Log2Tester = makeBroadcastTester( 1394 op=tensor.log2, 1395 expected=upcast_float16_ufunc(np.log2), 1396 good=_good_broadcast_unary_positive, 1397 grad=_grad_broadcast_unary_positive) 1398Log2InplaceTester = makeBroadcastTester( 1399 op=inplace.log2_inplace, 1400 expected=np.log2, 1401 good=_good_broadcast_unary_positive_float, 1402 inplace=True) 1403 1404Log10Tester = makeBroadcastTester( 1405 op=tensor.log10, 1406 expected=upcast_float16_ufunc(np.log10), 1407 good=_good_broadcast_unary_positive, 1408 grad=_grad_broadcast_unary_positive) 1409Log10InplaceTester = makeBroadcastTester( 1410 op=inplace.log10_inplace, 1411 expected=np.log10, 1412 good=_good_broadcast_unary_positive_float, 1413 inplace=True) 1414 1415Log1pTester = makeBroadcastTester( 1416 op=tensor.log1p, 1417 expected=upcast_float16_ufunc(np.log1p), 1418 good=_good_broadcast_unary_positive, 1419 grad=_grad_broadcast_unary_positive) 1420Log1pInplaceTester = makeBroadcastTester( 1421 op=inplace.log1p_inplace, 1422 expected=np.log1p, 1423 good=_good_broadcast_unary_positive_float, 1424 inplace=True) 1425 1426SqrtTester = makeBroadcastTester( 1427 op=tensor.sqrt, 1428 expected=upcast_float16_ufunc(np.sqrt), 1429 good=_good_broadcast_unary_positive, 1430 grad=_grad_broadcast_unary_positive) 1431SqrtInplaceTester = makeBroadcastTester( 1432 op=inplace.sqrt_inplace, 1433 expected=np.sqrt, 1434 good=_good_broadcast_unary_positive_float, 1435 inplace=True) 1436 1437_good_broadcast_unary_wide = dict( 1438 normal=(rand_ranged(-1000, 1000, (2, 3)),), 1439 integers=(randint_ranged(-1000, 1000, (2, 3)),), 1440 int8=[np.arange(-127, 128, dtype='int8')], 1441 uint8=[np.arange(0, 255, dtype='uint8')], 1442 uint16=[np.arange(0, 65535, dtype='uint16')], 1443 complex=(randc128_ranged(-1000, 1000, (2, 3)),), 1444 empty=(np.asarray([], dtype=config.floatX),),) 1445_good_broadcast_unary_wide_float = copymod( 1446 _good_broadcast_unary_wide, 1447 without=['integers', 'int8', 'uint8', 'uint16']) 1448_grad_broadcast_unary_wide = dict(normal=(rand_ranged(-1000, 1000, (2, 3)),),) 1449 1450if theano.config.floatX == 'float32': 1451 angle_eps = 1e-4 1452else: 1453 angle_eps = 1e-10 1454 1455Deg2radTester = makeBroadcastTester( 1456 op=tensor.deg2rad, 1457 expected=upcast_float16_ufunc(np.deg2rad), 1458 good=_good_broadcast_unary_normal_no_complex, 1459 grad=_grad_broadcast_unary_normal_no_complex, 1460 eps=angle_eps) 1461Deg2radInplaceTester = makeBroadcastTester( 1462 op=inplace.deg2rad_inplace, 1463 expected=np.deg2rad, 1464 good=_good_broadcast_unary_normal_float_no_complex, 1465 inplace=True, 1466 eps=angle_eps) 1467 1468Rad2degTester = makeBroadcastTester( 1469 op=tensor.rad2deg, 1470 expected=upcast_float16_ufunc(np.rad2deg), 1471 good=_good_broadcast_unary_normal_no_complex, 1472 grad=_grad_broadcast_unary_normal_no_complex, 1473 eps=angle_eps) 1474Rad2degInplaceTester = makeBroadcastTester( 1475 op=inplace.rad2deg_inplace, 1476 expected=np.rad2deg, 1477 good=_good_broadcast_unary_normal_float_no_complex, 1478 inplace=True, 1479 eps=angle_eps) 1480 1481SinTester = makeBroadcastTester( 1482 op=tensor.sin, 1483 expected=upcast_float16_ufunc(np.sin), 1484 good=_good_broadcast_unary_wide, 1485 grad=_grad_broadcast_unary_wide) 1486SinInplaceTester = makeBroadcastTester( 1487 op=inplace.sin_inplace, 1488 expected=np.sin, 1489 good=_good_broadcast_unary_wide_float, 1490 inplace=True) 1491 1492_good_broadcast_unary_arcsin = dict( 1493 normal=(rand_ranged(-1, 1, (2, 3)),), 1494 integers=(randint_ranged(-1, 1, (2, 3)),), 1495 int8=[np.arange(-1, 2, dtype='int8')], 1496 uint8=[np.arange(0, 2, dtype='uint8')], 1497 uint16=[np.arange(0, 2, dtype='uint16')], 1498 complex=(randc128_ranged(-1, 1, (2, 3)),), 1499 empty=(np.asarray([], dtype=config.floatX),),) 1500 1501_good_broadcast_unary_arcsin_float = copymod( 1502 _good_broadcast_unary_arcsin, 1503 without=['integers', 'int8', 'uint8', 'uint16']) 1504 1505# The actual range is [-1, 1] but the numerical gradient is too 1506# unstable near those values 1507_grad_broadcast_unary_arcsin = dict(normal=(rand_ranged(-0.9, 0.9, (2, 3)),),) 1508 1509ArcsinTester = makeBroadcastTester( 1510 op=tensor.arcsin, 1511 expected=upcast_float16_ufunc(np.arcsin), 1512 good=_good_broadcast_unary_arcsin, 1513 grad=_grad_broadcast_unary_arcsin) 1514ArcsinInplaceTester = makeBroadcastTester( 1515 op=inplace.arcsin_inplace, 1516 expected=np.arcsin, 1517 good=_good_broadcast_unary_arcsin_float, 1518 inplace=True) 1519 1520CosTester = makeBroadcastTester( 1521 op=tensor.cos, 1522 expected=upcast_float16_ufunc(np.cos), 1523 good=_good_broadcast_unary_wide, 1524 grad=_grad_broadcast_unary_wide) 1525CosInplaceTester = makeBroadcastTester( 1526 op=inplace.cos_inplace, 1527 expected=np.cos, 1528 good=_good_broadcast_unary_wide_float, 1529 inplace=True) 1530 1531 1532def test_py_c_match(): 1533 a = tensor.TensorType(dtype='int8', broadcastable=(False,))() 1534 f = theano.function([a], tensor.arccos(a), mode='DebugMode') 1535 # This can fail in DebugMode 1536 f(np.asarray([1, 0, -1], dtype='int8')) 1537 1538ArccosTester = makeBroadcastTester( 1539 op=tensor.arccos, 1540 expected=upcast_float16_ufunc(np.arccos), 1541 good=_good_broadcast_unary_arcsin, 1542 grad=_grad_broadcast_unary_arcsin) 1543ArccosInplaceTester = makeBroadcastTester( 1544 op=inplace.arccos_inplace, 1545 expected=np.arccos, 1546 good=_good_broadcast_unary_arcsin_float, 1547 inplace=True) 1548 1549_good_broadcast_unary_tan = dict( 1550 normal=(rand_ranged(-3.14, 3.14, (2, 3)),), 1551 shifted=(rand_ranged(3.15, 6.28, (2, 3)),), 1552 integers=(randint_ranged(-3, 3, (2, 3)),), 1553 int8=[np.arange(-3, 4, dtype='int8')], 1554 uint8=[np.arange(0, 4, dtype='uint8')], 1555 uint16=[np.arange(0, 4, dtype='uint16')], 1556 complex=(randc128_ranged(-3.14, 3.14, (2, 3)),), 1557 empty=(np.asarray([], dtype=config.floatX),),) 1558# We do not want to test around the discontinuity. 1559_grad_broadcast_unary_tan = dict(normal=(rand_ranged(-1.5, 1.5, (2, 3)),), 1560 shifted=(rand_ranged(1.6, 4.6, (2, 3)),)) 1561 1562TanTester = makeBroadcastTester( 1563 op=tensor.tan, 1564 expected=upcast_float16_ufunc(np.tan), 1565 good=_good_broadcast_unary_tan, 1566 grad=_grad_broadcast_unary_tan) 1567 1568TanInplaceTester = makeBroadcastTester( 1569 op=inplace.tan_inplace, 1570 expected=np.tan, 1571 good=copymod(_good_broadcast_unary_tan, without=['integers', 'int8', 'uint8', 'uint16']), 1572 inplace=True) 1573 1574ArctanTester = makeBroadcastTester( 1575 op=tensor.arctan, 1576 expected=upcast_float16_ufunc(np.arctan), 1577 good=_good_broadcast_unary_wide, 1578 grad=_grad_broadcast_unary_wide) 1579ArctanInplaceTester = makeBroadcastTester( 1580 op=inplace.arctan_inplace, 1581 expected=np.arctan, 1582 good=_good_broadcast_unary_wide_float, 1583 inplace=True) 1584 1585_good_broadcast_binary_arctan2 = dict( 1586 same_shapes=(rand(2, 3), rand(2, 3)), 1587 not_same_dimensions=(rand(2, 2), rand(2)), 1588 scalar=(rand(2, 3), rand(1, 1)), 1589 row=(rand(2, 3), rand(1, 3)), 1590 column=(rand(2, 3), rand(2, 1)), 1591 integers=(randint(2, 3), randint(2, 3)), 1592 int8=[np.arange(-127, 128, dtype='int8'), 1593 np.arange(-127, 128, dtype='int8')[:, np.newaxis]], 1594 uint8=[np.arange(0, 128, dtype='uint8'), 1595 np.arange(0, 128, dtype='uint8')[:, np.newaxis]], 1596 uint16=[np.arange(0, 128, dtype='uint16'), 1597 np.arange(0, 128, dtype='uint16')[:, np.newaxis]], 1598 dtype_mixup_1=(rand(2, 3), randint(2, 3)), 1599 dtype_mixup_2=(randint(2, 3), rand(2, 3)), 1600 empty=(np.asarray([], dtype=config.floatX), 1601 np.asarray([1], dtype=config.floatX)), 1602 ) 1603 1604_grad_broadcast_binary_arctan2 = dict( 1605 same_shapes=(rand(2, 3), rand(2, 3)), 1606 scalar=(rand(2, 3), rand(1, 1)), 1607 row=(rand(2, 3), rand(1, 3)), 1608 column=(rand(2, 3), rand(2, 1)), 1609 ) 1610 1611Arctan2Tester = makeBroadcastTester( 1612 op=tensor.arctan2, 1613 expected=upcast_float16_ufunc(np.arctan2), 1614 good=_good_broadcast_binary_arctan2, 1615 grad=_grad_broadcast_binary_arctan2) 1616 1617Arctan2InplaceTester = makeBroadcastTester( 1618 op=inplace.arctan2_inplace, 1619 expected=np.arctan2, 1620 good=copymod(_good_broadcast_binary_arctan2, 1621 without=['integers', 'int8', 'uint8', 1622 'uint16', 'dtype_mixup_2']), 1623 inplace=True) 1624 1625CoshTester = makeBroadcastTester( 1626 op=tensor.cosh, 1627 expected=upcast_float16_ufunc(np.cosh), 1628 good=dict(_good_broadcast_unary_normal, 1629 int8=[np.arange(-89, 90, dtype='int8')], 1630 uint8=[np.arange(0, 90, dtype='uint8')], 1631 uint16=[np.arange(0, 90, dtype='uint16')]), 1632 grad=_grad_broadcast_unary_normal) 1633CoshInplaceTester = makeBroadcastTester( 1634 op=inplace.cosh_inplace, 1635 expected=np.cosh, 1636 good=_good_broadcast_unary_normal_float, 1637 inplace=True) 1638 1639_good_broadcast_unary_arccosh = dict( 1640 normal=(rand_ranged(1, 1000, (2, 3)),), 1641 integers=(randint_ranged(1, 1000, (2, 3)),), 1642 uint8=[np.arange(1, 256, dtype='uint8')], 1643 complex=(randc128_ranged(1, 1000, (2, 3)),), 1644 empty=(np.asarray([], dtype=config.floatX),),) 1645_grad_broadcast_unary_arccosh = dict(normal=(rand_ranged(1 + _eps, 1000, (2, 3)),),) 1646 1647ArccoshTester = makeBroadcastTester( 1648 op=tensor.arccosh, 1649 expected=upcast_float16_ufunc(np.arccosh), 1650 good=_good_broadcast_unary_arccosh, 1651 grad=_grad_broadcast_unary_arccosh) 1652ArccoshInplaceTester = makeBroadcastTester( 1653 op=inplace.arccosh_inplace, 1654 expected=np.arccosh, 1655 good=copymod(_good_broadcast_unary_arccosh, without=['integers', 'uint8']), 1656 inplace=True) 1657 1658SinhTester = makeBroadcastTester( 1659 op=tensor.sinh, 1660 expected=upcast_float16_ufunc(np.sinh), 1661 good=dict(_good_broadcast_unary_normal, 1662 int8=[np.arange(-89, 90, dtype='int8')], 1663 uint8=[np.arange(0, 90, dtype='uint8')], 1664 uint16=[np.arange(0, 90, dtype='uint16')]), 1665 grad=_grad_broadcast_unary_normal) 1666SinhInplaceTester = makeBroadcastTester( 1667 op=inplace.sinh_inplace, 1668 expected=np.sinh, 1669 good=_good_broadcast_unary_normal_float, 1670 inplace=True) 1671 1672ArcsinhTester = makeBroadcastTester( 1673 op=tensor.arcsinh, 1674 expected=upcast_float16_ufunc(np.arcsinh), 1675 good=_good_broadcast_unary_normal, 1676 grad=_grad_broadcast_unary_normal) 1677ArcsinhInplaceTester = makeBroadcastTester( 1678 op=inplace.arcsinh_inplace, 1679 expected=np.arcsinh, 1680 good=_good_broadcast_unary_normal_float, 1681 inplace=True) 1682 1683TanhTester = makeBroadcastTester( 1684 op=tensor.tanh, 1685 expected=upcast_float16_ufunc(np.tanh), 1686 good=_good_broadcast_unary_normal, 1687 grad=_grad_broadcast_unary_normal) 1688TanhInplaceTester = makeBroadcastTester( 1689 op=inplace.tanh_inplace, 1690 expected=np.tanh, 1691 good=_good_broadcast_unary_normal_float, 1692 inplace=True) 1693 1694_good_broadcast_unary_arctanh = dict( 1695 normal=(rand_ranged(-1 + _eps, 1 - _eps, (2, 3)),), 1696 integers=(randint_ranged(-1 + _eps, 1 - _eps, (2, 3)),), 1697 int8=[np.arange(0, 1, dtype='int8')], 1698 uint8=[np.arange(0, 1, dtype='uint8')], 1699 uint16=[np.arange(0, 1, dtype='uint16')], 1700 complex=(randc128_ranged(-1 + _eps, 1 - _eps, (2, 3)),), 1701 empty=(np.asarray([], dtype=config.floatX),),) 1702_grad_broadcast_unary_arctanh = dict( 1703 normal=(rand_ranged(-1 + _eps, 1 - _eps, (2, 3)),),) 1704 1705ArctanhTester = makeBroadcastTester( 1706 op=tensor.arctanh, 1707 expected=upcast_float16_ufunc(np.arctanh), 1708 good=_good_broadcast_unary_arctanh, 1709 grad=_grad_broadcast_unary_arctanh) 1710ArctanhInplaceTester = makeBroadcastTester( 1711 op=inplace.arctanh_inplace, 1712 expected=np.arctanh, 1713 good=copymod(_good_broadcast_unary_arctanh, without=['integers', 'int8', 'uint8', 'uint16']), 1714 inplace=True) 1715 1716 1717# We can't test it if scipy is not installed! 1718# Precomputing the result is brittle(it have been broken!) 1719# As if we do any modification to random number here, 1720# The input random number will change and the output! 1721if imported_scipy_special: 1722 expected_erf = scipy.special.erf 1723 expected_erfc = scipy.special.erfc 1724 expected_erfinv = scipy.special.erfinv 1725 expected_erfcinv = scipy.special.erfcinv 1726 expected_gamma = scipy.special.gamma 1727 expected_gammaln = scipy.special.gammaln 1728 expected_psi = scipy.special.psi 1729 expected_tri_gamma = partial(scipy.special.polygamma, 1) 1730 expected_chi2sf = scipy.stats.chi2.sf 1731 expected_j0 = scipy.special.j0 1732 expected_j1 = scipy.special.j1 1733 expected_jv = scipy.special.jv 1734 expected_i0 = scipy.special.i0 1735 expected_i1 = scipy.special.i1 1736 expected_iv = scipy.special.iv 1737 skip_scipy = False 1738 expected_erfcx = scipy.special.erfcx 1739else: 1740 expected_erf = [] 1741 expected_erfc = [] 1742 expected_erfcx = [] 1743 expected_erfinv = [] 1744 expected_erfcinv = [] 1745 expected_gamma = [] 1746 expected_gammaln = [] 1747 expected_psi = [] 1748 expected_tri_gamma = [] 1749 expected_chi2sf = [] 1750 expected_j0 = [] 1751 expected_j1 = [] 1752 expected_jv = [] 1753 expected_i0 = [] 1754 expected_i1 = [] 1755 expected_iv = [] 1756 skip_scipy = "scipy is not present" 1757 1758ErfTester = makeBroadcastTester( 1759 op=tensor.erf, 1760 expected=expected_erf, 1761 good=_good_broadcast_unary_normal, 1762 grad=_grad_broadcast_unary_normal, 1763 eps=2e-10, 1764 mode=mode_no_scipy, 1765 skip=skip_scipy) 1766ErfInplaceTester = makeBroadcastTester( 1767 op=inplace.erf_inplace, 1768 expected=expected_erf, 1769 good=_good_broadcast_unary_normal_float, 1770 mode=mode_no_scipy, 1771 eps=2e-10, 1772 inplace=True, 1773 skip=skip_scipy) 1774 1775ErfcTester = makeBroadcastTester( 1776 op=tensor.erfc, 1777 expected=expected_erfc, 1778 good=_good_broadcast_unary_normal_float_no_complex, 1779 grad=_grad_broadcast_unary_normal, 1780 eps=2e-10, 1781 mode=mode_no_scipy, 1782 skip=skip_scipy) 1783ErfcInplaceTester = makeBroadcastTester( 1784 op=inplace.erfc_inplace, 1785 expected=expected_erfc, 1786 good=_good_broadcast_unary_normal_float_no_complex, 1787 eps=2e-10, 1788 mode=mode_no_scipy, 1789 inplace=True, 1790 skip=skip_scipy) 1791 1792ErfcxTester = makeBroadcastTester( 1793 op=tensor.erfcx, 1794 expected=expected_erfcx, 1795 good=_good_broadcast_unary_normal_float_no_complex_small_neg_range, 1796 grad=_grad_broadcast_unary_normal_small_neg_range, 1797 eps=2e-10, 1798 mode=mode_no_scipy, 1799 skip=skip_scipy) 1800ErfcxInplaceTester = makeBroadcastTester( 1801 op=inplace.erfcx_inplace, 1802 expected=expected_erfcx, 1803 good=_good_broadcast_unary_normal_float_no_complex_small_neg_range, 1804 eps=2e-10, 1805 mode=mode_no_scipy, 1806 inplace=True, 1807 skip=skip_scipy) 1808 1809ErfinvTester = makeBroadcastTester( 1810 op=tensor.erfinv, 1811 expected=expected_erfinv, 1812 good={'normal': [rand_ranged(-.9, .9, (2, 3))], 1813 'empty': [np.asarray([], dtype=config.floatX)]}, 1814 grad=_grad_broadcast_unary_abs1_no_complex, 1815 eps=2e-10, 1816 mode=mode_no_scipy, 1817 skip=skip_scipy) 1818 1819ErfcinvTester = makeBroadcastTester( 1820 op=tensor.erfcinv, 1821 expected=expected_erfcinv, 1822 good={'normal': [rand_ranged(0.001, 1.9, (2, 3))], 1823 'empty': [np.asarray([], dtype=config.floatX)]}, 1824 grad=_grad_broadcast_unary_0_2_no_complex, 1825 eps=2e-10, 1826 mode=mode_no_scipy, 1827 skip=skip_scipy) 1828 1829_good_broadcast_unary_gammaln = dict( 1830 normal=(rand_ranged(-1 + 1e-2, 10, (2, 3)),), 1831 empty=(np.asarray([], dtype=config.floatX),), 1832 int=(randint_ranged(1, 10, (2, 3)),), 1833 uint8=(randint_ranged(1, 6, (2, 3)).astype('uint8'),), 1834 uint16=(randint_ranged(1, 10, (2, 3)).astype('uint16'),), 1835 uint64=(randint_ranged(1, 10, (2, 3)).astype('uint64'),)) 1836_grad_broadcast_unary_gammaln = dict( 1837 # smaller range as our grad method does not estimate it well enough. 1838 normal=(rand_ranged(1e-1, 8, (2, 3)),),) 1839 1840GammaTester = makeBroadcastTester( 1841 op=tensor.gamma, 1842 expected=expected_gamma, 1843 good=_good_broadcast_unary_gammaln, 1844 grad=_grad_broadcast_unary_gammaln, 1845 mode=mode_no_scipy, 1846 eps=1e-5, 1847 skip=skip_scipy) 1848GammaInplaceTester = makeBroadcastTester( 1849 op=inplace.gamma_inplace, 1850 expected=expected_gamma, 1851 good=_good_broadcast_unary_gammaln, 1852 mode=mode_no_scipy, 1853 eps=1e-5, 1854 inplace=True, 1855 skip=skip_scipy) 1856 1857GammalnTester = makeBroadcastTester( 1858 op=tensor.gammaln, 1859 expected=expected_gammaln, 1860 good=_good_broadcast_unary_gammaln, 1861 grad=_grad_broadcast_unary_gammaln, 1862 eps=2e-10, 1863 mode=mode_no_scipy, 1864 skip=skip_scipy) 1865GammalnInplaceTester = makeBroadcastTester( 1866 op=inplace.gammaln_inplace, 1867 expected=expected_gammaln, 1868 good=_good_broadcast_unary_gammaln, 1869 eps=2e-10, 1870 mode=mode_no_scipy, 1871 inplace=True, 1872 skip=skip_scipy) 1873 1874_good_broadcast_unary_psi = dict( 1875 normal=(rand_ranged(1, 10, (2, 3)),), 1876 empty=(np.asarray([], dtype=config.floatX),), 1877 int=(randint_ranged(1, 10, (2, 3)),), 1878 uint8=(randint_ranged(1, 10, (2, 3)).astype('uint8'),), 1879 uint16=(randint_ranged(1, 10, (2, 3)).astype('uint16'),)) 1880 1881PsiTester = makeBroadcastTester( 1882 op=tensor.psi, 1883 expected=expected_psi, 1884 good=_good_broadcast_unary_psi, 1885 eps=2e-10, 1886 mode=mode_no_scipy, 1887 skip=skip_scipy) 1888PsiInplaceTester = makeBroadcastTester( 1889 op=inplace.psi_inplace, 1890 expected=expected_psi, 1891 good=_good_broadcast_unary_psi, 1892 eps=2e-10, 1893 mode=mode_no_scipy, 1894 inplace=True, 1895 skip=skip_scipy) 1896 1897_good_broadcast_unary_tri_gamma = _good_broadcast_unary_psi 1898 1899TriGammaTester = makeBroadcastTester( 1900 op=tensor.tri_gamma, 1901 expected=expected_tri_gamma, 1902 good=_good_broadcast_unary_psi, 1903 eps=2e-8, 1904 mode=mode_no_scipy, 1905 skip=skip_scipy) 1906TriGammaInplaceTester = makeBroadcastTester( 1907 op=inplace.tri_gamma_inplace, 1908 expected=expected_tri_gamma, 1909 good=_good_broadcast_unary_tri_gamma, 1910 eps=2e-8, 1911 mode=mode_no_scipy, 1912 inplace=True, 1913 skip=skip_scipy) 1914 1915# chi2sf takes two inputs, a value (x) and a degrees of freedom (k). 1916# not sure how to deal with that here... 1917 1918_good_broadcast_unary_chi2sf = dict( 1919 normal=(rand_ranged(1, 10, (2, 3)), 1920 np.asarray(1, dtype=config.floatX)), 1921 empty=(np.asarray([], dtype=config.floatX), 1922 np.asarray(1, dtype=config.floatX)), 1923 integers=(randint_ranged(1, 10, (2, 3)), 1924 np.asarray(1, dtype=config.floatX)), 1925 uint8=(randint_ranged(1, 10, (2, 3)).astype('uint8'), 1926 np.asarray(1, dtype=config.floatX)), 1927 uint16=(randint_ranged(1, 10, (2, 3)).astype('uint16'), 1928 np.asarray(1, dtype=config.floatX))) 1929 1930Chi2SFTester = makeBroadcastTester( 1931 op=tensor.chi2sf, 1932 expected=expected_chi2sf, 1933 good=_good_broadcast_unary_chi2sf, 1934 eps=2e-10, 1935 mode=mode_no_scipy, 1936 skip=skip_scipy, 1937 name='Chi2SF') 1938 1939Chi2SFInplaceTester = makeBroadcastTester( 1940 op=inplace.chi2sf_inplace, 1941 expected=expected_chi2sf, 1942 good=_good_broadcast_unary_chi2sf, 1943 eps=2e-10, 1944 mode=mode_no_scipy, 1945 inplace=True, 1946 skip=skip_scipy, 1947 name='Chi2SF') 1948 1949_good_broadcast_unary_bessel = dict( 1950 normal=(rand_ranged(-10, 10, (2, 3)),), 1951 empty=(np.asarray([], dtype=config.floatX),), 1952 int=(randint_ranged(-10, 10, (2, 3)),), 1953 uint8=(randint_ranged(0, 10, (2, 3)).astype('uint8'),), 1954 uint16=(randint_ranged(0, 10, (2, 3)).astype('uint16'),)) 1955 1956_grad_broadcast_unary_bessel = dict( 1957 normal=(rand_ranged(-10., 10., (2, 3)),),) 1958 1959_good_broadcast_binary_bessel = dict( 1960 normal=(rand_ranged(-5, 5, (2, 3)), 1961 rand_ranged(0, 10, (2, 3))), 1962 empty=(np.asarray([], dtype=config.floatX), 1963 np.asarray([], dtype=config.floatX)), 1964 integers=(randint_ranged(-5, 5, (2, 3)), 1965 randint_ranged(-10, 10, (2, 3))), 1966 uint8=(randint_ranged(0, 5, (2, 3)).astype('uint8'), 1967 randint_ranged(0, 10, (2, 3)).astype('uint8')), 1968 uint16=(randint_ranged(0, 5, (2, 3)).astype('uint16'), 1969 randint_ranged(0, 10, (2, 3)).astype('uint16'))) 1970 1971_grad_broadcast_binary_bessel = dict( 1972 normal=(rand_ranged(1, 5, (2, 3)), 1973 rand_ranged(0, 10, (2, 3)))) 1974 1975J0Tester = makeBroadcastTester( 1976 op=tensor.j0, 1977 expected=expected_j0, 1978 good=_good_broadcast_unary_bessel, 1979 grad=_grad_broadcast_unary_bessel, 1980 eps=2e-10, 1981 mode=mode_no_scipy, 1982 skip=skip_scipy) 1983 1984J0InplaceTester = makeBroadcastTester( 1985 op=inplace.j0_inplace, 1986 expected=expected_j0, 1987 good=_good_broadcast_unary_bessel, 1988 eps=2e-10, 1989 mode=mode_no_scipy, 1990 inplace=True, 1991 skip=skip_scipy) 1992 1993J1Tester = makeBroadcastTester( 1994 op=tensor.j1, 1995 expected=expected_j1, 1996 good=_good_broadcast_unary_bessel, 1997 grad=_grad_broadcast_unary_bessel, 1998 eps=2e-10, 1999 mode=mode_no_scipy, 2000 skip=skip_scipy) 2001 2002J1InplaceTester = makeBroadcastTester( 2003 op=inplace.j1_inplace, 2004 expected=expected_j1, 2005 good=_good_broadcast_unary_bessel, 2006 eps=2e-10, 2007 mode=mode_no_scipy, 2008 inplace=True, 2009 skip=skip_scipy) 2010 2011JvTester = makeBroadcastTester( 2012 op=tensor.jv, 2013 expected=expected_jv, 2014 good=_good_broadcast_binary_bessel, 2015 eps=2e-10, 2016 mode=mode_no_scipy, 2017 skip=skip_scipy) 2018 2019JvInplaceTester = makeBroadcastTester( 2020 op=inplace.jv_inplace, 2021 expected=expected_jv, 2022 good=_good_broadcast_binary_bessel, 2023 eps=2e-10, 2024 mode=mode_no_scipy, 2025 inplace=True, 2026 skip=skip_scipy) 2027 2028 2029def test_verify_jv_grad(): 2030 # Verify Jv gradient. 2031 # Implemented separately due to need to fix first input for which grad is 2032 # not defined. 2033 if skip_scipy: 2034 raise SkipTest("SciPy needed") 2035 v_val, x_val = _grad_broadcast_binary_bessel['normal'] 2036 2037 def fixed_first_input_jv(x): 2038 return tensor.jv(v_val, x) 2039 2040 utt.verify_grad(fixed_first_input_jv, [x_val]) 2041 2042 2043I0Tester = makeBroadcastTester( 2044 op=tensor.i0, 2045 expected=expected_i0, 2046 good=_good_broadcast_unary_bessel, 2047 grad=_grad_broadcast_unary_bessel, 2048 eps=2e-10, 2049 mode=mode_no_scipy, 2050 skip=skip_scipy) 2051 2052I0InplaceTester = makeBroadcastTester( 2053 op=inplace.i0_inplace, 2054 expected=expected_i0, 2055 good=_good_broadcast_unary_bessel, 2056 eps=2e-10, 2057 mode=mode_no_scipy, 2058 inplace=True, 2059 skip=skip_scipy) 2060 2061I1Tester = makeBroadcastTester( 2062 op=tensor.i1, 2063 expected=expected_i1, 2064 good=_good_broadcast_unary_bessel, 2065 grad=_grad_broadcast_unary_bessel, 2066 eps=2e-10, 2067 mode=mode_no_scipy, 2068 skip=skip_scipy) 2069 2070I1InplaceTester = makeBroadcastTester( 2071 op=inplace.i1_inplace, 2072 expected=expected_i1, 2073 good=_good_broadcast_unary_bessel, 2074 eps=2e-10, 2075 mode=mode_no_scipy, 2076 inplace=True, 2077 skip=skip_scipy) 2078 2079IvTester = makeBroadcastTester( 2080 op=tensor.iv, 2081 expected=expected_iv, 2082 good=_good_broadcast_binary_bessel, 2083 eps=2e-10, 2084 mode=mode_no_scipy, 2085 skip=skip_scipy) 2086 2087IvInplaceTester = makeBroadcastTester( 2088 op=inplace.iv_inplace, 2089 expected=expected_iv, 2090 good=_good_broadcast_binary_bessel, 2091 eps=2e-10, 2092 mode=mode_no_scipy, 2093 inplace=True, 2094 skip=skip_scipy) 2095 2096 2097def test_verify_iv_grad(): 2098 # Verify Iv gradient. 2099 # Implemented separately due to need to fix first input for which grad is 2100 # not defined. 2101 if skip_scipy: 2102 raise SkipTest("SciPy needed") 2103 2104 v_val, x_val = _grad_broadcast_binary_bessel['normal'] 2105 2106 def fixed_first_input_iv(x): 2107 return tensor.iv(v_val, x) 2108 2109 utt.verify_grad(fixed_first_input_iv, [x_val]) 2110 2111 2112ZerosLikeTester = makeBroadcastTester( 2113 op=tensor.zeros_like, 2114 expected=np.zeros_like, 2115 good=_good_broadcast_unary_normal, 2116 grad=_grad_broadcast_unary_normal, 2117 name='ZerosLike') 2118 2119OnesLikeTester = makeBroadcastTester( 2120 op=tensor.ones_like, 2121 expected=np.ones_like, 2122 good=_good_broadcast_unary_normal, 2123 grad=_grad_broadcast_unary_normal, 2124 name='OnesLike') 2125 2126# Complex operations 2127_good_complex_from_polar = dict( 2128 same_shapes=(abs(rand(2, 3)), rand(2, 3)), 2129 not_same_dimensions=(abs(rand(2, 2)), rand(2)), 2130 scalar=(abs(rand(2, 3)), rand(1, 1)), 2131 row=(abs(rand(2, 3)), rand(1, 3)), 2132 column=(abs(rand(2, 3)), rand(2, 1)), 2133 integers=(abs(randint(2, 3)), randint(2, 3)), 2134 empty=(np.asarray([], dtype=config.floatX), 2135 np.asarray([1], dtype=config.floatX)),) 2136_grad_complex_from_polar = dict( 2137 same_shapes=(abs(rand(2, 3)), rand(2, 3)), 2138 scalar=(abs(rand(2, 3)), rand(1, 1)), 2139 row=(abs(rand(2, 3)), rand(1, 3)), 2140 column=(abs(rand(2, 3)), rand(2, 1))) 2141 2142ComplexFromPolarTester = makeBroadcastTester( 2143 op=tensor.complex_from_polar, 2144 expected=lambda r, theta: r * np.cos(theta) + 1j * r * np.sin(theta), 2145 good=_good_complex_from_polar) 2146 2147ConjTester = makeBroadcastTester( 2148 op=tensor.conj, 2149 expected=np.conj, 2150 good=_good_broadcast_unary_normal) 2151ConjInplaceTester = makeBroadcastTester( 2152 op=inplace.conj_inplace, 2153 expected=np.conj, 2154 good=_good_broadcast_unary_normal, 2155 inplace=True) 2156 2157 2158DotTester = makeTester( 2159 name='DotTester', 2160 op=dot, 2161 expected=lambda x, y: np.dot(x, y), 2162 checks={}, 2163 good=dict(correct1=(rand(5, 7), rand(7, 5)), 2164 correct2=(rand(5, 7), rand(7, 9)), 2165 correct3=(rand(5, 7), rand(7)), 2166 correct4=(rand(5), rand(5, 7)), 2167 mixed1=(rand(5).astype('float32'), rand(5, 7)), 2168 mixed2=(rand(5).astype('float64'), rand(5, 7)), 2169 complex1=(randcomplex(5, 7), randcomplex(7)), 2170 complex2=(rand(5, 7), randcomplex(7)), 2171 complex3=(randcomplex(5, 7), rand(7)), 2172 empty1=(np.asarray([], dtype=config.floatX), 2173 np.asarray([], dtype=config.floatX)), 2174 empty2=(rand(5, 0), rand(0, 2)), 2175 empty3=(rand(0, 5), rand(5, 0)), 2176 ), 2177 bad_build=dict(), 2178 bad_runtime=dict(bad1=(rand(5, 7), rand(5, 7)), 2179 bad2=(rand(5, 7), rand(8, 3)))) 2180 2181BatchedDotTester = makeTester( 2182 name='BatchedDotTester', 2183 op=batched_dot, 2184 expected=(lambda xs, ys: 2185 np.asarray( 2186 list(x * y if x.ndim == 0 or y.ndim == 0 else np.dot(x, y) 2187 for x, y in zip(xs, ys)), 2188 dtype=theano.scalar.upcast(xs.dtype, ys.dtype))), 2189 checks={}, 2190 grad=dict(correct1=(rand(3, 5, 7), rand(3, 7, 5)), 2191 correct2=(rand(3, 5, 7), rand(3, 7, 9)), 2192 correct3=(rand(3, 5, 7), rand(3, 7)), 2193 correct4=(rand(3, 5), rand(3, 5, 7)), 2194 correct5=(rand(3), rand(3, 5, 7)), 2195 correct6=(rand(3, 5), rand(3)), 2196 correct7=(rand(3, 5), rand(3, 5)), 2197 correct8=(rand(3), rand(3)), 2198 correct9=(rand(3, 5, 7, 11), rand(3)), 2199 correct10=(rand(3, 2, 6, 5), rand(3, 5)), 2200 correct11=(rand(3, 2, 6, 5), rand(3, 5, 7)), 2201 correct12=(rand(3, 2, 6, 5), rand(3, 7, 5, 8)), 2202 mixed1=(rand(3, 5).astype('float32'), 2203 rand(3, 5, 7)), 2204 mixed2=(rand(3, 5).astype('float64'), 2205 rand(3, 5, 7))), 2206 good=dict(correct1=(rand(3, 5, 7), rand(3, 7, 5)), 2207 correct2=(rand(3, 5, 7), rand(3, 7, 9)), 2208 correct3=(rand(3, 5, 7), rand(3, 7)), 2209 correct4=(rand(3, 5), rand(3, 5, 7)), 2210 correct5=(rand(3), rand(3, 5, 7)), 2211 correct6=(rand(3, 5), rand(3)), 2212 correct7=(rand(3, 5), rand(3, 5)), 2213 correct8=(rand(3), rand(3)), 2214 correct9=(rand(3, 5, 7, 11), rand(3)), 2215 correct10=(rand(3, 7, 11, 5), rand(3, 5)), 2216 correct11=(rand(3, 7, 11, 5), rand(3, 5, 13)), 2217 correct12=(rand(3, 7, 11, 5), rand(3, 13, 5, 17)), 2218 mixed1=(rand(3, 5).astype('float32'), 2219 rand(3, 5, 7)), 2220 mixed2=(rand(3, 5).astype('float64'), 2221 rand(3, 5, 7))), 2222 bad_build=dict(no_batch_axis2=(rand(), rand(3, 5)), 2223 no_batch_axis3=(rand(3, 5), rand())), 2224 bad_runtime=dict(batch_dim_mismatch1=(rand(2, 5, 7), rand(3, 7, 9)), 2225 batch_dim_mismatch2=(rand(3, 5, 7), rand(2, 7, 9)), 2226 batch_dim_mismatch3=(rand(3), rand(5)), 2227 bad_dim1=(rand(3, 5, 7), rand(3, 5, 7)), 2228 bad_dim2=(rand(3, 5, 7), rand(3, 8, 3)), 2229 bad_dim3=(rand(3, 5), rand(3, 7)), 2230 bad_dim4=(rand(3, 5, 7, 11), rand(3, 5)), 2231 bad_dim5=(rand(3, 5, 7, 11), rand(3, 5, 13)), 2232 bad_dim6=(rand(3, 5, 7, 11), rand(3, 13, 5, 17)))) 2233 2234 2235def _numpy_second(x, y): 2236 return np.broadcast_arrays(x, y)[1] 2237 2238# Don't forget to modify the two lines after! 2239ALL_DTYPES = ('int8', 'int16', 'int32', 'int64', 'float32', 'float64', 2240 'uint8', 'uint16', 2241 'complex64', 'complex128') 2242REAL_DTYPES = ALL_DTYPES[:6] 2243COMPLEX_DTYPES = ALL_DTYPES[-2:] 2244 2245 2246def multi_dtype_checks(shape1, shape2, dtypes=ALL_DTYPES, nameprefix=''): 2247 for dtype1, dtype2 in itertools.combinations(dtypes, 2): 2248 name1 = '%s_%s_%s' % (nameprefix, dtype1, dtype2) 2249 name2 = '%s_%s_%s' % (nameprefix, dtype2, dtype1) 2250 obj1 = rand_of_dtype(shape1, dtype1) 2251 obj2 = rand_of_dtype(shape2, dtype2) 2252 yield (name1, (obj1, obj2)) 2253 yield (name2, (obj2, obj1)) 2254 2255 2256def multi_dtype_cast_checks(shape, dtypes=ALL_DTYPES, nameprefix=''): 2257 for dtype1, dtype2 in itertools.combinations(dtypes, 2): 2258 name1 = '%s_%s_%s' % (nameprefix, dtype1, dtype2) 2259 name2 = '%s_%s_%s' % (nameprefix, dtype2, dtype1) 2260 obj1 = rand_of_dtype(shape, dtype1) 2261 obj2 = rand_of_dtype(shape, dtype2) 2262 yield (name1, (obj1, dtype2)) 2263 yield (name2, (obj2, dtype1)) 2264 2265SecondBroadcastTester = makeTester( 2266 name='SecondBroadcastTester', 2267 op=second, 2268 expected=_numpy_second, 2269 good=dict(itertools.chain( 2270 multi_dtype_checks((4, 5), (5,)), 2271 multi_dtype_checks((2, 3, 2), (3, 2)), 2272 multi_dtype_checks((2, 3, 2), (2,)), 2273 )), 2274 # I can't think of any way to make this fail at build time 2275 # Just some simple smoke tests 2276 bad_runtime=dict( 2277 fail1=(rand(5, 4), rand(5)), 2278 fail2=(rand(3, 2, 3), rand(6, 9)), 2279 fail3=(randint(6, 2, 9), rand(3, 2)), 2280 ) 2281 ) 2282 2283# We exclude local_fill_to_alloc because it optimizes the "second" node 2284# away from the graph. 2285SecondSameRankTester = makeTester( 2286 name='SecondSameRankTester', 2287 op=second, 2288 expected=_numpy_second, 2289 good=dict(itertools.chain( 2290 multi_dtype_checks((4, 5), (4, 5)), 2291 multi_dtype_checks((1, 2), (3, 2)), 2292 multi_dtype_checks((3, 2), (1, 2)), 2293 )), 2294 # These sizes are not broadcastable to one another 2295 # and SHOULD raise an error, but currently don't. 2296 bad_runtime=dict(itertools.chain( 2297 multi_dtype_checks((4, 5), (5, 4)), 2298 multi_dtype_checks((1, 5), (5, 4)), 2299 )), 2300 mode=get_default_mode().excluding( 2301 'local_fill_to_alloc', 2302 'local_useless_fill') 2303 ) 2304 2305# Alloc 2306AllocTester = makeBroadcastTester( 2307 name='AllocTester', 2308 op=alloc, 2309 expected=(lambda x, *shp: np.zeros(shp, dtype=x.dtype) + x), 2310 good=dict( 2311 correct01=(rand(), np.int32(7)), 2312 correct01_bcast=(rand(1), np.int32(7)), 2313 correct02=(rand(), np.int32(4), np.int32(7)), 2314 correct12=(rand(7), np.int32(4), np.int32(7)), 2315 correct13=(rand(7), np.int32(2), np.int32(4), np.int32(7)), 2316 correct23=(rand(4, 7), np.int32(2), np.int32(4), np.int32(7)), 2317 correctb1=(rand(1, 7), np.int32(4), np.int32(7)), 2318 correctb2=(rand(1, 7), np.int32(2), np.int32(4), np.int32(7)), 2319 correctb3=(rand(7, 1), np.int32(7), np.int32(4)), 2320 correctb4=(rand(7, 1), np.int32(2), np.int32(7), np.int32(4)), 2321 ), 2322 bad_runtime=dict( 2323 bad_shape12=(rand(7), np.int32(7), np.int32(5)), 2324 ), 2325 bad_build=dict( 2326 vec=(rand(1), [np.int32(2)]), 2327 too_big32=(rand(6, 2, 4), np.int32(6), np.int32(2)), 2328 too_big32b=(rand(6, 2, 4), np.int32(6), np.int32(4)), 2329 too_big32c=(rand(6, 2, 4), np.int32(2), np.int32(4)), 2330 too_big32d=(rand(6, 2, 4), np.int32(2), np.int32(6)), 2331 too_big32e=(rand(6, 2, 4), np.int32(4), np.int32(6)), 2332 too_big32f=(rand(6, 2, 4), np.int32(4), np.int32(2)), 2333 ), 2334 ) 2335 2336# Since not all inputs of Alloc are differentiable, we need different testers 2337s1, s2, s3 = randint_ranged(1, 13, (3,)) 2338# alloc a scalar into a vector 2339Alloc01GradTester = makeBroadcastTester( 2340 name='Alloc01GradTester', 2341 op=(lambda x: alloc(x, s1)), 2342 expected=(lambda x: np.zeros((s1,), dtype=x.dtype) + x), 2343 grad=dict( 2344 x1=(rand(),), 2345 x2=(rand(),), 2346 x3=(rand(),), 2347 ), 2348 ) 2349 2350# alloc a vector into a tensor3 2351Alloc13GradTester = makeBroadcastTester( 2352 name='Alloc13GradTester', 2353 op=(lambda x: alloc(x, s1, s2, s3)), 2354 expected=(lambda x: np.zeros((s1, s2, s3), dtype=x.dtype) + x), 2355 grad=dict( 2356 x1=(rand(s3),), 2357 x2=(rand(s3),), 2358 x3=(rand(s3),), 2359 ), 2360 ) 2361 2362# unbroadcast a row to a matrix 2363Allocb1GradTester = makeBroadcastTester( 2364 name='Allocb1GradTester', 2365 op=lambda x: alloc(x, s1, s2), 2366 expected=(lambda x: np.zeros((s1, s2), dtype=x.dtype) + x), 2367 grad=dict( 2368 x1=(rand(1, s2),), 2369 x2=(rand(1, s2),), 2370 x3=(rand(1, s2),), 2371 ), 2372) 2373 2374# unbroadcast a row to a tensor3 2375Allocb2GradTester = makeBroadcastTester( 2376 name='Allocb2GradTester', 2377 op=lambda x: alloc(x, s1, s2, s3), 2378 expected=(lambda x: np.zeros((s1, s2, s3), dtype=x.dtype) + x), 2379 grad=dict( 2380 x1=(rand(1, s3),), 2381 x2=(rand(1, s3),), 2382 x3=(rand(1, s3),), 2383 ), 2384) 2385 2386# unbroadcast a col to a matrix 2387Allocb3GradTester = makeBroadcastTester( 2388 name='Allocb3GradTester', 2389 op=lambda x: alloc(x, s1, s2), 2390 expected=(lambda x: np.zeros((s1, s2), dtype=x.dtype) + x), 2391 grad=dict( 2392 x1=(rand(s1, 1),), 2393 x2=(rand(s1, 1),), 2394 x3=(rand(s1, 1),), 2395 ), 2396) 2397 2398# unbroadcast a col to a tensor3 2399Allocb4GradTester = makeBroadcastTester( 2400 name='Allocb4GradTester', 2401 op=lambda x: alloc(x, s1, s2, s3), 2402 expected=(lambda x: np.zeros((s1, s2, s3), dtype=x.dtype) + x), 2403 grad=dict( 2404 x1=(rand(s2, 1),), 2405 x2=(rand(s2, 1),), 2406 x3=(rand(s2, 1),), 2407 ), 2408) 2409 2410 2411# Partial un broadcast of a dimshuffled input 2412AllocDimshuffleGradTester = makeBroadcastTester( 2413 name='Allocb4GradTester', 2414 op=lambda x: alloc(x.dimshuffle('x', 'x', 0), 1, s2, s3), 2415 expected=(lambda x: np.zeros((1, s2, s3), dtype=x.dtype) + x), 2416 grad=dict( 2417 x1=(rand(s3),), 2418 x2=(rand(s3),), 2419 x3=(rand(s3),), 2420 ), 2421) 2422AllocDimshuffleGradTester2 = makeBroadcastTester( 2423 name='Allocb4GradTester', 2424 op=lambda x: alloc(x.dimshuffle('x', 0), 1, s2, s3), 2425 expected=(lambda x: np.zeros((1, s2, s3), dtype=x.dtype) + x), 2426 grad=dict( 2427 x1=(rand(s3),), 2428 x2=(rand(s3),), 2429 x3=(rand(s3),), 2430 ), 2431) 2432 2433 2434class ApplyDefaultTestOp(theano.Op): 2435 def __init__(self, id): 2436 self.default_output = id 2437 2438 def make_node(self, x): 2439 x = theano.tensor.as_tensor_variable(x) 2440 return theano.Apply(self, [x], [x.type()]) 2441 2442 2443class TestAsTensorVariable(unittest.TestCase): 2444 # Unit test for ensuring that as_tensor_variable handles Apply objects 2445 # correctly and removes leading broadcastable dimensions when possible. 2446 def setUp(self): 2447 self.x = tensor.scalar('x') 2448 2449 def test_one_output(self): 2450 good_apply_var = ApplyDefaultTestOp(0).make_node(self.x) 2451 as_tensor_variable(good_apply_var) 2452 2453 def test_below_zero_output(self): 2454 bad_apply_var = ApplyDefaultTestOp(-1).make_node(self.x) 2455 self.assertRaises(AttributeError, as_tensor_variable, bad_apply_var) 2456 2457 def test_above_output_len(self): 2458 bad_apply_var = ApplyDefaultTestOp(2).make_node(self.x) 2459 self.assertRaises(AttributeError, as_tensor_variable, bad_apply_var) 2460 2461 def test_list(self): 2462 bad_apply_var = ApplyDefaultTestOp([0, 1]).make_node(self.x) 2463 self.assertRaises(AttributeError, as_tensor_variable, bad_apply_var) 2464 2465 def test_strip_leading_broadcastable(self): 2466 x = tensor.TensorType(config.floatX, (True, False))('x') 2467 x = as_tensor_variable(x, ndim=1) 2468 assert(x.ndim == 1) 2469 2470 x = tensor.matrix('x', dtype=config.floatX) 2471 self.assertRaises(ValueError, as_tensor_variable, x, ndim=1) 2472 2473 2474class TestAlloc(unittest.TestCase): 2475 dtype = config.floatX 2476 mode = mode_opt 2477 shared = staticmethod(theano.shared) 2478 allocs = [tensor.Alloc()] * 3 2479 2480 def setUp(self): 2481 self.rng = np.random.RandomState(seed=utt.fetch_seed()) 2482 2483 def test_alloc_constant_folding(self): 2484 test_params = np.asarray(self.rng.randn(50 * 60), 2485 self.dtype) 2486 2487 some_vector = vector('some_vector', dtype=self.dtype) 2488 some_matrix = some_vector.reshape((60, 50)) 2489 variables = self.shared(np.ones((50,), dtype=self.dtype)) 2490 idx = tensor.constant(np.arange(50)) 2491 2492 for alloc_, (subtensor, n_alloc) in zip(self.allocs, [ 2493 # IncSubtensor1 2494 (some_matrix[:60], 2), 2495 # AdvancedIncSubtensor1 2496 (some_matrix[arange(60)], 2), 2497 # AdvancedIncSubtensor 2498 (some_matrix[idx, idx], 1) 2499 ]): 2500 derp = sum(dot(subtensor, variables)) 2501 2502 fobj = theano.function([some_vector], derp, mode=self.mode) 2503 grad_derp = theano.grad(derp, some_vector) 2504 fgrad = theano.function([some_vector], grad_derp, 2505 mode=self.mode) 2506 2507 topo_obj = fobj.maker.fgraph.toposort() 2508 assert np.sum([isinstance(node.op, type(alloc_)) 2509 for node in topo_obj]) == 0 2510 2511 topo_grad = fgrad.maker.fgraph.toposort() 2512 assert np.sum([isinstance(node.op, type(alloc_)) 2513 for node in topo_grad]) == n_alloc, ( 2514 alloc_, subtensor, n_alloc, topo_grad) 2515 fobj(test_params) 2516 fgrad(test_params) 2517 2518 def test_alloc_output(self): 2519 val = tensor.constant(self.rng.randn(1, 1), dtype=self.dtype) 2520 for alloc_ in self.allocs: 2521 # The output is the result of the alloc operation, 2522 # we do not want it to be constant-folded 2523 out = alloc_(val, 50, 60) 2524 2525 f = theano.function([], out, mode=self.mode) 2526 topo = f.maker.fgraph.toposort() 2527 assert np.sum([isinstance(node.op, type(alloc_)) 2528 for node in topo]) == 1 2529 assert not isinstance(topo[0].op, DeepCopyOp) 2530 2531 def test_ones(self): 2532 for shp in [[], 1, [1], [1, 2], [1, 2, 3]]: 2533 ones = theano.function([], [tensor.ones(shp)], mode=self.mode) 2534 assert np.allclose(ones(), np.ones(shp)) 2535 2536 # scalar doesn't have to be provided as input 2537 x = scalar() 2538 shp = [] 2539 ones_scalar = theano.function([], [tensor.ones(x.shape)], 2540 mode=self.mode) 2541 assert np.allclose(ones_scalar(), np.ones(shp)) 2542 2543 for (typ, shp) in [(vector, [3]), (matrix, [3, 4])]: 2544 x = typ() 2545 ones_tensor = theano.function([x], [tensor.ones(x.shape)], 2546 mode=self.mode) 2547 inp = np.zeros(shp, dtype=config.floatX) 2548 assert np.allclose(ones_tensor(inp), 2549 np.ones(shp)) 2550 2551 def test_zeros(self): 2552 for shp in [[], 1, [1], [1, 2], [1, 2, 3]]: 2553 zeros = theano.function([], [tensor.zeros(shp)], 2554 mode=self.mode) 2555 assert np.allclose(zeros(), np.zeros(shp)) 2556 2557 # scalar doesn't have to be provided as input 2558 x = scalar() 2559 shp = [] 2560 zeros_scalar = theano.function([], [tensor.zeros(x.shape)], 2561 mode=self.mode) 2562 assert np.allclose(zeros_scalar(), np.zeros(shp)) 2563 2564 for (typ, shp) in [(vector, [3]), (matrix, [3, 4])]: 2565 x = typ() 2566 zeros_tensor = theano.function([x], [tensor.zeros(x.shape)], 2567 mode=self.mode) 2568 inp = np.zeros(shp, dtype=config.floatX) 2569 assert np.allclose(zeros_tensor(inp), 2570 np.zeros(shp)) 2571 2572 2573# This is slow for the ('int8', 3) version. 2574def test_eye(): 2575 def check(dtype, N, M_=None, k=0): 2576 # Theano does not accept None as a tensor. 2577 # So we must use a real value. 2578 M = M_ 2579 # Currently DebugMode does not support None as inputs even if this is 2580 # allowed. 2581 if M is None and theano.config.mode in ['DebugMode', 'DEBUG_MODE']: 2582 M = N 2583 N_symb = tensor.iscalar() 2584 M_symb = tensor.iscalar() 2585 k_symb = tensor.iscalar() 2586 f = function([N_symb, M_symb, k_symb], 2587 eye(N_symb, M_symb, k_symb, dtype=dtype)) 2588 result = f(N, M, k) 2589 assert np.allclose(result, np.eye(N, M_, k, dtype=dtype)) 2590 assert result.dtype == np.dtype(dtype) 2591 for dtype in ALL_DTYPES: 2592 yield check, dtype, 3 2593 # M != N, k = 0 2594 yield check, dtype, 3, 5 2595 yield check, dtype, 5, 3 2596 # N == M, k != 0 2597 yield check, dtype, 3, 3, 1 2598 yield check, dtype, 3, 3, -1 2599 # N < M, k != 0 2600 yield check, dtype, 3, 5, 1 2601 yield check, dtype, 3, 5, -1 2602 # N > M, k != 0 2603 yield check, dtype, 5, 3, 1 2604 yield check, dtype, 5, 3, -1 2605 2606 2607class test_triangle(unittest.TestCase): 2608 def test_tri(self): 2609 def check(dtype, N, M_=None, k=0): 2610 # Theano does not accept None as a tensor. 2611 # So we must use a real value. 2612 M = M_ 2613 # Currently DebugMode does not support None as inputs even if this is 2614 # allowed. 2615 if M is None and theano.config.mode in ['DebugMode', 'DEBUG_MODE']: 2616 M = N 2617 N_symb = tensor.iscalar() 2618 M_symb = tensor.iscalar() 2619 k_symb = tensor.iscalar() 2620 f = function([N_symb, M_symb, k_symb], 2621 tri(N_symb, M_symb, k_symb, dtype=dtype)) 2622 result = f(N, M, k) 2623 self.assertTrue( 2624 np.allclose(result, np.tri(N, M_, k, dtype=dtype))) 2625 self.assertTrue(result.dtype == np.dtype(dtype)) 2626 for dtype in ALL_DTYPES: 2627 yield check, dtype, 3 2628 # M != N, k = 0 2629 yield check, dtype, 3, 5 2630 yield check, dtype, 5, 3 2631 # N == M, k != 0 2632 yield check, dtype, 3, 3, 1 2633 yield check, dtype, 3, 3, -1 2634 # N < M, k != 0 2635 yield check, dtype, 3, 5, 1 2636 yield check, dtype, 3, 5, -1 2637 # N > M, k != 0 2638 yield check, dtype, 5, 3, 1 2639 yield check, dtype, 5, 3, -1 2640 2641 def test_tril_triu(self): 2642 def check_l(m, k=0): 2643 m_symb = matrix(dtype=m.dtype) 2644 k_symb = iscalar() 2645 f = function([m_symb, k_symb], tril(m_symb, k_symb)) 2646 result = f(m, k) 2647 self.assertTrue(np.allclose(result, np.tril(m, k))) 2648 self.assertTrue(result.dtype == np.dtype(dtype)) 2649 2650 def check_u(m, k=0): 2651 m_symb = matrix(dtype=m.dtype) 2652 k_symb = iscalar() 2653 f = function([m_symb, k_symb], triu(m_symb, k_symb)) 2654 result = f(m, k) 2655 self.assertTrue(np.allclose(result, np.triu(m, k))) 2656 self.assertTrue(result.dtype == np.dtype(dtype)) 2657 2658 for dtype in ALL_DTYPES: 2659 m = rand_of_dtype((10, 10), dtype) 2660 yield check_l, m, 0 2661 yield check_l, m, 1 2662 yield check_l, m, -1 2663 2664 yield check_u, m, 0 2665 yield check_u, m, 1 2666 yield check_u, m, -1 2667 2668 m = rand_of_dtype((10, 5), dtype) 2669 yield check_l, m, 0 2670 yield check_l, m, 1 2671 yield check_l, m, -1 2672 2673 yield check_u, m, 0 2674 yield check_u, m, 1 2675 yield check_u, m, -1 2676 2677 2678class test_nonzero(unittest.TestCase): 2679 def test_nonzero(self): 2680 def check(m): 2681 m_symb = theano.tensor.tensor(dtype=m.dtype, 2682 broadcastable=(False,) * m.ndim) 2683 2684 f_tuple = function([m_symb], nonzero(m_symb, return_matrix=False)) 2685 f_matrix = function([m_symb], nonzero(m_symb, return_matrix=True)) 2686 2687 self.assertTrue(np.allclose(f_matrix(m), 2688 np.vstack(np.nonzero(m)))) 2689 for i, j in zip(f_tuple(m), np.nonzero(m)): 2690 self.assertTrue(np.allclose(i, j)) 2691 2692 rand0d = np.array(rand()) 2693 self.assertRaises(ValueError, check, rand0d) 2694 2695 rand1d = rand(8) 2696 rand1d[:4] = 0 2697 check(rand1d) 2698 2699 rand2d = rand(8, 9) 2700 rand2d[:4] = 0 2701 check(rand2d) 2702 2703 rand3d = rand(8, 9, 10) 2704 rand3d[:4] = 0 2705 check(rand3d) 2706 2707 rand4d = rand(8, 9, 10, 11) 2708 rand4d[:4] = 0 2709 check(rand4d) 2710 2711 def test_flatnonzero(self): 2712 def check(m): 2713 m_symb = theano.tensor.tensor(dtype=m.dtype, 2714 broadcastable=(False,) * m.ndim) 2715 f = function([m_symb], flatnonzero(m_symb)) 2716 result = f(m) 2717 assert np.allclose(result, np.flatnonzero(m)) 2718 2719 rand0d = np.array(rand()) 2720 self.assertRaises(ValueError, check, rand0d) 2721 2722 rand1d = rand(8) 2723 rand1d[:4] = 0 2724 check(rand1d) 2725 2726 rand2d = rand(8, 9) 2727 rand2d[:4] = 0 2728 check(rand2d) 2729 2730 rand3d = rand(8, 9, 10) 2731 rand3d[:4] = 0 2732 check(rand3d) 2733 2734 rand4d = rand(8, 9, 10, 11) 2735 rand4d[:4] = 0 2736 check(rand4d) 2737 2738 def test_nonzero_values(self): 2739 def check(m): 2740 m_symb = theano.tensor.tensor(dtype=m.dtype, 2741 broadcastable=(False,) * m.ndim) 2742 f = function([m_symb], nonzero_values(m_symb)) 2743 result = f(m) 2744 assert np.allclose(result, m[np.nonzero(m)]) 2745 2746 rand0d = rand() 2747 self.assertRaises(ValueError, check, rand0d) 2748 2749 rand1d = rand(8) 2750 rand1d[:4] = 0 2751 check(rand1d) 2752 2753 rand2d = rand(8, 9) 2754 rand2d[:4] = 0 2755 check(rand2d) 2756 2757 rand3d = rand(8, 9, 10) 2758 rand3d[:4] = 0 2759 check(rand3d) 2760 2761 rand4d = rand(8, 9, 10, 11) 2762 rand4d[:4] = 0 2763 check(rand4d) 2764 2765 2766def test_identity(): 2767 def check(dtype): 2768 obj = rand_of_dtype((2,), dtype) 2769 sym = tensor.vector(dtype=dtype) 2770 f = function([sym], tensor_copy(sym)) 2771 assert np.all(obj == f(obj)) 2772 assert obj.dtype == f(obj).dtype 2773 topo = f.maker.fgraph.toposort() 2774 assert len(topo) == 1 2775 if theano.config.mode != 'FAST_COMPILE': 2776 assert isinstance(topo[0].op, DeepCopyOp) 2777 2778 for dtype in ALL_DTYPES: 2779 yield check, dtype 2780 2781 2782class CastTester(unittest.TestCase): 2783 def test_good_between_real_types(self): 2784 good = itertools.chain( 2785 multi_dtype_cast_checks((2,), dtypes=REAL_DTYPES), 2786 # Casts from foo to foo 2787 [('%s_%s' % (rand_of_dtype((2,), dtype), dtype), 2788 (rand_of_dtype((2,), dtype), dtype)) 2789 for dtype in ALL_DTYPES]) 2790 for testname, (obj, dtype) in good: 2791 inp = tensor.vector(dtype=obj.dtype) 2792 out = tensor.cast(inp, dtype=dtype) 2793 f = function([inp], out) 2794 assert f(obj).dtype == np.dtype(dtype) 2795 2796 # Test astype too 2797 out2 = inp.astype(dtype=dtype) 2798 assert out2.type == out.type 2799 2800 def test_cast_from_real_to_complex(self): 2801 for real_dtype in REAL_DTYPES: 2802 for complex_dtype in COMPLEX_DTYPES: 2803 inp = tensor.vector(dtype=real_dtype) 2804 out = tensor.cast(inp, dtype=complex_dtype) 2805 f = function([inp], out) 2806 obj = rand_of_dtype((2, ), real_dtype) 2807 assert f(obj).dtype == np.dtype(complex_dtype) 2808 2809 def test_cast_from_complex_to_real_raises_error(self): 2810 for real_dtype in REAL_DTYPES: 2811 for complex_dtype in COMPLEX_DTYPES: 2812 inp = tensor.vector(dtype=real_dtype) 2813 self.assertRaises(TypeError, tensor.cast( 2814 inp, dtype=complex_dtype)) 2815 2816ClipTester = makeTester( 2817 name='ClipTester', 2818 op=clip, 2819 expected=lambda x, y, z: np.clip(x, y, z), 2820 good=dict(correct1=((5 * rand(5, 5)).astype('float32'), 2821 np.array(-1, dtype='float32'), 2822 np.array(1, dtype='float32')), 2823 correct2=((5 * rand(5, 5)).astype('float64'), 2824 np.array(-1, dtype='float64'), 2825 np.array(1, dtype='float64')), 2826 correct3=(randint(5, 5).astype('int8'), 2827 np.array(-1, dtype='int8'), 2828 np.array(1, dtype='int8')), 2829 correct4=(randint(5, 5).astype('int16'), 2830 np.array(-1, dtype='int16'), 2831 np.array(1, dtype='int16')), 2832 correct5=(randint(5, 5).astype('int32'), 2833 np.array(-1, dtype='int32'), 2834 np.array(1, dtype='int32')), 2835 correct6=(randint(5, 5).astype('int64'), 2836 np.array(-1, dtype='int64'), 2837 np.array(1, dtype='int64')), 2838 # min > max case moved below as numpy has changed 2839 correct8=(randint(0, 5).astype('uint8'), 2840 np.array(2, dtype='uint8'), 2841 np.array(4, dtype='uint8')), 2842 correct9=(randint(0, 5).astype('uint16'), 2843 np.array(2, dtype='uint16'), 2844 np.array(4, dtype='uint16')),) 2845 # I can't think of any way to make this fail at runtime 2846 ) 2847 2848 2849# min > max case - numpy.clip has changed but we haven't 2850# https://github.com/Theano/Theano/issues/6715 2851BackwardsClipTester = makeTester( 2852 name='BackwardsClipTester', 2853 op=clip, 2854 expected=lambda x, y, z: np.where(x < y, y, np.minimum(x, z)), 2855 good=dict(correct7=((5 * rand(5, 5)).astype('float64'), 2856 np.array(1, dtype='float64'), 2857 np.array(-1, dtype='float64')),) 2858 ) 2859 2860 2861class T_Clip(unittest.TestCase): 2862 def test_complex_value(self): 2863 for dtype in ['complex64', 'complex128']: 2864 a = tensor.vector(dtype=dtype) 2865 b = tensor.scalar() 2866 c = tensor.scalar() 2867 self.assertRaises(TypeError, clip, a, b, c) 2868 2869 def test_clip_repeat_grad(self): 2870 # This is testing for the issue #633 2871 x, y = tensor.vectors('xy') 2872 a = clip(x, y, x) 2873 g = theano.gradient.grad(a.sum(), x) 2874 fn = theano.function([x, y], [g]) 2875 2876 # Test the other way around as well 2877 a2 = clip(x, x, y) 2878 g2 = theano.gradient.grad(a2.sum(), x) 2879 fn2 = theano.function([x, y], [g2]) 2880 2881 # Test for the equal case too 2882 a3 = theano.tensor.clip(x, x, x) 2883 g3 = theano.gradient.grad(a3.sum(), x) 2884 fn3 = theano.function([x], [g3]) 2885 2886 rng = np.random.RandomState(utt.fetch_seed()) 2887 2888 nvals = 50 2889 xval = rng.rand(nvals).astype(config.floatX) 2890 # To ensure that the min < x 2891 yval_mn = rng.rand(nvals).astype(config.floatX) - 1.0 2892 2893 # To ensure that the max > x 2894 yval_mx = rng.rand(nvals).astype(config.floatX) + 1.0 2895 2896 aval, = fn(xval, yval_mn) 2897 aval2, = fn2(xval, yval_mx) 2898 aval3, = fn3(xval) 2899 self.assertTrue(np.all(aval == 1.)) 2900 self.assertTrue(np.all(aval2 == 1.)) 2901 self.assertTrue(np.all(aval3 == 1.)) 2902 2903 def test_clip_repeat_verify_grad(self): 2904 # Additional tests for issue gh-633 2905 utt.verify_grad( 2906 op=lambda x: clip(x, 0, x), 2907 pt=[rand_nonzero((3, 7))]) 2908 2909 utt.verify_grad( 2910 op=lambda x: clip(x, x, 0), 2911 pt=[rand_nonzero((3, 7))]) 2912 2913 utt.verify_grad( 2914 op=lambda x: clip(0, x, x), 2915 pt=[rand_nonzero((3, 7))]) 2916 2917 utt.verify_grad( 2918 op=lambda x: clip(x, x, x), 2919 pt=[rand_nonzero((3, 7))]) 2920 2921 2922# TODO: consider moving this function / functionality to gradient.py 2923# rationale: it's tricky, and necessary every time you want to verify 2924# gradient numerically 2925 2926 2927def test_batched_dot(): 2928 first = theano.tensor.tensor3("first") 2929 second = theano.tensor.tensor3("second") 2930 output = theano.tensor.basic.batched_dot(first, second) 2931 first_val = np.random.rand(10, 10, 20).astype(config.floatX) 2932 second_val = np.random.rand(10, 20, 5).astype(config.floatX) 2933 result_fn = theano.function([first, second], output) 2934 result = result_fn(first_val, second_val) 2935 assert result.shape[0] == first_val.shape[0] 2936 assert result.shape[1] == first_val.shape[1] 2937 assert result.shape[2] == second_val.shape[2] 2938 2939 first_mat = theano.tensor.dmatrix("first") 2940 second_mat = theano.tensor.dmatrix("second") 2941 output = theano.tensor.basic.batched_dot(first_mat, second_mat) 2942 first_mat_val = np.random.rand(10, 10).astype(config.floatX) 2943 second_mat_val = np.random.rand(10, 10).astype(config.floatX) 2944 result_fn = theano.function([first_mat, second_mat], output) 2945 result = result_fn(first_mat_val, second_mat_val) 2946 2947 assert result.shape[0] == first_mat_val.shape[0] 2948 2949 2950def test_batched_dot_not_contiguous(): 2951 def np_genarray(*_shape): 2952 size = 1 2953 for dimsize in _shape: 2954 size *= dimsize 2955 return np.arange(size, dtype=floatX).reshape(_shape) 2956 2957 X = tensor3() 2958 W = tensor3() 2959 Z = batched_dot(X, W) 2960 f = function([X, W], Z) 2961 2962 w = np_genarray(30, 10, 5) 2963 reversed_x_container = np_genarray(20, 40, 30) 2964 x_container = reversed_x_container.T 2965 2966 def check_first_dim(inverted): 2967 direction = -1 if inverted else 1 2968 x = x_container[::direction, ::2, ::2] 2969 assert x.shape == (30, 20, 10) 2970 assert x.strides[0] == direction * np.dtype(floatX).itemsize 2971 assert not (x.flags['C_CONTIGUOUS'] or x.flags['F_CONTIGUOUS']) 2972 result = f(x, w) 2973 ref_result = np.asarray(list(np.dot(u, v) for u, v in zip(x, w))) 2974 utt.assert_allclose(ref_result, result) 2975 2976 for inverted in (0, 1): 2977 yield (check_first_dim, inverted) 2978 2979 2980def test_batched_tensordot(): 2981 first = theano.tensor.tensor4("first") 2982 second = theano.tensor.tensor4("second") 2983 axes = [[1, 2], [3, 1]] 2984 output = theano.tensor.basic.batched_tensordot(first, second, axes) 2985 first_val = np.random.rand(8, 10, 20, 3).astype(config.floatX) 2986 second_val = np.random.rand(8, 20, 5, 10).astype(config.floatX) 2987 result_fn = theano.function([first, second], output) 2988 result = result_fn(first_val, second_val) 2989 assert result.shape[0] == first_val.shape[0] 2990 assert result.shape[1] == first_val.shape[3] 2991 assert result.shape[2] == second_val.shape[2] 2992 2993 first_mat = theano.tensor.dmatrix("first") 2994 second_mat = theano.tensor.dmatrix("second") 2995 axes = 1 2996 output = theano.tensor.basic.batched_tensordot(first_mat, second_mat, axes) 2997 first_mat_val = np.random.rand(10, 4).astype(config.floatX) 2998 second_mat_val = np.random.rand(10, 4).astype(config.floatX) 2999 result_fn = theano.function([first_mat, second_mat], output) 3000 result = result_fn(first_mat_val, second_mat_val) 3001 assert result.shape[0] == first_mat_val.shape[0] 3002 assert len(result.shape) == 1 3003 3004 3005def test_tensor_values_eq_approx(): 3006 # test, inf, -inf and nan equal themself 3007 a = np.asarray([-np.inf, -1, 0, 1, np.inf, np.nan]) 3008 assert TensorType.values_eq_approx(a, a) 3009 3010 # test inf, -inf don't equal themself 3011 b = np.asarray([np.inf, -1, 0, 1, np.inf, np.nan]) 3012 assert not TensorType.values_eq_approx(a, b) 3013 b = np.asarray([-np.inf, -1, 0, 1, -np.inf, np.nan]) 3014 assert not TensorType.values_eq_approx(a, b) 3015 3016 # test allow_remove_inf 3017 b = np.asarray([np.inf, -1, 0, 1, 5, np.nan]) 3018 assert TensorType.values_eq_approx(a, b, allow_remove_inf=True) 3019 b = np.asarray([np.inf, -1, 0, 1, 5, 6]) 3020 assert not TensorType.values_eq_approx(a, b, allow_remove_inf=True) 3021 3022 # test allow_remove_nan 3023 b = np.asarray([np.inf, -1, 0, 1, 5, np.nan]) 3024 assert not TensorType.values_eq_approx(a, b, allow_remove_nan=False) 3025 b = np.asarray([-np.inf, -1, 0, 1, np.inf, 6]) 3026 assert not TensorType.values_eq_approx(a, b, allow_remove_nan=False) 3027 3028 3029def test_nan_inf_constant_signature(): 3030 # Test that the signature of a constant tensor containing NaN and Inf 3031 # values is correct. 3032 test_constants = [ 3033 [np.nan, np.inf, 0, 1], 3034 [np.nan, np.inf, -np.inf, 1], 3035 [0, np.inf, -np.inf, 1], 3036 [0, 3, -np.inf, 1], 3037 [0, 3, np.inf, 1], 3038 [np.nan, 3, 4, 1], 3039 [0, 3, 4, 1], 3040 np.nan, 3041 np.inf, 3042 -np.inf, 3043 0, 3044 1, 3045 ] 3046 n = len(test_constants) 3047 # We verify that signatures of two rows i, j in the matrix above are 3048 # equal if and only if i == j. 3049 for i in xrange(n): 3050 for j in xrange(n): 3051 x = constant(test_constants[i]) 3052 y = constant(test_constants[j]) 3053 assert (x.signature() == y.signature()) == (i == j) 3054 3055 # Also test that nan !=0 and nan != nan. 3056 x = tensor.scalar() 3057 mode = get_default_mode() 3058 if isinstance(mode, theano.compile.debugmode.DebugMode): 3059 # Disable the check preventing usage of NaN / Inf values. 3060 # We first do a copy of the mode to avoid side effects on other tests. 3061 mode = copy(mode) 3062 mode.check_isfinite = False 3063 f = theano.function([x], eq(x, np.nan), mode=mode) 3064 3065 assert f(0) == 0 3066 assert f(np.nan) == 0 3067 3068 3069def test_isnan(): 3070 for x in [tensor.matrix(), tensor.imatrix(), tensor.matrix(dtype='bool')]: 3071 y = tensor.isnan(x) 3072 assert isinstance(y.owner.op, tensor.Elemwise) == ( 3073 x.dtype not in tensor.discrete_dtypes) 3074 assert y.dtype == 'bool' 3075 3076 # Test c code generator even for int type. 3077 y = tensor.isnan_(x) 3078 assert isinstance(y.owner.op, tensor.Elemwise) 3079 assert y.dtype == 'bool' 3080 f = theano.function([x], y, allow_input_downcast=True) 3081 f([[0, 1, 2]]) 3082 3083 3084class T_Shape(unittest.TestCase): 3085 def test_basic0(self): 3086 s = shape(np.ones((5, 3))) 3087 self.assertTrue((eval_outputs([s]) == [5, 3]).all()) 3088 3089 def test_basic1(self): 3090 s = shape(np.ones((2))) 3091 self.assertTrue((eval_outputs([s]) == [2]).all()) 3092 3093 def test_basic2(self): 3094 s = shape(np.ones((5, 3, 10))) 3095 self.assertTrue((eval_outputs([s]) == [5, 3, 10]).all()) 3096 3097 3098class T_max_and_argmax(unittest.TestCase): 3099 def setUp(self): 3100 utt.seed_rng() 3101 MaxAndArgmax.debug = 0 3102 3103 def test0(self): 3104 n = as_tensor_variable(5.0) 3105 v, i = eval_outputs(max_and_argmax(n)) 3106 self.assertTrue(v == 5.0) 3107 self.assertTrue(i == 0) 3108 assert i.dtype == 'int64' 3109 v = eval_outputs(max_and_argmax(n)[0].shape) 3110 assert len(v) == 0 3111 v = eval_outputs(max_and_argmax(n)[1].shape) 3112 assert len(v) == 0 3113 3114 def test1(self): 3115 n = as_tensor_variable([1, 2, 3, 2, -6]) 3116 v, i = eval_outputs(max_and_argmax(n)) 3117 self.assertTrue(v == 3) 3118 self.assertTrue(i == 2) 3119 assert i.dtype == 'int64' 3120 v = eval_outputs(max_and_argmax(n)[0].shape) 3121 assert len(v) == 0 3122 3123 def test2(self): 3124 data = rand(2, 3) 3125 n = as_tensor_variable(data) 3126 for (axis, np_axis) in [(-1, -1), (0, 0), (1, 1), (None, None), 3127 ([0, 1], None), ([1, 0], None), 3128 (NoneConst.clone(), None), 3129 (constant(0), 0)]: 3130 v, i = eval_outputs(max_and_argmax(n, axis)) 3131 assert i.dtype == 'int64' 3132 self.assertTrue(np.all(v == np.max(data, np_axis))) 3133 self.assertTrue(np.all(i == np.argmax(data, np_axis))) 3134 v_shape = eval_outputs(max_and_argmax(n, axis)[0].shape) 3135 assert tuple(v_shape) == np.max(data, np_axis).shape 3136 3137 def test2_float16(self): 3138 # Test negative values and bigger range to make sure numpy don't do the argmax as on uint16 3139 data = (rand(20, 30).astype("float16") - 0.5) * 20 3140 n = shared(data) 3141 for (axis, np_axis) in [(-1, -1), (0, 0), (1, 1), (None, None), 3142 ([0, 1], None), ([1, 0], None), 3143 (NoneConst.clone(), None), 3144 (constant(0), 0)]: 3145 v, i = eval_outputs(max_and_argmax(n, axis), (MaxAndArgmax,)) 3146 assert i.dtype == 'int64' 3147 self.assertTrue(np.all(v == np.max(data, np_axis))) 3148 self.assertTrue(np.all(i == np.argmax(data, np_axis))) 3149 v_shape = eval_outputs(max_and_argmax(n, axis)[0].shape) 3150 assert tuple(v_shape) == np.max(data, np_axis).shape 3151 3152 def test2_invalid(self): 3153 n = as_tensor_variable(rand(2, 3)) 3154 # Silence expected error messages 3155 _logger = logging.getLogger('theano.gof.opt') 3156 oldlevel = _logger.level 3157 _logger.setLevel(logging.CRITICAL) 3158 try: 3159 try: 3160 eval_outputs(max_and_argmax(n, 3)) 3161 assert False 3162 except ValueError: 3163 pass 3164 finally: 3165 _logger.setLevel(oldlevel) 3166 3167 def test2_invalid_neg(self): 3168 n = as_tensor_variable(rand(2, 3)) 3169 old_stderr = sys.stderr 3170 sys.stderr = StringIO() 3171 try: 3172 try: 3173 eval_outputs(max_and_argmax(n, -3)) 3174 assert False 3175 except ValueError: 3176 pass 3177 finally: 3178 sys.stderr = old_stderr 3179 3180 def test2_valid_neg(self): 3181 n = as_tensor_variable(rand(2, 3)) 3182 v, i = eval_outputs(max_and_argmax(n, -1)) 3183 assert i.dtype == 'int64' 3184 self.assertTrue(v.shape == (2,)) 3185 self.assertTrue(i.shape == (2,)) 3186 self.assertTrue(np.all(v == np.max(n.value, -1))) 3187 self.assertTrue(np.all(i == np.argmax(n.value, -1))) 3188 v, i = eval_outputs(max_and_argmax(n, -2)) 3189 assert i.dtype == 'int64' 3190 self.assertTrue(v.shape == (3,)) 3191 self.assertTrue(i.shape == (3,)) 3192 self.assertTrue(np.all(v == np.max(n.value, -2))) 3193 self.assertTrue(np.all(i == np.argmax(n.value, -2))) 3194 v = eval_outputs(max_and_argmax(n, -1)[0].shape) 3195 assert v == (2) 3196 v = eval_outputs(max_and_argmax(n, -2)[0].shape) 3197 assert v == (3) 3198 3199 def test3(self): 3200 data = rand(2, 3, 4) 3201 n = as_tensor_variable(data) 3202 for (axis, np_axis) in [(-1, -1), (0, 0), (1, 1), (None, None), 3203 ([0, 1, 2], None), ([1, 2, 0], None)]: 3204 v, i = eval_outputs(max_and_argmax(n, axis)) 3205 assert i.dtype == 'int64' 3206 self.assertTrue(np.all(v == np.max(data, np_axis))) 3207 self.assertTrue(np.all(i == np.argmax(data, np_axis))) 3208 v = eval_outputs(max_and_argmax(n, axis)[0].shape) 3209 assert tuple(v) == np.max(data, np_axis).shape 3210 3211 def test_arg_grad(self): 3212 # The test checks that the gradient of argmax(x).sum() is 0 3213 3214 x = matrix() 3215 cost = argmax(x, axis=0).sum() 3216 gx = grad(cost, x) 3217 val = tensor.get_scalar_constant_value(gx) 3218 assert val == 0.0 3219 3220 def test_grad(self): 3221 data = rand(2, 3) 3222 n = as_tensor_variable(data) 3223 3224 def safe_verify_grad(func, data): 3225 # Wrapper around 'verify_grad' that picks a proper value for epsilon. 3226 # 3227 # This is needed because 'verify_grad' may fail when its epsilon is 3228 # too large, due to the fact the argmax is not continuous. 3229 # We make sure epsilon is less than the minimum absolute value found 3230 # in the matrix of pairwise differences between all elements in the 3231 # data. This way, the argmax will not change when adding epsilon. 3232 3233 # 'data' is a one-element list. 3234 data_tensor, = data 3235 # Flatten it into a 1D vector. 3236 data_vector = data_tensor.flatten() 3237 # Compute pairwise absolute differences. 3238 diff = np.abs(data_vector.reshape((-1, 1)) - data_vector) 3239 # Alter the diagonal to avoid a zero minimum. 3240 for i in xrange(len(diff)): 3241 diff[i, i] = 1 3242 # Find an appropriate epsilon. 3243 eps = builtin_min(numeric_grad.type_eps[config.floatX], 3244 diff.min() / 2) 3245 # Run gradient verification. 3246 utt.verify_grad(func, data, eps=eps) 3247 3248 def check_grad_max(data, max_grad_data, axis=None): 3249 # Why this is needed? verify_grad is not enough? 3250 # This works only for axis in [0, None]. 3251 assert axis in [0, None] 3252 z = np.zeros_like(data) 3253 z = z.flatten() 3254 argmax = np.argmax(data, axis=axis) 3255 if argmax.ndim == 0: 3256 z[argmax] += 1 3257 else: 3258 for id, v in enumerate(argmax): 3259 z[v * np.prod(data.shape[data.ndim - 1:axis:-1]) + 3260 id] += 1 3261 3262 z = z.reshape(data.shape) 3263 assert np.all(max_grad_data == z) 3264 3265 for axis in (-1, 0, 1, None): 3266 for j in xrange(2): 3267 safe_verify_grad(lambda v: max_and_argmax(v, axis=axis)[j], 3268 [data]) 3269 if axis != 1: 3270 safe_verify_grad(lambda v: max_and_argmax(v.flatten(), 3271 axis=axis)[j], 3272 [data]) 3273 if axis in (0, None): 3274 check_grad_max(data, eval_outputs(grad( 3275 max_and_argmax(n, axis=axis)[0].sum(), n)), axis=axis) 3276 check_grad_max(data, eval_outputs(grad( 3277 max_and_argmax(n.flatten())[0], n))) 3278 3279 # Test 3d inner dimensions 3280 data = rand(3, 4, 5) 3281 3282 for i in [0, 1, 2]: 3283 safe_verify_grad(lambda v: max_and_argmax(v, axis=[i])[0], [data]) 3284 safe_verify_grad(lambda v: max_and_argmax(v, axis=[i])[1], [data]) 3285 3286 # Test 4d inner dimensions 3287 data = rand(2, 3, 4, 5) 3288 3289 for i in [0, 1, 2, 3]: 3290 safe_verify_grad(lambda v: max_and_argmax(v, axis=[i])[0], [data]) 3291 safe_verify_grad(lambda v: max_and_argmax(v, axis=[i])[1], [data]) 3292 3293 # Test grad with multiple axes 3294 for i in [[0, 1], [0, 0]]: 3295 safe_verify_grad(lambda v: max_and_argmax(v, axis=i)[0], [data]) 3296 safe_verify_grad(lambda v: max_and_argmax(v, axis=i)[1], [data]) 3297 3298 def test_preserve_broadcastable(self): 3299 # Ensure the original broadcastable flags are preserved by Max/Argmax. 3300 x = tensor.matrix().dimshuffle('x', 0, 'x', 1, 'x') 3301 y = x.max(axis=1) 3302 assert y.type.broadcastable == (True, True, False, True) 3303 3304 def test_multiple_axes(self): 3305 data = np.arange(24).reshape(3, 2, 4) 3306 x = as_tensor_variable(data) 3307 v, i = eval_outputs(max_and_argmax(x, [1, -1])) 3308 assert np.all(v == np.array([7, 15, 23])) 3309 assert np.all(i == np.array([7, 7, 7])) 3310 3311 v = eval_outputs(max_and_argmax(x, [1, -1])[0].shape) 3312 assert tuple(v) == np.max(data, (1, -1)).shape 3313 3314 def test_zero_shape(self): 3315 x = tensor.matrix() 3316 m, i = max_and_argmax(x, axis=1) 3317 f = theano.function([x], [m, i]) 3318 xv = np.zeros((0, 4), dtype=floatX) 3319 mv, iv = f(xv) 3320 assert mv.shape == (0,) 3321 assert iv.shape == (0,) 3322 3323 def test_numpy_input(self): 3324 ar = np.array([1, 2, 3]) 3325 max, argmax = max_and_argmax(ar, axis=None) 3326 self.assertEqual(max.eval(), 3) 3327 self.assertEqual(argmax.eval(), 2) 3328 3329 3330class T_argmin_argmax(unittest.TestCase): 3331 def setUp(self): 3332 utt.seed_rng() 3333 MaxAndArgmax.debug = 0 3334 3335 def test_scalar(self): 3336 for fct in [argmin, argmax]: 3337 n = as_tensor_variable(5.0) 3338 i = eval_outputs(fct(n)) 3339 self.assertTrue(i == 0) 3340 v = eval_outputs(fct(n).shape) 3341 assert len(v) == 0 3342 3343 def test_list(self): 3344 n = as_tensor_variable([1, 2, 3, 2, -6]) 3345 i = eval_outputs(argmin(n)) 3346 self.assertTrue(i == 4) 3347 v = eval_outputs(argmin(n).shape) 3348 assert len(v) == 0 3349 3350 n = as_tensor_variable([1, 2, 3, 2, -6]) 3351 i = eval_outputs(argmax(n)) 3352 self.assertTrue(i == 2) 3353 v = eval_outputs(argmax(n).shape) 3354 assert len(v) == 0 3355 3356 def test2(self): 3357 data = rand(2, 3) 3358 n = as_tensor_variable(data) 3359 for fct, nfct in [(argmax, np.argmax), (argmin, np.argmin)]: 3360 for (axis, np_axis) in [(-1, -1), (0, 0), (1, 1), (None, None), 3361 ([0, 1], None), ([1, 0], None)]: 3362 v = eval_outputs(fct(n, axis)) 3363 self.assertTrue(np.all(v == nfct(data, np_axis))) 3364 v_shape = eval_outputs(fct(n, axis).shape) 3365 assert tuple(v_shape) == nfct(data, np_axis).shape 3366 3367 def test2_float16(self): 3368 # Test negative values and bigger range to make sure numpy don't do the argmax as on uint16 3369 data = (rand(20, 30).astype("float16") - 0.5) * 20 3370 n = shared(data) 3371 mode = get_default_mode().including("local_max_and_argmax", "uncanonicalize") 3372 for fct, nfct in [(argmax, np.argmax), (argmin, np.argmin)]: 3373 for (axis, np_axis) in [(-1, -1), (0, 0), (1, 1), (None, None), 3374 ([0, 1], None), ([1, 0], None)]: 3375 v = eval_outputs(fct(n, axis), (Argmax,), mode=mode) 3376 self.assertTrue(np.all(v == nfct(data, np_axis))) 3377 v_shape = eval_outputs(fct(n, axis).shape, mode=mode) 3378 assert tuple(v_shape) == nfct(data, np_axis).shape 3379 3380 def test2_invalid(self): 3381 for fct, nfct in [(argmax, np.argmax), (argmin, np.argmin)]: 3382 n = as_tensor_variable(rand(2, 3)) 3383 # Silence expected error messages 3384 _logger = logging.getLogger('theano.gof.opt') 3385 oldlevel = _logger.level 3386 _logger.setLevel(logging.CRITICAL) 3387 try: 3388 try: 3389 eval_outputs(fct(n, 3)) 3390 assert False 3391 except ValueError: 3392 pass 3393 finally: 3394 _logger.setLevel(oldlevel) 3395 3396 def test2_invalid_neg(self): 3397 for fct, nfct in [(argmax, np.argmax), (argmin, np.argmin)]: 3398 n = as_tensor_variable(rand(2, 3)) 3399 old_stderr = sys.stderr 3400 sys.stderr = StringIO() 3401 try: 3402 try: 3403 eval_outputs(fct(n, -3)) 3404 assert False 3405 except ValueError: 3406 pass 3407 finally: 3408 sys.stderr = old_stderr 3409 3410 def test2_valid_neg(self): 3411 for fct, nfct in [(argmax, np.argmax), (argmin, np.argmin)]: 3412 n = as_tensor_variable(rand(2, 3)) 3413 i = eval_outputs(fct(n, -1)) 3414 self.assertTrue(i.shape == (2,)) 3415 self.assertTrue(np.all(i == nfct(n.value, -1))) 3416 i = eval_outputs(fct(n, -2)) 3417 self.assertTrue(i.shape == (3,)) 3418 self.assertTrue(np.all(i == nfct(n.value, -2))) 3419 3420 v = eval_outputs(fct(n, -1).shape) 3421 assert v == (2) 3422 v = eval_outputs(fct(n, -2).shape) 3423 assert v == (3) 3424 3425 def test3(self): 3426 data = rand(2, 3, 4) 3427 n = as_tensor_variable(data) 3428 for fct, nfct in [(argmax, np.argmax), (argmin, np.argmin)]: 3429 for (axis, np_axis) in [(-1, -1), (0, 0), (1, 1), (2, 2), 3430 (None, None), ([0, 1, 2], None), 3431 ([1, 0, 2], None)]: 3432 v = eval_outputs(fct(n, axis)) 3433 self.assertTrue(np.all(v == nfct(data, np_axis))) 3434 v_shape = eval_outputs(fct(n, axis).shape) 3435 assert tuple(v_shape) == nfct(data, np_axis).shape 3436 3437 def test_grad_argmin(self): 3438 data = rand(2, 3) 3439 n = as_tensor_variable(data) 3440 n.name = 'n' 3441 3442 # test grad of argmin 3443 utt.verify_grad(lambda v: argmin(v, axis=-1), [data]) 3444 3445 utt.verify_grad(lambda v: argmin(v, axis=[0]), [data]) 3446 3447 utt.verify_grad(lambda v: argmin(v, axis=[1]), [data]) 3448 3449 utt.verify_grad(lambda v: argmin(v.flatten()), [data]) 3450 3451 try: 3452 cost = argmin(n, axis=-1) 3453 cost.name = None 3454 grad(cost, n) 3455 raise Exception('Expected an error') 3456 except TypeError: 3457 pass 3458 3459 def test_grad_argmax(self): 3460 data = rand(2, 3) 3461 n = as_tensor_variable(data) 3462 3463 # test grad of argmax 3464 utt.verify_grad(lambda v: argmax(v, axis=-1), [data]) 3465 3466 utt.verify_grad(lambda v: argmax(v, axis=[0]), [data]) 3467 3468 utt.verify_grad(lambda v: argmax(v, axis=[1]), [data]) 3469 3470 utt.verify_grad(lambda v: argmax(v.flatten()), [data]) 3471 3472 try: 3473 grad(argmax(n, axis=-1), n) 3474 raise Exception('Expected an error') 3475 except TypeError: 3476 pass 3477 3478 def test_uint(self): 3479 for dtype in ('uint8', 'uint16', 'uint32', 'uint64'): 3480 itype = np.iinfo(dtype) 3481 data = np.array([itype.min + 3, itype.min, itype.max - 5, itype.max], dtype) 3482 n = as_tensor_variable(data) 3483 i = eval_outputs(argmin(n)) 3484 self.assertEqual(i, 1) 3485 i = eval_outputs(argmax(n)) 3486 self.assertEqual(i, 3) 3487 3488 def test_bool(self): 3489 data = np.array([True, False], 'bool') 3490 n = as_tensor_variable(data) 3491 i = eval_outputs(argmin(n)) 3492 self.assertEqual(i, 1) 3493 i = eval_outputs(argmax(n)) 3494 self.assertEqual(i, 0) 3495 3496 3497class T_min_max(unittest.TestCase): 3498 def setUp(self): 3499 utt.seed_rng() 3500 MaxAndArgmax.debug = 0 3501 3502 def test_scalar(self): 3503 for fct in [max, min]: 3504 n = as_tensor_variable(5.0) 3505 v = eval_outputs(fct(n)) 3506 self.assertTrue(v == 5.0) 3507 3508 v = eval_outputs(fct(n).shape) 3509 assert len(v) == 0 3510 3511 def test_list(self): 3512 for fct, nfct in [(max, np.max), (min, np.min)]: 3513 n = as_tensor_variable([1, 2, 3, 2, -6]) 3514 v = eval_outputs([fct(n)]) 3515 self.assertTrue(v == nfct(n.value)) 3516 3517 v = eval_outputs(fct(n).shape) 3518 assert len(v) == 0 3519 3520 def test2(self): 3521 data = rand(2, 3) 3522 n = as_tensor_variable(data) 3523 for fct, nfct in [(max, np.max), (min, np.min)]: 3524 for (axis, np_axis) in [(-1, -1), (0, 0), (1, 1), (None, None), 3525 ([0, 1], None), ([1, 0], None)]: 3526 v = eval_outputs(fct(n, axis)) 3527 self.assertTrue(np.all(v == nfct(data, np_axis))) 3528 v_shape = eval_outputs(fct(n, axis).shape) 3529 assert tuple(v_shape) == nfct(data, np_axis).shape 3530 3531 def test2_invalid(self): 3532 for fct in [max, min]: 3533 n = as_tensor_variable(rand(2, 3)) 3534 # Silence expected error messages 3535 _logger = logging.getLogger('theano.gof.opt') 3536 oldlevel = _logger.level 3537 _logger.setLevel(logging.CRITICAL) 3538 try: 3539 try: 3540 eval_outputs(fct(n, 3)) 3541 assert False 3542 except ValueError: 3543 pass 3544 finally: 3545 _logger.setLevel(oldlevel) 3546 3547 def test2_invalid_neg(self): 3548 for fct in [max, min]: 3549 n = as_tensor_variable(rand(2, 3)) 3550 old_stderr = sys.stderr 3551 sys.stderr = StringIO() 3552 try: 3553 try: 3554 eval_outputs(fct(n, -3)) 3555 assert False 3556 except ValueError: 3557 pass 3558 finally: 3559 sys.stderr = old_stderr 3560 3561 def test2_valid_neg(self): 3562 for fct, nfct in [(max, np.max), (min, np.min)]: 3563 n = as_tensor_variable(rand(2, 3)) 3564 v = eval_outputs(fct(n, -1)) 3565 self.assertTrue(v.shape == (2,)) 3566 self.assertTrue(np.all(v == nfct(n.value, -1))) 3567 v = eval_outputs(fct(n, -2)) 3568 self.assertTrue(v.shape == (3,)) 3569 self.assertTrue(np.all(v == nfct(n.value, -2))) 3570 3571 v = eval_outputs(fct(n, -1).shape) 3572 assert v == (2) 3573 v = eval_outputs(fct(n, -2).shape) 3574 assert v == (3) 3575 3576 def test3(self): 3577 # Test with 1 axis or all axis out of 3 dims 3578 data = rand(2, 3, 4) 3579 n = as_tensor_variable(data) 3580 for fct, nfct in [(max, np.max), (min, np.min)]: 3581 for (axis, np_axis) in [(-1, -1), (0, 0), (1, 1), (2, 2), 3582 (None, None), ([0, 1, 2], None), 3583 ([1, 0, 2], None)]: 3584 v = eval_outputs(fct(n, axis)) 3585 self.assertTrue(np.all(v == nfct(data, np_axis))) 3586 v_shape = eval_outputs(fct(n, axis).shape) 3587 assert tuple(v_shape) == nfct(data, np_axis).shape 3588 3589 def test3b(self): 3590 # Test with 2 axis out of 3 dims 3591 data = rand(2, 3, 4) 3592 n = as_tensor_variable(data) 3593 for fct, nfct in [(max, np.max), (min, np.min)]: 3594 for axis in [[0, 1], [1, 2], [0, 2]]: 3595 v = eval_outputs(fct(n, axis)) 3596 np_v = nfct(nfct(data, axis[1]), axis[0]) 3597 self.assertTrue(np.all(v == np_v)) 3598 v_shape = eval_outputs(fct(n, axis).shape) 3599 assert tuple(v_shape) == np_v.shape 3600 3601 def test_grad_max(self): 3602 data = rand(2, 3) 3603 n = as_tensor_variable(data) 3604 3605 def check_grad_max(data, max_grad_data, axis=None): 3606 # This work only for axis in [0,None] 3607 assert axis in [0, None] 3608 z = np.zeros_like(data) 3609 z = z.flatten() 3610 argmax = np.argmax(data, axis=axis) 3611 if argmax.ndim == 0: 3612 z[np.argmax(data, axis=axis)] += 1 3613 else: 3614 for id, v in enumerate(argmax): 3615 z[v * np.prod(data.shape[data.ndim - 1:axis:-1]) + 3616 id] += 1 3617 3618 z = z.reshape(data.shape) 3619 assert np.all(max_grad_data == z) 3620 3621 # test grad of max 3622 # axis is the last one 3623 utt.verify_grad(lambda v: max(v, axis=-1), [data]) 3624 3625 utt.verify_grad(lambda v: max(v, axis=[0]), [data]) 3626 check_grad_max(data, eval_outputs(grad(max(n, axis=0).sum(), n)), 3627 axis=0) 3628 3629 utt.verify_grad(lambda v: max(v, axis=[1]), [data]) 3630 # check_grad_max(data,eval_outputs(grad(max(n,axis=1),n)),axis=1) 3631 3632 utt.verify_grad(lambda v: max(v.flatten()), [data]) 3633 check_grad_max(data, eval_outputs(grad(max(n.flatten()), n))) 3634 3635 def test_grad_min(self): 3636 data = rand(2, 3) 3637 n = as_tensor_variable(data) 3638 3639 def check_grad_min(data, min_grad_data, axis=None): 3640 # This work only for axis in [0, None] 3641 assert axis in [0, None] 3642 z = np.zeros_like(data) 3643 z = z.flatten() 3644 argmin = np.argmin(data, axis=axis) 3645 if argmin.ndim == 0: 3646 z[np.argmin(data, axis=axis)] += 1 3647 else: 3648 for id, v in enumerate(argmin): 3649 z[v * np.prod(data.shape[data.ndim - 1:axis:-1]) + 3650 id] += 1 3651 3652 z = z.reshape(data.shape) 3653 assert np.all(min_grad_data == z) 3654 3655 # test grad of min 3656 # axis is the last one 3657 utt.verify_grad(lambda v: min(v, axis=-1), [data]) 3658 3659 utt.verify_grad(lambda v: min(v, axis=[0]), [data]) 3660 check_grad_min(data, eval_outputs(grad(min(n, axis=0).sum(), n)), 3661 axis=0) 3662 3663 utt.verify_grad(lambda v: min(v, axis=[1]), [data]) 3664 # check_grad_min(data,eval_outputs(grad(min(n,axis=1),n)),axis=1) 3665 3666 utt.verify_grad(lambda v: min(v.flatten()), [data]) 3667 check_grad_min(data, eval_outputs(grad(min(n.flatten()), n))) 3668 3669 def _grad_list(self): 3670 # Test the gradient when we have multiple axis at the same time. 3671 # 3672 # This not implemented, so we disable the test. See ticket: 3673 # http://www.assembla.com/spaces/theano/tickets/511 3674 data = rand(2, 3) 3675 for fct in [max_and_argmax, max, min]: 3676 utt.verify_grad(lambda v: fct(v, axis=[0, 1]), [data]) 3677 # n = as_tensor_variable(data) 3678 # check_grad_max(data, eval_outputs(grad(max_and_argmax(n, 3679 # axis=1)[0], n)),axis=1) 3680 3681 def test_uint(self): 3682 for dtype in ('uint8', 'uint16', 'uint32', 'uint64'): 3683 itype = np.iinfo(dtype) 3684 data = np.array([itype.min + 3, itype.min, itype.max - 5, itype.max], dtype) 3685 n = as_tensor_variable(data) 3686 self.assertEqual(min(n).dtype, dtype) 3687 i = eval_outputs(min(n)) 3688 self.assertEqual(i, itype.min) 3689 self.assertEqual(max(n).dtype, dtype) 3690 i = eval_outputs(max(n)) 3691 self.assertEqual(i, itype.max) 3692 3693 def test_bool(self): 3694 data = np.array([True, False], 'bool') 3695 n = as_tensor_variable(data) 3696 self.assertEqual(min(n).dtype, 'bool') 3697 i = eval_outputs(min(n)) 3698 self.assertEqual(i, False) 3699 self.assertEqual(max(n).dtype, 'bool') 3700 i = eval_outputs(max(n)) 3701 self.assertEqual(i, True) 3702 3703 3704def test_basic_allclose(): 3705 # This was raised by a user in https://github.com/Theano/Theano/issues/2975 3706 assert tensor.basic._allclose(-0.311023883434, -0.311022856884) 3707 3708 3709class T_outer(unittest.TestCase): 3710 def test_outer(self): 3711 for m in range(4): 3712 for n in range(4): 3713 x = tensor.tensor(dtype='floatX', broadcastable=(False,) * m) 3714 y = tensor.tensor(dtype='floatX', broadcastable=(False,) * n) 3715 s1 = np.random.randint(1, 10, m) 3716 s2 = np.random.randint(1, 10, n) 3717 v1 = np.asarray(np.random.rand(*s1)).astype(floatX) 3718 v2 = np.asarray(np.random.rand(*s2)).astype(floatX) 3719 o = tensor.outer(x, y).eval({x: v1, y: v2}) 3720 assert_allclose(o, np.outer(v1, v2)) 3721 3722 def test_grad(self): 3723 # Test the combined graph of the graph of outer 3724 # with broadcastable dimensions, just in case. 3725 for shp0, shp1 in [((1,), (2,)), 3726 ((3,), (1,)), 3727 ((1,), (1,)), 3728 ((3,), (2,)), 3729 ((3, 2), (1, 1)), 3730 ((3, 2), (1, 4)), 3731 ((3, 2), (4, 1)), 3732 ((3, 2), (4, 5)), 3733 ((1, 2), (4, 5)), 3734 ((3, 1), (4, 5)), 3735 ((1, 1), (4, 5)), 3736 ((1, 1), (1, 1)), 3737 ]: 3738 data0 = np.random.rand(*shp0).astype(floatX) 3739 data1 = np.random.rand(*shp1).astype(floatX) 3740 utt.verify_grad(tensor.outer, [data0, data1]) 3741 3742 3743class T_GetVectorLength(unittest.TestCase): 3744 def test_get_vector_length(self): 3745 x = theano.shared(np.zeros((2, 3, 4, 5))) 3746 assert len(list(x.shape)) == 4 3747 assert len(list(x.shape[2:4])) == 2 3748 assert len(list(x.shape[2:])) == 2 3749 assert len(list(x.shape[1:4])) == 3 3750 assert len(list(x.shape[2:2])) == 0 3751 assert len(list(x.shape[1:5])) == 3 3752 assert len(list(x.shape[1:10])) == 3 3753 # Test step 3754 assert len(list(x.shape[1:10:2])) == 2 3755 # Test neg start 3756 assert len(list(x.shape[-1:4])) == 1 3757 assert len(list(x.shape[-6:4])) == 4 3758 # test neg stop 3759 assert len(list(x.shape[1:-2])) == 1 3760 assert len(list(x.shape[1:-1])) == 2 3761 3762 3763class T_Join_and_Split(unittest.TestCase): 3764 # Split is tested by each verify_grad method. 3765 def setUp(self): 3766 Join.debug = False 3767 utt.seed_rng() 3768 self.mode = theano.compile.get_default_mode().excluding( 3769 'constant_folding') 3770 self.join_op = Join() 3771 self.split_op_class = Split 3772 self.make_vector_op = opt.MakeVector() 3773 self.floatX = config.floatX 3774 self.hide_error = theano.config.mode not in [ 3775 'DebugMode', 'DEBUG_MODE', 'FAST_COMPILE'] 3776 self.shared = shared 3777 3778 def eval_outputs_and_check_join(self, outputs): 3779 f = theano.function([], outputs, self.mode) 3780 topo = f.maker.fgraph.toposort() 3781 assert [True for node in topo 3782 if isinstance(node.op, type(self.join_op))] 3783 variables = f() 3784 if isinstance(variables, (tuple, list)) and len(variables) == 1: 3785 return variables[0] 3786 return variables 3787 3788 def eval_outputs_and_check_vector(self, outputs, 3789 make_vector_op=None): 3790 if make_vector_op is None: 3791 make_vector_op = self.make_vector_op 3792 f = theano.function([], outputs, self.mode) 3793 topo = f.maker.fgraph.toposort() 3794 assert [True for node in topo 3795 if isinstance(node.op, type(make_vector_op))] 3796 variables = f() 3797 if isinstance(variables, (tuple, list)) and len(variables) == 1: 3798 return variables[0] 3799 return variables 3800 3801 def test_join_scalar(self): 3802 a = as_tensor_variable(1) 3803 b = as_tensor_variable(2) 3804 self.assertRaises(TypeError, join, 0, a, b) 3805 3806 def test_stack_mixed_type_constants(self): 3807 # tested only on cpu as gpu support only float32 3808 a = as_tensor_variable(1) 3809 b = as_tensor_variable(2.0) 3810 c = tensor._shared(np.asarray(3.0, dtype=self.floatX)) 3811 s = stack([a, b, c]) 3812 want = np.array([1, 2, 3]) 3813 out = self.eval_outputs_and_check_vector([s], opt.MakeVector()) 3814 self.assertTrue((out == want).all()) 3815 3816 def test_stack_scalar(self): 3817 a = self.shared(np.asarray(1., dtype=self.floatX)) 3818 b = as_tensor_variable(2.) 3819 c = as_tensor_variable(3.) 3820 s = stack([a, b, c]) 3821 3822 want = np.array([1, 2, 3]) 3823 out = self.eval_outputs_and_check_vector([s]) 3824 self.assertTrue((out == want).all()) 3825 3826 def test_stack_scalar_make_vector(self): 3827 # Test that calling stack() on scalars instantiates MakeVector, 3828 # not Join. Test that the floatX dtype stay floatX, not downcasted 3829 # to int64 3830 a = tensor.scalar('a', dtype=self.floatX) 3831 b = tensor.scalar('b', dtype=self.floatX) 3832 s = stack([a, b, a, b]) 3833 f = function([a, b], s, mode=self.mode) 3834 val = f(1, 2) 3835 # print val 3836 self.assertTrue(np.all(val == [1, 2, 1, 2])) 3837 topo = f.maker.fgraph.toposort() 3838 assert len([n for n in topo if isinstance(n.op, opt.MakeVector)]) > 0 3839 assert len([n for n in topo if isinstance(n, type(self.join_op))]) == 0 3840 assert f.maker.fgraph.outputs[0].dtype == self.floatX 3841 3842 def test_stack_scalar_make_vector_dtype(self): 3843 # Test that calling stack() on scalars instantiates MakeVector, 3844 # event when the scalar don't have the same dtype. 3845 a = tensor.iscalar('a') 3846 b = tensor.lscalar('b') 3847 s = stack([a, b, a, b]) 3848 f = function([a, b], s, mode=self.mode) 3849 val = f(1, 2) 3850 self.assertTrue(np.all(val == [1, 2, 1, 2])) 3851 topo = f.maker.fgraph.toposort() 3852 assert len([n for n in topo if isinstance(n.op, opt.MakeVector)]) > 0 3853 assert len([n for n in topo if isinstance(n, type(self.join_op))]) == 0 3854 assert f.maker.fgraph.outputs[0].dtype == 'int64' 3855 3856 def test_stack_scalar_make_vector_constant(self): 3857 # Test that calling stack() on scalars instantiates MakeVector, 3858 # event when the scalar are simple int type. 3859 a = tensor.iscalar('a') 3860 b = tensor.lscalar('b') 3861 # test when the constant is the first element. 3862 # The first element is used in a special way 3863 s = stack([10, a, b, np.int8(3)]) 3864 f = function([a, b], s, mode=self.mode) 3865 val = f(1, 2) 3866 self.assertTrue(np.all(val == [10, 1, 2, 3])) 3867 topo = f.maker.fgraph.toposort() 3868 assert len([n for n in topo if isinstance(n.op, opt.MakeVector)]) > 0 3869 assert len([n for n in topo if isinstance(n, type(self.join_op))]) == 0 3870 assert f.maker.fgraph.outputs[0].dtype == 'int64' 3871 3872 def test_stack_new_interface(self): 3873 # Test the new numpy-like interface: stack(tensors, axis=0). 3874 3875 # Testing against old interface 3876 warnings.simplefilter('always', DeprecationWarning) 3877 a = tensor.imatrix('a') 3878 b = tensor.imatrix('b') 3879 s1 = stack(a, b) 3880 s2 = stack([a, b]) 3881 f = function([a, b], [s1, s2], mode=self.mode) 3882 v1, v2 = f([[1, 2]], [[3, 4]]) 3883 self.assertTrue(v1.shape == v2.shape) 3884 self.assertTrue(np.all(v1 == v2)) 3885 # Testing axis parameter 3886 s3 = stack([a, b], 1) 3887 f = function([a, b], s3, mode=self.mode) 3888 v3 = f([[1, 2]], [[3, 4]]) 3889 v4 = np.array([[[1, 2], [3, 4]]]) 3890 self.assertTrue(v3.shape == v4.shape) 3891 self.assertTrue(np.all(v3 == v4)) 3892 # Testing negative axis 3893 v1 = [[1, 2, 3], [4, 5, 6]] 3894 v2 = [[7, 8, 9], [10, 11, 12]] 3895 s = stack([a, b], axis=-1) 3896 f = function([a, b], s, mode=self.mode) 3897 v = np.zeros((2, 3, 2)) 3898 v[:, :, 0] = v1 3899 v[:, :, 1] = v2 3900 out = f(v1, v2) 3901 self.assertTrue(v.shape == out.shape) 3902 self.assertTrue(np.all(v == out)) 3903 s = stack([a, b], axis=-2) 3904 f = function([a, b], s, mode=self.mode) 3905 v = np.zeros((2, 2, 3)) 3906 v[:, 0, :] = v1 3907 v[:, 1, :] = v2 3908 out = f(v1, v2) 3909 self.assertTrue(v.shape == out.shape) 3910 self.assertTrue(np.all(v == out)) 3911 # Testing out-of-bounds axis 3912 self.assertRaises(IndexError, stack, [a, b], 4) 3913 self.assertRaises(IndexError, stack, [a, b], -4) 3914 # Testing depreciation warning 3915 with warnings.catch_warnings(record=True) as w: 3916 s = stack(a, b) 3917 assert len(w) == 1 3918 assert issubclass(w[-1].category, DeprecationWarning) 3919 with warnings.catch_warnings(record=True) as w: 3920 s = stack([a, b]) 3921 s = stack([a, b], 1) 3922 s = stack([a, b], axis=1) 3923 s = stack(tensors=[a, b]) 3924 s = stack(tensors=[a, b], axis=1) 3925 assert not w 3926 3927 def test_stack_hessian(self): 3928 # Test the gradient of stack when used in hessian, see gh-1589 3929 a = tensor.dvector('a') 3930 b = tensor.dvector('b') 3931 A = stack([a, b]) 3932 B = A.T.dot(A) 3933 Ha, Hb = hessian(B.sum(), [a, b]) 3934 3935 # Try some values 3936 a_v = np.random.rand(4) 3937 b_v = np.random.rand(4) 3938 f = theano.function([a, b], [Ha, Hb]) 3939 Ha_v, Hb_v = f(a_v, b_v) 3940 # The Hessian is always a matrix full of 2 3941 assert Ha_v.shape == (4, 4) 3942 assert Hb_v.shape == (4, 4) 3943 assert np.allclose(Ha_v, 2.) 3944 assert np.allclose(Hb_v, 2.) 3945 3946 def test_stack_hessian2(self): 3947 # Test the hessian macro when the gradient itself does not depend 3948 # on the input (but the cost does) 3949 a = tensor.dvector('a') 3950 b = tensor.dvector('b') 3951 A = stack([a, b]) 3952 Ha, Hb = hessian(A.sum(), [a, b]) 3953 3954 # Try some values 3955 a_v = np.random.rand(4) 3956 b_v = np.random.rand(4) 3957 f = theano.function([a, b], [Ha, Hb]) 3958 Ha_v, Hb_v = f(a_v, b_v) 3959 # The Hessian is always a matrix full of 0 3960 assert Ha_v.shape == (4, 4) 3961 assert Hb_v.shape == (4, 4) 3962 assert np.allclose(Ha_v, 0.) 3963 assert np.allclose(Hb_v, 0.) 3964 3965 def test_join_concatenate_one_element(self): 3966 # Fast test of concatenate as this is an alias for join. 3967 # also test that we remove the Join op if there is only 1 input 3968 m = tensor.fmatrix() 3969 c = tensor.concatenate([m]) 3970 f = theano.function(inputs=[m], outputs=[c], 3971 mode=self.mode.including('local_join_1')) 3972 topo = f.maker.fgraph.toposort() 3973 assert len(topo) == 1 3974 assert isinstance(topo[0].op, DeepCopyOp) 3975 3976 def test_join_vector(self): 3977 a = self.shared(np.array([1, 2, 3], dtype=self.floatX)) 3978 b = as_tensor_variable(np.array([7, 8, 9], dtype=self.floatX)) 3979 3980 s = join(0, a, b) 3981 want = np.array([1, 2, 3, 7, 8, 9]) 3982 out = self.eval_outputs_and_check_join([s]) 3983 self.assertTrue((out == want).all()) 3984 3985 def test_roll(self): 3986 3987 for get_shift in [lambda a:a, lambda x:theano.shared(x)]: 3988 # Test simple 1D example 3989 a = self.shared(np.array([1, 2, 3, 4, 5, 6], dtype=self.floatX)) 3990 b = roll(a, get_shift(2)) 3991 want = np.array([5, 6, 1, 2, 3, 4]) 3992 out = theano.function([], b)() 3993 3994 assert (out == want).all() 3995 3996 # Test simple 1D example with explicit 0 axis 3997 b = roll(a, get_shift(-1), 0) 3998 want = np.array([2, 3, 4, 5, 6, 1]) 3999 out = theano.function([], b)() 4000 4001 assert (out == want).all() 4002 4003 # Test 2D example - ensure that behavior matches np.roll behavior 4004 a = self.shared(np.arange(21).reshape((3, 7)).astype(self.floatX)) 4005 b = roll(a, get_shift(-2), 1) 4006 4007 want = np.roll(a.get_value(borrow=True), -2, 1) 4008 out = theano.function([], b)() 4009 4010 assert (out == want).all() 4011 4012 # Test example when axis < 0 - ensure that behavior matches np.roll behavior 4013 a = self.shared(np.arange(24).reshape((3, 2, 4)).astype(self.floatX)) 4014 b = roll(a, get_shift(-2), -2) 4015 4016 want = np.roll(a.get_value(borrow=True), -2, -2) 4017 out = theano.function([], b)() 4018 4019 assert (out == want).all() 4020 4021 # Test rolling on axis 0 4022 want = np.roll(a.get_value(borrow=True), -2, 0) 4023 b = roll(a, get_shift(-2), 0) 4024 out = theano.function([], b)() 4025 4026 assert (out == want).all() 4027 4028 # Test rolling on default axis with ndim > 1 4029 want = np.roll(a.get_value(borrow=True), 2) 4030 b = roll(a, get_shift(2)) 4031 out = theano.function([], b)() 4032 4033 assert (out == want).all() 4034 4035 # Test rolling on axis 0 with a positive shift that is 4036 # larger than axis size 4037 want = np.roll(a.get_value(borrow=True), 4, 0) 4038 b = roll(a, get_shift(4), 0) 4039 out = theano.function([], b)() 4040 4041 assert (out == want).all() 4042 4043 # Test rolling on axis 0 with a negative shift that is 4044 # larger than axis size 4045 want = np.roll(a.get_value(borrow=True), -4, 0) 4046 b = roll(a, get_shift(-4), 0) 4047 out = theano.function([], b)() 4048 4049 assert (out == want).all() 4050 4051 def test_stack_vector(self): 4052 a = self.shared(np.array([1, 2, 3], dtype=self.floatX)) 4053 b = as_tensor_variable(np.array([7, 8, 9], dtype=self.floatX)) 4054 4055 s = stack([a, b]) 4056 want = np.array([[1, 2, 3], [7, 8, 9]]) 4057 out = self.eval_outputs_and_check_join([s]) 4058 self.assertTrue((out == want).all()) 4059 4060 def test_join_matrix0(self): 4061 a = self.shared(np.array([[1, 2, 3], [4, 5, 6]], 4062 dtype=self.floatX)) 4063 b = as_tensor_variable(np.array([[7, 8, 9]], dtype=self.floatX)) 4064 s = join(0, a, b) 4065 4066 want = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) 4067 out = self.eval_outputs_and_check_join([s]) 4068 self.assertTrue((out == want).all()) 4069 4070 def test_join_matrix1(self): 4071 av = np.array([[.1, .2, .3], [.4, .5, .6]], dtype='float32') 4072 bv = np.array([[.7], [.8]], dtype='float32') 4073 a = self.shared(av) 4074 b = as_tensor_variable(bv) 4075 s = join(1, a, b) 4076 want = np.array([[.1, .2, .3, .7], [.4, .5, .6, .8]], 4077 dtype='float32') 4078 out = self.eval_outputs_and_check_join([s]) 4079 self.assertTrue((out == want).all()) 4080 4081 utt.verify_grad(lambda a, b: join(1, a, b), [av, bv], 4082 mode=self.mode) 4083 4084 def test_join_matrix_dtypes(self): 4085 if "float32" in self.shared.__name__: 4086 raise SkipTest( 4087 "The shared variable constructor" 4088 " need to support other dtype then float32") 4089 # Test mixed dtype. There was a bug that caused crash in the past. 4090 av = np.array([[1, 2, 3], [4, 5, 6]], dtype='int8') 4091 bv = np.array([[7], [8]], dtype='float32') 4092 a = self.shared(av) 4093 b = as_tensor_variable(bv) 4094 s = join(1, a, b) 4095 want = np.array([[1, 2, 3, 7], [4, 5, 6, 8]], dtype='float32') 4096 out = self.eval_outputs_and_check_join([s]) 4097 self.assertTrue((out == want).all()) 4098 4099 grad(s.sum(), b) 4100 grad(s.sum(), a) 4101 utt.verify_grad(lambda b: join(1, a, b), [bv], 4102 eps=1.0e-2, mode=self.mode) 4103 4104 def test_join_matrix_ints(self): 4105 if "float32" in self.shared.__name__: 4106 raise SkipTest( 4107 "The shared variable constructor" 4108 " need to support other dtype then float32") 4109 # Test mixed dtype. There was a bug that caused crash in the past. 4110 av = np.array([[1, 2, 3], [4, 5, 6]], dtype='int8') 4111 bv = np.array([[7], [8]], dtype='int32') 4112 a = self.shared(av) 4113 b = as_tensor_variable(bv) 4114 s = join(1, a, b) 4115 want = np.array([[1, 2, 3, 7], [4, 5, 6, 8]], dtype='float32') 4116 out = self.eval_outputs_and_check_join([s]) 4117 self.assertTrue((out == want).all()) 4118 4119 assert (np.asarray(grad(s.sum(), b).eval()) == 0).all() 4120 assert (np.asarray(grad(s.sum(), a).eval()) == 0).all() 4121 4122 def test_join_matrix1_using_vertical_stack(self): 4123 a = self.shared(np.array([[1, 2, 3], [4, 5, 6]], dtype=self.floatX)) 4124 b = as_tensor_variable(np.array([[7, 8, 9]], dtype=self.floatX)) 4125 c = as_tensor_variable(np.array([[9, 8, 7]], dtype=self.floatX)) 4126 s = vertical_stack(a, b, c) 4127 4128 want = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [9, 8, 7]]) 4129 out = self.eval_outputs_and_check_join([s]) 4130 self.assertTrue((out == want).all()) 4131 4132 def test_join_matrix1_using_horizontal_stack(self): 4133 av = np.array([[.1, .2, .3], [.4, .5, .6]], dtype='float32') 4134 bv = np.array([[.7], [.8]], dtype='float32') 4135 cv = np.array([[.3, .2, .1], [.6, .5, .4]], dtype='float32') 4136 a = self.shared(av) 4137 b = as_tensor_variable(bv) 4138 c = as_tensor_variable(cv) 4139 s = horizontal_stack(a, b, c) 4140 want = np.array([[.1, .2, .3, .7, .3, .2, .1], 4141 [.4, .5, .6, .8, .6, .5, .4]], 4142 dtype='float32') 4143 out = self.eval_outputs_and_check_join([s]) 4144 self.assertTrue((out == want).all()) 4145 4146 utt.verify_grad(lambda a, b: join(1, a, b), [av, bv], 4147 mode=self.mode) 4148 4149 def test_join_matrixV(self): 4150 # variable join axis 4151 v = np.array([[.1, .2, .3], [.4, .5, .6]], dtype=self.floatX) 4152 a = self.shared(v) 4153 b = as_tensor_variable(v) 4154 ax = lscalar() 4155 s = join(ax, a, b) 4156 4157 f = inplace_func([ax], [s], mode=self.mode) 4158 topo = f.maker.fgraph.toposort() 4159 assert [True for node in topo 4160 if isinstance(node.op, type(self.join_op))] 4161 4162 want = np.array([[.1, .2, .3], [.4, .5, .6], 4163 [.1, .2, .3], [.4, .5, .6]]) 4164 got = f(0) 4165 assert np.allclose(got, want) 4166 4167 want = np.array([[.1, .2, .3, .1, .2, .3], 4168 [.4, .5, .6, .4, .5, .6]]) 4169 got = f(1) 4170 assert np.allclose(got, want) 4171 4172 utt.verify_grad(lambda a, b: join(0, a, b), [v, 2 * v], mode=self.mode) 4173 utt.verify_grad(lambda a, b: join(1, a, b), [v, 2 * v], mode=self.mode) 4174 4175 def test_join_matrixV_negative_axis(self): 4176 # variable join negative axis 4177 v = np.array([[.1, .2, .3], [.4, .5, .6]], dtype=self.floatX) 4178 a = self.shared(v) 4179 b = as_tensor_variable(v) 4180 ax = lscalar() 4181 s = join(ax, a, b) 4182 4183 f = inplace_func([ax], [s], mode=self.mode) 4184 topo = f.maker.fgraph.toposort() 4185 assert [True for node in topo 4186 if isinstance(node.op, type(self.join_op))] 4187 4188 want = np.array([[.1, .2, .3, .1, .2, .3], 4189 [.4, .5, .6, .4, .5, .6]]) 4190 4191 got = f(-1) 4192 assert np.allclose(got, want) 4193 4194 want = np.array([[.1, .2, .3], [.4, .5, .6], 4195 [.1, .2, .3], [.4, .5, .6]]) 4196 got = f(-2) 4197 assert np.allclose(got, want) 4198 4199 self.assertRaises(IndexError, f, -3) 4200 4201 def test_join_matrixC_negative_axis(self): 4202 # constant join negative axis 4203 v = np.array([[.1, .2, .3], [.4, .5, .6]], dtype=self.floatX) 4204 a = self.shared(v) 4205 b = as_tensor_variable(v) 4206 4207 s = join(-1, a, b) 4208 f = theano.function([], [s], mode=self.mode) 4209 topo = f.maker.fgraph.toposort() 4210 assert [True for node in topo 4211 if isinstance(node.op, type(self.join_op))] 4212 4213 want = np.array([[.1, .2, .3, .1, .2, .3], 4214 [.4, .5, .6, .4, .5, .6]]) 4215 4216 got = f() 4217 assert np.allclose(got, want) 4218 4219 s = join(-2, a, b) 4220 f = theano.function([], [s], mode=self.mode) 4221 topo = f.maker.fgraph.toposort() 4222 assert [True for node in topo 4223 if isinstance(node.op, type(self.join_op))] 4224 4225 want = np.array([[.1, .2, .3], [.4, .5, .6], 4226 [.1, .2, .3], [.4, .5, .6]]) 4227 4228 got = f() 4229 assert np.allclose(got, want) 4230 4231 self.assertRaises(IndexError, join, -3, a, b) 4232 4233 utt.verify_grad(lambda a, b: join(-1, a, b), [v, 2 * v], 4234 mode=self.mode) 4235 4236 def test_vector_len(self): 4237 x = lscalar('x') 4238 y = dscalar('y') 4239 4240 triple = as_tensor_variable((x, y, 9.0)) 4241 assert 3 == get_vector_length(triple) 4242 4243 a, b, c = triple 4244 f = function([x, y], [b, c, a], mode=self.mode) 4245 topo = f.maker.fgraph.toposort() 4246 assert [True for node in topo if isinstance(node.op, opt.MakeVector)] 4247 4248 assert np.allclose(f(4, 5), [5, 9, 4]) 4249 4250 def test_broadcastable_flag_assignment_mixed_otheraxes(self): 4251 # Test that the broadcastable flags for the output of 4252 # a join operation on non-join axes are True if one or 4253 # more inputs is broadcastable on that dimension. 4254 rng = np.random.RandomState(seed=utt.fetch_seed()) 4255 a_val = rng.rand(1, 4, 1).astype(self.floatX) 4256 b_val = rng.rand(1, 3, 1).astype(self.floatX) 4257 4258 a = self.shared(a_val, broadcastable=(False, False, True)) 4259 b = self.shared(b_val, broadcastable=(True, False, True)) 4260 c = self.join_op(1, a, b) 4261 assert c.type.broadcastable[0] and c.type.broadcastable[2] 4262 assert not c.type.broadcastable[1] 4263 4264 # Opt can remplace the int by a Theano constant 4265 c = self.join_op(theano.tensor.constant(1), a, b) 4266 assert c.type.broadcastable[0] and c.type.broadcastable[2] 4267 assert not c.type.broadcastable[1] 4268 4269 # In case futur opt insert other useless stuff 4270 c = self.join_op(theano.tensor.cast(theano.tensor.constant(1), 4271 dtype="int32"), 4272 a, b) 4273 assert c.type.broadcastable[0] and c.type.broadcastable[2] 4274 assert not c.type.broadcastable[1] 4275 4276 f = function([], c, mode=self.mode) 4277 topo = f.maker.fgraph.toposort() 4278 assert [True for node in topo 4279 if isinstance(node.op, type(self.join_op))] 4280 4281 f() 4282 utt.verify_grad((lambda a, b: join(1, a, b)), [a_val, b_val], rng=rng, 4283 mode=self.mode) 4284 4285 # Should raise an error if dimension 0 does not match 4286 a.set_value(rng.rand(2, 4, 1).astype(self.floatX)) 4287 self.assertRaises(ValueError, f) 4288 4289 def test_broadcastable_flag_assignment_mixed_thisaxes(self): 4290 # Test that the broadcastable flag of the join axis 4291 # is False when some inputs are broadcastable on that 4292 # dimension. 4293 rng = np.random.RandomState(seed=utt.fetch_seed()) 4294 a_val = rng.rand(2, 4, 1).astype(self.floatX) 4295 b_val = rng.rand(1, 4, 1).astype(self.floatX) 4296 4297 a = self.shared(a_val, broadcastable=(False, False, True)) 4298 b = self.shared(b_val, broadcastable=(True, False, True)) 4299 c = self.join_op(0, a, b) 4300 assert not c.type.broadcastable[0] 4301 4302 f = function([], c, mode=self.mode) 4303 topo = f.maker.fgraph.toposort() 4304 assert [True for node in topo 4305 if isinstance(node.op, type(self.join_op))] 4306 4307 f() 4308 utt.verify_grad((lambda a, b: join(0, a, b)), [a_val, b_val], rng=rng, 4309 mode=self.mode) 4310 # Should raise an error if b_val.shape[0] is not 1 4311 # We can't set the value| 4312 self.assertRaises(TypeError, b.set_value, 4313 rng.rand(3, 4, 1).astype(self.floatX)) 4314 a = TensorType(dtype=self.floatX, broadcastable=[0, 0, 1])() 4315 b = TensorType(dtype=self.floatX, broadcastable=[1, 0, 1])() 4316 c = self.join_op(0, a, b) 4317 f = function([a, b], c, mode=self.mode) 4318 bad_b_val = rng.rand(3, 4, 1).astype(self.floatX) 4319 self.assertRaises(TypeError, f, a_val, bad_b_val) 4320 4321 def test_broadcastable_flags_all_broadcastable_on_joinaxis(self): 4322 # Test that joining together several inputs which are all 4323 # broadcastable on the join dimension results in the output 4324 # being non-broadcastable on the join dimension. 4325 rng = np.random.RandomState(seed=utt.fetch_seed()) 4326 a_val = rng.rand(1, 4, 1).astype(self.floatX) 4327 b_val = rng.rand(1, 4, 1).astype(self.floatX) 4328 4329 a = self.shared(a_val, broadcastable=(True, False, True)) 4330 b = self.shared(b_val, broadcastable=(True, False, True)) 4331 c = self.join_op(0, a, b) 4332 assert not c.type.broadcastable[0] 4333 4334 f = function([], c, mode=self.mode) 4335 topo = f.maker.fgraph.toposort() 4336 assert [True for node in topo 4337 if isinstance(node.op, type(self.join_op))] 4338 4339 f() 4340 utt.verify_grad((lambda a, b: join(0, a, b)), [a_val, b_val], rng=rng, 4341 mode=self.mode) 4342 4343 def test_broadcastable_single_input_broadcastable_dimension(self): 4344 # Test that all broadcastable flags are preserved by a 4345 # single-input join. 4346 rng = np.random.RandomState(seed=utt.fetch_seed()) 4347 a_val = rng.rand(1, 4, 1).astype(self.floatX) 4348 a = self.shared(a_val, broadcastable=(True, False, True)) 4349 b = self.join_op(0, a) 4350 assert b.type.broadcastable[0] 4351 assert b.type.broadcastable[2] 4352 assert not b.type.broadcastable[1] 4353 4354 f = function([], b, mode=self.mode) 4355 topo = f.maker.fgraph.toposort() 4356 if theano.config.mode != 'FAST_COMPILE': 4357 assert not [True for node in topo 4358 if isinstance(node.op, type(self.join_op))] 4359 4360 f() 4361 utt.verify_grad((lambda a: join(0, a)), [a_val], rng=rng, 4362 mode=self.mode) 4363 # Should raise an error if length of dimension 0 is not 1 4364 self.assertRaises(TypeError, a.set_value, 4365 rng.rand(2, 4, 1).astype(self.floatX)) 4366 # self.assertRaises(TypeError, f, bad_a_val) 4367 4368 def test_broadcastable_flags_many_dims_and_inputs(self): 4369 # Test that the right broadcastable flags get set for a join 4370 # with many inputs and many input dimensions. 4371 a = TensorType(dtype=self.floatX, broadcastable=[1, 0, 1, 0, 0, 0])() 4372 b = TensorType(dtype=self.floatX, broadcastable=[1, 1, 1, 0, 0, 0])() 4373 c = TensorType(dtype=self.floatX, broadcastable=[1, 0, 0, 0, 0, 0])() 4374 d = TensorType(dtype=self.floatX, broadcastable=[1, 0, 1, 1, 0, 1])() 4375 e = TensorType(dtype=self.floatX, broadcastable=[1, 0, 1, 0, 0, 1])() 4376 f = self.join_op(0, a, b, c, d, e) 4377 fb = f.type.broadcastable 4378 assert not fb[0] and fb[1] and fb[2] and fb[3] and not fb[4] and fb[5] 4379 g = self.join_op(1, a, b, c, d, e) 4380 gb = g.type.broadcastable 4381 assert gb[0] and not gb[1] and gb[2] and gb[3] and not gb[4] and gb[5] 4382 h = self.join_op(4, a, b, c, d, e) 4383 hb = h.type.broadcastable 4384 assert hb[0] and hb[1] and hb[2] and hb[3] and not hb[4] and hb[5] 4385 4386 f = function([a, b, c, d, e], f, mode=self.mode) 4387 topo = f.maker.fgraph.toposort() 4388 assert [True for node in topo 4389 if isinstance(node.op, type(self.join_op))] 4390 4391 rng = np.random.RandomState(seed=utt.fetch_seed()) 4392 a_val = rng.rand(1, 1, 1, 1, 2, 1).astype(self.floatX) 4393 b_val = rng.rand(1, 1, 1, 1, 2, 1).astype(self.floatX) 4394 c_val = rng.rand(1, 1, 1, 1, 2, 1).astype(self.floatX) 4395 d_val = rng.rand(1, 1, 1, 1, 2, 1).astype(self.floatX) 4396 e_val = rng.rand(1, 1, 1, 1, 2, 1).astype(self.floatX) 4397 f(a_val, b_val, c_val, d_val, e_val) 4398 utt.verify_grad((lambda a, b, c, d, e: join(0, a, b, c, d, e)), 4399 [a_val, b_val, c_val, d_val, e_val], rng=rng, 4400 mode=self.mode) 4401 # Should raise an error if length of dimension 0 is not 1 4402 bad_val = rng.rand(2, 1, 1, 1, 2, 1).astype(self.floatX) 4403 self.assertRaises(TypeError, f, bad_val, b_val, c_val, d_val, e_val) 4404 self.assertRaises(TypeError, f, a_val, bad_val, c_val, d_val, e_val) 4405 self.assertRaises(TypeError, f, a_val, b_val, bad_val, d_val, e_val) 4406 self.assertRaises(TypeError, f, a_val, b_val, c_val, bad_val, e_val) 4407 self.assertRaises(TypeError, f, a_val, b_val, c_val, d_val, bad_val) 4408 # Should raise an error if any dimension other than 4 has length != 1 4409 bad_a_val = rng.rand(1, 2, 1, 1, 2, 1).astype(self.floatX) 4410 bad_b_val = rng.rand(1, 1, 1, 1, 2, 2).astype(self.floatX) 4411 bad_c_val = rng.rand(1, 1, 2, 1, 2, 1).astype(self.floatX) 4412 bad_d_val = rng.rand(1, 2, 1, 1, 2, 1).astype(self.floatX) 4413 bad_e_val = rng.rand(1, 1, 1, 2, 2, 1).astype(self.floatX) 4414 self.assertRaises(ValueError, f, bad_a_val, b_val, c_val, d_val, e_val) 4415 self.assertRaises(ValueError, f, a_val, bad_b_val, c_val, d_val, e_val) 4416 self.assertRaises(ValueError, f, a_val, b_val, bad_c_val, d_val, e_val) 4417 self.assertRaises(ValueError, f, a_val, b_val, c_val, bad_d_val, e_val) 4418 self.assertRaises(ValueError, f, a_val, b_val, c_val, d_val, bad_e_val) 4419 4420 def test_infer_shape_join(self): 4421 def get_mat(s1, s2): 4422 return np.asarray(np.random.uniform(size=(s1, s2)), 4423 dtype=self.floatX) 4424 4425 x1 = self.shared(get_mat(3, 4)) 4426 x2 = self.shared(get_mat(2, 4)) 4427 x3 = self.shared(get_mat(1, 4)) 4428 4429 # Test dim 0 4430 z = self.join_op(0, x1, x2, x3) 4431 f = theano.function([], z.shape, mode=self.mode) 4432 topo = f.maker.fgraph.toposort() 4433 4434 out = f() 4435 assert (out == [6, 4]).all() 4436 4437 if theano.config.mode != 'FAST_COMPILE': 4438 for node in f.maker.fgraph.toposort(): 4439 assert not isinstance(node.op, type(self.join_op)) 4440 4441 # Test dim 1 4442 x1.set_value(get_mat(3, 4)) 4443 x2.set_value(get_mat(3, 4)) 4444 x3.set_value(get_mat(3, 5)) 4445 z = self.join_op(1, x1, x2, x3) 4446 f = theano.function([], z.shape, mode=self.mode) 4447 topo = f.maker.fgraph.toposort() 4448 out = f() 4449 assert (out == [3, 13]).all() 4450 4451 if theano.config.mode != 'FAST_COMPILE': 4452 for node in topo: 4453 assert not isinstance(node.op, type(self.join_op)) 4454 4455 with change_flags(compute_test_value='off'): 4456 # Test hide error 4457 x1.set_value(get_mat(3, 4)) 4458 x2.set_value(get_mat(3, 4)) 4459 x3.set_value(get_mat(2, 5)) 4460 if not self.hide_error: 4461 self.assertRaises(ValueError, f) 4462 else: 4463 f() 4464 4465 def test_rebroadcast(self): 4466 # Regression test for a crash that used to happen when rebroadcasting. 4467 x = tensor.TensorType(self.floatX, [False, False, True])() 4468 u = tensor.TensorType(self.floatX, [False, False, True])() 4469 # This line used to crash. 4470 tensor.concatenate([x, -u], axis=2) 4471 4472 def test_concatenate_same(self): 4473 # Test that we can concatenate the same tensor multiple time. 4474 4475 # In the past it was broken on the GPU. 4476 rng = np.random.RandomState(seed=utt.fetch_seed()) 4477 T_shared = self.shared(rng.rand(3, 4).astype(self.floatX)) 4478 Tout = tensor.concatenate([T_shared, T_shared]) 4479 f = function([], Tout, mode=self.mode) 4480 out = f() 4481 if theano.config.mode != 'FAST_COMPILE': 4482 assert [True for node in f.maker.fgraph.toposort() 4483 if isinstance(node.op, type(self.join_op))] 4484 assert np.allclose(out, 4485 np.concatenate([T_shared.get_value(), 4486 T_shared.get_value()])) 4487 4488 def test_mixed_ndim_error(self): 4489 rng = np.random.RandomState(seed=utt.fetch_seed()) 4490 v = self.shared(rng.rand(4).astype(self.floatX)) 4491 m = self.shared(rng.rand(4, 4).astype(self.floatX)) 4492 self.assertRaises(TypeError, self.join_op, 0, v, m) 4493 4494 def test_split_0elem(self): 4495 rng = np.random.RandomState(seed=utt.fetch_seed()) 4496 m = self.shared(rng.rand(4, 6).astype(self.floatX)) 4497 o = self.split_op_class(2)(m, 0, [4, 0]) 4498 f = function([], o, mode=self.mode) 4499 assert any([isinstance(node.op, self.split_op_class) 4500 for node in f.maker.fgraph.toposort()]) 4501 o1, o2 = f() 4502 assert np.allclose(o1, m.get_value(borrow=True)) 4503 assert np.allclose(o2, m.get_value(borrow=True)[4:]) 4504 4505 @change_flags(compute_test_value='off') 4506 def test_split_neg(self): 4507 rng = np.random.RandomState(seed=utt.fetch_seed()) 4508 m = self.shared(rng.rand(4, 6).astype(self.floatX)) 4509 o = self.split_op_class(2)(m, 0, [5, -1]) 4510 f = function([], o, mode=self.mode) 4511 assert any([isinstance(node.op, self.split_op_class) 4512 for node in f.maker.fgraph.toposort()]) 4513 self.assertRaises(ValueError, f) 4514 4515 4516def test_join_inplace(): 4517 # Test join to work inplace. 4518 # 4519 # This function tests the case when several elements are passed to the 4520 # join function but all except one of them are empty. In this case join 4521 # should work inplace and the output should be the view of the non-empty 4522 # element. 4523 s = tensor.lscalar() 4524 x = tensor.vector('x') 4525 z = tensor.zeros((s,)) 4526 4527 join = Join(view=0) 4528 c = join(0, x, z, z) 4529 4530 f = theano.function([theano.In(x, borrow=True), s], theano.Out(c, borrow=True)) 4531 4532 data = np.array([3, 4, 5], dtype=theano.config.floatX) 4533 print(f(data, 0)) 4534 4535 if theano.config.mode not in ["DebugMode", "DEBUG_MODE"]: 4536 assert f(data, 0) is data 4537 assert np.allclose(f(data, 0), [3, 4, 5]) 4538 4539 4540def test_join_oneInput(): 4541 # Test join when only 1 input is given. 4542 # 4543 # This functions tests the case when concatenate is called 4544 # on an array of tensors but the array has only one element. 4545 # In this case, we would like to avoid the computational 4546 # overhead of concatenation of one element. 4547 x_0 = theano.tensor.fmatrix() 4548 x_1 = theano.tensor.fmatrix() 4549 x_2 = theano.tensor.fvector() 4550 join_0 = theano.tensor.concatenate([x_0], axis=1) 4551 join_1 = theano.tensor.concatenate([x_0, x_1, theano.tensor.shape_padright(x_2)], 4552 axis=1) 4553 4554 assert join_0 is x_0 4555 assert join_1 is not x_0 4556 4557 4558class test_comparison(unittest.TestCase): 4559 # Test <, >, <=, >=, == and != 4560 # 4561 # Test that we can do the comparison with different 4562 # combination of tensor(shared and constant variable) with 4563 # ndarray. ndarray cmp tensor was crashing. In a NumPy PR (should 4564 # be in the release 1.8 of NumPy), it will work. So we assert it 4565 # work(futur behavior) or raise an error(current NumPy release). 4566 def setUp(self): 4567 utt.seed_rng() 4568 self.mode = None 4569 self.shared = shared 4570 self.dtypes = ['float64', 'float32', 'complex64', 'complex128'] 4571 4572 def inplace_func(self, inputs, outputs, check_isfinite=None): 4573 mode = self.mode 4574 if check_isfinite is False: 4575 if mode is None: 4576 mode = get_default_mode() 4577 mode.check_isfinite = False 4578 f = inplace_func(inputs, outputs, mode=mode) 4579 return f 4580 4581 def test_gt(self): 4582 for dtype in self.dtypes: 4583 l = np.asarray([0., -1., 1.], dtype=dtype) 4584 r = np.asarray([0., 1., -1.], dtype=dtype) 4585 for x, y, err in [ 4586 (self.shared(l.astype(dtype)), 4587 self.shared(r.astype(dtype)), False), 4588 (l, self.shared(r.astype(dtype)), True), 4589 (tensor.constant(l), self.shared(r.astype(dtype)), False), 4590 (self.shared(l.astype(dtype)), r, False), 4591 (self.shared(l.astype(dtype)), tensor.constant(r), False), 4592 ]: 4593 try: 4594 fn = self.inplace_func([], x > y) 4595 v = fn() 4596 self.assertTrue(np.all(v == (l > r)), (v, (l > r))) 4597 except TypeError: 4598 assert err 4599 4600 def test_lt(self): 4601 for dtype in self.dtypes: 4602 l = np.asarray([0., -1., 1.], dtype=dtype) 4603 r = np.asarray([0., 1., -1.], dtype=dtype) 4604 for x, y, err in [ 4605 (self.shared(l.astype(dtype)), self.shared(r.astype(dtype)), False), 4606 (l, self.shared(r.astype(dtype)), True), 4607 (tensor.constant(l), self.shared(r.astype(dtype)), False), 4608 (self.shared(l.astype(dtype)), r, False), 4609 (self.shared(l.astype(dtype)), tensor.constant(r), False), 4610 ]: 4611 try: 4612 fn = self.inplace_func([], x < y) 4613 v = fn() 4614 self.assertTrue(np.all(v == (l < r)), (v, (l < r))) 4615 except TypeError: 4616 assert err 4617 4618 def test_le(self): 4619 for dtype in self.dtypes: 4620 l = np.asarray([0., -1., 1.], dtype=dtype) 4621 r = np.asarray([0., 1., -1.], dtype=dtype) 4622 for x, y, err in [ 4623 (self.shared(l.astype(dtype)), 4624 self.shared(r.astype(dtype)), False), 4625 (l, self.shared(r.astype(dtype)), True), 4626 (tensor.constant(l), self.shared(r.astype(dtype)), False), 4627 (self.shared(l.astype(dtype)), r, False), 4628 (self.shared(l.astype(dtype)), tensor.constant(r), False), 4629 ]: 4630 try: 4631 fn = self.inplace_func([], x <= y) 4632 v = fn() 4633 self.assertTrue(np.all(v == (l <= r)), (v, (l <= r))) 4634 except TypeError: 4635 assert err 4636 4637 def test_ge(self): 4638 for dtype in self.dtypes: 4639 l = np.asarray([0., -1., 1.], dtype=dtype) 4640 r = np.asarray([0., 1., -1.], dtype=dtype) 4641 for x, y, err in [ 4642 (self.shared(l.astype(dtype)), 4643 self.shared(r.astype(dtype)), False), 4644 (l, self.shared(r.astype(dtype)), True), 4645 (tensor.constant(l), self.shared(r.astype(dtype)), False), 4646 (self.shared(l.astype(dtype)), r, False), 4647 (self.shared(l.astype(dtype)), tensor.constant(r), False), 4648 ]: 4649 try: 4650 fn = self.inplace_func([], x >= y) 4651 v = fn() 4652 self.assertTrue(np.all(v == (l >= r)), (v, (l >= r))) 4653 except TypeError: 4654 assert err 4655 4656 def test_eq(self): 4657 for dtype in self.dtypes: 4658 l = np.asarray([0., -1., 1.], dtype=dtype) 4659 r = np.asarray([0., 1., -1.], dtype=dtype) 4660 for x, y, err in [ 4661 (self.shared(l.astype(dtype)), 4662 self.shared(r.astype(dtype)), False), 4663 (l, self.shared(r.astype(dtype)), True), 4664 (tensor.constant(l), self.shared(r.astype(dtype)), False), 4665 (self.shared(l.astype(dtype)), r, False), 4666 (self.shared(l.astype(dtype)), tensor.constant(r), False), 4667 ]: 4668 try: 4669 fn = self.inplace_func([], eq(x, y)) 4670 v = fn() 4671 self.assertTrue(np.all(v == (l == r)), (v, (l == r))) 4672 except TypeError: 4673 assert err 4674 4675 def test_neq(self): 4676 for dtype in self.dtypes: 4677 l = np.asarray([0., -1., 1.], dtype=dtype) 4678 r = np.asarray([0., 1., -1.], dtype=dtype) 4679 for x, y, err in [ 4680 (self.shared(l.astype(dtype)), 4681 self.shared(r.astype(dtype)), False), 4682 (l, self.shared(r.astype(dtype)), True), 4683 (tensor.constant(l), self.shared(r.astype(dtype)), False), 4684 (self.shared(l.astype(dtype)), r, False), 4685 (self.shared(l.astype(dtype)), tensor.constant(r), False), 4686 ]: 4687 try: 4688 fn = self.inplace_func([], neq(x, y)) 4689 v = fn() 4690 self.assertTrue(np.all(v == (l != r)), (v, (l != r))) 4691 except TypeError: 4692 assert err 4693 4694 def test_isclose(self): 4695 for dtype in self.dtypes: 4696 l = np.asarray( 4697 [0., 1., -1., 0., 4698 np.nan, np.inf, -np.inf, np.inf], 4699 dtype=dtype) 4700 r = np.asarray( 4701 [0., 1.0001, -1.000000000001, np.nan, 4702 np.nan, np.inf, np.inf, 0.], 4703 dtype=dtype) 4704 for x, y, err in [ 4705 (self.shared(l.astype(dtype)), 4706 self.shared(r.astype(dtype)), False), 4707 (l, self.shared(r.astype(dtype)), True), 4708 (constant(l), self.shared(r.astype(dtype)), False), 4709 (self.shared(l.astype(dtype)), r, False), 4710 (self.shared(l.astype(dtype)), constant(r), False), 4711 ]: 4712 try: 4713 o1 = isclose(x, y, equal_nan=False) 4714 fn1 = self.inplace_func([], o1, check_isfinite=False) 4715 4716 o2 = isclose(x, y, equal_nan=True) 4717 fn2 = self.inplace_func([], o2, check_isfinite=False) 4718 4719 v1 = fn1() 4720 v2 = fn2() 4721 self.assertTrue( 4722 np.all( 4723 v1 == np.asarray( 4724 [True, False, True, False, 4725 False, True, False, False], 4726 dtype="bool" 4727 ) 4728 ), 4729 np.all( 4730 v2 == np.asarray( 4731 [True, False, True, False, 4732 True, True, False, False], 4733 dtype="bool" 4734 ) 4735 ) 4736 ) 4737 except TypeError: 4738 if not dtype.startswith('complex'): 4739 raise 4740 assert err 4741 4742 def test_allclose(self): 4743 # equal_nan argument not in current version of numpy allclose, 4744 # force it to False. 4745 for dtype in self.dtypes: 4746 l = np.asarray( 4747 [0., 1., -1., 0., 4748 np.nan, np.inf, -np.inf, np.inf], 4749 dtype=dtype) 4750 r = np.asarray( 4751 [0., 1.0001, -1.000000000001, np.nan, 4752 np.nan, np.inf, np.inf, 0.], 4753 dtype=dtype) 4754 for x, y, err in [ 4755 (self.shared(l.astype(dtype)), 4756 self.shared(r.astype(dtype)), False), 4757 (l, self.shared(r.astype(dtype)), True), 4758 (constant(l), self.shared(r.astype(dtype)), False), 4759 (self.shared(l.astype(dtype)), r, False), 4760 (self.shared(l.astype(dtype)), constant(r), False), 4761 ]: 4762 try: 4763 fn = self.inplace_func([], allclose(x, y, equal_nan=False), 4764 check_isfinite=False) 4765 v = fn() 4766 self.assertTrue(np.all(v == np.allclose(l, r))) 4767 except TypeError: 4768 if not dtype.startswith('complex'): 4769 assert err 4770 4771 4772class test_bitwise(unittest.TestCase): 4773 dtype = ['int8', 'int16', 'int32', 'int64', ] 4774 4775 def test_or(self): 4776 for dtype in self.dtype: 4777 x, y = vector(dtype=dtype), vector(dtype=dtype) 4778 fn = inplace_func([x, y], x | y) 4779 l = theano._asarray([0, 0, 1, 1], dtype=dtype) 4780 r = theano._asarray([0, 1, 0, 1], dtype=dtype) 4781 v = fn(l, r) 4782 self.assertTrue(np.all(v == (operator.or_(l, r))), (l, r, v)) 4783 4784 def test_xor(self): 4785 for dtype in self.dtype: 4786 x, y = vector(dtype=dtype), vector(dtype=dtype) 4787 fn = inplace_func([x, y], x ^ y) 4788 ix = x 4789 ix = inplace.xor_inplace(ix, y) 4790 gn = inplace_func([x, y], ix) 4791 l = theano._asarray([0, 0, 1, 1], dtype=dtype) 4792 r = theano._asarray([0, 1, 0, 1], dtype=dtype) 4793 v = fn(l, r) 4794 self.assertTrue(np.all(v == (operator.xor(l, r))), (l, r, v)) 4795 v = gn(l, r) 4796 # test the in-place stuff 4797 self.assertTrue(np.all(l == np.asarray([0, 1, 1, 0])), l) 4798 4799 def test_and(self): 4800 for dtype in self.dtype: 4801 x, y = vector(dtype=dtype), vector(dtype=dtype) 4802 fn = inplace_func([x, y], x & y) 4803 l = theano._asarray([0, 0, 1, 1], dtype=dtype) 4804 r = theano._asarray([0, 1, 0, 1], dtype=dtype) 4805 v = fn(l, r) 4806 self.assertTrue(np.all(v == (operator.and_(l, r))), (l, r, v)) 4807 4808 def test_inv(self): 4809 for dtype in self.dtype: 4810 x = vector(dtype=dtype) 4811 fn = inplace_func([x], ~x) 4812 for l in [[0, 0, 1, 1], [0, 1, 0, 1], 4813 [0, 0, 1, 1], [0, 1, 0, 1], 4814 [-1, 2 ** 16, 2 ** 16 - 1] 4815 ]: 4816 l = theano._asarray([0, 0, 1, 1], dtype=dtype) 4817 v = fn(l) 4818 self.assertTrue(np.all(v == (~l)), (l, v)) 4819 4820 def test_eye(self): 4821 n = iscalar() 4822 m = iscalar() 4823 k = iscalar() 4824 fn = theano.function([m, n, k], eye(m, n, k)) 4825 self.assertTrue(np.all(fn(5, 6, 1) == np.eye(5, 6, 1))) 4826 4827 4828class T_add(unittest.TestCase): 4829 def setUp(self): 4830 utt.seed_rng() 4831 4832 def test_complex_all_ops(self): 4833 for nbits in (64, 128): 4834 a = shared(np.ones(3, dtype='complex%i' % nbits) + 0.5j) 4835 b = shared(np.ones(3, dtype='complex%i' % nbits) + 1.5j) 4836 tests = (("+", lambda x, y: x + y), 4837 ("-", lambda x, y: x - y), 4838 ("*", lambda x, y: x * y), 4839 ("/", lambda x, y: x / y)) 4840 for s, fn in tests: 4841 f = inplace_func([], fn(a, b)) 4842 # print 'valid output:', fn(a.data, b.data) 4843 # print 'theano output:', f(a.data, b.data) 4844 self.assertTrue(a.type.values_eq_approx(fn( 4845 a.get_value(), b.get_value()), f())) 4846 4847 def test_grad_scalar_l(self): 4848 utt.verify_grad(add, [np.asarray([3.0]), rand(3)]) 4849 4850 def test_grad_scalar_r(self): 4851 utt.verify_grad(add, [rand(3), np.asarray([3.0])]) 4852 4853 def test_grad_row(self): 4854 utt.verify_grad(add, [rand(3, 5), rand(1, 5)]) 4855 4856 def test_grad_col(self): 4857 utt.verify_grad(add, [rand(3, 5), rand(3, 1)]) 4858 4859 4860class T_ceil(unittest.TestCase): 4861 def test_complex(self): 4862 self.assertRaises(TypeError, tensor.ceil, tensor.zvector()) 4863 4864 4865class T_exp(unittest.TestCase): 4866 def test_grad_0(self): 4867 utt.verify_grad(exp, [ 4868 np.asarray([[1.5089518, 1.48439076, -4.7820262], 4869 [2.04832468, 0.50791564, -1.58892269]])]) 4870 4871 def test_grad_1(self): 4872 utt.verify_grad(inplace.exp_inplace, [ 4873 np.asarray([[1.5089518, 1.48439076, -4.7820262], 4874 [2.04832468, 0.50791564, -1.58892269]])]) 4875 4876 if theano.config.cycle_detection == 'fast' and theano.config.mode != 'FAST_COMPILE': 4877 test_grad_1 = unittest.expectedFailure(test_grad_1) 4878 4879 def test_int(self): 4880 x = ivector() 4881 f = function([x], exp(x)) 4882 exp_3 = f([3]) 4883 assert exp_3.dtype == 'float64' 4884 4885 def test_complex(self): 4886 x = zvector() 4887 assert exp(x).dtype == 'complex128' 4888 f = function([x], exp(x)) 4889 exp_3 = f([3 + 2j]) 4890 assert np.allclose(exp_3, np.exp(3 + 2j)) 4891 4892 4893class T_divimpl(unittest.TestCase): 4894 def test_impls(self): 4895 i = iscalar() 4896 ii = lscalar() 4897 d = dscalar() 4898 f = fscalar() 4899 c = cscalar() 4900 4901 assert np.allclose(function([i, d], i / d)(5, 7.0), (5.0 / 7.0)) 4902 assert np.allclose(function([i, d], d / i)(5, 7.0), (7.0 / 5.0)) 4903 assert np.allclose(function([i, f], i / f)(5, 11.0), (5.0 / 11.0)) 4904 assert np.allclose(function([i, f], f / i)(5, 11.0), (11.0 / 5.0)) 4905 assert np.allclose(function([i, ii], i // ii)(5, 3), (5 // 3)) 4906 assert np.allclose(function([i, ii], ii // i)(5, 3), (3 // 5)) 4907 assert np.allclose(function([i, ii], true_div(i, ii))(5, 3), 4908 (5. / 3.)) 4909 assert np.allclose(function([i, ii], true_div(ii, i))(5, 3), 4910 (3. / 5.)) 4911 assert np.allclose(function([i, c], i / c)(5, np.complex(5, 3)), 4912 (5. / (5 + 3j))) 4913 assert np.allclose(function([i, c], c / i)(5, np.complex(5, 3)), 4914 ((5 + 3j) / 5.)) 4915 4916 4917class T_mean(unittest.TestCase): 4918 def test_regression_mean_of_ndarray_failure(self): 4919 try: 4920 tensor.mean(np.zeros(1)) 4921 except AttributeError: 4922 self.fail() 4923 4924 def test_mean_f16(self): 4925 x = tensor.vector(dtype='float16') 4926 y = x.mean() 4927 f = theano.function([x], y) 4928 utt.assert_allclose(f(np.ones((100000,), dtype='float16')), 1.0) 4929 4930 def test0(self): 4931 # Simple test... 4932 x = tensor.vector() 4933 f = theano.function([x], tensor.mean(x)) 4934 data = rand(50) 4935 assert np.allclose(f(data), np.mean(data)) 4936 4937 def test_list(self): 4938 ll = [theano.shared(0.), theano.shared(2.)] 4939 tensor.mean(ll).eval() == 1 4940 4941 4942class test_matinv(unittest.TestCase): 4943 4944 def mat_reciprocal(self, dim): 4945 # symbolic program 4946 # broadcastable=[False,False] means that the shape of matrix is two dimensional, 4947 # and none of the dimensions are constrained to have length 1. 4948 # Note that TensorType's constructor does not actually allocate any memory. 4949 # TODO: Make TensorType syntax more explicit, and maybe give shape or number of dimensions. 4950 4951 rng = np.random.RandomState(seed=utt.fetch_seed()) 4952 4953 a, b = matrices('ab') 4954 ab = a * b 4955 # Here, as_tensor_variable actually uses the data allocated by np. 4956 diff = ab - as_tensor_variable(np.ones((dim, dim), 4957 dtype=config.floatX)) 4958 # Sum of squared errors 4959 ssdiff = sum((diff ** 2.0)) 4960 4961 g_b = grad(ssdiff, b) 4962 4963 # compilation to function 4964 # [a,b] are the inputs, [ssdiff,g_b] are the outputs 4965 fn = inplace_func([a, b], [ssdiff, g_b]) 4966 4967 # use the function 4968 x = rng.rand(dim, dim) + 0.1 # Initialized s.t. x is not too tiny 4969 w = rng.rand(dim, dim) 4970 x = np.asarray(x, dtype=config.floatX) 4971 w = np.asarray(w, dtype=config.floatX) 4972 4973 for i in xrange(100): 4974 ssd, gw = fn(x, w) 4975 # print ssd, x*w, x, w 4976 if i == 0: 4977 ssd0 = ssd 4978 w -= 0.4 * gw 4979 4980 return ssd0, ssd 4981 4982 def test_reciprocal(self): 4983 # Matrix reciprocal by gradient descent 4984 ssd0, ssd = self.mat_reciprocal(3) 4985 4986 rng = np.random.RandomState(seed=utt.fetch_seed()) 4987 # hand-coded numpy implementation for verification 4988 x = rng.rand(3, 3) + 0.1 4989 w = rng.rand(3, 3) 4990 x = np.asarray(x, dtype=config.floatX) 4991 w = np.asarray(w, dtype=config.floatX) 4992 ones = np.ones((3, 3), dtype=config.floatX) 4993 4994 myssd0 = np.sum((x * w - ones) ** 2.0) 4995 # we want at least a test that is not too fast. So we make one here. 4996 for i in xrange(100): 4997 gw = 2 * (x * w - ones) * x # derivative of dMSE/dw 4998 myssd = np.sum((x * w - ones) ** 2) 4999 w -= 0.4 * gw 5000 self.assertAlmostEqual(ssd0, myssd0) 5001 self.assertAlmostEqual(ssd, myssd) 5002 5003 5004class t_dot(unittest.TestCase): 5005 def setUp(self): 5006 utt.seed_rng() 5007 5008 def cmp_dot(self, x, y): 5009 # x, y are matrices or numbers 5010 def spec(x): 5011 x = np.asarray(x) 5012 return type(x), x.dtype, x.shape 5013 nz = np.dot(x, y) 5014 tz = eval_outputs([dot(as_tensor_variable(x), as_tensor_variable(y))]) 5015 self.assertTrue(tz.dtype == nz.dtype, 5016 (tz.dtype, tz.dtype.num, nz.dtype, nz.dtype.num)) 5017 self.assertTrue(tz.shape == nz.shape, (tz.shape, nz.shape)) 5018 utt.assert_allclose(nz, tz, rtol=1e-4, atol=1e-4) 5019 5020 def test_Op_dims(self): 5021 # _dot is a Dot op instance 5022 _dot = theano.tensor.basic._dot 5023 d0 = scalar() 5024 d1 = vector() 5025 d2 = matrix() 5026 d3 = tensor3() 5027 5028 self.assertRaises(TypeError, _dot, d0, d0) 5029 self.assertRaises(TypeError, _dot, d0, d1) 5030 self.assertRaises(TypeError, _dot, d0, d2) 5031 self.assertRaises(TypeError, _dot, d0, d3) 5032 self.assertRaises(TypeError, _dot, d1, d0) 5033 _dot(d1, d1) 5034 _dot(d1, d2) 5035 self.assertRaises(TypeError, _dot, d1, d3) 5036 self.assertRaises(TypeError, _dot, d2, d0) 5037 _dot(d2, d1) 5038 _dot(d2, d2) 5039 self.assertRaises(TypeError, _dot, d2, d3) 5040 self.assertRaises(TypeError, _dot, d3, d0) 5041 self.assertRaises(TypeError, _dot, d3, d1) 5042 self.assertRaises(TypeError, _dot, d3, d2) 5043 self.assertRaises(TypeError, _dot, d3, d3) 5044 5045 def test_dot_0d_0d(self): 5046 self.cmp_dot(rand(), rand()) 5047 5048 def test_dot_0d_1d(self): 5049 self.cmp_dot(rand(), rand(5)) 5050 5051 def test_dot_0d_2d(self): 5052 self.cmp_dot(rand(), rand(6, 7)) 5053 5054 def test_dot_0d_3d(self): 5055 self.cmp_dot(rand(), rand(8, 6, 7)) 5056 5057 def test_dot_1d_0d(self): 5058 self.cmp_dot(rand(5), rand()) 5059 5060 def test_dot_1d_1d(self): 5061 self.cmp_dot(rand(5), rand(5)) 5062 5063 def test_dot_1d0_1d0(self): 5064 self.cmp_dot(rand(0), rand(0)) 5065 5066 # numpy return matrix not aligned... 5067 def test_dot_1d_1d0(self): 5068 self.assertRaises(ValueError, self.cmp_dot, rand(5), rand(0)) 5069 5070 # numpy return matrix not aligned... 5071 def test_dot_1d0_1d(self): 5072 self.assertRaises(ValueError, self.cmp_dot, rand(0), rand(5)) 5073 5074 def test_dot_1d_2d(self): 5075 self.cmp_dot(rand(6), rand(6, 7)) 5076 5077 def test_dot_1d0_2d(self): 5078 self.cmp_dot(rand(0), rand(0, 7)) 5079 5080 def test_dot_1d_2d0(self): 5081 self.cmp_dot(rand(6), rand(6, 0)) 5082 5083 def test_dot_1d0_2d0(self): 5084 self.cmp_dot(rand(0), rand(0, 0)) 5085 5086 def test_dot_1d_3d(self): 5087 self.cmp_dot(rand(6), rand(8, 6, 7)) 5088 5089 def test_dot_2d_0d(self): 5090 self.cmp_dot(rand(5, 6), rand()) 5091 5092 def test_dot_2d_1d(self): 5093 self.cmp_dot(rand(5, 6), rand(6)) 5094 5095 def test_dot_2d0_1d(self): 5096 self.cmp_dot(rand(0, 6), rand(6)) 5097 5098 def test_dot_2d_1d0(self): 5099 self.cmp_dot(rand(5, 0), rand(0)) 5100 5101 def test_dot_2d0_1d0(self): 5102 self.cmp_dot(rand(0, 0), rand(0)) 5103 5104 def test_dot_2d_2d(self): 5105 self.cmp_dot(rand(5, 6), rand(6, 7)) 5106 5107 def test_dot_2d0_2d(self): 5108 self.cmp_dot(rand(0, 6), rand(6, 7)) 5109 5110 def test_dot_2d_2d0(self): 5111 self.cmp_dot(rand(5, 6), rand(6, 0)) 5112 5113 def test_dot_2d0_2d0(self): 5114 self.cmp_dot(rand(0, 6), rand(6, 0)) 5115 5116 def test_dot_2d_0_2d(self): 5117 self.cmp_dot(rand(5, 0), rand(0, 7)) 5118 5119 def test_dot_2d0_0_2d0(self): 5120 self.cmp_dot(rand(0, 6), rand(6, 0)) 5121 5122 def test_dot_2d_3d(self): 5123 self.cmp_dot(rand(5, 6), rand(8, 6, 7)) 5124 5125 def test_dot_3d_0d(self): 5126 self.cmp_dot(rand(4, 5, 6), rand()) 5127 5128 def test_dot_3d_1d(self): 5129 self.cmp_dot(rand(4, 5, 6), rand(6)) 5130 5131 def test_dot_3d_2d(self): 5132 self.cmp_dot(rand(4, 5, 6), rand(6, 7)) 5133 5134 def test_dot_3d_3d(self): 5135 self.cmp_dot(rand(4, 5, 6), rand(8, 6, 7)) 5136 5137 def not_aligned(self, x, y): 5138 ctv_backup = config.compute_test_value 5139 config.compute_test_value = 'off' 5140 try: 5141 z = dot(x, y) 5142 finally: 5143 config.compute_test_value = ctv_backup 5144 # constant folding will complain to _logger that things are not aligned 5145 # this is normal, testers are not interested in seeing that output. 5146 _logger = logging.getLogger('theano.gof.opt') 5147 oldlevel = _logger.level 5148 _logger.setLevel(logging.CRITICAL) 5149 try: 5150 try: 5151 eval_outputs([z]) 5152 assert False # should have raised exception 5153 except ValueError as e: 5154 e0 = exc_message(e) 5155 self.assertTrue( 5156 # Reported by numpy. 5157 e0.split()[1:4] == ['are', 'not', 'aligned'] or 5158 # Reported by blas or Theano. 5159 e0.split()[0:2] == ['Shape', 'mismatch:'] or 5160 # Reported by Theano perform 5161 (e0.split()[0:4] == 5162 ['Incompatible', 'shapes', 'for', 'gemv']) or 5163 e) 5164 finally: 5165 _logger.setLevel(oldlevel) 5166 5167 def test_align_1_1(self): 5168 self.not_aligned(rand(5), rand(6)) 5169 5170 def test_align_1_2(self): 5171 self.not_aligned(rand(5), rand(6, 4)) 5172 5173 def test_align_1_3(self): 5174 self.not_aligned(rand(5), rand(6, 4, 7)) 5175 5176 def test_align_2_1(self): 5177 self.not_aligned(rand(5, 4), rand(6)) 5178 5179 def test_align_2_2(self): 5180 self.not_aligned(rand(5, 4), rand(6, 7)) 5181 5182 def test_align_2_3(self): 5183 self.not_aligned(rand(5, 4), rand(6, 7, 8)) 5184 5185 def test_align_3_1(self): 5186 self.not_aligned(rand(5, 4, 3), rand(6)) 5187 5188 def test_align_3_2(self): 5189 self.not_aligned(rand(5, 4, 3), rand(6, 7)) 5190 5191 def test_align_3_3(self): 5192 self.not_aligned(rand(5, 4, 3), rand(6, 7, 8)) 5193 5194 def test_grad(self): 5195 utt.verify_grad(dot, [rand(2, 3), rand(3, 2)]) 5196 utt.verify_grad(dot, [rand(2), rand(2, 3)]) 5197 utt.verify_grad(dot, [rand(3, 2), rand(2)]) 5198 utt.verify_grad(dot, [rand(2), rand(2)]) 5199 utt.verify_grad(dot, [rand(), rand(2)]) 5200 utt.verify_grad(dot, [rand(), rand(2, 5)]) 5201 utt.verify_grad(dot, [rand(2), rand()]) 5202 utt.verify_grad(dot, [rand(2, 5), rand()]) 5203 utt.verify_grad(dot, [rand(2, 3, 4), rand(4)]) 5204 utt.verify_grad(dot, [rand(3), rand(2, 3, 4)]) 5205 utt.verify_grad(dot, [rand(4, 3), rand(2, 3, 4)]) 5206 utt.verify_grad(dot, [rand(2, 3, 4), rand(4, 5)]) 5207 utt.verify_grad(dot, [rand(2, 3, 4), rand(3, 4, 5)]) 5208 5209 @attr('slow') 5210 def test_broadcastable_patterns(self): 5211 5212 # 5213 # These examples should all work because we broadcastable or 5214 # no, all dimensions of all results have size 1. 5215 # 5216 def val_for(r): 5217 if r.dtype.startswith('complex'): 5218 # We want to test complex at the same time, so we give a value 5219 # To the imaginary component. 5220 # This strange way of doing things is the only way that worked 5221 # on numpy 1.4.1 5222 if r.ndim == 0: 5223 return np.asarray(np.complex(1.1, 2.1), 5224 dtype=r.dtype) 5225 if r.ndim == 1: 5226 if r.dtype == 'complex64': 5227 return np.complex64([np.complex(1.2, 2.2)]) 5228 elif r.dtype == 'complex128': 5229 return np.complex128([np.complex(1.2, 2.2)]) 5230 elif r.ndim == 2: 5231 if r.dtype == 'complex64': 5232 return np.complex64([[np.complex(1.3, 2.3)]]) 5233 elif r.dtype == 'complex128': 5234 return np.complex128([[np.complex(1.3, 2.3)]]) 5235 5236 if r.ndim == 0: 5237 return np.asarray(1.1, dtype=r.dtype) 5238 if r.ndim == 1: 5239 return np.asarray([1.2], dtype=r.dtype) 5240 elif r.ndim == 2: 5241 return np.asarray([[1.3]], dtype=r.dtype) 5242 raise ValueError() 5243 5244 for dtype0 in ('float32', 'float64', 'complex64'): 5245 for dtype1 in ('float32', 'complex64', 'complex128'): 5246 for bc0 in ((True,), (False,), (True, True), 5247 (True, False), (False, True), 5248 (False, False)): 5249 x = TensorType(dtype=dtype0, broadcastable=bc0)() 5250 for bc1 in ((True,), (False,), (True, True), 5251 (True, False), (False, True), 5252 (False, False)): 5253 5254 y = TensorType(dtype=dtype1, broadcastable=bc1)() 5255 z = dot(x, y) 5256 t = TensorType(dtype=dtype0, 5257 broadcastable=z.broadcastable)() 5258 5259 rval = z * 3 + 2 * t 5260 f = function([x, y, t], rval) 5261 xval = val_for(x) 5262 yval = val_for(y) 5263 tval = val_for(t) 5264 5265 f(xval, yval, tval) # debugmode checks result 5266 if (dtype0.startswith('float') and 5267 dtype1.startswith('float')): 5268 g = grad(z.sum(), x) 5269 assert g.broadcastable == x.broadcastable 5270 g = grad(z.sum(), y) 5271 assert g.broadcastable == y.broadcastable 5272 5273 5274class T_tensorfromscalar(unittest.TestCase): 5275 def test0(self): 5276 s = scal.constant(56) 5277 t = tensor_from_scalar(s) 5278 self.assertTrue(t.owner.op is tensor_from_scalar) 5279 self.assertTrue(t.type.broadcastable == (), t.type.broadcastable) 5280 self.assertTrue(t.type.ndim == 0, t.type.ndim) 5281 self.assertTrue(t.type.dtype == s.type.dtype) 5282 5283 v = eval_outputs([t]) 5284 5285 self.assertTrue(v == 56, v) 5286 self.assertTrue(isinstance(v, np.ndarray)) 5287 self.assertTrue(v.shape == (), v.shape) 5288 5289 def test1(self): 5290 s = scal.constant(56) 5291 t = as_tensor_variable(s) 5292 self.assertTrue(t.owner.op is tensor_from_scalar) 5293 self.assertTrue(t.type.broadcastable == (), t.type.broadcastable) 5294 self.assertTrue(t.type.ndim == 0, t.type.ndim) 5295 self.assertTrue(t.type.dtype == s.type.dtype) 5296 5297 v = eval_outputs([t]) 5298 5299 self.assertTrue(v == 56, v) 5300 self.assertTrue(isinstance(v, np.ndarray)) 5301 self.assertTrue(v.shape == (), v.shape) 5302 5303 g = grad(t, s) 5304 self.assertTrue(eval_outputs([g]) == 0.) 5305 5306 def test2(self): 5307 s = scal.constant(56.) 5308 t = as_tensor_variable(s) 5309 self.assertTrue(t.owner.op is tensor_from_scalar) 5310 self.assertTrue(t.type.broadcastable == (), t.type.broadcastable) 5311 self.assertTrue(t.type.ndim == 0, t.type.ndim) 5312 self.assertTrue(t.type.dtype == s.type.dtype) 5313 5314 v = eval_outputs([t]) 5315 5316 self.assertTrue(v == 56., v) 5317 self.assertTrue(isinstance(v, np.ndarray)) 5318 self.assertTrue(v.shape == (), v.shape) 5319 5320 g = grad(t, s) 5321 self.assertTrue(eval_outputs([g]) == 1.) 5322 5323 5324class T_scalarfromtensor(unittest.TestCase): 5325 def test0(self): 5326 tt = constant(56) # scal.constant(56) 5327 ss = scalar_from_tensor(tt) 5328 self.assertTrue(ss.owner.op is scalar_from_tensor) 5329 self.assertTrue(ss.type.dtype == tt.type.dtype) 5330 5331 v = eval_outputs([ss]) 5332 5333 self.assertTrue(v == 56, v) 5334 if config.cast_policy == 'custom': 5335 self.assertTrue(isinstance(v, np.int8)) 5336 elif config.cast_policy in ('numpy', 'numpy+floatX'): 5337 self.assertTrue(isinstance( 5338 v, getattr(np, str(np.asarray(56).dtype)))) 5339 else: 5340 raise NotImplementedError(config.cast_policy) 5341 self.assertTrue(v.shape == (), v.shape) 5342 tt = lscalar() 5343 ss = scalar_from_tensor(tt) 5344 ss.owner.op.grad([tt], [ss]) 5345 fff = function([tt], ss) 5346 v = fff(np.asarray(5)) 5347 self.assertTrue(v == 5, v) 5348 self.assertTrue(isinstance(v, np.int64)) 5349 self.assertTrue(v.shape == (), v.shape) 5350 5351 5352class test_grad(unittest.TestCase): 5353 class Obj1(gof.op.Op): 5354 def __init__(self): 5355 self.gval0 = scalar('e') 5356 self.gval1 = scalar('f') 5357 5358 def make_node(self): 5359 inputs = [scalar('a'), scalar('c')] 5360 outputs = [scalar('b'), scalar('d')] 5361 return gof.Apply(self, inputs, outputs) 5362 5363 def grad(self, inp, grads): 5364 x0, x1 = inp 5365 gz0, gz1 = grads 5366 return self.gval0, self.gval1 5367 5368 def test_1param(self): 5369 # grad: Test passing a single variable param 5370 o = test_grad.Obj1() 5371 a1 = o.make_node() 5372 self.assertTrue(o.gval0 is tensor.grad(a1.outputs[0], a1.inputs[0])) 5373 5374 def test_Nparam(self): 5375 # grad: Test passing multiple variable params 5376 o = test_grad.Obj1() 5377 a1 = o.make_node() 5378 g0, g1 = grad(a1.outputs[0], a1.inputs) 5379 g0.name = None 5380 self.assertTrue(o.gval0 is g0) 5381 self.assertTrue(o.gval1 is g1) 5382 5383 def test_grad_keep_type(self): 5384 # Tests that the theano grad method returns a list if it is passed a list 5385 # and a single variable if it is passed a single variable. 5386 # pylearn2 depends on theano behaving this way. This functionality has been 5387 # added three times and erroneously removed twice. If you do anything that 5388 # requires changing this test or making it fail you are almost certainly 5389 # making a common mistake, NOT fixing something. 5390 5391 X = tensor.matrix() 5392 y = X.sum() 5393 5394 G = tensor.grad(y, [X]) 5395 5396 assert isinstance(G, list) 5397 5398 G = tensor.grad(y, X) 5399 5400 assert not isinstance(G, list) 5401 5402 def test_1None_rval(self): 5403 # grad: Test returning a single zero value from grad 5404 o = test_grad.Obj1() 5405 a1 = o.make_node() 5406 g = grad(a1.outputs[0], a1.outputs[1], 5407 disconnected_inputs='ignore') 5408 self.assertTrue(g.owner.op == fill) 5409 self.assertTrue(g.owner.inputs[1].data == 0) 5410 self.assertRaises(TypeError, grad, a1.outputs[0], 'wtf') 5411 5412 def test_NNone_rval(self): 5413 # grad: Test returning some zero value from grad 5414 o = test_grad.Obj1() 5415 a1 = o.make_node() 5416 g0, g1, g2 = grad(a1.outputs[0], a1.inputs + [scalar('z')], 5417 disconnected_inputs='ignore') 5418 self.assertTrue(o.gval0 is g0) 5419 self.assertTrue(o.gval1 is g1) 5420 self.assertTrue(g2.owner.op == fill) 5421 self.assertTrue(g2.owner.inputs[1].data == 0) 5422 5423 def test_zero_gradient_shape(self): 5424 # Ensure that a zero gradient has the proper shape. 5425 x = dmatrix() 5426 f = theano.function([x], grad(dscalar(), x, 5427 disconnected_inputs='ignore')) 5428 a = np.ones((3, 7)) 5429 self.assertTrue((f(a) == 0).all()) # Zero gradient. 5430 self.assertTrue(a.shape == f(a).shape) # With proper shape. 5431 5432 def test_cost_is_scalar(self): 5433 # grad: Test that a non-scalar cost raises a TypeError 5434 v = vector() 5435 m = matrix() 5436 # grad(v,...) and grad(m,...) should fail 5437 self.assertRaises(TypeError, grad, v, v) 5438 self.assertRaises(TypeError, grad, m, m) 5439 5440 5441class T_op_cache(unittest.TestCase): 5442 def setUp(self): 5443 utt.seed_rng() 5444 5445 def test0(self): 5446 # trigger bug in ticket #162 5447 v = matrix() 5448 v.name = 'v' 5449 gv = fill(v / v, 1.0) / v - (fill(v / v, 1.0) * v) / (v * v) 5450 fn_py = inplace_func([v], gv) 5451 fn_c_or_py = inplace_func([v], gv) 5452 5453 a = rand(5, 2).astype(config.floatX) 5454 self.assertTrue(np.all(fn_py(a) == fn_c_or_py(a))) 5455 5456 5457class T_reshape(utt.InferShapeTester, utt.TestOptimizationMixin): 5458 def __init__(self, name, shared=tensor._shared, op=Reshape, mode=None, 5459 ignore_topo=(DeepCopyOp, opt.MakeVector, 5460 opt.Shape_i, DimShuffle, theano.tensor.Elemwise)): 5461 self.shared = shared 5462 self.op = op 5463 # The tag canonicalize is needed for the shape test in FAST_COMPILE 5464 self.mode = mode 5465 self.ignore_topo = ignore_topo 5466 super(T_reshape, self).__init__(name) 5467 5468 def function(self, inputs, outputs, ignore_empty=False): 5469 f = function(inputs, outputs, mode=self.mode) 5470 if self.mode is not None or theano.config.mode != "FAST_COMPILE": 5471 topo = f.maker.fgraph.toposort() 5472 topo_ = [node for node in topo if not isinstance(node.op, 5473 self.ignore_topo)] 5474 if ignore_empty: 5475 assert len(topo_) <= 1, topo_ 5476 else: 5477 assert len(topo_) == 1, topo_ 5478 if len(topo_) > 0: 5479 assert type(topo_[0].op) is self.op 5480 return f 5481 5482 def test_reshape(self): 5483 a = dvector() 5484 b = dmatrix() 5485 d = dmatrix() 5486 5487 # basic to 1 dim(without list) 5488 c = reshape(b, as_tensor_variable(6), ndim=1) 5489 f = self.function([b], c) 5490 5491 b_val1 = np.asarray([[0, 1, 2], [3, 4, 5]]) 5492 c_val1 = np.asarray([0, 1, 2, 3, 4, 5]) 5493 b_val2 = b_val1.T 5494 c_val2 = np.asarray([0, 3, 1, 4, 2, 5]) 5495 5496 f_out1 = f(b_val1) 5497 f_out2 = f(b_val2) 5498 assert np.all(f_out1 == c_val1), (f_out1, c_val1) 5499 assert np.all(f_out2 == c_val2), (f_out2, c_val2) 5500 # print f.maker.fgraph.toposort() 5501 # check that we remove the useless reshape 5502 5503 # basic to 1 dim(with list) 5504 c = reshape(b, (as_tensor_variable(6),), ndim=1) 5505 f = self.function([b], c) 5506 assert np.all(f(np.asarray([[0, 1, 2], [3, 4, 5]])) == 5507 np.asarray([0, 1, 2, 3, 4, 5])) 5508 # print f.maker.fgraph.toposort() 5509 # check that we remove the useless reshape 5510 5511 # basic to shape object of same ndim 5512 c = reshape(b, d.shape) 5513 f = self.function([b, d], c) 5514 assert np.all(f(np.asarray([[0, 1, 2], [3, 4, 5]]), 5515 [[0, 1], [2, 3], [4, 5]]) == 5516 np.asarray([[0, 1], [2, 3], [4, 5]])) 5517 5518 # basic to 2 dims 5519 c = reshape(a, [2, 3]) 5520 f = self.function([a], c) 5521 assert np.all(f(np.asarray([0, 1, 2, 3, 4, 5])) == 5522 np.asarray([[0, 1, 2], [3, 4, 5]])) 5523 5524 # test that it works without inplace operations 5525 a_val = np.asarray([0, 1, 2, 3, 4, 5]) 5526 a_val_copy = np.asarray([0, 1, 2, 3, 4, 5]) 5527 b_val = np.asarray([[0, 1, 2], [3, 4, 5]]) 5528 5529 f_sub = self.function([a, b], c - b) 5530 assert np.all(f_sub(a_val, b_val) == 0.0) 5531 assert np.all(a_val == a_val_copy) 5532 5533 # test that it works with inplace operations 5534 a_val = theano._asarray([0, 1, 2, 3, 4, 5], dtype='float64') 5535 a_val_copy = theano._asarray([0, 1, 2, 3, 4, 5], dtype='float64') 5536 b_val = theano._asarray([[0, 1, 2], [3, 4, 5]], dtype='float64') 5537 5538 f_sub = self.function([a, b], c - b) 5539 assert np.all(f_sub(a_val, b_val) == 0.0) 5540 assert np.all(a_val == a_val_copy) 5541 5542 # verify gradient 5543 def just_vals(v): 5544 return Reshape(2)(v, theano._asarray([2, 3], dtype='int32')) 5545 utt.verify_grad(just_vals, [a_val], mode=self.mode) 5546 5547 # test infer_shape 5548 self._compile_and_check([a], [c], (a_val,), self.op) 5549 5550 # test broadcast flag for constant value of 1 5551 c = reshape(b, (b.shape[0], b.shape[1], 1)) 5552 # That reshape may get replaced with a dimshuffle, with is ignored, 5553 # so we pass "ignore_empty=True" 5554 f = self.function([b], c, ignore_empty=True) 5555 assert np.all(f(np.asarray([[0, 1, 2], [3, 4, 5]])) == 5556 np.asarray([[[0], [1], [2]], [[3], [4], [5]]])) 5557 assert (f.maker.fgraph.toposort()[-1].outputs[0].type.broadcastable == 5558 (False, False, True)) 5559 5560 # test broadcast flag for constant value of 1 if it cannot be 5561 # replaced with dimshuffle 5562 c = reshape(b, (b.shape[1], b.shape[0], 1)) 5563 f = self.function([b], c, ignore_empty=True) 5564 assert np.all(f(np.asarray([[0, 1, 2], [3, 4, 5]])) == 5565 np.asarray([[[0], [1]], [[2], [3]], [[4], [5]]])) 5566 assert (f.maker.fgraph.toposort()[-1].outputs[0].type.broadcastable == 5567 (False, False, True)) 5568 5569 def test_m1(self): 5570 t = tensor3() 5571 rng = np.random.RandomState(seed=utt.fetch_seed()) 5572 val = rng.uniform(size=(3, 4, 5)).astype(config.floatX) 5573 for out in [t.reshape([-1]), t.reshape([-1, 5]), 5574 t.reshape([5, -1]), t.reshape([5, -1, 3])]: 5575 self._compile_and_check([t], [out], [val], self.op) 5576 5577 def test_reshape_long_in_shape(self): 5578 v = dvector('v') 5579 r = v.reshape((v.shape[0], L(1))) 5580 print(r.eval({v: np.arange(5.)})) 5581 assert np.allclose(r.eval({v: np.arange(5.)}).T, 5582 np.arange(5.)) 5583 5584 def test_bad_shape(self): 5585 a = matrix('a') 5586 shapes = ivector('shapes') 5587 rng = np.random.RandomState(seed=utt.fetch_seed()) 5588 a_val = rng.uniform(size=(3, 4)).astype(config.floatX) 5589 5590 # Test reshape to 1 dim 5591 r = a.reshape(shapes, ndim=1) 5592 5593 f = self.function([a, shapes], r) 5594 self.assertRaises(ValueError, f, a_val, [13]) 5595 5596 # Test reshape to 2 dim 5597 r = a.reshape(shapes, ndim=2) 5598 5599 f = self.function([a, shapes], r) 5600 5601 self.assertRaises(ValueError, f, a_val, [-1, 5]) 5602 self.assertRaises(ValueError, f, a_val, [7, -1]) 5603 self.assertRaises(ValueError, f, a_val, [7, 5]) 5604 self.assertRaises(ValueError, f, a_val, [-1, -1]) 5605 5606 def test_0(self): 5607 x = fvector('x') 5608 f = self.function([x], x.reshape((0, 100))) 5609 assert f(np.ndarray((0,), dtype='float32')).shape == (0, 100) 5610 5611 def test_empty_shp(self): 5612 const = theano.tensor.constant([1]).reshape(()) 5613 f = function([], const) 5614 assert f().shape == () 5615 5616 5617def test_make_column_matrix_broadcastable(): 5618 # The goal of the operation made by `b` is to ensure the second dimension 5619 # of the column matrix is broadcastable. 5620 a = tensor.dmatrix() 5621 b = a.reshape((a.shape[0], )).dimshuffle(0, 'x') 5622 f = function([a], b) 5623 assert (f(np.zeros((3, 1))) + np.ones(2) == np.ones((3, 2))).all() 5624 5625 5626def test_flatten_outdimNone(): 5627 a = dmatrix() 5628 c = flatten(a) 5629 f = inplace_func([a], c) 5630 a_val = theano._asarray([[0, 1, 2], [3, 4, 5]], dtype='float64') 5631 c_val = theano._asarray([0, 1, 2, 3, 4, 5], dtype='float64') 5632 assert np.all(f(a_val) == c_val) 5633 f = inplace_func([a], c) 5634 assert np.all(f(a_val) == c_val) 5635 5636 utt.verify_grad(flatten, [a_val]) 5637 5638 5639def test_flatten_scalar(): 5640 a = dscalar() 5641 c = flatten(a) 5642 f = inplace_func([a], c) 5643 a_val = theano._asarray(3.0, dtype='float64') 5644 c_val = theano._asarray([3.0], dtype='float64') 5645 assert np.all(f(a_val) == c_val) 5646 f = inplace_func([a], c) 5647 assert np.all(f(a_val) == c_val) 5648 5649 # utt.verify_grad(flatten, [a_val]) #TODO: fix verify_grd to work on scalars 5650 5651 5652def test_flatten_ndim1(): 5653 a = dmatrix() 5654 c = flatten(a, 1) 5655 f = inplace_func([a], c) 5656 a_val = theano._asarray([[0, 1, 2], [3, 4, 5]], dtype='float64') 5657 c_val = theano._asarray([0, 1, 2, 3, 4, 5], dtype='float64') 5658 assert np.all(f(a_val) == c_val) 5659 f = inplace_func([a], c) 5660 assert np.all(f(a_val) == c_val) 5661 5662 utt.verify_grad(flatten, [a_val]) 5663 5664 5665def test_flatten_ndim2(): 5666 a = dmatrix() 5667 c = flatten(a, 2) 5668 f = inplace_func([a], c) 5669 a_val = theano._asarray([[0, 1, 2], [3, 4, 5]], dtype='float64') 5670 assert np.all(f(a_val) == a_val) 5671 f = inplace_func([a], c) 5672 assert np.all(f(a_val) == a_val) 5673 5674 flatten_2 = partial(flatten, ndim=2) 5675 utt.verify_grad(flatten_2, [a_val]) 5676 5677 5678def test_flatten_ndim2_of_3(): 5679 a = TensorType('float64', (False, False, False))() 5680 c = flatten(a, 2) 5681 f = inplace_func([a], c) 5682 a_val = theano._asarray([[[0, 1], [2, 3]], [[4, 5], [6, 7]]], 5683 dtype='float64') 5684 c_val = theano._asarray([[0, 1, 2, 3], [4, 5, 6, 7]], dtype='float64') 5685 assert np.all(f(a_val) == c_val) 5686 f = inplace_func([a], c) 5687 assert np.all(f(a_val) == c_val) 5688 5689 flatten_2 = partial(flatten, ndim=2) 5690 utt.verify_grad(flatten_2, [a_val]) 5691 # test outdim parameter name 5692 flatten_2 = partial(flatten, outdim=2) 5693 utt.verify_grad(flatten_2, [a_val]) 5694 5695 5696def test_flatten_broadcastable(): 5697 # Ensure that the broadcastable pattern of the output is coherent with 5698 # that of the input 5699 5700 inp = TensorType('float64', (False, False, False, False))() 5701 out = flatten(inp, ndim=2) 5702 assert out.broadcastable == (False, False) 5703 5704 inp = TensorType('float64', (False, False, False, True))() 5705 out = flatten(inp, ndim=2) 5706 assert out.broadcastable == (False, False) 5707 5708 inp = TensorType('float64', (False, True, False, True))() 5709 out = flatten(inp, ndim=2) 5710 assert out.broadcastable == (False, False) 5711 5712 inp = TensorType('float64', (False, True, True, True))() 5713 out = flatten(inp, ndim=2) 5714 assert out.broadcastable == (False, True) 5715 5716 inp = TensorType('float64', (True, False, True, True))() 5717 out = flatten(inp, ndim=3) 5718 assert out.broadcastable == (True, False, True) 5719 5720 5721def test_flatten_ndim_invalid(): 5722 a = dmatrix() 5723 assert_raises(ValueError, flatten, a, 3) 5724 assert_raises(ValueError, flatten, a, 0) 5725 5726 5727def test_is_flat(): 5728 # tests is_flat method for constant and symbolic variables, 5729 # as well as reshaped constant and symbolic variables on the 5730 # given outdim 5731 5732 # Constant variable 5733 assert tensor.is_flat(tensor.as_tensor_variable(np.zeros((10)))) 5734 assert tensor.is_flat(tensor.as_tensor_variable(np.zeros((10, 10, 10))), 5735 ndim=3) 5736 assert not tensor.is_flat( 5737 tensor.as_tensor_variable(np.zeros((10, 10, 10)))) 5738 5739 # Symbolic variable 5740 assert tensor.is_flat(tensor.vector()) 5741 assert tensor.is_flat(tensor.tensor3(), ndim=3) 5742 assert not tensor.is_flat(tensor.tensor3()) 5743 5744 # Reshape with constant shape 5745 X = tensor.tensor4() 5746 assert tensor.is_flat(X.reshape((-1, ))) 5747 assert tensor.is_flat(X.reshape((10, 10, -1)), ndim=3) 5748 assert not tensor.is_flat(X.reshape((10, 10, -1))) 5749 5750 # Reshape with symbolic shape 5751 X = tensor.tensor4() 5752 assert tensor.is_flat(X.reshape((tensor.iscalar(), ))) 5753 assert tensor.is_flat(X.reshape((tensor.iscalar(), ) * 3), ndim=3) 5754 assert not tensor.is_flat(X.reshape((tensor.iscalar(), ) * 3)) 5755 5756 5757def test_tile(): 5758 def run_tile(x, x_, reps, use_symbolic_reps): 5759 if use_symbolic_reps: 5760 rep_symbols = [iscalar() for _ in range(len(reps))] 5761 f = function([x] + rep_symbols, tile(x, rep_symbols)) 5762 return f(*([x_] + list(reps))) 5763 else: 5764 f = function([x], tile(x, reps)) 5765 return f(x_) 5766 5767 rng = np.random.RandomState(utt.fetch_seed()) 5768 5769 for use_symbolic_reps in [False, True]: 5770 # Test the one-dimensional case. 5771 x = vector() 5772 x_ = rng.randn(5).astype(config.floatX) 5773 assert np.all(run_tile(x, x_, (2,), use_symbolic_reps) == 5774 np.tile(x_, (2,))) 5775 5776 # Test the two-dimensional case. 5777 x = matrix() 5778 x_ = rng.randn(2, 4).astype(config.floatX) 5779 assert np.all(run_tile(x, x_, (2, 3), use_symbolic_reps) == 5780 np.tile(x_, (2, 3))) 5781 5782 # Test the three-dimensional case. 5783 x = tensor3() 5784 x_ = rng.randn(2, 4, 3).astype(config.floatX) 5785 assert np.all(run_tile(x, x_, (2, 3, 4), use_symbolic_reps) == 5786 np.tile(x_, (2, 3, 4))) 5787 5788 # Test the four-dimensional case. 5789 x = tensor4() 5790 x_ = rng.randn(2, 4, 3, 5).astype(config.floatX) 5791 assert np.all(run_tile(x, x_, (2, 3, 4, 6), use_symbolic_reps) == 5792 np.tile(x_, (2, 3, 4, 6))) 5793 5794 # Test when reps is integer, tensor.scalar or tensor.vector. 5795 # Test 1,2,3,4-dimensional cases. 5796 # Test input x has the shape [2], [2, 4], [2, 4, 3], [2, 4, 3, 5]. 5797 test_shape = [2, 4, 3, 5] 5798 k = 0 5799 for xtype in [vector(), matrix(), tensor3(), tensor4()]: 5800 x = xtype 5801 k = k + 1 5802 x_ = rng.randn(*test_shape[0:k]).astype(config.floatX) 5803 5804 # integer: 5805 reps_ = 2 5806 f = function([x], tile(x, reps_)) 5807 assert np.all(f(x_) == np.tile(x_, reps_)) 5808 5809 # tensor.scalar: 5810 reps = iscalar() 5811 reps_ = 2 5812 f = function([x, reps], tile(x, reps)) 5813 assert np.all(f(x_, reps_) == np.tile(x_, reps_)) 5814 5815 # tensor.vector: 5816 reps = ivector() 5817 reps_ = [2] if k == 1 or k == 2 else [2, 3] 5818 ndim_ = k 5819 f = function([x, reps], tile(x, reps, ndim_)) 5820 assert np.all(f(x_, reps_) == np.tile(x_, reps_)) 5821 5822 # list of integers: 5823 reps_ = [2, 3, 4] 5824 f = function([x], tile(x, reps_)) 5825 assert np.all(f(x_) == np.tile(x_, reps_)) 5826 5827 # list of integers and tensor.scalars: 5828 d = iscalar() 5829 reps = [2, d, 4] 5830 f = function([x, d], tile(x, reps)) 5831 reps_ = [2, 3, 4] 5832 assert np.all(f(x_, 3) == np.tile(x_, reps_)) 5833 5834 # reps is list, len(reps) > x.ndim, 3 cases below: 5835 r = [2, 3, 4, 5, 6] 5836 reps_ = r[:k + 1] # len(reps_) = x.ndim+1 5837 # (1) ndim = None. 5838 f = function([x], tile(x, reps_)) 5839 assert np.all(f(x_) == np.tile(x_, reps_)) 5840 # (2) ndim = len(reps). 5841 ndim_ = len(reps_) 5842 f = function([x], tile(x, reps_, ndim_)) 5843 assert np.all(f(x_) == np.tile(x_, reps_)) 5844 # (3) ndim > len(reps) 5845 ndim_ = len(reps_) + 1 5846 f = function([x], tile(x, reps_, ndim_)) 5847 assert np.all(f(x_) == np.tile(x_, [1] + reps_)) 5848 5849 # reps is list, ndim > x.ndim > len(reps): 5850 r = [2, 3, 4, 5] 5851 if k > 1: 5852 ndim_ = k + 1 5853 reps_ = r[:k - 1] 5854 f = function([x], tile(x, reps_, ndim_)) 5855 assert np.all(f(x_) == np.tile(x_, [1, 1] + reps_)) 5856 5857 # error raising test: ndim not specified when reps is vector 5858 reps = ivector() 5859 np.testing.assert_raises(ValueError, tile, x, reps) 5860 5861 # error raising test: not a integer 5862 for reps in [2.5, fscalar(), fvector()]: 5863 np.testing.assert_raises(ValueError, tile, x, reps) 5864 5865 # error raising test: the dimension of reps exceeds 1 5866 reps = imatrix() 5867 np.testing.assert_raises(ValueError, tile, x, reps) 5868 5869 # error raising test: ndim is not None, ndim < x.ndim 5870 # 3 cases below (reps is list/tensor.scalar/tensor.vector): 5871 for reps in [[2, 3, 4], iscalar(), ivector()]: 5872 if k > 1: 5873 ndim = k - 1 5874 np.testing.assert_raises(ValueError, tile, x, reps, ndim) 5875 5876 # error raising test: reps is list, len(reps) > ndim 5877 r = [2, 3, 4, 5, 6] 5878 reps = r[:k + 1] 5879 ndim = k 5880 np.testing.assert_raises(ValueError, tile, x, reps, ndim) 5881 5882 # error raising test: 5883 # reps is tensor.vector and len(reps_value) > ndim, 5884 # reps_value is the real value when excuting the function. 5885 reps = ivector() 5886 r = [2, 3, 4, 5, 6, 7] 5887 reps_ = r[:k + 2] 5888 ndim_ = k + 1 5889 f = function([x, reps], tile(x, reps, ndim_)) 5890 np.testing.assert_raises(AssertionError, f, x_, reps_) 5891 5892 5893def test_tile_grad(): 5894 5895 def grad_tile(x, reps, np_x): 5896 y = tile(x, reps) 5897 z = y.sum() 5898 g = theano.function([x], grad(z, x)) 5899 grad_res = g(np_x) 5900 # The gradient should be the product of the tiling dimensions 5901 # (since the gradients are additive through the tiling operation) 5902 assert np.all(grad_res == np.prod(reps)) 5903 5904 rng = np.random.RandomState(utt.fetch_seed()) 5905 5906 # test vector 5907 grad_tile(vector('x'), [3], rng.randn(5).astype(config.floatX)) 5908 # test matrix 5909 grad_tile(matrix('x'), [3, 4], rng.randn(2, 3).astype(config.floatX)) 5910 # test tensor3 5911 grad_tile(tensor3('x'), [3, 4, 5], 5912 rng.randn(2, 4, 3).astype(config.floatX)) 5913 # test tensor4 5914 grad_tile(tensor4('x'), [3, 4, 5, 6], 5915 rng.randn(2, 4, 3, 5).astype(config.floatX)) 5916 5917 5918class TestARange(unittest.TestCase): 5919 def setUp(self): 5920 utt.seed_rng() 5921 5922 def test_Op_integers(self): 5923 # Test behaviour of ARange Op on integer inputs 5924 start, stop, step = iscalars('start', 'stop', 'step') 5925 out = ARange(start.type.dtype)(start, stop, step) 5926 f = function([start, stop, step], out) 5927 5928 assert np.all(f(0, 5, 1) == np.arange(0, 5, 1)) 5929 assert np.all(f(2, 11, 4) == np.arange(2, 11, 4)) 5930 assert np.all(f(-5, 1, 1) == np.arange(-5, 1, 1)) 5931 assert np.all(f(10, 2, -2) == np.arange(10, 2, -2)) 5932 assert np.all(f(10, 2, 2) == np.arange(10, 2, 2)) 5933 assert np.all(f(0, 0, 1) == np.arange(0, 0, 1)) 5934 5935 def test_grads(self): 5936 def f(start, stop, step): 5937 return ARange(start.type.dtype)(start, stop, step) 5938 5939 rng = np.random.RandomState(utt.fetch_seed()) 5940 # Due to the random projection, we should not use the exact 5941 # point that change the shape of the output. 5942 for start, stop, step in [(0, 4.9, 1), 5943 (5.1, 0, -0.5), 5944 (1, 5.1, 0.5)]: 5945 utt.verify_grad(f, [np.asarray(start).astype(config.floatX), 5946 np.asarray(stop).astype(config.floatX), 5947 np.asarray(step).astype(config.floatX)], 5948 rng=rng) 5949 5950 def test_integers(self): 5951 # Test arange constructor, on integer outputs 5952 start, stop, step = iscalars('start', 'stop', 'step') 5953 out = arange(start, stop, step) 5954 f = function([start, stop, step], out) 5955 5956 if config.cast_policy == 'custom': 5957 assert out.dtype == 'int64' 5958 elif config.cast_policy in ('numpy', 'numpy+floatX'): 5959 numpy_dtype = np.arange(np.array(1, dtype='int32')).dtype 5960 assert out.dtype == numpy_dtype 5961 else: 5962 raise NotImplementedError(config.cast_policy) 5963 assert np.all(f(0, 5, 1) == np.arange(0, 5, 1)) 5964 assert np.all(f(2, 11, 4) == np.arange(2, 11, 4)) 5965 assert np.all(f(-5, 1, 1) == np.arange(-5, 1, 1)) 5966 assert np.all(f(10, 2, -2) == np.arange(10, 2, -2)) 5967 assert np.all(f(10, 2, 2) == np.arange(10, 2, 2)) 5968 assert np.all(f(0, 0, 1) == np.arange(0, 0, 1)) 5969 5970 def test_float32(self): 5971 # Test arange constructor, on float32 outputs 5972 start, stop, step = fscalars('start', 'stop', 'step') 5973 out = arange(start, stop, step) 5974 f = function([start, stop, step], out) 5975 5976 if config.cast_policy == 'custom': 5977 assert out.dtype == start.type.dtype 5978 elif config.cast_policy == 'numpy': 5979 numpy_dtype = np.arange(np.array(0, dtype=start.dtype), 5980 np.array(1, dtype=stop.dtype), 5981 np.array(1, dtype=step.dtype)).dtype 5982 assert out.dtype == numpy_dtype 5983 elif config.cast_policy == 'numpy+floatX': 5984 assert out.dtype == config.floatX 5985 else: 5986 raise NotImplementedError(config.cast_policy) 5987 arg_vals = [(0, 5, 1), (2, 11, 4), (-5, 1.1, 1.2), (1.3, 2, -2.1), 5988 (10, 2, 2)] 5989 for arg_v in arg_vals: 5990 start_v, stop_v, step_v = arg_v 5991 start_v_, stop_v_, step_v_ = np.asarray(arg_v, 5992 dtype=start.type.dtype) 5993 f_val = f(start_v_, stop_v_, step_v_) 5994 if config.cast_policy == 'custom': 5995 expected_val = np.arange(start_v, stop_v, step_v, 5996 dtype=start.type.dtype) 5997 elif config.cast_policy in ('numpy', 'numpy+floatX'): 5998 expected_val = np.arange(start_v_, stop_v_, step_v_, 5999 dtype=out.dtype) 6000 else: 6001 raise NotImplementedError(config.cast_policy) 6002 assert np.all(f_val == expected_val) 6003 6004 def test_float64(self): 6005 # Test arange constructor, on float64 outputs 6006 start, stop, step = dscalars('start', 'stop', 'step') 6007 out = arange(start, stop, step) 6008 f = function([start, stop, step], out) 6009 6010 assert out.dtype == start.type.dtype 6011 arg_vals = [(0, 5, 1), (2, 11, 4), (-5, 1.1, 1.2), 6012 (1.3, 2, -2.1), (10, 2, 2)] 6013 for arg_v in arg_vals: 6014 start_v, stop_v, step_v = arg_v 6015 start_v_, stop_v_, step_v_ = np.asarray(arg_v, 6016 dtype=start.type.dtype) 6017 f_val = f(start_v_, stop_v_, step_v_) 6018 if config.cast_policy == 'custom': 6019 expected_val = np.arange(start_v, stop_v, step_v, 6020 dtype=start.type.dtype) 6021 elif config.cast_policy in ('numpy', 'numpy+floatX'): 6022 expected_val = np.arange(start_v_, stop_v_, step_v_) 6023 else: 6024 raise NotImplementedError(config.cast_policy) 6025 assert np.all(f_val == expected_val) 6026 6027 def test_default_step(self): 6028 # Test that arange constructor uses the correct default step 6029 start, stop = iscalars('start', 'stop') 6030 out = arange(start, stop) 6031 f = function([start, stop], out) 6032 6033 if config.cast_policy == 'custom': 6034 assert out.dtype == 'int64' 6035 elif config.cast_policy in ('numpy', 'numpy+floatX'): 6036 assert out.dtype == np.arange(np.int32(0), 6037 np.int32(1)).dtype 6038 else: 6039 raise NotImplementedError(config.cast_policy) 6040 assert np.all(f(0, 5) == np.arange(0, 5)) 6041 assert np.all(f(-5, 1) == np.arange(-5, 1)) 6042 assert np.all(f(0, 0) == np.arange(0, 0)) 6043 6044 dstart, dstop = dscalars('start', 'stop') 6045 dout = arange(dstart, dstop) 6046 df = function([dstart, dstop], dout) 6047 6048 assert dout.dtype == dstart.type.dtype 6049 # print df(0.2, 5.3) 6050 # print np.arange(0.2, 5.3) 6051 assert np.all(df(0.2, 5.3) == np.arange(0.2, 5.3)) 6052 assert np.all(df(0.8, 5.3) == np.arange(0.8, 5.3)) 6053 assert np.all(df(-0.7, 5.3) == np.arange(-0.7, 5.3)) 6054 6055 def test_default_start(self): 6056 # Test that arange constructor uses the correct default start 6057 stop = iscalar('stop') 6058 out = arange(stop) 6059 f = function([stop], out) 6060 6061 if config.cast_policy == 'custom': 6062 assert out.dtype == 'int64' 6063 elif config.cast_policy in ('numpy', 'numpy+floatX'): 6064 assert out.dtype == np.arange(np.int32(1)).dtype 6065 else: 6066 raise NotImplementedError(config.cast_policy) 6067 assert np.all(f(8) == np.arange(8)) 6068 assert np.all(f(-2) == np.arange(-2)) 6069 6070 fstop = fscalar('stop') 6071 fout = arange(fstop) 6072 ff = function([fstop], fout) 6073 6074 if config.cast_policy == 'custom': 6075 assert fout.dtype == fstop.type.dtype 6076 elif config.cast_policy == 'numpy': 6077 assert fout.dtype == np.arange(np.float32(1)).dtype 6078 elif config.cast_policy == 'numpy+floatX': 6079 if config.floatX == 'float32': 6080 assert fout.dtype == 'float32' 6081 else: 6082 assert fout.dtype == np.arange(np.float32(1)).dtype 6083 else: 6084 raise NotImplementedError(config.cast_policy) 6085 6086 fstop_values = [0.2, -0.7, 8.5] 6087 for fstop_v in fstop_values: 6088 fstop_v32 = np.float32(fstop_v) 6089 assert np.all(ff(fstop_v32) == np.arange(fstop_v)) 6090 6091 def test_upcast(self): 6092 # Test that arange computes output type adequately 6093 if config.cast_policy == 'custom': 6094 assert arange(iscalar()).dtype == 'int64' 6095 assert arange(fscalar()).dtype == fscalar().dtype 6096 assert arange(dscalar()).dtype == dscalar().dtype 6097 6098 # int32 + float32 -> float64 6099 assert arange(iscalar(), fscalar()).dtype == dscalar().dtype 6100 assert arange(iscalar(), dscalar()).dtype == dscalar().dtype 6101 assert arange(fscalar(), dscalar()).dtype == dscalar().dtype 6102 6103 assert arange(iscalar(), fscalar(), dscalar()).dtype == \ 6104 dscalar().dtype 6105 elif config.cast_policy in ('numpy', 'numpy+floatX'): 6106 for dtype in get_numeric_types(): 6107 # Test with a single argument. 6108 arange_dtype = arange(scalar(dtype=str(dtype))).dtype 6109 numpy_dtype = np.arange(np.array(1, dtype=dtype)).dtype 6110 if (dtype != 'float64' and 6111 numpy_dtype == 'float64' and 6112 config.cast_policy == 'numpy+floatX' and 6113 config.floatX == 'float32'): 6114 # We want a float32 arange. 6115 assert arange_dtype == 'float32' 6116 else: 6117 # Follow numpy. 6118 assert arange_dtype == numpy_dtype 6119 6120 # Test with two arguments. 6121 for stop_dtype in get_numeric_types(): 6122 arange_dtype = arange( 6123 start=scalar(dtype=str(dtype)), 6124 stop=scalar(dtype=str(stop_dtype))).dtype 6125 numpy_dtype = np.arange( 6126 start=np.array(0, dtype=dtype), 6127 stop=np.array(1, dtype=stop_dtype)).dtype 6128 if (dtype != 'float64' and 6129 stop_dtype != 'float64' and 6130 numpy_dtype == 'float64' and 6131 config.cast_policy == 'numpy+floatX' and 6132 config.floatX == 'float32'): 6133 # We want a float32 arange. 6134 assert arange_dtype == 'float32' 6135 else: 6136 # Follow numpy. 6137 assert arange_dtype == numpy_dtype 6138 6139 # Test with three arguments. 6140 for step_dtype in get_numeric_types(): 6141 arange_dtype = arange( 6142 start=scalar(dtype=str(dtype)), 6143 stop=scalar(dtype=str(stop_dtype)), 6144 step=scalar(dtype=str(step_dtype))).dtype 6145 numpy_dtype = np.arange( 6146 start=np.array(0, dtype=dtype), 6147 stop=np.array(1, dtype=stop_dtype), 6148 step=np.array(1, dtype=step_dtype)).dtype 6149 if (dtype != 'float64' and 6150 stop_dtype != 'float64' and 6151 step_dtype != 'float64' and 6152 numpy_dtype == 'float64' and 6153 config.cast_policy == 'numpy+floatX' and 6154 config.floatX == 'float32'): 6155 # We want a float32 arange. 6156 assert arange_dtype == 'float32' 6157 else: 6158 # Follow numpy. 6159 assert arange_dtype == numpy_dtype 6160 else: 6161 raise NotImplementedError(config.cast_policy) 6162 6163 def test_dtype_cache(self): 6164 # Checks that the same Op is returned on repeated calls to arange 6165 # using the same dtype, but not for different dtypes. 6166 6167 start, stop, step = iscalars('start', 'stop', 'step') 6168 out1 = arange(start, stop, step) 6169 out2 = arange(start, stop, step, dtype=out1.dtype) 6170 out3 = arange(start, stop, 2., dtype=out1.dtype) 6171 out4 = arange(start, stop, 2.) 6172 6173 assert out1.owner.op is out2.owner.op 6174 assert out2.owner.op is out3.owner.op 6175 assert out3.owner.op is not out4.owner.op 6176 6177 def test_infer_shape(self): 6178 start, stop, step = iscalars('start', 'stop', 'step') 6179 out = arange(start, stop, step) 6180 mode = theano.config.mode 6181 if mode == 'FAST_COMPILE': 6182 mode = 'FAST_RUN' 6183 mode = compile.mode.get_mode(mode).excluding('fusion') 6184 f = function([start, stop, step], out.shape, mode=mode) 6185 assert len(f.maker.fgraph.toposort()) == 9 6186 6187 if config.cast_policy == 'custom': 6188 assert out.dtype == 'int64' 6189 elif config.cast_policy in ('numpy', 'numpy+floatX'): 6190 numpy_dtype = np.arange(np.array(0, dtype=start.dtype), 6191 np.array(1, dtype=stop.dtype), 6192 np.array(1, dtype=step.dtype)).dtype 6193 assert out.dtype == numpy_dtype 6194 else: 6195 raise NotImplementedError(config.cast_policy) 6196 6197 assert np.all(f(0, 5, 1) == len(np.arange(0, 5, 1))) 6198 assert np.all(f(2, 11, 4) == len(np.arange(2, 11, 4))) 6199 assert np.all(f(-5, 1, 1) == len(np.arange(-5, 1, 1))) 6200 assert np.all(f(10, 2, -2) == len(np.arange(10, 2, -2))) 6201 assert np.all(f(10, 2, 2) == len(np.arange(10, 2, 2))) 6202 assert np.all(f(0, 0, 1) == len(np.arange(0, 0, 1))) 6203 6204 out = arange(start, stop, 1) 6205 f = function([start, stop], out.shape, mode=mode) 6206 assert len(f.maker.fgraph.toposort()) == 5 6207# 4 [Elemwise{sub,no_inplace}(stop, start), Elemwise{Cast{int64}}(Elemwise{sub,no_inplace}.0), Elemwise{Maximum{output_types_preference=transfer_type{0}}}[(0, 0)](Elemwise{Cast{int64}}.0, 0), MakeVector(Elemwise{Maximum{output_types_preference=transfer_type{0}}}[(0, 0)].0)] 6208 if config.cast_policy == 'custom': 6209 assert out.dtype == 'int64' 6210 elif config.cast_policy in ('numpy', 'numpy+floatX'): 6211 assert out.dtype == np.arange( 6212 np.int32(0), np.int32(1), np.int32(1)).dtype 6213 else: 6214 raise NotImplementedError(config.cast_policy) 6215 assert np.all(f(0, 5) == len(np.arange(0, 5))) 6216 assert np.all(f(2, 11) == len(np.arange(2, 11))) 6217 assert np.all(f(-5, 1) == len(np.arange(-5, 1))) 6218 assert np.all(f(10, 2) == len(np.arange(10, 2))) 6219 assert np.all(f(10, 2) == len(np.arange(10, 2))) 6220 assert np.all(f(0, 0) == len(np.arange(0, 0))) 6221 assert np.all(f(-64, 64) == len(np.arange(-64, 64))) 6222 assert arange(-64, 64).shape.eval() == [128] 6223 assert arange(-64, 64, 2).shape.eval() == [64] 6224 6225 out = arange(0, stop, 1) 6226 f = function([stop], out.shape, mode=mode) 6227 assert len(f.maker.fgraph.toposort()) == 2 6228 # [Elemwise{Cast{int64}}(stop), MakeVector(Elemwise{Cast{int64}}.0)] 6229 6230 if config.cast_policy == 'custom': 6231 assert out.dtype == 'int64' 6232 elif config.cast_policy in ('numpy', 'numpy+floatX'): 6233 numpy_dtype = np.arange(0, 6234 np.array(1, dtype=stop.dtype), 6235 1).dtype 6236 assert out.dtype == numpy_dtype 6237 else: 6238 raise NotImplementedError(config.cast_policy) 6239 6240 assert np.all(f(5) == len(np.arange(0, 5))) 6241 assert np.all(f(11) == len(np.arange(0, 11))) 6242 assert np.all(f(1) == len(np.arange(0, 1))) 6243 assert np.all(f(2) == len(np.arange(0, 2))) 6244 assert np.all(f(2) == len(np.arange(0, 2))) 6245 assert np.all(f(0) == len(np.arange(0, 0))) 6246 6247 6248class TestNdGrid(unittest.TestCase): 6249 6250 def setUp(self): 6251 pass 6252 6253 def test_mgrid_numpy_equiv(self): 6254 nmgrid = (np.mgrid[0:1:.1, 1:10:1., 10:100:10.], 6255 np.mgrid[0:2:1, 1:10:1, 10:100:10]) 6256 tmgrid = (mgrid[0:1:.1, 1:10:1., 10:100:10.], 6257 mgrid[0:2:1, 1:10:1, 10:100:10]) 6258 for n, t in zip(nmgrid, tmgrid): 6259 for ng, tg in zip(n, t): 6260 utt.assert_allclose(ng, tg.eval()) 6261 6262 def test_ogrid_numpy_equiv(self): 6263 nogrid = (np.ogrid[0:1:.1, 1:10:1., 10:100:10.], 6264 np.ogrid[0:2:1, 1:10:1, 10:100:10]) 6265 togrid = (ogrid[0:1:.1, 1:10:1., 10:100:10.], 6266 ogrid[0:2:1, 1:10:1, 10:100:10]) 6267 for n, t in zip(nogrid, togrid): 6268 for ng, tg in zip(n, t): 6269 utt.assert_allclose(ng, tg.eval()) 6270 6271 def test_mgrid_theano_variable_numpy_equiv(self): 6272 nfmgrid = np.mgrid[0:1:.1, 1:10:1., 10:100:10.] 6273 nimgrid = np.mgrid[0:2:1, 1:10:1, 10:100:10] 6274 i, j, k = dscalars('i', 'j', 'k') 6275 l, m, n = iscalars('l', 'm', 'n') 6276 tfmgrid = mgrid[i:1:.1, 1:j:1., 10:100:k] 6277 timgrid = mgrid[l:2:1, 1:m:1, 10:100:n] 6278 ff = theano.function([i, j, k], tfmgrid) 6279 fi = theano.function([l, m, n], timgrid) 6280 for n, t in zip((nfmgrid, nimgrid), (ff(0, 10, 10.), fi(0, 10, 10))): 6281 for ng, tg in zip(n, t): 6282 utt.assert_allclose(ng, tg) 6283 6284 def test_ogrid_theano_variable_numpy_equiv(self): 6285 nfogrid = np.ogrid[0:1:.1, 1:10:1., 10:100:10.] 6286 niogrid = np.ogrid[0:2:1, 1:10:1, 10:100:10] 6287 i, j, k = dscalars('i', 'j', 'k') 6288 l, m, n = iscalars('l', 'm', 'n') 6289 tfogrid = ogrid[i:1:.1, 1:j:1., 10:100:k] 6290 tiogrid = ogrid[l:2:1, 1:m:1, 10:100:n] 6291 ff = theano.function([i, j, k], tfogrid) 6292 fi = theano.function([l, m, n], tiogrid) 6293 for n, t in zip((nfogrid, niogrid), (ff(0, 10, 10.), fi(0, 10, 10))): 6294 for ng, tg in zip(n, t): 6295 utt.assert_allclose(ng, tg) 6296 6297 6298class TestInversePermutation(unittest.TestCase): 6299 def setUp(self): 6300 utt.seed_rng() 6301 6302 def test_dim1(self): 6303 # Test the inversion of one permutation (int vector) 6304 p = ivector() 6305 inv = inverse_permutation(p) 6306 assert inv.dtype == p.dtype 6307 f_inverse = function([p], inv) 6308 6309 # Generate a random permutation 6310 rng = np.random.RandomState(utt.fetch_seed()) 6311 p_val = rng.permutation(10).astype('int32') 6312 inv_val = f_inverse(p_val) 6313 6314 # Check that the inverse of the inverse is the original permutation 6315 assert np.all(f_inverse(inv_val) == p_val) 6316 # Check that permutation(inverse) == inverse(permutation) = identity 6317 assert np.all(p_val[inv_val] == np.arange(10)) 6318 assert np.all(inv_val[p_val] == np.arange(10)) 6319 6320 def test_dim2(self): 6321 # Test the inversion of several permutations at a time 6322 # Each row of p is a different permutation to inverse 6323 p = imatrix() 6324 inv = inverse_permutation(p) 6325 f_inverse = function([p], inv) 6326 6327 rng = np.random.RandomState(utt.fetch_seed()) 6328 # Generate 10 random permutations 6329 p_val = np.asarray([rng.permutation(10) for i in range(7)], 6330 dtype='int32') 6331 inv_val = f_inverse(p_val) 6332 6333 # Check that the inverse of the inverse is the original permutation list 6334 assert np.all(f_inverse(inv_val) == p_val) 6335 # Check that, for each permutation, 6336 # permutation(inverse) == inverse(permutation) = identity 6337 for p_row, i_row in zip(p_val, inv_val): 6338 assert np.all(p_row[i_row] == np.arange(10)) 6339 assert np.all(i_row[p_row] == np.arange(10)) 6340 6341 6342class TestPermuteRowElements(unittest.TestCase): 6343 def setUp(self): 6344 utt.seed_rng() 6345 6346 def test_1_1(self): 6347 # Test PermuteRowElements(vector, vector) 6348 input = dvector() 6349 p = ivector() 6350 out = permute_row_elements(input, p) 6351 permute = function([input, p], out) 6352 6353 rng = np.random.RandomState(utt.fetch_seed()) 6354 input_val = rng.uniform(size=(5,)) 6355 p_val = rng.permutation(5).astype('int32') 6356 out_val = permute(input_val, p_val) 6357 6358 # Should be equivalent to advanced indexing 6359 out_bis = input_val[p_val] 6360 assert np.all(out_val == out_bis) 6361 6362 # Verify gradient 6363 def permute_fixed(s_input): 6364 # Auxiliary op defined to get rid of gradient wrt p_val 6365 return permute_row_elements(s_input, p_val) 6366 utt.verify_grad(permute_fixed, [input_val]) 6367 6368 def test_2_1(self): 6369 # Test broadcasting in PermuteRowElements(matrix, vector) 6370 input = matrix() 6371 p = ivector() 6372 out = permute_row_elements(input, p) 6373 permute = function([input, p], out) 6374 6375 rng = np.random.RandomState(utt.fetch_seed()) 6376 input_val = rng.uniform(size=(3, 5)).astype(config.floatX) 6377 p_val = rng.permutation(5).astype('int32') 6378 out_val = permute(input_val, p_val) 6379 6380 # The same permutation should be applied to every row of the input matrix. 6381 out_bis = np.asarray([r[p_val] for r in input_val]) 6382 assert np.all(out_val == out_bis) 6383 6384 # Verify gradient 6385 def permute_fixed(s_input): 6386 # Auxiliary op defined to get rid of gradient wrt p_val 6387 return permute_row_elements(s_input, p_val) 6388 utt.verify_grad(permute_fixed, [input_val]) 6389 6390 def test_2_2(self): 6391 # Test PermuteRowElements(matrix, matrix) 6392 input = matrix() 6393 p = imatrix() 6394 out = permute_row_elements(input, p) 6395 permute = function([input, p], out) 6396 6397 rng = np.random.RandomState(utt.fetch_seed()) 6398 input_val = rng.uniform(size=(3, 5)).astype(config.floatX) 6399 p_val = np.asarray([rng.permutation(5) for i in range(3)], 6400 dtype='int32') 6401 out_val = permute(input_val, p_val) 6402 6403 # Each row of p contains a permutation to apply to the corresponding 6404 # row of input 6405 out_bis = np.asarray([i_row[p_row] 6406 for i_row, p_row in zip(input_val, p_val)]) 6407 assert np.all(out_val == out_bis) 6408 6409 # Verify gradient 6410 def permute_fixed(s_input): 6411 # Auxiliary op defined to get rid of gradient wrt p_val 6412 return permute_row_elements(s_input, p_val) 6413 utt.verify_grad(permute_fixed, [input_val]) 6414 6415 def test_1_2(self): 6416 # Test PermuteRowElements(vector, matrix) 6417 # Different permutations will be applied to the same input vector 6418 input = vector() 6419 p = imatrix() 6420 out = permute_row_elements(input, p) 6421 permute = function([input, p], out) 6422 6423 rng = np.random.RandomState(utt.fetch_seed()) 6424 input_val = rng.uniform(size=(5,)).astype(config.floatX) 6425 p_val = np.asarray([rng.permutation(5) 6426 for i in range(3)], dtype='int32') 6427 out_val = permute(input_val, p_val) 6428 6429 # Each row of p contains a permutation to apply to the input vector 6430 out_bis = np.asarray([input_val[p_row] for p_row in p_val]) 6431 assert np.all(out_val == out_bis) 6432 6433 # Verify gradient 6434 def permute_fixed(s_input): 6435 # Auxiliary op defined to get rid of gradient wrt p_val 6436 return permute_row_elements(s_input, p_val) 6437 utt.verify_grad(permute_fixed, [input_val]) 6438 6439 def test_3b_2(self): 6440 # Test permute_row_elements on a more complex broadcasting pattern: 6441 # input.type.broadcastable = (False, True, False), 6442 # p.type.broadcastable = (False, False). 6443 6444 input = TensorType('floatX', (False, True, False))() 6445 p = imatrix() 6446 out = permute_row_elements(input, p) 6447 permute = function([input, p], out) 6448 6449 rng = np.random.RandomState(utt.fetch_seed()) 6450 input_val = rng.uniform(size=(4, 1, 5)).astype(config.floatX) 6451 p_val = np.asarray([rng.permutation(5) for i in range(3)], 6452 dtype='int32') 6453 out_val = permute(input_val, p_val) 6454 6455 # Each row of p contains a permutation to apply to each row 6456 # of the input tensor 6457 out_bis = np.asarray([[in_mat[0, p_row] for p_row in p_val] 6458 for in_mat in input_val]) 6459 assert np.all(out_val == out_bis) 6460 6461 # Verify gradient 6462 def permute_fixed(s_input): 6463 # Auxiliary op defined to get rid of gradient wrt p_val 6464 return permute_row_elements(s_input, p_val) 6465 utt.verify_grad(permute_fixed, [input_val]) 6466 6467 6468class test_tensordot(unittest.TestCase): 6469 def TensorDot(self, axes): 6470 # Since tensordot is no longer an op, mimic the old op signature 6471 # to allow easy use of verify_grad. 6472 return lambda a, b: tensordot(a, b, axes) 6473 6474 def setUp(self): 6475 utt.seed_rng() 6476 6477 def test0(self): 6478 6479 # Test vector-vector 6480 avec = vector() 6481 bvec = vector() 6482 axes = ((0, ), (0, )) 6483 c = tensordot(avec, bvec, axes) 6484 f1 = inplace_func([avec, bvec], c) 6485 aval = rand(5) 6486 bval = rand(5) 6487 out0 = np.tensordot(aval, bval, axes) 6488 out1 = f1(aval, bval) 6489 utt.assert_allclose(out0, out1) 6490 utt.verify_grad(self.TensorDot(axes), [aval, bval]) 6491 6492 # Test matrix-vector 6493 bmat = matrix() 6494 axes = ((0, ), (1, )) 6495 c = tensordot(avec, bmat, axes) 6496 f2 = inplace_func([avec, bmat], c) 6497 aval = rand(5) 6498 bval = rand(8, 5) 6499 utt.assert_allclose(np.tensordot(aval, bval, axes), 6500 f2(aval, bval)) 6501 utt.verify_grad(self.TensorDot(axes), [aval, bval]) 6502 6503 # Test matrix-matrix 6504 amat = matrix() 6505 for axes, shps in [[((0,), (0,)), [(4, 7), (4, 9)]], 6506 [((0,), (1,)), [(4, 7), (9, 4)]], 6507 [((1,), (0,)), [(4, 7), (7, 9)]], 6508 [((1,), (1,)), [(4, 7), (9, 7)]], 6509 [((0, 1), (0, 1)), [(4, 7), (4, 7)]], 6510 # [((0, 1), (1, 0)), [(4, 7), (7, 4)]], 6511 # [((1, 0), (1, 0)), [(4, 7), (4, 7)]], 6512 # [((1, 0), (0, 1)), [(4, 7), (7, 4)]], 6513 ]: 6514 c = tensordot(amat, bmat, axes) 6515 f3 = inplace_func([amat, bmat], c) 6516 aval = rand(*shps[0]) 6517 bval = rand(*shps[1]) 6518 utt.assert_allclose(np.tensordot(aval, bval, axes), 6519 f3(aval, bval)) 6520 utt.verify_grad(self.TensorDot(axes), [aval, bval]) 6521 6522 # Test ndarray-matrix, sum over one dim of matrix 6523 for axes, shps in [[((2,), (1,)), [(1, 2, 3, 4), (2, 3)]], 6524 [((0,), (1,)), [(1, 2, 3, 4), (3, 1)]], 6525 [((0,), (0,)), [(1, 2, 3, 4), (1, 3)]], 6526 [((3,), (0,)), [(1, 2, 3, 4), (4, 1)]], 6527 # [((3, 1), (0, 1)), [(1, 2, 3, 4), (4, 2)]], 6528 # [((0, 1), (1, 0)), [(1, 2, 3, 4), (2, 1)]], 6529 # [((3, 1), (1, 0)), [(1, 2, 3, 4), (2, 4)]], 6530 ]: 6531 atens = tensor4() 6532 c = tensordot(atens, bmat, axes) 6533 f4 = inplace_func([atens, bmat], c) 6534 aval = rand(*shps[0]) 6535 bval = rand(*shps[1]) 6536 utt.assert_allclose(np.tensordot(aval, bval, axes), 6537 f4(aval, bval)) 6538 utt.verify_grad(self.TensorDot(axes), [aval, bval]) 6539 6540 # Test ndarray-ndarray 6541 atens = tensor4() 6542 btens = tensor3() 6543 axes = ((1, 3), (0, 2)) 6544 c = tensordot(atens, btens, axes) 6545 f5 = inplace_func([atens, btens], c) 6546 aval = rand(4, 3, 5, 2) 6547 bval = rand(3, 4, 2) 6548 utt.assert_allclose(np.tensordot(aval, bval, axes), 6549 f5(aval, bval)) 6550 utt.verify_grad(self.TensorDot(axes), [aval, bval]) 6551 6552 axes = (axes[1], axes[0]) 6553 c = tensordot(btens, atens, axes) 6554 f6 = inplace_func([btens, atens], c) 6555 utt.assert_allclose(np.tensordot(bval, aval, axes), 6556 f6(bval, aval)) 6557 utt.verify_grad(self.TensorDot(axes), [bval, aval]) 6558 6559 def test_raise_error(self): 6560 amat = matrix() 6561 bmat = matrix() 6562 bvec = vector() 6563 6564 # Test invalid length for axes 6565 self.assertRaises(ValueError, tensordot, amat, bmat, (0, 1, 2)) 6566 6567 # Test axes of uneven length 6568 self.assertRaises(ValueError, tensordot, amat, bmat, ((0, 1), (0))) 6569 6570 # Test invalid len(axes) given inputs are matrices 6571 self.assertRaises(ValueError, tensordot, amat, bmat, ((0, 1, 2), (0, 1, 2))) 6572 6573 # Test invalid axes[1] given that y is a vector 6574 self.assertRaises(ValueError, tensordot, amat, bvec, (0, 1)) 6575 6576 # Test invalid scalar axes given inputs are matrices 6577 self.assertRaises(ValueError, tensordot, amat, bvec, 2) 6578 6579 def test_weird_valid_axes(self): 6580 # Test matrix-matrix 6581 amat = matrix() 6582 bmat = matrix() 6583 for axes in [0, 6584 (1, 0), 6585 [1, 0], 6586 (1, (0, )), 6587 ((1, ), 0), 6588 ([1], [0]), 6589 ([], [])]: 6590 c = tensordot(amat, bmat, axes) 6591 f3 = inplace_func([amat, bmat], c) 6592 aval = rand(4, 7) 6593 bval = rand(7, 9) 6594 utt.assert_allclose(np.tensordot(aval, bval, axes), 6595 f3(aval, bval)) 6596 utt.verify_grad(self.TensorDot(axes), [aval, bval]) 6597 6598 def test_scalar_axes(self): 6599 # Test matrix-matrix 6600 amat = fmatrix() 6601 bmat = dmatrix() 6602 # We let at float64 to test mix of float32 and float64. 6603 axes = 1 6604 aval = rand(4, 5).astype('float32') 6605 bval = rand(5, 3) 6606 c = tensordot(amat, bmat, axes) 6607 f3 = inplace_func([amat, bmat], c) 6608 self.assertTrue(np.allclose(np.tensordot(aval, bval, axes), 6609 f3(aval, bval))) 6610 utt.verify_grad(self.TensorDot(axes), [aval, bval]) 6611 6612 # Test tensor-tensor 6613 amat = tensor3() 6614 bmat = tensor3() 6615 axes = 2 6616 aval = rand(3, 4, 5) 6617 bval = rand(4, 5, 3) 6618 c = tensordot(amat, bmat, axes) 6619 f3 = inplace_func([amat, bmat], c) 6620 self.assertTrue(np.allclose(np.tensordot(aval, bval, axes), 6621 f3(aval, bval))) 6622 utt.verify_grad(self.TensorDot(axes), [aval, bval]) 6623 6624 def test_scalar0(self): 6625 # Test tensor-tensor 6626 amat = matrix() 6627 bmat = matrix() 6628 axes = 0 6629 aval = rand(4, 5) 6630 bval = rand(5, 4) 6631 c = tensordot(amat, bmat, axes) 6632 f3 = inplace_func([amat, bmat], c) 6633 self.assertTrue(np.allclose(np.tensordot(aval, bval, axes), 6634 f3(aval, bval))) 6635 utt.verify_grad(self.TensorDot(axes), [aval, bval]) 6636 6637 def test_broadcastable1(self): 6638 x = TensorType(dtype=floatX, broadcastable=(True, False, False))('x') 6639 y = tensor3('y') 6640 z = tensordot(x, y) 6641 assert z.broadcastable == (True, False) 6642 f = inplace_func([x, y], z) 6643 xv = rand(1, 3, 4) 6644 yv = rand(3, 4, 5) 6645 zv = f(xv, yv) 6646 self.assertTrue(np.allclose(np.tensordot(xv, yv), zv)) 6647 6648 def test_broadcastable2(self): 6649 x = TensorType(dtype=floatX, broadcastable=(True, False, False))('x') 6650 y = tensor3('y') 6651 axes = [[2, 1], [0, 1]] 6652 z = tensordot(x, y, axes=axes) 6653 assert z.broadcastable == (True, False) 6654 f = inplace_func([x, y], z) 6655 xv = rand(1, 3, 4) 6656 yv = rand(4, 3, 5) 6657 zv = f(xv, yv) 6658 self.assertTrue(np.allclose(np.tensordot(xv, yv, axes=axes), zv)) 6659 6660 6661def test_smallest_stack(): 6662 sx, sy = dscalar(), dscalar() 6663 6664 rval = inplace_func([sx, sy], stack([sx, sy]))(-4.0, -2.0) 6665 assert type(rval) == np.ndarray 6666 assert [-4, -2] == list(rval) 6667 6668 6669def test_smallest(): 6670 x = dvector() 6671 y = dvector() 6672 z = dvector() 6673 f1 = inplace_func([x], smallest(x)) 6674 assert np.all([1, 2, 3] == f1([1, 2, 3])) 6675 f3 = inplace_func([x, y, z], smallest(x, y, z)) 6676 assert np.all([1, 2, 3] == f3([1, 3, 9], [7, 7, 7], [8, 2, 3])) 6677 6678 sx, sy = dscalar(), dscalar() 6679 6680 assert -4 == inplace_func([sx, sy], smallest(sx, sy))(-4.0, -2.0) 6681 6682 6683def test_reshape_member_fn(): 6684 x = dmatrix() 6685 y = x.reshape((4, 5, 6)) 6686 assert y.owner.op == Reshape(3) 6687 6688 6689def test_var(): 6690 a = Tensor(dtype='float64', broadcastable=[False, False, False])() 6691 f = function([a], var(a)) 6692 6693 a_val = np.arange(60).reshape(3, 4, 5) 6694 assert np.allclose(np.var(a_val), f(a_val)) 6695 6696 f = function([a], var(a, axis=0)) 6697 assert np.allclose(np.var(a_val, axis=0), f(a_val)) 6698 6699 f = function([a], var(a, axis=1)) 6700 assert np.allclose(np.var(a_val, axis=1), f(a_val)) 6701 6702 f = function([a], var(a, axis=2)) 6703 assert np.allclose(np.var(a_val, axis=2), f(a_val)) 6704 6705 f = function([a], var(a, axis=0, ddof=0)) 6706 assert np.allclose(np.var(a_val, axis=0, ddof=0), f(a_val)) 6707 6708 f = function([a], var(a, axis=1, ddof=1)) 6709 assert np.allclose(np.var(a_val, axis=1, ddof=1), f(a_val)) 6710 6711 f = function([a], var(a, axis=2, ddof=1)) 6712 assert np.allclose(np.var(a_val, axis=2, ddof=1), f(a_val)) 6713 6714 f = function([a], var(a, ddof=0, corrected=True)) 6715 mean_a = np.mean(a_val) 6716 centered_a = a_val - mean_a 6717 v = np.mean(centered_a ** 2) 6718 error = (np.mean(centered_a)) ** 2 6719 v = v - error 6720 assert np.allclose(v, f(a_val)) 6721 6722 f = function([a], var(a, axis=2, ddof=1, corrected=True)) 6723 mean_a = np.mean(a_val, axis=2, keepdims=True) 6724 centered_a = a_val - mean_a 6725 v = np.var(a_val, axis=2, ddof=1) 6726 shp_inp = np.shape(a_val) 6727 shp = shp_inp - np.array(1) 6728 error = (np.sum(centered_a, axis=2)) ** 2 6729 error = np.true_divide(error, shp[1] * shp_inp[1]) 6730 v = v - error 6731 assert np.allclose(v, f(a_val)) 6732 6733 # Test that we don't upcast float16 computation 6734 assert theano.tensor.vector(dtype='float16').var().dtype == 'float16' 6735 6736 6737class T_sum(unittest.TestCase): 6738 def test_sum_overflow(self): 6739 # Ensure that overflow errors are a little bit harder to get 6740 a = Tensor(dtype='int8', broadcastable=[False])() 6741 f = function([a], sum(a)) 6742 assert f([1] * 300) == 300 6743 6744 def test_list(self): 6745 ll = [theano.shared(0.), theano.shared(2.)] 6746 tensor.sum(ll).eval() == 2 6747 6748 6749@dec.skipif( 6750 isinstance(get_default_mode(), theano.compile.debugmode.DebugMode), 6751 ("This test fails in DEBUG_MODE, but the generated code is OK. " 6752 "It is actually a problem of DEBUG_MODE, see #626.")) 6753def test_default(): 6754 x, y = scalars('xy') 6755 z = default(x, y) 6756 f = function([x, y], z) 6757 assert f(1, 2) == 1 6758 assert f(None, 2) == 2 6759 assert f(1, None) == 1 6760 6761 6762@dec.skipif( 6763 isinstance(get_default_mode(), theano.compile.debugmode.DebugMode), 6764 ("This test fails in DEBUG_MODE, but the generated code is OK. " 6765 "It is actually a problem of DEBUG_MODE, see #626.")) 6766def test_default_state(): 6767 x, y = scalars('xy') 6768 # print config.floatX 6769 # print x.type 6770 # print y.type 6771 z = default(x, 3.8) 6772 new_x = y + z 6773 f = function([y, compile.In(x, update=new_x, value=12.0)], new_x) 6774 assert f(3) == 15 6775 f['x'] = None 6776 assert np.allclose(f(1), 4.8) 6777 assert np.allclose(f(np.asarray(2.2, dtype=config.floatX)), 7) 6778 6779 6780def test_autocast(): 6781 backup_config = config.cast_policy 6782 # Call test functions for all possible values of `config.cast_policy`. 6783 for autocast_cfg in ( 6784 'custom', 6785 # 'numpy', # Commented out until it is implemented properly. 6786 'numpy+floatX', 6787 ): 6788 config.cast_policy = autocast_cfg 6789 try: 6790 eval('_test_autocast_' + autocast_cfg.replace('+', '_'))() 6791 finally: 6792 config.cast_policy = backup_config 6793 6794 6795def _test_autocast_custom(): 6796 # Called from `test_autocast`. 6797 assert config.cast_policy == 'custom' 6798 orig_autocast = autocast_float.dtypes 6799 6800 # Test that autocast_float_as sets the autocast dtype correctly 6801 with autocast_float_as('float32'): 6802 assert autocast_float.dtypes == ('float32',) 6803 assert autocast_float.dtypes == orig_autocast 6804 6805 with autocast_float_as('float64'): 6806 assert autocast_float.dtypes == ('float64',) 6807 assert autocast_float.dtypes == orig_autocast 6808 6809 # Test that we can set it back to something, and nest it 6810 with autocast_float_as('float32'): 6811 assert autocast_float.dtypes == ('float32',) 6812 with autocast_float_as('float64'): 6813 assert autocast_float.dtypes == ('float64',) 6814 assert autocast_float.dtypes == ('float32',) 6815 assert autocast_float.dtypes == orig_autocast 6816 6817 # Test that the autocasting dtype is used correctly in expression-building 6818 with autocast_float_as('float32'): 6819 assert (dvector() + 1.1).dtype == 'float64' 6820 assert (fvector() + 1.1).dtype == 'float32' 6821 assert ((fvector() + theano._asarray(1.1, dtype='float64')).dtype == 6822 'float64') 6823 assert ((fvector() + theano._asarray(1.1, dtype='float32')).dtype == 6824 'float32') 6825 6826 assert (dvector() + 1).dtype == 'float64' 6827 assert (fvector() + 1).dtype == 'float32' 6828 6829 # Test that the autocasting dtype is used correctly in expression-building 6830 with autocast_float_as('float64'): 6831 assert (dvector() + 1.1).dtype == 'float64' 6832 assert (fvector() + 1.1).dtype == 'float64' 6833 assert (fvector() + 1.0).dtype == 'float64' 6834 assert ((fvector() + theano._asarray(1.1, dtype='float64')).dtype == 6835 'float64') 6836 assert ((fvector() + theano._asarray(1.1, dtype='float32')).dtype == 6837 'float32') 6838 6839 assert (dvector() + 1).dtype == 'float64' 6840 assert (fvector() + 1).dtype == 'float32' 6841 6842 # Test that the autocasting dtype is used correctly in expression-building 6843 with autocast_float_as('float32', 'float64'): 6844 assert (dvector() + 1.1).dtype == 'float64' 6845 assert (fvector() + 1.1).dtype == theano.config.floatX 6846 assert (fvector() + 1.0).dtype == 'float32' 6847 assert (dvector() + np.float32(1.1)).dtype == 'float64' 6848 assert (dvector() + np.float64(1.1)).dtype == 'float64' 6849 assert (dvector() + np.float(1.1)).dtype == 'float64' 6850 assert (fvector() + np.float32(1.1)).dtype == 'float32' 6851 assert (fvector() + np.float64(1.1)).dtype == 'float64' 6852 assert (fvector() + np.float(1.1)).dtype == theano.config.floatX 6853 assert (lvector() + np.int64(1)).dtype == 'int64' 6854 assert (lvector() + np.int32(1)).dtype == 'int64' 6855 assert (lvector() + np.int16(1)).dtype == 'int64' 6856 assert (lvector() + np.int8(1)).dtype == 'int64' 6857 assert (ivector() + np.int8(1)).dtype == 'int32' 6858 assert (wvector() + np.int8(1)).dtype == 'int16' 6859 assert (bvector() + np.int8(1)).dtype == 'int8' 6860 with autocast_float_as('float64'): 6861 assert (fvector() + 1.0).dtype == 'float64' 6862 6863 6864def _test_autocast_numpy(): 6865 # Called from `test_autocast`. 6866 assert config.cast_policy == 'numpy' 6867 # Go through some typical scalar values. 6868 6869 def ok(z): 6870 assert tensor.constant(z).dtype == np.asarray(z).dtype 6871 for x in ([2 ** i for i in xrange(63)] + 6872 [0, L(0), L(1), L(2 ** 63 - 1)] + 6873 [0., 1., 1.1, 1.5]): 6874 n_x = np.asarray(x) 6875 # Make sure the data type is the same as the one found by numpy. 6876 ok(x) 6877 ok(-x) 6878 ok(x - 1) 6879 ok(-x + 1) 6880 ok(n_x) 6881 6882 6883def _test_autocast_numpy_floatX(): 6884 # Called from `test_autocast`. 6885 assert config.cast_policy == 'numpy+floatX' 6886 backup_floatX = config.floatX 6887 6888 def ok(z, floatX): 6889 if (isinstance(z, float) and 6890 floatX == 'float32' and 6891 not hasattr(z, 'dtype')): 6892 # Special case where we use 'float32' instead of 'float64'. 6893 assert tensor.constant(z).dtype == 'float32' 6894 else: 6895 assert tensor.constant(z).dtype == np.asarray(z).dtype 6896 try: 6897 # Test with various values of `config.floatX`. 6898 for floatX in ('float32', 'float64'): 6899 config.floatX = floatX 6900 # Go through some typical scalar values. 6901 # We only consider 'int' and 'long' Python values that can fit 6902 # into int64, as that is the maximal integer type that Theano 6903 # supports, and that is the maximal type in Python indexing. 6904 for x in ([2 ** i - 1 for i in xrange(64)] + 6905 [0, L(0), L(1), L(2 ** 63 - 1)] + 6906 [0., 1., 1.1, 1.5]): 6907 ok(x, floatX) 6908 ok(-x, floatX) 6909 ok(x - 1, floatX) 6910 ok(-x + 1, floatX) 6911 ok(np.asarray(x), floatX) 6912 ok(np.float64(x), floatX) 6913 finally: 6914 config.floatX = backup_floatX 6915 6916 6917class test_arithmetic_cast(unittest.TestCase): 6918 # Test output types of basic arithmeric operations (* / + - //). 6919 # 6920 # We only test the behavior for `config.cast_policy` set to either 'numpy' or 6921 # 'numpy+floatX': the 'custom' behavior is (at least partially) tested in 6922 # `_test_autocast_custom`. 6923 def test_arithmetic_cast(self): 6924 backup_config = config.cast_policy 6925 dtypes = get_numeric_types(with_complex=True) 6926 6927 # Here: 6928 # scalar == scalar stored as a 0d array 6929 # array == 1d array 6930 # i_scalar == scalar type used internally by Theano 6931 def theano_scalar(dtype): 6932 return tensor.scalar(dtype=str(dtype)) 6933 6934 def numpy_scalar(dtype): 6935 return np.array(1, dtype=dtype) 6936 6937 def theano_array(dtype): 6938 return tensor.vector(dtype=str(dtype)) 6939 6940 def numpy_array(dtype): 6941 return np.array([1], dtype=dtype) 6942 6943 def theano_i_scalar(dtype): 6944 return theano.scalar.Scalar(str(dtype))() 6945 6946 def numpy_i_scalar(dtype): 6947 return numpy_scalar(dtype) 6948 6949 if config.int_division == 'int': 6950 # Avoid deprecation warning during tests. 6951 warnings.filterwarnings('ignore', message='Division of two integer', 6952 category=DeprecationWarning) 6953 try: 6954 for cfg in ('numpy+floatX', ): # Used to test 'numpy' as well. 6955 config.cast_policy = cfg 6956 for op in (operator.add, operator.sub, operator.mul, 6957 operator_div, operator.floordiv): 6958 for a_type in dtypes: 6959 for b_type in dtypes: 6960 # Note that we do not test division between 6961 # integers if it is forbidden. 6962 # Theano deals with integer division in its own 6963 # special way (depending on `config.int_division`). 6964 is_int_division = ( 6965 op is operator_div and 6966 a_type in tensor.discrete_dtypes and 6967 b_type in tensor.discrete_dtypes) 6968 # We will test all meaningful combinations of 6969 # scalar and array operations. 6970 for combo in ( 6971 ('scalar', 'scalar'), 6972 ('array', 'array'), 6973 ('scalar', 'array'), 6974 ('array', 'scalar'), 6975 ('i_scalar', 'i_scalar'), 6976 ): 6977 6978 theano_args = list( 6979 map(eval, ['theano_%s' % c for c in combo])) 6980 numpy_args = list( 6981 map(eval, ['numpy_%s' % c for c in combo])) 6982 try: 6983 theano_dtype = op( 6984 theano_args[0](a_type), 6985 theano_args[1](b_type)).type.dtype 6986 # Should have crashed if it is an integer 6987 # division and `config.int_division` does 6988 # not allow it. 6989 assert not (is_int_division and 6990 config.int_division == 'raise') 6991 except theano.scalar.IntegerDivisionError: 6992 assert (is_int_division and 6993 config.int_division == 'raise') 6994 # This is the expected behavior. 6995 continue 6996 # For numpy we have a problem: 6997 # http://projects.scipy.org/numpy/ticket/1827 6998 # As a result we only consider the highest data 6999 # type that numpy may return. 7000 numpy_dtypes = [ 7001 op(numpy_args[0](a_type), 7002 numpy_args[1](b_type)).dtype, 7003 op(numpy_args[1](b_type), 7004 numpy_args[0](a_type)).dtype] 7005 numpy_dtype = theano.scalar.upcast( 7006 *list(map(str, numpy_dtypes))) 7007 if numpy_dtype == theano_dtype: 7008 # Same data type found, all is good! 7009 continue 7010 if (cfg == 'numpy+floatX' and 7011 config.floatX == 'float32' and 7012 a_type != 'float64' and 7013 b_type != 'float64' and 7014 numpy_dtype == 'float64'): 7015 # We should keep float32. 7016 assert theano_dtype == 'float32' 7017 continue 7018 if 'array' in combo and 'scalar' in combo: 7019 # For mixed scalar / array operations, 7020 # Theano may differ from numpy as it does 7021 # not try to prevent the scalar from 7022 # upcasting the array. 7023 array_type, scalar_type = ( 7024 (a_type, b_type)[list(combo).index(arg)] 7025 for arg in ('array', 'scalar')) 7026 up_type = theano.scalar.upcast(array_type, 7027 scalar_type) 7028 if ( 7029 # The two data types are different. 7030 scalar_type != array_type and 7031 # The array type is not enough to hold 7032 # the scalar type as well. 7033 array_type != up_type and 7034 # Theano upcasted the result array. 7035 theano_dtype == up_type and 7036 # But Numpy kept its original type. 7037 array_type == numpy_dtype): 7038 # Then we accept this difference in 7039 # behavior. 7040 continue 7041 if (is_int_division and 7042 config.int_division == 'floatX'): 7043 assert theano_dtype == config.floatX 7044 continue 7045 if (cfg == 'numpy+floatX' and 7046 a_type == 'complex128' and 7047 (b_type == 'float32' or 7048 b_type == 'float16') and 7049 combo == ('scalar', 'array') and 7050 theano_dtype == 'complex128' and 7051 numpy_dtype == 'complex64'): 7052 # In numpy 1.6.x adding a complex128 with 7053 # a float32 may result in a complex64. As 7054 # of 1.9.2. this is still the case so it is 7055 # probably by design 7056 raise SkipTest("Known issue with" 7057 "numpy see #761") 7058 # In any other situation: something wrong is 7059 # going on! 7060 assert False 7061 finally: 7062 config.cast_policy = backup_config 7063 if config.int_division == 'int': 7064 # Restore default deprecation warning behavior. 7065 warnings.filterwarnings( 7066 'default', 7067 message='Division of two integer', 7068 category=DeprecationWarning) 7069 7070 7071class T_long_tensor(unittest.TestCase): 7072 def test_fit_int64(self): 7073 bitwidth = theano.configdefaults.python_int_bitwidth() 7074 for exponent in xrange(bitwidth): 7075 val = L(2 ** exponent - 1) 7076 scalar_ct = constant(val) 7077 7078 assert scalar_ct.dtype in tensor.int_dtypes, (exponent, val, scalar_ct.dtype) 7079 assert scalar_ct.value == val 7080 7081 vector_ct = constant([val, val]) 7082 # On Python 2, np.array() on a "long" returns int64, 7083 # but on Python 3, all integers are long, and np.asarray 7084 # will not force the upcasting, and return the native int width. 7085 if PY3 and bitwidth == 32: 7086 assert vector_ct.dtype == 'int32' 7087 else: 7088 assert vector_ct.dtype == 'int64' 7089 assert np.all(vector_ct.value == val) 7090 7091 matrix_ct = constant([[val, val]]) 7092 # On Python 2, np.array() on a "long" returns int64, 7093 # but on Python 3, all integers are long, and np.asarray 7094 # will not force the upcasting, and return the native int width. 7095 if PY3 and bitwidth == 32: 7096 assert matrix_ct.dtype == 'int32' 7097 else: 7098 assert matrix_ct.dtype == 'int64' 7099 assert np.all(matrix_ct.value == val) 7100 7101 def test_too_big(self): 7102 val = L(2 ** 64) 7103 # This fail for all NumPy version. 7104 self.assertRaises(Exception, constant, val) 7105 self.assertRaises(Exception, constant, [val, val]) 7106 self.assertRaises(Exception, constant, [[val, val]]) 7107 7108 7109class test_broadcast(unittest.TestCase): 7110 def test_broadcast_bigdim(self): 7111 def f(): 7112 x = matrix() 7113 addbroadcast(x, 2) 7114 self.assertRaises(ValueError, f) 7115 7116 def test_unbroadcast_addbroadcast(self): 7117 # test that the unbroadcast fct don't insert not needed broadcast 7118 # and fuse consecutive Rebroadcast op 7119 7120 x = matrix() 7121 assert unbroadcast(x, 0) is x 7122 assert unbroadcast(x, 1) is x 7123 assert unbroadcast(x, 1, 0) is x 7124 assert unbroadcast(x, 0, 1) is x 7125 7126 assert addbroadcast(x, 0) is not x 7127 assert addbroadcast(x, 1) is not x 7128 assert addbroadcast(x, 1, 0).owner.inputs[0] is x 7129 7130 assert unbroadcast(addbroadcast(x, 0), 0) is x 7131 assert addbroadcast(unbroadcast(x, 0), 0) is not x 7132 x = row() 7133 assert unbroadcast(x, 0) is not x 7134 assert unbroadcast(x, 1) is x 7135 assert unbroadcast(x, 1, 0) is not x 7136 assert unbroadcast(x, 0, 1) is not x 7137 7138 assert addbroadcast(x, 0) is x 7139 assert addbroadcast(x, 1).owner.inputs[0] is x 7140 assert addbroadcast(x, 1, 0).owner.inputs[0] is x 7141 assert addbroadcast(x, 0, 1).owner.inputs[0] is x 7142 7143 assert unbroadcast(addbroadcast(x, 1), 1) is x 7144 assert addbroadcast(unbroadcast(x, 1), 1) is not x 7145 7146 # The first broadcast is remove the broadcast, so the second 7147 # should not make one 7148 assert unbroadcast(unbroadcast(x, 0), 0).owner.inputs[0] is x 7149 7150 # Test that consecutive Rebroadcast op are fused 7151 x = TensorType(dtype='float64', broadcastable=(True, True))() 7152 assert unbroadcast(unbroadcast(x, 1), 0).owner.inputs[0] is x 7153 assert addbroadcast(unbroadcast(x, 1), 0).owner.inputs[0] is x 7154 assert addbroadcast(unbroadcast(x, 0), 0) is x 7155 7156 def test_patternbroadcast(self): 7157 # Test that patternbroadcast with an empty broadcasting pattern works 7158 x = scalar('x') 7159 m = tensor.matrix('m') 7160 s = patternbroadcast(m, x.broadcastable) 7161 assert s is m 7162 x2 = patternbroadcast(x, x.broadcastable) 7163 assert x2 is x 7164 7165 def test_infer_shape(self): 7166 x = matrix() 7167 y = addbroadcast(x, 0) 7168 f = theano.function([x], y.shape) 7169 assert (f(np.zeros((1, 5), dtype=config.floatX)) == [1, 5]).all() 7170 topo = f.maker.fgraph.toposort() 7171 if theano.config.mode != 'FAST_COMPILE': 7172 assert len(topo) == 2 7173 assert isinstance(topo[0].op, opt.Shape_i) 7174 assert isinstance(topo[1].op, opt.MakeVector) 7175 7176 x = matrix() 7177 y = unbroadcast(x, 0) 7178 f = theano.function([x], y.shape) 7179 assert (f(np.zeros((2, 5), dtype=config.floatX)) == [2, 5]).all() 7180 topo = f.maker.fgraph.toposort() 7181 if theano.config.mode != 'FAST_COMPILE': 7182 assert len(topo) == 3 7183 assert isinstance(topo[0].op, opt.Shape_i) 7184 assert isinstance(topo[1].op, opt.Shape_i) 7185 assert isinstance(topo[2].op, opt.MakeVector) 7186 7187 x = row() 7188 y = unbroadcast(x, 0) 7189 f = theano.function([x], y.shape) 7190 assert (f(np.zeros((1, 5), dtype=config.floatX)) == [1, 5]).all() 7191 topo = f.maker.fgraph.toposort() 7192 if theano.config.mode != 'FAST_COMPILE': 7193 assert len(topo) == 2 7194 assert isinstance(topo[0].op, opt.Shape_i) 7195 assert isinstance(topo[1].op, opt.MakeVector) 7196 7197 7198def test_len(): 7199 for shape_ in [(5,), (3, 4), (7, 4, 6)]: 7200 x = tensor.tensor(dtype='floatX', broadcastable=(False,) * len(shape_)) 7201 assert_raises(TypeError, len, x) 7202 7203 7204def test_mod(): 7205 # We add this test as not all language and C implementation give the same 7206 # sign to the result. This check that the c_code of `Mod` is implemented 7207 # as Python. That is what we want. 7208 x, y = fscalars('xy') 7209 fn = gof.DualLinker().accept( 7210 gof.FunctionGraph([x, y], [x % y])).make_function() 7211 for a, b in ((0, 1), (1, 1), (0, -1), (1, -1), (-1, -1), 7212 (1, 2), (-1, 2), (1, -2), (-1, -2), 7213 (5, 3), (-5, 3), (5, -3), (-5, -3) 7214 ): 7215 assert fn(a, b) == a % b, (a,) 7216 7217 7218def test_divmod(): 7219 # Confirm that divmod is equivalent to the python version. 7220 x, y = fscalars('xy') 7221 d, r = divmod(x, y) 7222 fn = gof.DualLinker().accept( 7223 gof.FunctionGraph([x, y], [d, r])).make_function() 7224 for a, b in ((0, 1), (1, 1), (0, -1), (1, -1), (-1, -1), 7225 (1, 2), (-1, 2), (1, -2), (-1, -2), 7226 (5, 3), (-5, 3), (5, -3), (-5, -3) 7227 ): 7228 d_v, r_v = fn(a, b) 7229 d_vp, r_vp = divmod(a, b) 7230 assert d_v == d_vp and r_v == r_vp, (a,) 7231 7232 7233def test_mod_compile(): 7234 # This test generate an Elemwise of Composite as: 7235 # Elemwise{ 7236 # Composite{ 7237 # Composite{ 7238 # Composite{ 7239 # Composite{mod,EQ}, 7240 # Switch}, 7241 # mul}, 7242 # add}} 7243 # 7244 # The c_code generated is not compiling as of 30 June 2010. I fix the 7245 # compilation in the same commit. 7246 x = tensor.vector() 7247 y = tensor.vector() 7248 out = tensor.switch(tensor.eq(3 % x.shape[0], 0), y, y[:-1]) 7249 7250 theano.function([x, y], out) 7251 7252 7253def test_unalign(): 7254 if config.floatX == 'float64': 7255 dtype = "b1,f8" 7256 else: 7257 dtype = "b1,f4" 7258 7259 a = np.empty(10000, dtype=dtype)['f1'] 7260 b = np.empty(10000, dtype=dtype)['f1'] 7261 assert not a.flags.aligned 7262 assert not b.flags.aligned 7263 a[:] = rand(len(a)) 7264 b[:] = rand(len(b)) 7265 out_numpy = 2 * a + 3 * b 7266 7267 av, bv = tensor.vectors('ab') 7268 f = theano.function([av, bv], 2 * av + 3 * bv) 7269 f.maker.fgraph.toposort() 7270 7271 try: 7272 out_theano = f(a, b) 7273 assert not a.flags.aligned 7274 assert not b.flags.aligned 7275 assert np.allclose(out_numpy, out_theano) 7276 assert False 7277 except TypeError: 7278 pass 7279 7280 a = np.empty((), dtype=dtype)['f1'] 7281 b = np.empty((), dtype=dtype)['f1'] 7282 assert not a.flags.aligned 7283 assert not b.flags.aligned 7284 out_numpy = 2 * a + 3 * b 7285 7286 av, bv = tensor.scalars('ab') 7287 f = theano.function([av, bv], 2 * av + 3 * bv) 7288 f.maker.fgraph.toposort() 7289 try: 7290 out_theano = f(a, b) 7291 assert not a.flags.aligned 7292 assert not b.flags.aligned 7293 assert np.allclose(out_numpy, out_theano) 7294 assert False 7295 except TypeError: 7296 pass 7297 7298 7299def test_dimshuffle_duplicate(): 7300 x = tensor.vector() 7301 7302 success = False 7303 7304 try: 7305 tensor.DimShuffle((False, ), (0, 0))(x) 7306 except ValueError as e: 7307 assert str(e).find("may not appear twice") != -1 7308 success = True 7309 7310 assert success 7311 7312 7313class T_get_scalar_constant_value(unittest.TestCase): 7314 def test_get_scalar_constant_value(self): 7315 a = tensor.stack([1, 2, 3]) 7316 assert get_scalar_constant_value(a[0]) == 1 7317 assert get_scalar_constant_value(a[1]) == 2 7318 assert get_scalar_constant_value(a[2]) == 3 7319 7320 b = tensor.iscalar() 7321 a = tensor.stack([b, 2, 3]) 7322 self.assertRaises(tensor.basic.NotScalarConstantError, get_scalar_constant_value, a[0]) 7323 assert get_scalar_constant_value(a[1]) == 2 7324 assert get_scalar_constant_value(a[2]) == 3 7325 7326 # For now get_scalar_constant_value goes through only MakeVector and Join of 7327 # scalars. 7328 v = tensor.ivector() 7329 a = tensor.stack([v, [2], [3]]) 7330 self.assertRaises(tensor.NotScalarConstantError, get_scalar_constant_value, a[0]) 7331 self.assertRaises(tensor.NotScalarConstantError, get_scalar_constant_value, a[1]) 7332 self.assertRaises(tensor.NotScalarConstantError, get_scalar_constant_value, a[2]) 7333 7334 # Test the case SubTensor(Shape(v)) when the dimensions 7335 # is broadcastable. 7336 v = tensor.row() 7337 assert get_scalar_constant_value(v.shape[0]) == 1 7338 7339 def test_subtensor_of_constant(self): 7340 c = constant(rand(5)) 7341 for i in range(c.value.shape[0]): 7342 assert get_scalar_constant_value(c[i]) == c.value[i] 7343 c = constant(rand(5, 5)) 7344 for i in range(c.value.shape[0]): 7345 for j in range(c.value.shape[1]): 7346 assert get_scalar_constant_value(c[i, j]) == c.value[i, j] 7347 7348 def test_numpy_array(self): 7349 # Regression test for crash when called on a numpy array. 7350 assert get_scalar_constant_value(np.array(3)) == 3 7351 self.assertRaises( 7352 tensor.NotScalarConstantError, 7353 get_scalar_constant_value, 7354 np.array([0, 1])) 7355 self.assertRaises( 7356 tensor.EmptyConstantError, 7357 get_scalar_constant_value, 7358 np.array([])) 7359 7360 def test_make_vector(self): 7361 mv = opt.make_vector(1, 2, 3) 7362 self.assertRaises( 7363 tensor.NotScalarConstantError, 7364 get_scalar_constant_value, 7365 mv) 7366 assert get_scalar_constant_value(mv[0]) == 1 7367 assert get_scalar_constant_value(mv[1]) == 2 7368 assert get_scalar_constant_value(mv[2]) == 3 7369 assert get_scalar_constant_value(mv[np.int32(0)]) == 1 7370 assert get_scalar_constant_value(mv[np.int64(1)]) == 2 7371 assert get_scalar_constant_value(mv[np.uint(2)]) == 3 7372 t = theano.scalar.Scalar('int64') 7373 self.assertRaises( 7374 tensor.NotScalarConstantError, 7375 get_scalar_constant_value, 7376 mv[t()]) 7377 7378 def test_shape_i(self): 7379 c = theano.tensor.constant(np.random.rand(3, 4)) 7380 s = opt.Shape_i(0)(c) 7381 assert get_scalar_constant_value(s) == 3 7382 s = opt.Shape_i(1)(c) 7383 assert get_scalar_constant_value(s) == 4 7384 d = theano.shared(np.random.randn(1, 1), broadcastable=(True, True)) 7385 f = theano.tensor.basic.ScalarFromTensor()(opt.Shape_i(0)(d)) 7386 assert get_scalar_constant_value(f) == 1 7387 7388 def test_elemwise(self): 7389 # We test only for a few elemwise, the list of all supported 7390 # elemwise are in the fct. 7391 c = theano.tensor.constant(np.random.rand()) 7392 s = c + 1 7393 assert np.allclose(get_scalar_constant_value(s), c.data + 1) 7394 s = c - 1 7395 assert np.allclose(get_scalar_constant_value(s), c.data - 1) 7396 s = c * 1.2 7397 assert np.allclose(get_scalar_constant_value(s), c.data * 1.2) 7398 s = c < 0.5 7399 assert np.allclose(get_scalar_constant_value(s), int(c.data < 0.5)) 7400 s = tensor.second(c, .4) 7401 assert np.allclose(get_scalar_constant_value(s), .4) 7402 7403 def test_assert(self): 7404 # Make sure we still get the constant value if it is wrapped in 7405 # an Assert. 7406 c = theano.tensor.constant(2) 7407 x = theano.tensor.scalar() 7408 7409 # condition is always True 7410 a = opt.Assert()(c, c > 1) 7411 assert get_scalar_constant_value(a) == 2 7412 7413 with change_flags(compute_test_value='off'): 7414 # condition is always False 7415 a = opt.Assert()(c, c > 2) 7416 self.assertRaises( 7417 tensor.NotScalarConstantError, 7418 get_scalar_constant_value, a) 7419 7420 # condition is not constant 7421 a = opt.Assert()(c, c > x) 7422 self.assertRaises( 7423 tensor.NotScalarConstantError, 7424 get_scalar_constant_value, a) 7425 7426 def test_second(self): 7427 # Second should apply when the value is constant but not the shape 7428 c = theano.tensor.constant(np.random.rand()) 7429 shp = theano.tensor.vector() 7430 s = theano.tensor.second(shp, c) 7431 assert get_scalar_constant_value(s) == c.data 7432 7433 def test_copy(self): 7434 # Make sure we do not return the internal storage of a constant, 7435 # so we cannot change the value of a constant by mistake. 7436 c = theano.tensor.constant(3) 7437 d = extract_constant(c) 7438 d += 1 7439 e = extract_constant(c) 7440 self.assertTrue(e == 3, (c, d, e)) 7441 7442 7443class T_as_tensor_variable(unittest.TestCase): 7444 # We test that ticket #649 stay fixed. 7445 # We should not allow as_tensor_variable to accept True or False 7446 # But it should upcast an ndarray of bool to uint8 7447 def test_bool(self): 7448 self.assertRaises(TypeError, as_tensor_variable, True) 7449 self.assertRaises(TypeError, as_tensor_variable, False) 7450 7451 def test_ndarray_bool(self): 7452 ten = as_tensor_variable(np.array([True, False, False, True, True])) 7453 assert ten.type.dtype == 'bool' 7454 7455 def test_memmap(self): 7456 inp = np.random.rand(4, 3) 7457 f, fname = mkstemp() 7458 new_inp = np.memmap(fname, dtype=inp.dtype, 7459 mode='w+', shape=inp.shape) 7460 new_inp[...] = inp 7461 as_tensor_variable(new_inp) 7462 7463 def test_empty_dtype(self): 7464 old = theano.config.floatX 7465 for dtype in ['float16', 'float32', 'float64']: 7466 try: 7467 theano.config.floatX = dtype 7468 assert theano.tensor.as_tensor_variable(()).dtype == dtype 7469 assert theano.tensor.as_tensor_variable([]).dtype == dtype 7470 finally: 7471 theano.config.floatX = old 7472 7473 7474class test_complex_mod(unittest.TestCase): 7475 # Make sure % fails on complex numbers. 7476 def test_fail(self): 7477 x = vector(dtype='complex64') 7478 try: 7479 x % 5 7480 assert False 7481 except theano.scalar.ComplexError: 7482 pass 7483 7484 7485class test_size(unittest.TestCase): 7486 # Ensure the `size` attribute of tensors behaves as in numpy. 7487 def test_matrix(self): 7488 x = tensor.matrix() 7489 y = np.zeros((5, 7), dtype=config.floatX) 7490 assert y.size == function([x], x.size)(y) 7491 7492 def test_vector(self): 7493 x = tensor.vector() 7494 y = np.zeros(7, dtype=config.floatX) 7495 assert y.size == function([x], x.size)(y) 7496 7497 def test_scalar(self): 7498 x = tensor.scalar() 7499 y = np.array(7, dtype=config.floatX) 7500 assert y.size == function([x], x.size)(y) 7501 7502 def test_shared(self): 7503 # NB: we also test higher order tensors at the same time. 7504 y = np.zeros((1, 2, 3, 4), dtype=config.floatX) 7505 x = theano.shared(y) 7506 assert y.size == function([], x.size)() 7507 7508 7509class test_diag(unittest.TestCase): 7510 # Test that tensor.diag has the same behavior as np.diag. 7511 # np.diag has two behaviors: 7512 # 7513 # (1) when given a vector, it returns a matrix with that vector as the 7514 # diagonal. 7515 # (2) when given a matrix, returns a vector which is the diagonal of the 7516 # matrix. 7517 # 7518 # (1) and (2) are tested by test_alloc_diag and test_extract_diag 7519 # respectively. 7520 # 7521 # test_diag test makes sure that linalg.diag instantiates 7522 # the right op based on the dimension of the input. 7523 def __init__(self, name, mode=None, shared=tensor._shared, 7524 floatX=None, type=tensor.TensorType): 7525 self.mode = mode 7526 self.shared = shared 7527 if floatX is None: 7528 floatX = config.floatX 7529 self.floatX = floatX 7530 self.type = type 7531 super(test_diag, self).__init__(name) 7532 7533 def test_diag(self): 7534 rng = np.random.RandomState(utt.fetch_seed()) 7535 7536 # test vector input 7537 x = theano.tensor.vector() 7538 g = diag(x) 7539 assert isinstance(g.owner.op, AllocDiag) 7540 f = theano.function([x], g) 7541 for shp in [5, 0, 1]: 7542 m = rng.rand(shp).astype(self.floatX) 7543 v = np.diag(m) 7544 r = f(m) 7545 # The right matrix is created 7546 assert (r == v).all() 7547 7548 # Test matrix input 7549 xx = self.shared(rng.rand(3, 5)) 7550 g = diag(xx) 7551 assert isinstance(g.owner.op, ExtractDiag) 7552 f = theano.function([], g) 7553 for shp in [(5, 3), (3, 5), (5, 1), (1, 5), (5, 0), (0, 5), 7554 (1, 0), (0, 1)]: 7555 m = rng.rand(*shp).astype(self.floatX) 7556 xx.set_value(m) 7557 v = np.diag(m) 7558 r = f() 7559 # The right matrix is created 7560 assert (r == v).all() 7561 7562 # Test scalar input 7563 xx = theano.tensor.scalar() 7564 np.testing.assert_raises(ValueError, diag, xx) 7565 7566 def test_infer_shape(self): 7567 rng = np.random.RandomState(utt.fetch_seed()) 7568 7569 x = theano.tensor.vector() 7570 g = diag(x) 7571 f = theano.function([x], g.shape) 7572 topo = f.maker.fgraph.toposort() 7573 if config.mode != 'FAST_COMPILE': 7574 assert np.sum( 7575 [isinstance(node.op, AllocDiag) for node in topo]) == 0 7576 for shp in [5, 0, 1]: 7577 m = rng.rand(shp).astype(self.floatX) 7578 assert (f(m) == np.diag(m).shape).all() 7579 7580 x = theano.tensor.matrix() 7581 g = diag(x) 7582 f = theano.function([x], g.shape) 7583 topo = f.maker.fgraph.toposort() 7584 if config.mode != 'FAST_COMPILE': 7585 assert np.sum( 7586 [isinstance(node.op, ExtractDiag) for node in topo]) == 0 7587 for shp in [(5, 3), (3, 5), (5, 1), (1, 5), (5, 0), (0, 5), 7588 (1, 0), (0, 1)]: 7589 m = rng.rand(*shp).astype(self.floatX) 7590 assert (f(m) == np.diag(m).shape).all() 7591 7592 def test_diag_grad(self): 7593 rng = np.random.RandomState(utt.fetch_seed()) 7594 x = rng.rand(5) 7595 tensor.verify_grad(diag, [x], rng=rng) 7596 x = rng.rand(5, 3) 7597 tensor.verify_grad(diag, [x], rng=rng) 7598 7599 7600class TestAllocDiag(unittest.TestCase): 7601 def __init__(self, name, alloc_diag=AllocDiag, mode=None): 7602 self.alloc_diag = alloc_diag 7603 7604 if mode is None: 7605 mode = theano.compile.mode.get_default_mode() 7606 self.mode = mode 7607 7608 super(TestAllocDiag, self).__init__(name) 7609 7610 def _generator(self): 7611 dims = 4 7612 shape = (5,) * dims 7613 xv = np.random.randn(*shape).astype(config.floatX) 7614 for d in xrange(1, dims + 1): 7615 # Create a TensorType of the same dimensions as 7616 # as the data we want to test. 7617 x = TensorType(dtype=config.floatX, broadcastable=(False,) * d)('x') 7618 7619 # Make a slice of the test data that has the 7620 # dimensions we need by doing xv[0,...,0] 7621 # For example, for an array of shape (5,), we 7622 # need to do xv[0, 0, 0, 0]. 7623 test_val = xv[((0,) * (dims - d))] 7624 yield x, test_val 7625 7626 def test_alloc_diag_values(self): 7627 for x, test_val in self._generator(): 7628 for offset, axis1, axis2 in [(0, 0, 1), (0, 1, 2), (1, 0, 1), 7629 (0, 1, 3), (0, 2, 3), (1, 2, 3), 7630 (-1, 0, 1), (-2, 0, 1), (-1, 1, 2)]: 7631 # Test AllocDiag values 7632 if np.maximum(axis1, axis2) > len(test_val.shape): 7633 continue 7634 adiag_op = self.alloc_diag(offset=offset, 7635 axis1=axis1, 7636 axis2=axis2) 7637 f = theano.function([x], adiag_op(x)) 7638 # AllocDiag and extract the diagonal again 7639 # to check 7640 diag_arr = f(test_val) 7641 rediag = np.diagonal( 7642 diag_arr, 7643 offset=offset, 7644 axis1=axis1, 7645 axis2=axis2 7646 ) 7647 assert np.all(rediag == test_val) 7648 7649 # Test infer_shape 7650 f_shape = theano.function([x], adiag_op(x).shape, mode='FAST_RUN') 7651 7652 theano.printing.debugprint(f_shape.maker.fgraph.outputs[0]) 7653 output_shape = f_shape(test_val) 7654 assert not any(isinstance(node.op, self.alloc_diag) 7655 for node in f_shape.maker.fgraph.toposort()) 7656 rediag_shape = np.diagonal( 7657 np.ones(output_shape), 7658 offset=offset, 7659 axis1=axis1, 7660 axis2=axis2 7661 ).shape 7662 assert np.all(rediag_shape == test_val.shape) 7663 7664 diag_x = adiag_op(x) 7665 sum_diag_x = tensor.sum(diag_x) 7666 grad_x = tensor.grad(sum_diag_x, x) 7667 grad_diag_x = tensor.grad(sum_diag_x, diag_x) 7668 f_grad_x = theano.function([x], grad_x, mode=self.mode) 7669 f_grad_diag_x = theano.function([x], grad_diag_x, mode=self.mode) 7670 grad_input = f_grad_x(test_val) 7671 grad_diag_input = f_grad_diag_x(test_val) 7672 true_grad_input = np.diagonal( 7673 grad_diag_input, 7674 offset=offset, 7675 axis1=axis1, 7676 axis2=axis2 7677 ) 7678 7679 assert np.all(true_grad_input == grad_input) 7680 7681 7682class test_numpy_assumptions(unittest.TestCase): 7683 # Verify that some assumptions Theano makes on Numpy's behavior still hold. 7684 def test_ndarray_copy(self): 7685 # A copy or deepcopy of the ndarray type should not create a new object. 7686 # 7687 # This is because Theano makes some comparisons of the form: 7688 # if type(x) is np.ndarray 7689 assert copy(np.ndarray) is np.ndarray 7690 assert deepcopy(np.ndarray) is np.ndarray 7691 7692 def test_dtype_equality(self): 7693 # Ensure dtype string comparisons are consistent. 7694 # 7695 # Theano often uses string representations of dtypes (e.g. 'float32'). We 7696 # need to make sure that comparing the string representations is the same 7697 # as comparing the dtype objects themselves. 7698 dtypes = get_numeric_types(with_complex=True) 7699 # Perform all pairwise comparisons of dtypes, making sure comparing 7700 # their string representation yields the same result. 7701 for dtype1_idx, dtype1 in enumerate(dtypes): 7702 for dtype2 in dtypes[dtype1_idx + 1:]: 7703 assert (dtype1 == dtype2) == (str(dtype1) == str(dtype2)) 7704 7705 7706def test_transpose(): 7707 x1 = tensor.dvector('x1') 7708 x2 = tensor.dmatrix('x2') 7709 x3 = tensor.dtensor3('x3') 7710 7711 x1v = np.arange(24) 7712 x2v = np.arange(24).reshape(2, 12) 7713 x3v = np.arange(24).reshape(2, 3, 4) 7714 7715 f = theano.function([x1, x2, x3], [ 7716 tensor.transpose(x1), 7717 tensor.transpose(x2), 7718 tensor.transpose(x3), 7719 x1.transpose(), 7720 x2.transpose(), 7721 x3.transpose(), 7722 x2.transpose(0, 1), 7723 x3.transpose((0, 2, 1)), 7724 tensor.transpose(x2, [0, 1]), 7725 tensor.transpose(x3, [0, 2, 1]), 7726 ]) 7727 7728 t1, t2, t3, t1b, t2b, t3b, t2c, t3c, t2d, t3d = f(x1v, x2v, x3v) 7729 assert t1.shape == np.transpose(x1v).shape 7730 assert t2.shape == np.transpose(x2v).shape 7731 assert t3.shape == np.transpose(x3v).shape 7732 assert np.all(t1 == np.transpose(x1v)) 7733 assert np.all(t2 == np.transpose(x2v)) 7734 assert np.all(t3 == np.transpose(x3v)) 7735 assert np.all(t1b == x1v.transpose()) 7736 assert np.all(t2b == x2v.transpose()) 7737 assert np.all(t3b == x3v.transpose()) 7738 assert t2c.shape == (2, 12) 7739 assert t3c.shape == (2, 4, 3) 7740 assert np.all(t2c == x2v.transpose([0, 1])) 7741 assert np.all(t3c == x3v.transpose([0, 2, 1])) 7742 assert t2d.shape == (2, 12) 7743 assert t3d.shape == (2, 4, 3) 7744 assert np.all(t2d == np.transpose(x2v, [0, 1])) 7745 assert np.all(t3d == np.transpose(x3v, [0, 2, 1])) 7746 7747 # Check that we create a name. 7748 assert tensor.transpose(x1).name == 'x1.T' 7749 assert tensor.transpose(x2).name == 'x2.T' 7750 assert tensor.transpose(x3).name == 'x3.T' 7751 assert tensor.transpose(tensor.dmatrix()).name is None 7752 7753 7754def test_stacklists(): 7755 a, b, c, d = map(scalar, 'abcd') 7756 X = stacklists([[a, b], 7757 [c, d]]) 7758 f = function([a, b, c, d], X) 7759 result = f(1, 2, 3, 4) 7760 assert result.shape == (2, 2) 7761 assert np.allclose(f(1, 2, 3, 4), np.asarray([[1, 2], [3, 4]])) 7762 7763 X = stacklists([a, b, c, d]) 7764 f = function([a, b, c, d], X) 7765 result = f(1, 2, 3, 4) 7766 assert result.shape == (4,) 7767 assert np.allclose(f(1, 2, 3, 4), np.asarray([[1, 2, 3, 4]])) 7768 7769 X = stacklists([[[a], [b]], [[c], [d]]]) 7770 f = function([a, b, c, d], X) 7771 result = f(1, 2, 3, 4) 7772 assert result.shape == (2, 2, 1) 7773 7774 a, b, c, d = [matrix(x) for x in 'abcd'] 7775 X = stacklists([[a, b], 7776 [c, d]]) 7777 f = function([a, b, c, d], X) 7778 x = np.ones((4, 4), 'float32') 7779 assert f(x, x, x, x).shape == (2, 2, 4, 4) 7780 7781 7782class TestSpecifyShape(unittest.TestCase): 7783 mode = None 7784 input_type = TensorType 7785 7786 def shortDescription(self): 7787 return None 7788 7789 def test_bad_shape(self): 7790 # Test that at run time we raise an exception when the shape 7791 # is not the one specified 7792 specify_shape = SpecifyShape() 7793 7794 x = vector() 7795 xval = np.random.rand(2).astype(floatX) 7796 f = theano.function([x], specify_shape(x, [2]), mode=self.mode) 7797 f(xval) 7798 xval = np.random.rand(3).astype(floatX) 7799 self.assertRaises(AssertionError, f, xval) 7800 7801 assert isinstance([n for n in f.maker.fgraph.toposort() 7802 if isinstance(n.op, SpecifyShape)][0].inputs[0].type, 7803 self.input_type) 7804 7805 x = matrix() 7806 xval = np.random.rand(2, 3).astype(floatX) 7807 f = theano.function([x], specify_shape(x, [2, 3]), mode=self.mode) 7808 assert isinstance([n for n in f.maker.fgraph.toposort() 7809 if isinstance(n.op, SpecifyShape)][0].inputs[0].type, 7810 self.input_type) 7811 f(xval) 7812 for shape_ in [(1, 3), (2, 2), (5, 5)]: 7813 xval = np.random.rand(*shape_).astype(floatX) 7814 self.assertRaises(AssertionError, f, xval) 7815 7816 def test_bad_number_of_shape(self): 7817 # Test that the number of dimensions provided is good 7818 specify_shape = SpecifyShape() 7819 7820 x = vector() 7821 shape_vec = ivector() 7822 xval = np.random.rand(2).astype(floatX) 7823 self.assertRaises(AssertionError, specify_shape, x, []) 7824 self.assertRaises(AssertionError, specify_shape, x, [2, 2]) 7825 7826 f = theano.function([x, shape_vec], specify_shape(x, shape_vec), 7827 mode=self.mode) 7828 assert isinstance([n for n in f.maker.fgraph.toposort() 7829 if isinstance(n.op, SpecifyShape)][0].inputs[0].type, 7830 self.input_type) 7831 self.assertRaises(AssertionError, f, xval, []) 7832 self.assertRaises(AssertionError, f, xval, [2, 2]) 7833 7834 x = matrix() 7835 xval = np.random.rand(2, 3).astype(floatX) 7836 for shape_ in [(), 7837 (1,), 7838 (2, 3, 4)]: 7839 self.assertRaises(AssertionError, specify_shape, x, shape_) 7840 f = theano.function([x, shape_vec], specify_shape(x, shape_vec), 7841 mode=self.mode) 7842 assert isinstance([n for n in f.maker.fgraph.toposort() 7843 if isinstance(n.op, SpecifyShape)][0].inputs[0].type, 7844 self.input_type) 7845 self.assertRaises(AssertionError, f, xval, shape_) 7846 7847 7848class TestInferShape(utt.InferShapeTester): 7849 7850 def test_infer_shape(self): 7851 7852 # Flatten 7853 atens3 = tensor3() 7854 atens3_val = rand(4, 5, 3) 7855 for outdim in (3, 2, 1): 7856 self._compile_and_check([atens3], 7857 [flatten(atens3, outdim)], 7858 [atens3_val], Reshape, 7859 excluding=['local_useless_reshape']) 7860 7861 amat = matrix() 7862 amat_val = rand(4, 5) 7863 for outdim in (2, 1): 7864 self._compile_and_check([amat], 7865 [flatten(amat, outdim)], 7866 [amat_val], Reshape, 7867 excluding=['local_useless_reshape']) 7868 7869 avec = vector() 7870 avec_val = rand(4) 7871 outdim = 1 7872 self._compile_and_check([avec], 7873 [flatten(avec, outdim)], 7874 [avec_val], Reshape, 7875 excluding=['local_useless_reshape']) 7876 7877 # Eye 7878 aiscal = iscalar() 7879 biscal = iscalar() 7880 ciscal = iscalar() 7881 self._compile_and_check([aiscal, biscal, ciscal], 7882 [Eye()(aiscal, biscal, ciscal)], 7883 [4, 4, 0], Eye) 7884 7885 self._compile_and_check([aiscal, biscal, ciscal], 7886 [Eye()(aiscal, biscal, ciscal)], 7887 [4, 5, 0], Eye) 7888 7889 self._compile_and_check([aiscal, biscal, ciscal], 7890 [Eye()(aiscal, biscal, ciscal)], 7891 [3, 5, 0], Eye) 7892 7893 # Tri 7894 aiscal = iscalar() 7895 biscal = iscalar() 7896 ciscal = iscalar() 7897 self._compile_and_check([aiscal, biscal, ciscal], 7898 [Tri()(aiscal, biscal, ciscal)], 7899 [4, 4, 0], Tri) 7900 7901 self._compile_and_check([aiscal, biscal, ciscal], 7902 [Tri()(aiscal, biscal, ciscal)], 7903 [4, 5, 0], Tri) 7904 7905 self._compile_and_check([aiscal, biscal, ciscal], 7906 [Tri()(aiscal, biscal, ciscal)], 7907 [3, 5, 0], Tri) 7908 7909 # ExtractDiag 7910 atens3 = tensor3() 7911 atens3_val = rand(4, 5, 3) 7912 atens3_diag = ExtractDiag()(atens3) 7913 self._compile_and_check([atens3], [atens3_diag], 7914 [atens3_val], ExtractDiag) 7915 atens3_diag = ExtractDiag(1)(atens3) 7916 self._compile_and_check([atens3], [atens3_diag], 7917 [atens3_val], ExtractDiag) 7918 atens3_diag = ExtractDiag(-1)(atens3) 7919 self._compile_and_check([atens3], [atens3_diag], 7920 [atens3_val], ExtractDiag) 7921 atens3_diag = ExtractDiag(1, 0, 2)(atens3) 7922 self._compile_and_check([atens3], [atens3_diag], 7923 [atens3_val], ExtractDiag) 7924 atens3_diag = ExtractDiag(1, 1, 2)(atens3) 7925 self._compile_and_check([atens3], [atens3_diag], 7926 [atens3_val], ExtractDiag) 7927 atens3_diag = ExtractDiag(1, 2, 0)(atens3) 7928 self._compile_and_check([atens3], [atens3_diag], 7929 [atens3_val], ExtractDiag) 7930 7931 # AllocDiag 7932 advec = dvector() 7933 advec_val = rand(4) 7934 self._compile_and_check([advec], [AllocDiag()(advec)], 7935 [advec_val], AllocDiag) 7936 7937 # Shape 7938 # 'opt.Makevector' precludes optimizer from disentangling 7939 # elements of shape 7940 adtens = tensor3() 7941 adtens_val = rand(4, 5, 3) 7942 self._compile_and_check([adtens], 7943 [Shape()(adtens)], 7944 [adtens_val], (opt.MakeVector, Shape)) 7945 7946 # Dot 7947 7948 # vec/vec 7949 advec = dvector() 7950 bdvec = dvector() 7951 advec_val = rand(4) 7952 bdvec_val = rand(4) 7953 self._compile_and_check([advec, bdvec], 7954 [Dot()(advec, bdvec)], 7955 [advec_val, bdvec_val], 7956 (Dot, tensor.blas.Dot22, 7957 tensor.blas.Gemv, tensor.blas_c.CGemv)) 7958 7959 # mat/mat 7960 admat = dmatrix() 7961 bdmat = dmatrix() 7962 admat_val = rand(4, 5) 7963 bdmat_val = rand(5, 3) 7964 self._compile_and_check([admat, bdmat], 7965 [Dot()(admat, bdmat)], 7966 [admat_val, bdmat_val], 7967 (Dot, tensor.blas.Dot22)) 7968 7969 # vec/mat 7970 bdmat_val = rand(4, 5) 7971 self._compile_and_check([advec, bdmat], 7972 [Dot()(advec, bdmat)], 7973 [advec_val, bdmat_val], 7974 (Dot, tensor.blas.Dot22, 7975 tensor.blas.Gemv, tensor.blas_c.CGemv)) 7976 7977 # mat/vec 7978 admat_val = rand(5, 4) 7979 self._compile_and_check([admat, bdvec], 7980 [Dot()(admat, bdvec)], 7981 [admat_val, bdvec_val], 7982 (Dot, tensor.blas.Dot22, 7983 tensor.blas.Gemv, tensor.blas_c.CGemv)) 7984 7985 # Split 7986 aivec = ivector() 7987 adtens_val = rand(4, 10, 3) 7988 aivec_val = [2, 5, 3] 7989 for aiscal_val in [1, -2]: 7990 self._compile_and_check( 7991 [adtens, aiscal, aivec], 7992 [Split(3)(adtens, aiscal, aivec)[0]], 7993 [adtens_val, aiscal_val, aivec_val], (Split)) 7994 7995 # Join 7996 cdmat = dmatrix() 7997 admat_val = rand(1, 3) 7998 bdmat_val = rand(2, 3) 7999 cdmat_val = rand(4, 3) 8000 for aiscal_val in [0, -2]: 8001 self._compile_and_check( 8002 [aiscal, admat, bdmat, cdmat], 8003 [Join()(aiscal, admat, bdmat, cdmat)], 8004 [aiscal_val, admat_val, bdmat_val, cdmat_val], Join) 8005 8006 admat_val = rand(4, 1) 8007 bdmat_val = rand(4, 3) 8008 cdmat_val = rand(4, 2) 8009 for aiscal_val in [-1, 1]: 8010 self._compile_and_check( 8011 [aiscal, admat, bdmat, cdmat], 8012 [Join()(aiscal, admat, bdmat, cdmat)], 8013 [aiscal_val, admat_val, bdmat_val, cdmat_val], Join) 8014 8015 # PermuteRowElements 8016 abool = True 8017 rng = np.random.RandomState(utt.fetch_seed()) 8018 advec_val = rand(5) 8019 aivec_val = rng.permutation(5).astype('int32') 8020 self._compile_and_check([advec, aivec], 8021 [PermuteRowElements()(advec, aivec, abool)], 8022 [advec_val, aivec_val], PermuteRowElements) 8023 8024 admat_val = rand(3, 5) 8025 self._compile_and_check([admat, aivec], 8026 [PermuteRowElements()(admat, aivec, abool)], 8027 [admat_val, aivec_val], PermuteRowElements) 8028 8029 adtens3 = dtensor3() 8030 adtens3_val = rand(3, 2, 5) 8031 self._compile_and_check([adtens3, aivec], 8032 [PermuteRowElements()(adtens3, aivec, abool)], 8033 [adtens3_val, aivec_val], PermuteRowElements) 8034 8035 aimat = imatrix() 8036 perma = rng.permutation(5).astype('int32') 8037 permb = rng.permutation(5).astype('int32') 8038 permc = rng.permutation(5).astype('int32') 8039 aimat_val = np.vstack((perma, permb, permc)) 8040 admat_val = rand(3, 5) 8041 self._compile_and_check([admat, aimat], 8042 [PermuteRowElements()(admat, aimat, abool)], 8043 [admat_val, aimat_val], PermuteRowElements) 8044 8045 aitens3 = itensor3() 8046 perma = rng.permutation(5).astype('int32') 8047 permb = rng.permutation(5).astype('int32') 8048 permc = rng.permutation(5).astype('int32') 8049 bimat_val = np.vstack((perma, permb, permc)) 8050 aitens3_val = np.empty((2, 3, 5), 'int32') 8051 aitens3_val[0, ::, ::] = aimat_val 8052 aitens3_val[1, ::, ::] = bimat_val 8053 self._compile_and_check([admat, aitens3], 8054 [PermuteRowElements()(admat, aitens3, abool)], 8055 [admat_val, aitens3_val], PermuteRowElements) 8056 8057 # ScalarFromTensor 8058 aiscal = iscalar() 8059 self._compile_and_check([aiscal], 8060 [TensorFromScalar()(ScalarFromTensor()(aiscal))], 8061 [45], ScalarFromTensor, 8062 excluding=["local_tensor_scalar_tensor"]) 8063 8064 # TensorFromScalar 8065 aiscal = scal.float64() 8066 8067 self._compile_and_check([aiscal], 8068 [TensorFromScalar()(aiscal)], 8069 [4.], TensorFromScalar) 8070 8071 # Rebroadcast 8072 adtens4 = dtensor4() 8073 adict = [(0, False), (1, True), (2, False), (3, True)] 8074 adtens4_val = rand(2, 1, 3, 1) 8075 self._compile_and_check([adtens4], 8076 [Rebroadcast(*adict)(adtens4)], 8077 [adtens4_val], Rebroadcast, 8078 warn=False) 8079 8080 adtens4_bro = TensorType('float64', (True, True, True, False))() 8081 bdict = [(0, True), (1, False), (2, False), (3, False)] 8082 adtens4_bro_val = rand(1, 1, 1, 3) 8083 self._compile_and_check([adtens4_bro], 8084 [Rebroadcast(*bdict)(adtens4_bro)], 8085 [adtens4_bro_val], Rebroadcast) 8086 8087 # Alloc 8088 randint = np.random.randint 8089 adscal = dscalar() 8090 aiscal = lscalar() 8091 biscal = lscalar() 8092 ciscal = lscalar() 8093 discal = lscalar() 8094 adscal_val = rand() 8095 aiscal_val = randint(3, 6, size=()) 8096 biscal_val = randint(3, 6, size=()) 8097 ciscal_val = randint(3, 6, size=()) 8098 discal_val = randint(3, 6, size=()) 8099 self._compile_and_check( 8100 [adscal, aiscal, biscal, ciscal, discal], 8101 [Alloc()(adscal, aiscal, biscal, ciscal, discal)], 8102 [adscal_val, aiscal_val, biscal_val, ciscal_val, discal_val], 8103 Alloc) 8104 8105 # MaxAndArgmax, 8106 adtens3_val = rand(4, 5, 3) 8107 self._compile_and_check([adtens3], 8108 max_and_argmax(adtens3, None), 8109 [adtens3_val], MaxAndArgmax) 8110 8111 self._compile_and_check([adtens3], 8112 max_and_argmax(adtens3, 0), 8113 [adtens3_val], MaxAndArgmax) 8114 8115 self._compile_and_check([adtens3], 8116 max_and_argmax(adtens3, 1), 8117 [adtens3_val], MaxAndArgmax) 8118 8119 self._compile_and_check([adtens3], 8120 max_and_argmax(adtens3, 2), 8121 [adtens3_val], MaxAndArgmax) 8122 8123 self._compile_and_check([adtens3], 8124 max_and_argmax(adtens3, [0, 1, 2]), 8125 [adtens3_val], MaxAndArgmax) 8126 8127 # ARange 8128 self._compile_and_check([aiscal, biscal, ciscal], 8129 [ARange('int64')(aiscal, biscal, ciscal)], 8130 [0, 5, 1], ARange) 8131 self._compile_and_check([aiscal, biscal, ciscal], 8132 [ARange('int64')(aiscal, biscal, ciscal)], 8133 [2, 11, 4], ARange) 8134 self._compile_and_check([aiscal, biscal, ciscal], 8135 [ARange('int64')(aiscal, biscal, ciscal)], 8136 [-5, 1, 1], ARange) 8137 self._compile_and_check([aiscal, biscal, ciscal], 8138 [ARange('int64')(aiscal, biscal, ciscal)], 8139 [10, 2, -2], ARange) 8140 self._compile_and_check([aiscal, biscal, ciscal], 8141 [ARange('int64')(aiscal, biscal, ciscal)], 8142 [10, 2, 2], ARange) 8143 self._compile_and_check([aiscal, biscal, ciscal], 8144 [ARange('int64')(aiscal, biscal, ciscal)], 8145 [0, 0, 1], ARange) 8146 8147 # SpecifyShape 8148 aivec_val = [3, 4, 2, 5] 8149 adtens4_val = rand(*aivec_val) 8150 self._compile_and_check([adtens4, aivec], 8151 [SpecifyShape()(adtens4, aivec)], 8152 [adtens4_val, aivec_val], SpecifyShape) 8153 8154 # Mean 8155 adtens3_val = rand(3, 4, 5) 8156 aiscal_val = 2 8157 self._compile_and_check([adtens3], 8158 [Mean(None)(adtens3)], 8159 [adtens3_val], Mean) 8160 self._compile_and_check([adtens3], 8161 [Mean(aiscal_val)(adtens3)], 8162 [adtens3_val], Mean) 8163 8164 # Reshape 8165 # TODO: generalize infer_shape to account for tensor variable 8166 # (non-constant) input shape 8167 admat = dmatrix() 8168 aivec = ivector() 8169 ndim = 1 8170 admat_val = rand(3, 4) 8171 self._compile_and_check([admat], 8172 [Reshape(ndim)(admat, [12])], 8173 [admat_val], Reshape) 8174 8175 self._compile_and_check([admat], 8176 [Reshape(ndim)(admat, [-1])], 8177 [admat_val], Reshape) 8178 8179 ndim = 2 8180 self._compile_and_check([admat], 8181 [Reshape(ndim)(admat, [4, 3])], 8182 [admat_val], Reshape) 8183 8184 self._compile_and_check([admat], 8185 [Reshape(ndim)(admat, [4, -1])], 8186 [admat_val], Reshape) 8187 8188 self._compile_and_check([admat], 8189 [Reshape(ndim)(admat, [3, -1])], 8190 [admat_val], Reshape) 8191 8192 self._compile_and_check([admat], 8193 [Reshape(ndim)(admat, [-1, 3])], 8194 [admat_val], Reshape) 8195 self._compile_and_check([admat], 8196 [Reshape(ndim)(admat, [-1, 4])], 8197 [admat_val], Reshape) 8198 8199 # enable when infer_shape is generalized: 8200 # self._compile_and_check([admat, aivec], 8201 # [Reshape(ndim)(admat, aivec)], 8202 # [admat_val, [4, 3]], Reshape) 8203 # 8204 # self._compile_and_check([admat, aivec], 8205 # [Reshape(ndim)(admat, aivec)], 8206 # [admat_val, [4, -1]], Reshape) 8207 8208 adtens4 = dtensor4() 8209 ndim = 4 8210 adtens4_val = rand(2, 4, 3, 5) 8211 self._compile_and_check([adtens4], 8212 [Reshape(ndim)(adtens4, [1, -1, 10, 4])], 8213 [adtens4_val], Reshape) 8214 8215 self._compile_and_check([adtens4], 8216 [Reshape(ndim)(adtens4, [1, 3, 10, 4])], 8217 [adtens4_val], Reshape) 8218 8219 # enable when infer_shape is generalized: 8220 # self._compile_and_check([adtens4, aivec], 8221 # [Reshape(ndim)(adtens4, aivec)], 8222 # [adtens4_val, [1, -1, 10, 4]], Reshape) 8223 # 8224 # self._compile_and_check([adtens4, aivec], 8225 # [Reshape(ndim)(adtens4, aivec)], 8226 # [adtens4_val, [1, 3, 10, 4]], Reshape) 8227 8228 # Tile op is deprecated so the tile function doesn't use it 8229 # anymore, we'll test here the op directly 8230 advec = dvector() 8231 advec_val = rand(5) 8232 aivec_val = [3] 8233 ndim = 1 8234 self._compile_and_check([advec], 8235 [Tile(ndim)(advec, aivec_val)], 8236 [advec_val], Tile) 8237 8238 admat = dmatrix() 8239 admat_val = rand(2, 4) 8240 aivec_val = [2, 3] 8241 ndim = 2 8242 self._compile_and_check([admat], 8243 [Tile(ndim)(admat, aivec_val)], 8244 [admat_val], Tile) 8245 8246 adtens4 = dtensor4() 8247 adtens4_val = rand(2, 4, 3, 5) 8248 aivec_val = [2, 3, 1, 4] 8249 ndim = 4 8250 self._compile_and_check([adtens4], 8251 [Tile(ndim)(adtens4, aivec_val)], 8252 [adtens4_val], Tile) 8253 8254 8255class TestTensorInstanceMethods(unittest.TestCase): 8256 def setUp(self): 8257 self.vars = matrices('X', 'Y') 8258 self.vals = [m.astype(floatX) for m in [rand(2, 2), rand(2, 2)]] 8259 8260 def test_argmin(self): 8261 X, _ = self.vars 8262 x, _ = self.vals 8263 assert_array_equal(X.argmin().eval({X: x}), x.argmin()) 8264 8265 def test_argmax(self): 8266 X, _ = self.vars 8267 x, _ = self.vals 8268 assert_array_equal(X.argmax().eval({X: x}), x.argmax()) 8269 8270 def test_argsort(self): 8271 X, _ = self.vars 8272 x, _ = self.vals 8273 assert_array_equal(X.argsort().eval({X: x}), x.argsort()) 8274 assert_array_equal(X.argsort(1).eval({X: x}), x.argsort(1)) 8275 8276 def test_clip(self): 8277 X, Y = self.vars 8278 x, y = self.vals 8279 # np.clip gives unexpected values when min > max, 8280 # so we have to make sure that min <= max in that test, 8281 # otherwise it randomly fails. 8282 Z = X.clip(Y - 0.5, Y + 0.5) 8283 z = x.clip(y - 0.5, y + 0.5) 8284 assert_array_equal(Z.eval({X: x, Y: y}), z) 8285 8286 def test_dot(self): 8287 X, Y = self.vars 8288 x, y = self.vals 8289 # Use allclose comparison as a user reported on the mailing 8290 # list failure otherwise with array that print exactly the same. 8291 assert_allclose(x.dot(y), X.dot(Y).eval({X: x, Y: y})) 8292 Z = X.dot(Y) 8293 z = x.dot(y) 8294 assert_allclose(x.dot(z), X.dot(Z).eval({X: x, Z: z})) 8295 8296 def test_real_imag(self): 8297 X, Y = self.vars 8298 x, y = self.vals 8299 Z = X + Y * 1j 8300 z = x + y * 1j 8301 assert_array_equal(Z.real.eval({Z: z}), x) 8302 assert_array_equal(Z.imag.eval({Z: z}), y) 8303 8304 def test_conj(self): 8305 X, Y = self.vars 8306 x, y = self.vals 8307 Z = X + Y * 1j 8308 z = x + y * 1j 8309 assert_array_equal(Z.conj().eval({Z: z}), z.conj()) 8310 assert_array_equal(Z.conjugate().eval({Z: z}), z.conj()) 8311 8312 def test_round(self): 8313 X, _ = self.vars 8314 x, _ = self.vals 8315 assert_array_equal(X.round().eval({X: x}), x.round()) 8316 8317 def test_std(self): 8318 X, _ = self.vars 8319 x, _ = self.vals 8320 # std() is implemented as theano tree and does not pass its 8321 # args directly to numpy. This sometimes results in small 8322 # difference, so we use allclose test. 8323 assert_allclose(X.std().eval({X: x}), x.std()) 8324 8325 def test_repeat(self): 8326 X, _ = self.vars 8327 x, _ = self.vals 8328 assert_array_equal(X.repeat(2).eval({X: x}), x.repeat(2)) 8329 8330 def test_trace(self): 8331 X, _ = self.vars 8332 x, _ = self.vals 8333 assert_array_equal(X.trace().eval({X: x}), x.trace()) 8334 8335 def test_ravel(self): 8336 X, _ = self.vars 8337 x, _ = self.vals 8338 assert_array_equal(X.ravel().eval({X: x}), x.ravel()) 8339 8340 def test_diagonal(self): 8341 X, _ = self.vars 8342 x, _ = self.vals 8343 assert_array_equal(X.diagonal().eval({X: x}), x.diagonal()) 8344 assert_array_equal(X.diagonal(1).eval({X: x}), x.diagonal(1)) 8345 assert_array_equal(X.diagonal(-1).eval({X: x}), x.diagonal(-1)) 8346 for offset, axis1, axis2 in [(1, 0, 1), (-1, 0, 1), (0, 1, 0), (-2, 1, 0)]: 8347 assert_array_equal(X.diagonal(offset, axis1, axis2).eval({X: x}), 8348 x.diagonal(offset, axis1, axis2)) 8349 8350 def test_take(self): 8351 X, _ = self.vars 8352 x, _ = self.vals 8353 indices = [1, 0, 3] 8354 assert_array_equal(X.take(indices).eval({X: x}), x.take(indices)) 8355 indices = [1, 0, 1] 8356 assert_array_equal(X.take(indices, 1).eval({X: x}), x.take(indices, 1)) 8357 indices = np.array([-10, 5, 12], dtype='int32') 8358 assert_array_equal(X.take(indices, 1, mode='wrap').eval({X: x}), 8359 x.take(indices, 1, mode='wrap')) 8360 assert_array_equal(X.take(indices, -1, mode='wrap').eval({X: x}), 8361 x.take(indices, -1, mode='wrap')) 8362 assert_array_equal(X.take(indices, 1, mode='clip').eval({X: x}), 8363 x.take(indices, 1, mode='clip')) 8364 assert_array_equal(X.take(indices, -1, mode='clip').eval({X: x}), 8365 x.take(indices, -1, mode='clip')) 8366 # Test error handling 8367 self.assertRaises(IndexError, X.take(indices).eval, {X: x}) 8368 self.assertRaises(IndexError, (2 * X.take(indices)).eval, {X: x}) 8369 self.assertRaises(TypeError, X.take, [0.0]) 8370 indices = [[1, 0, 1], [0, 1, 1]] 8371 assert_array_equal(X.take(indices, 1).eval({X: x}), x.take(indices, 1)) 8372 # Test equivalent advanced indexing 8373 assert_array_equal(X[:, indices].eval({X: x}), x[:, indices]) 8374 8375 def test_cumsum(self): 8376 X, _ = self.vars 8377 x, _ = self.vals 8378 assert_array_equal(X.cumsum().eval({X: x}), x.cumsum()) 8379 8380 def test_cumprod(self): 8381 X, _ = self.vars 8382 x, _ = self.vals 8383 assert_array_equal(X.cumprod().eval({X: x}), x.cumprod()) 8384 8385 8386def test_norm(): 8387 x = theano.tensor.vector('x') 8388 n = x.norm(2) 8389 f = theano.function([x], n) 8390 assert np.allclose(f([1, 1]), np.sqrt(2)) 8391 8392 8393class test_cov(unittest.TestCase): 8394 8395 def test_core(self): 8396 x = theano.tensor.matrix('x') 8397 c = theano.tensor.cov(x) 8398 f = theano.function([x], c) 8399 8400 # basic cov function 8401 data = np.asarray(np.random.rand(3, 5), dtype=config.floatX) 8402 assert np.allclose(f(data), np.cov(data)) 8403 8404 data = np.asarray(np.random.rand(5, 3), dtype=config.floatX) 8405 assert np.allclose(f(data), np.cov(data)) 8406 8407 data = np.asarray(np.random.rand(10, 10), dtype=config.floatX) 8408 assert np.allclose(f(data), np.cov(data)) 8409 8410 data = np.asarray(np.random.rand(2, 2), dtype=config.floatX) 8411 assert np.allclose(f(data), np.cov(data)) 8412 8413 data = np.asarray(np.random.rand(1, 2), dtype=config.floatX) 8414 assert np.allclose(f(data), np.cov(data)) 8415 8416 def test_rowvar(self): 8417 for rowvar in [True, False]: 8418 x = theano.tensor.matrix('x') 8419 c = theano.tensor.cov(x, rowvar=rowvar) 8420 f = theano.function([x], c) 8421 8422 data = np.asarray(np.random.rand(3, 5), dtype=config.floatX) 8423 assert np.allclose(f(data), np.cov(data, rowvar=rowvar)) 8424 8425 data = np.asarray(np.random.rand(5, 3), dtype=config.floatX) 8426 assert np.allclose(f(data), np.cov(data, rowvar=rowvar)) 8427 8428 data = np.asarray(np.random.rand(10, 10), dtype=config.floatX) 8429 assert np.allclose(f(data), np.cov(data, rowvar=rowvar)) 8430 8431 data = np.asarray(np.random.rand(2, 2), dtype=config.floatX) 8432 assert np.allclose(f(data), np.cov(data, rowvar=rowvar)) 8433 8434 # check when variables are along the first axis 8435 x = theano.tensor.matrix('x') 8436 c = theano.tensor.cov(x, rowvar=False) 8437 f = theano.function([x], c) 8438 data = np.asarray(np.random.rand(2, 1), dtype=config.floatX) 8439 assert np.allclose(f(data), np.cov(data, rowvar=False)) 8440 8441 def test_y(self): 8442 # test y 8443 x = theano.tensor.matrix('x') 8444 y = theano.tensor.matrix('y') 8445 c = theano.tensor.cov(x, y=y) 8446 f = theano.function([x, y], c) 8447 8448 data = np.asarray(np.random.rand(3, 5), dtype=config.floatX) 8449 y = np.asarray(np.random.rand(3, 5), dtype=config.floatX) 8450 assert np.allclose(f(data, y), np.cov(data, y=y)) 8451 8452 data = np.asarray(np.random.rand(5, 3), dtype=config.floatX) 8453 y = np.asarray(np.random.rand(5, 3), dtype=config.floatX) 8454 assert np.allclose(f(data, y), np.cov(data, y=y)) 8455 8456 data = np.asarray(np.random.rand(10, 10), dtype=config.floatX) 8457 y = np.asarray(np.random.rand(10, 10), dtype=config.floatX) 8458 assert np.allclose(f(data, y), np.cov(data, y=y)) 8459 8460 data = np.asarray(np.random.rand(2, 2), dtype=config.floatX) 8461 y = np.asarray(np.random.rand(2, 2), dtype=config.floatX) 8462 assert np.allclose(f(data, y), np.cov(data, y=y)) 8463 8464 def test_ddof(self): 8465 8466 for ddof in range(0, 5): 8467 x = theano.tensor.matrix('x') 8468 c = theano.tensor.cov(x, ddof=ddof) 8469 f = theano.function([x], c) 8470 8471 data = np.asarray(np.random.rand(3, 5), dtype=config.floatX) 8472 assert np.allclose(f(data), np.cov(data, ddof=ddof)) 8473 8474 def test_bias(self): 8475 8476 for bias in [True, False]: 8477 x = theano.tensor.matrix('x') 8478 c = theano.tensor.cov(x, bias=bias) 8479 f = theano.function([x], c) 8480 8481 data = np.asarray(np.random.rand(3, 5), dtype=config.floatX) 8482 assert np.allclose(f(data), np.cov(data, bias=bias)) 8483 8484 for ddof in range(0, 5): 8485 for bias in [True, False]: 8486 x = theano.tensor.matrix('x') 8487 c = theano.tensor.cov(x, ddof=ddof, bias=bias) 8488 f = theano.function([x], c) 8489 8490 data = np.asarray(np.random.rand(3, 5), dtype=config.floatX) 8491 assert np.allclose(f(data), np.cov(data, ddof=ddof, bias=bias)) 8492 8493 8494class test_ptp(unittest.TestCase): 8495 def test_scalar(self): 8496 # Should return 0 for all scalar 8497 x = scalar('x') 8498 p = ptp(x) 8499 f = theano.function([x], p) 8500 8501 y = np.asarray(rand() * 2000 - 1000, dtype=config.floatX) 8502 result = f(y) 8503 numpyResult = np.ptp(y) 8504 8505 self.assertTrue(np.array_equal(result, numpyResult)) 8506 8507 def test_vector(self): 8508 8509 x = vector('x') 8510 p = ptp(x, 0) 8511 f = theano.function([x], p) 8512 8513 y = rand_ranged(-1000, 1000, [100]) 8514 result = f(y) 8515 numpyResult = np.ptp(y, 0) 8516 8517 self.assertTrue(np.array_equal(result, numpyResult)) 8518 8519 def test_matrix_first_axis(self): 8520 8521 x = matrix('x') 8522 p = ptp(x, 1) 8523 f = theano.function([x], p) 8524 8525 y = rand_ranged(-1000, 1000, [100, 100]) 8526 result = f(y) 8527 numpyResult = np.ptp(y, 1) 8528 8529 self.assertTrue(np.array_equal(result, numpyResult)) 8530 8531 def test_matrix_second_axis(self): 8532 x = matrix('x') 8533 p = ptp(x, 0) 8534 f = theano.function([x], p) 8535 8536 y = rand_ranged(-1000, 1000, [100, 100]) 8537 result = f(y) 8538 numpyResult = np.ptp(y, 0) 8539 8540 self.assertTrue(np.array_equal(result, numpyResult)) 8541 8542 def test_matrix_neg_axis(self): 8543 x = matrix('x') 8544 p = ptp(x, -1) 8545 f = theano.function([x], p) 8546 8547 y = rand_ranged(-1000, 1000, [100, 100]) 8548 result = f(y) 8549 numpyResult = np.ptp(y, -1) 8550 8551 self.assertTrue(np.array_equal(result, numpyResult)) 8552 8553 def test_matrix_no_axis(self): 8554 x = matrix('x') 8555 p = ptp(x) 8556 f = theano.function([x], p) 8557 8558 y = rand_ranged(-1000, 1000, [100, 100]) 8559 result = f(y) 8560 numpyResult = np.ptp(y) 8561 8562 self.assertTrue(np.array_equal(result, numpyResult)) 8563 8564 def test_interface(self): 8565 x = matrix('x') 8566 p = x.ptp(1) 8567 f = theano.function([x], p) 8568 8569 y = rand_ranged(-1000, 1000, [100, 100]) 8570 result = f(y) 8571 numpyResult = np.ptp(y, 1) 8572 8573 self.assertTrue(np.array_equal(result, numpyResult)) 8574 8575if __name__ == '__main__': 8576 8577 t = TestInferShape('setUp') 8578 t.setUp() 8579 t.test_infer_shape() 8580 8581 8582class T_swapaxes(unittest.TestCase): 8583 8584 def test_no_dimensional_input(self): 8585 self.assertRaises(IndexError, swapaxes, 2, 0, 1) 8586 8587 def test_unidimensional_input(self): 8588 self.assertRaises(IndexError, swapaxes, [2, 1], 0, 1) 8589 8590 def test_not_enough_dimension(self): 8591 self.assertRaises(IndexError, swapaxes, [[2, 1], [3, 4]], 3, 4) 8592 8593 def test_doubleswap(self): 8594 y = matrix() 8595 n = swapaxes(y, 0, 1) 8596 f = function([y], n) 8597 testMatrix = [[2, 1], [3, 4]] 8598 self.assertTrue(np.array_equal(testMatrix, f(f(testMatrix)))) 8599 8600 def test_interface(self): 8601 x = theano.tensor.matrix() 8602 x.swapaxes(0, 1) 8603 8604 def test_numpy_compare(self): 8605 rng = np.random.RandomState(utt.fetch_seed()) 8606 A = tensor.matrix("A", dtype=theano.config.floatX) 8607 Q = swapaxes(A, 0, 1) 8608 fn = function([A], [Q]) 8609 a = rng.rand(4, 4).astype(theano.config.floatX) 8610 8611 n_s = np.swapaxes(a, 0, 1) 8612 t_s = fn(a) 8613 assert np.allclose(n_s, t_s) 8614 8615 8616class T_Power(unittest.TestCase): 8617 def test_numpy_compare(self): 8618 rng = np.random.RandomState(utt.fetch_seed()) 8619 A = tensor.matrix("A", dtype=theano.config.floatX) 8620 Q = power(A, 3) 8621 fn = function([A], [Q]) 8622 a = rng.rand(4, 4).astype(theano.config.floatX) 8623 8624 n_p = np.power(a, 3) 8625 t_p = fn(a) 8626 assert np.allclose(n_p, t_p) 8627 8628 def test_multiple_power(self): 8629 x = tensor.vector() 8630 y = [1, 2, 3] 8631 z = power(x, y) 8632 f = function([x], z) 8633 assert np.allclose(f([1, 2, 3]), [1, 4, 27]) 8634 8635 def test_wrong_shape(self): 8636 x = tensor.vector() 8637 y = [1, 2, 3] 8638 z = power(x, y) 8639 f = function([x], z) 8640 self.assertRaises(ValueError, f, [1, 2, 3, 4]) 8641 8642 8643class T_Choose(utt.InferShapeTester): 8644 op = staticmethod(choose) 8645 op_class = Choose 8646 modes = ['raise', 'wrap', 'clip'] 8647 8648 def test_numpy_compare(self): 8649 8650 a = tensor.vector(dtype='int32') 8651 b = tensor.matrix(dtype='float32') 8652 8653 A = np.random.randint(0, 4, 4).astype('int32') 8654 B = np.asarray(np.random.rand(4, 4), dtype='float32') 8655 8656 for m in self.modes: 8657 f = function([a, b], choose(a, b, mode=m)) 8658 t_c = f(A, B) 8659 n_c = np.choose(A, B, mode=m) 8660 assert np.allclose(t_c, n_c) 8661 8662 def test_method(self): 8663 a = tensor.vector(dtype='int32') 8664 b = tensor.matrix(dtype='float32') 8665 8666 A = np.random.randint(0, 4, 4).astype('int32') 8667 B = np.asarray(np.random.rand(4, 4), dtype='float32') 8668 8669 for m in self.modes: 8670 f = function([a, b], a.choose(b, mode=m)) 8671 t_c = f(A, B) 8672 n_c = A.choose(B, mode=m) 8673 assert np.allclose(t_c, n_c) 8674 8675 def test_broadcasted(self): 8676 a = tensor.scalar(dtype='int32') 8677 b = tensor.matrix(dtype='float32') 8678 8679 # Test when a is broadcastable 8680 A = 3 8681 B = np.asarray(np.random.rand(4, 4), dtype='float32') 8682 8683 for m in self.modes: 8684 f = function([a, b], choose(a, b, mode=m)) 8685 t_c = f(A, B) 8686 n_c = np.choose(A, B, mode=m) 8687 assert np.allclose(t_c, n_c) 8688 8689 # Test when the result should be broadcastable 8690 b = theano.tensor.col(dtype='float32') 8691 B = np.asarray(np.random.rand(4, 1), dtype='float32') 8692 for m in self.modes: 8693 f = function([a, b], choose(a, b, mode=m)) 8694 assert choose(a, b, mode=m).broadcastable[0] 8695 t_c = f(A, B) 8696 n_c = np.choose(A, B, mode=m) 8697 assert np.allclose(t_c, n_c) 8698 8699 def test_dtype_error(self): 8700 a = tensor.scalar(dtype='float32') 8701 b = tensor.matrix(dtype='float32') 8702 8703 self.assertRaises(TypeError, choose, a, b) 8704 8705 def test_numpy_compare_tuple(self): 8706 8707 a = tensor.tensor3(dtype='int32') 8708 b = tensor.tensor3(dtype='float32') 8709 c = tensor.tensor3(dtype='float32') 8710 8711 A = np.random.randint(0, 2, (2, 1, 1)).astype('int32') 8712 B = np.asarray(np.random.rand(1, 6, 1), dtype='float32') 8713 C = np.asarray(np.random.rand(1, 1, 5), dtype='float32') 8714 8715 for m in self.modes: 8716 f = function([a, b, c], choose(a, (b, c), mode=m)) 8717 t_c = f(A, B, C) 8718 n_c = np.choose(A, (B, C), mode=m) 8719 assert np.allclose(t_c, n_c) 8720 8721 def test_infer_shape(self): 8722 for shp1, shp2 in [ 8723 ((5, 4), (7, 4)), 8724 ((1, 4), (7, 4)), 8725 ((5, 1), (7, 4)), 8726 ((5, 4), (1, 4)), 8727 ((5, 4), (7, 1)), 8728 8729 ((5, 4), (4,)), 8730 ((1, 4), (4,)), 8731 ((5, 1), (4,)), 8732 ((5, 4), (1,)), 8733 8734 ((4,), (5, 4)), 8735 ((1,), (5, 4)), 8736 ((4,), (1, 4)), 8737 ((4,), (3, 1)), 8738 8739 ((4,), (4,)), 8740 ((1,), (4,)), 8741 ((4,), (1,)), 8742 ((1,), (1,)), 8743 ]: 8744 a = tensor.tensor(dtype='int32', 8745 broadcastable=[n == 1 for n in shp1]) 8746 c = tensor.tensor(dtype='float32', 8747 broadcastable=[n == 1 for n in shp2]) 8748 A = np.asarray(np.random.rand(*shp1) * shp2[0], dtype='int32') 8749 C = np.asarray(np.random.rand(*shp2) * shp2[0], dtype='float32') 8750 self._compile_and_check([a, c], # theano.function inputs 8751 [self.op(a, c)], # theano.function outputs 8752 # Always use not square matrix! 8753 # inputs data 8754 [A, C], 8755 # Op that should be removed from the graph. 8756 self.op_class) 8757 8758# Disabled as it isn't implemented. 8759 def ___test_infer_shape_tuple(self): 8760 8761 a = tensor.tensor3(dtype='int32') 8762 b = tensor.tensor3(dtype='int32') 8763 c = tensor.tensor3(dtype='int32') 8764 8765 A = np.asarray([1, 0], dtype='int32').reshape((2, 1, 1)) 8766 B = np.asarray(np.random.rand(1, 4, 1), dtype='int32') 8767 C = np.asarray(np.random.rand(1, 1, 7), dtype='int32') 8768 8769 f = function([a, b, c], choose(a, (b, c))) 8770 shape = (2, 4, 7) 8771 assert np.allclose(f(A, B, C).shape, shape) 8772 8773 self._compile_and_check([a, b, c], # theano.function inputs 8774 [self.op(a, (b, c))], # theano.function outputs 8775 # Always use not square matrix! 8776 # inputs data 8777 [A, B, C], 8778 # Op that should be removed from the graph. 8779 self.op_class) 8780 8781 8782def test_allocempty(): 8783 # Test that we allocated correctly 8784 f = theano.function([], AllocEmpty("float32")(2, 3)) 8785 assert len(f.maker.fgraph.apply_nodes) == 1 8786 out = f() 8787 8788 assert out.shape == (2, 3) 8789 assert out.dtype == 'float32' 8790 8791 8792def test_symbolic_slice(): 8793 x = theano.tensor.tensor4('x') 8794 a, b = x.shape[:2] 8795 output = a.eval({x: np.zeros((5, 4, 3, 2), dtype=theano.config.floatX)}) 8796 assert output == np.array(5) 8797