1from __future__ import absolute_import, print_function, division 2from itertools import product 3import time 4import unittest 5 6from nose.plugins.skip import SkipTest 7import numpy as np 8from six.moves import xrange 9try: 10 import scipy.sparse as sp 11 import scipy.sparse 12 from scipy.sparse import csr_matrix 13except ImportError: 14 pass # The variable enable_sparse will be used to disable the test file. 15 16import theano 17from theano import tensor 18from theano import sparse 19from theano import compile, config, gof 20from theano.sparse import enable_sparse 21from theano.tensor.basic import _allclose 22from theano.tests.unittest_tools import attr 23 24if not enable_sparse: 25 raise SkipTest('Optional package SciPy not installed') 26 27from theano.sparse.basic import _is_dense, _is_sparse, _mtypes 28from theano.sparse.basic import _is_dense_variable, _is_sparse_variable 29from theano.sparse import ( 30 as_sparse_variable, as_sparse_or_tensor_variable, 31 CSR, CSC, CSM, CSMProperties, csm_properties, 32 DenseFromSparse, 33 SparseType, CSMGrad, 34 StructuredDot, 35 StructuredDotGradCSC, StructuredDotGradCSR, 36 AddSS, AddSD, MulSS, MulSD, Transpose, Neg, Remove0, 37 add, mul, structured_dot, transpose, 38 csc_from_dense, csr_from_dense, dense_from_sparse, 39 Dot, Usmm, sp_ones_like, GetItemScalar, GetItemList, GetItem2Lists, 40 SparseFromDense, 41 Cast, cast, HStack, VStack, AddSSData, add_s_s_data, 42 structured_minimum, structured_maximum, structured_add, 43 mul_s_v, structured_add_s_v, 44 SamplingDot, sampling_dot, 45 Diag, diag, SquareDiagonal, square_diagonal, 46 EnsureSortedIndices, ensure_sorted_indices, clean, 47 ConstructSparseFromList, construct_sparse_from_list, 48 TrueDot, true_dot, eq, neq, le, ge, gt, lt) 49 50# Probability distributions are currently tested in test_sp2.py 51# from theano.sparse import ( 52# Poisson, poisson, Binomial, Multinomial, multinomial) 53 54from theano.sparse.opt import (StructuredDotCSC, UsmmCscDense, CSMGradC) 55 56from theano.tests import unittest_tools as utt 57 58 59def as_sparse_format(data, format): 60 if format == 'csc': 61 return scipy.sparse.csc_matrix(data) 62 elif format == 'csr': 63 return scipy.sparse.csr_matrix(data) 64 else: 65 raise NotImplementedError() 66 67 68def eval_outputs(outputs): 69 return compile.function([], outputs)()[0] 70 71 72# scipy 0.17 will return sparse values in all cases while previous 73# version sometimes wouldn't. This will make everything dense so that 74# we can use assert_allclose. 75def as_ndarray(val): 76 if hasattr(val, 'toarray'): 77 return val.toarray() 78 return val 79 80 81def random_lil(shape, dtype, nnz): 82 rval = sp.lil_matrix(shape, dtype=dtype) 83 huge = 2 ** 30 84 for k in range(nnz): 85 # set non-zeros in random locations (row x, col y) 86 idx = np.random.randint(1, huge+1, size=2) % shape 87 value = np.random.rand() 88 # if dtype *int*, value will always be zeros! 89 if dtype in theano.sparse.integer_dtypes: 90 value = int(value * 100) 91 # The call to tuple is needed as scipy 0.13.1 do not support 92 # ndarray with length 2 as idx tuple. 93 rval.__setitem__( 94 tuple(idx), 95 value) 96 return rval 97 98 99def sparse_random_inputs(format, shape, n=1, out_dtype=None, p=0.5, gap=None, 100 explicit_zero=False, unsorted_indices=False): 101 """ 102 Return a tuple containing everything needed to perform a test. 103 104 If `out_dtype` is `None`, theano.config.floatX is used. 105 106 :param format: Sparse format. 107 :param shape: Shape of data. 108 :param n: Number of variable. 109 :param out_dtype: dtype of output. 110 :param p: Sparsity proportion. 111 :param gap: Tuple for the range of the random sample. When 112 length is 1, it is assumed to be the exclusive 113 max, when `gap` = (`a`, `b`) it provide a sample 114 from [a, b[. If `None` is used, it provide [0, 1] 115 for float dtypes and [0, 50[ for integer dtypes. 116 :param explicit_zero: When True, we add explicit zero in the 117 returned sparse matrix 118 :param unsorted_indices: when True, we make sure there is 119 unsorted indices in the returned 120 sparse matrix. 121 :return: (variable, data) where both `variable` and `data` are list. 122 123 :note: explicit_zero and unsorted_indices was added in Theano 0.6rc4 124 """ 125 126 if out_dtype is None: 127 out_dtype = theano.config.floatX 128 129 assert 0 <= p <= 1 130 assert len(shape) == 2 131 assert out_dtype in sparse.all_dtypes 132 assert gap is None or isinstance(gap, (tuple, list)) 133 if gap is not None and out_dtype.startswith('u'): 134 assert gap[0] >= 0 135 136 def _rand(): 137 where = np.random.binomial(1, p, size=shape).astype('int8') 138 139 if out_dtype in sparse.discrete_dtypes: 140 if not gap: 141 value = np.random.randint(50, size=shape) 142 elif len(gap) == 2: 143 value = np.random.randint(gap[0], gap[1], size=shape) 144 else: 145 value = np.random.randint(gap[0], size=shape) 146 else: 147 if not gap: 148 value = np.random.random(shape) 149 elif len(gap) == 2: 150 a, b = gap 151 value = a + np.random.random(shape) * (b - a) 152 else: 153 value = np.random.random(shape) * gap[0] 154 return (where * value).astype(out_dtype) 155 156 variable = [getattr(theano.sparse, format + '_matrix')(dtype=out_dtype) 157 for k in range(n)] 158 data = [getattr(scipy.sparse, format + '_matrix')(_rand(), dtype=out_dtype) 159 for k in range(n)] 160 if unsorted_indices: 161 for idx in range(n): 162 d = data[idx] 163 # these flip the matrix, but it's random anyway 164 if format == 'csr': 165 d = scipy.sparse.csr_matrix( 166 (d.data, d.shape[1] - 1 - d.indices, d.indptr), 167 shape=d.shape) 168 if format == 'csc': 169 d = scipy.sparse.csc_matrix( 170 (d.data, d.shape[0] - 1 - d.indices, d.indptr), 171 shape=d.shape) 172 assert not d.has_sorted_indices 173 data[idx] = d 174 if explicit_zero: 175 for idx in range(n): 176 assert data[idx].nnz > 1, ( 177 "can't make a sparse matrix with explicit 0") 178 d_idx = np.random.randint(data[idx].nnz) 179 data[idx].data[d_idx] = 0 180 181 # numpy 1.5.0 with scipy 0.9.0 have scipy.sparse.XXX_matrix return 182 # typenum 10(ulonglong) instead of 8(uint64) event if they are the same! 183 # Theano don't like ulonglong type_num 184 dtype = np.dtype(out_dtype) # Convert into dtype object. 185 if data[0].dtype.num != dtype.num and dtype.str == data[0].dtype.str: 186 data[0].data = theano._asarray(data[0].data, out_dtype) 187 assert data[0].dtype.num == dtype.num 188 return (variable, data) 189 190 191def verify_grad_sparse(op, pt, structured=False, *args, **kwargs): 192 """ 193 Wrapper for theano.test.unittest_tools.py:verify_grad which 194 converts sparse variables back and forth. 195 196 Parameters 197 ---------- 198 op 199 Op to check. 200 pt 201 List of inputs to realize the tests. 202 structured 203 True to tests with a structured grad, False otherwise. 204 args 205 Other `verify_grad` parameters if any. 206 kwargs 207 Other `verify_grad` keywords if any. 208 209 Returns 210 ------- 211 None 212 """ 213 214 def conv_none(x): 215 return x 216 217 def conv_csr(ind, indptr, shp): 218 def f(spdata): 219 return CSR(spdata, ind, indptr, shp) 220 return f 221 222 def conv_csc(ind, indptr, shp): 223 def f(spdata): 224 return CSC(spdata, ind, indptr, shp) 225 return f 226 227 iconv = [] 228 dpt = [] 229 230 for p in pt: 231 if _is_sparse(p): 232 if structured: 233 dpt.append(p.data) 234 else: 235 dpt.append(p.toarray()) 236 if p.format == 'csr': 237 if structured: 238 iconv.append(conv_csr(p.indices[:p.size], p.indptr, 239 p.shape)) 240 else: 241 iconv.append(csr_from_dense) 242 elif p.format == 'csc': 243 if structured: 244 iconv.append(conv_csc(p.indices[:p.size], p.indptr, 245 p.shape)) 246 else: 247 iconv.append(csc_from_dense) 248 else: 249 raise NotImplementedError("No conv for %s" % (p.format,)) 250 else: 251 dpt.append(p) 252 iconv.append(conv_none) 253 output = op(*[as_sparse_or_tensor_variable(p) for p in pt]) 254 if isinstance(output, (list, tuple)): 255 raise NotImplementedError("verify_grad can't deal with " 256 "multiple outputs") 257 if _is_sparse_variable(output): 258 oconv = DenseFromSparse(structured=structured) 259 else: 260 oconv = conv_none 261 262 def conv_op(*inputs): 263 ipt = [conv(i) for i, conv in zip(inputs, iconv)] 264 out = op(*ipt) 265 return oconv(out) 266 267 return utt.verify_grad(conv_op, dpt, *args, **kwargs) 268verify_grad_sparse.E_grad = utt.verify_grad.E_grad 269 270 271class T_verify_grad_sparse(unittest.TestCase): 272 class FailOp(gof.op.Op): 273 def __init__(self, structured): 274 self.structured = structured 275 276 def __eq__(self, other): 277 return (type(self) == type(other)) and \ 278 self.structured == other.structured 279 280 def __hash__(self): 281 return hash(type(self)) ^ hash(self.structured) 282 283 def make_node(self, x): 284 x = as_sparse_variable(x) 285 return gof.Apply(self, [x], [x.type()]) 286 287 def perform(self, node, inputs, outputs): 288 (x,) = inputs 289 (out,) = outputs 290 assert _is_sparse(x) 291 out[0] = -x 292 293 def grad(self, inputs, gout): 294 (x,) = inputs 295 (gz,) = gout 296 assert _is_sparse_variable(x) and _is_sparse_variable(gz) 297 if self.structured: 298 return sp_ones_like(x) * dense_from_sparse(gz), 299 else: 300 return gz, 301 302 def infer_shape(self, node, shapes): 303 return [shapes[0]] 304 305 def test_grad_fail(self): 306 self.assertRaises(verify_grad_sparse.E_grad, 307 verify_grad_sparse, 308 self.FailOp(structured=False), 309 [sp.csr_matrix(random_lil((10, 40), 310 config.floatX, 3))]) 311 312 self.assertRaises(verify_grad_sparse.E_grad, 313 verify_grad_sparse, 314 self.FailOp(structured=True), 315 [sp.csr_matrix(random_lil((10, 40), 316 config.floatX, 3))]) 317 318 319class T_transpose(unittest.TestCase): 320 def setUp(self): 321 utt.seed_rng() 322 323 def test_transpose_csc(self): 324 sp = scipy.sparse.csc_matrix(scipy.sparse.eye(5, 3)) 325 a = as_sparse_variable(sp) 326 self.assertFalse(a.data is sp) 327 self.assertTrue(a.data.shape == (5, 3)) 328 self.assertTrue(a.type.dtype == 'float64', a.type.dtype) 329 self.assertTrue(a.type.format == 'csc', a.type.format) 330 ta = transpose(a) 331 self.assertTrue(ta.type.dtype == 'float64', ta.type.dtype) 332 self.assertTrue(ta.type.format == 'csr', ta.type.format) 333 334 vta = eval_outputs([ta]) 335 self.assertTrue(vta.shape == (3, 5)) 336 337 def test_transpose_csr(self): 338 a = as_sparse_variable(scipy.sparse.csr_matrix(scipy.sparse.eye(5, 3))) 339 self.assertTrue(a.data.shape == (5, 3)) 340 self.assertTrue(a.type.dtype == 'float64') 341 self.assertTrue(a.type.format == 'csr') 342 ta = transpose(a) 343 self.assertTrue(ta.type.dtype == 'float64', ta.type.dtype) 344 self.assertTrue(ta.type.format == 'csc', ta.type.format) 345 346 vta = eval_outputs([ta]) 347 self.assertTrue(vta.shape == (3, 5)) 348 349 350class SparseInferShapeTester(utt.InferShapeTester): 351 def test_getitem_2d(self): 352 raise SkipTest('infer_shape not implemented for GetItem2d yet') 353 354 def test_getitem_scalar(self): 355 x = SparseType('csr', dtype=config.floatX)() 356 self._compile_and_check([x], 357 [x[2, 2]], 358 [sp.csr_matrix(random_lil((10, 40), 359 config.floatX, 3))], 360 GetItemScalar) 361 362 def test_csm(self): 363 for sparsetype in ('csr', 'csc'): 364 x = tensor.vector() 365 y = tensor.ivector() 366 z = tensor.ivector() 367 s = tensor.ivector() 368 call = getattr(sp, sparsetype + '_matrix') 369 spm = call(random_lil((300, 400), config.floatX, 5)) 370 out = CSM(sparsetype)(x, y, z, s) 371 self._compile_and_check([x, y, z, s], 372 [out], 373 [spm.data, spm.indices, spm.indptr, 374 spm.shape], 375 CSM 376 ) 377 378 def test_csm_grad(self): 379 for sparsetype in ('csr', 'csc'): 380 x = tensor.vector() 381 y = tensor.ivector() 382 z = tensor.ivector() 383 s = tensor.ivector() 384 call = getattr(sp, sparsetype + '_matrix') 385 spm = call(random_lil((300, 400), config.floatX, 5)) 386 out = tensor.grad(dense_from_sparse( 387 CSM(sparsetype)(x, y, z, s) 388 ).sum(), x) 389 self._compile_and_check([x, y, z, s], 390 [out], 391 [spm.data, spm.indices, spm.indptr, 392 spm.shape], 393 (CSMGrad, CSMGradC) 394 ) 395 396 def test_transpose(self): 397 x = SparseType('csr', dtype=config.floatX)() 398 self._compile_and_check([x], 399 [x.T], 400 [sp.csr_matrix(random_lil((10, 40), 401 config.floatX, 3))], 402 Transpose) 403 404 def test_neg(self): 405 x = SparseType('csr', dtype=config.floatX)() 406 self._compile_and_check([x], 407 [-x], 408 [sp.csr_matrix(random_lil((10, 40), 409 config.floatX, 3))], 410 Neg) 411 412 def test_add_ss(self): 413 x = SparseType('csr', dtype=config.floatX)() 414 y = SparseType('csr', dtype=config.floatX)() 415 self._compile_and_check([x, y], 416 [x + y], 417 [sp.csr_matrix(random_lil((10, 40), 418 config.floatX, 3)), 419 sp.csr_matrix(random_lil((10, 40), 420 config.floatX, 3))], 421 AddSS) 422 423 def test_add_sd(self): 424 x = SparseType('csr', dtype=config.floatX)() 425 y = tensor.matrix() 426 self._compile_and_check( 427 [x, y], 428 [x + y], 429 [sp.csr_matrix(random_lil((10, 40), 430 config.floatX, 3)), 431 np.random.randn(10, 40).astype(config.floatX)], 432 (AddSD, sparse.opt.AddSD_ccode)) 433 434 def test_mul_ss(self): 435 x = SparseType('csr', dtype=config.floatX)() 436 y = SparseType('csr', dtype=config.floatX)() 437 self._compile_and_check([x, y], 438 [x * y], 439 [sp.csr_matrix(random_lil((10, 40), 440 config.floatX, 3)), 441 ] * 2, 442 MulSS) 443 444 def test_mul_sd(self): 445 x = SparseType('csr', dtype=config.floatX)() 446 y = tensor.matrix() 447 self._compile_and_check( 448 [x, y], 449 [x * y], 450 [sp.csr_matrix(random_lil((10, 40), 451 config.floatX, 3)), 452 np.random.randn(10, 40).astype(config.floatX)], 453 MulSD, excluding=["local_mul_s_d"]) 454 455 def test_remove0(self): 456 x = SparseType('csr', dtype=config.floatX)() 457 self._compile_and_check([x], 458 [Remove0()(x)], 459 [sp.csr_matrix(random_lil((10, 40), 460 config.floatX, 3))], 461 Remove0) 462 463 def test_dot(self): 464 x = SparseType('csc', dtype=config.floatX)() 465 y = SparseType('csc', dtype=config.floatX)() 466 self._compile_and_check( 467 [x, y], 468 [Dot()(x, y)], 469 [sp.csc_matrix(random_lil((4, 5), 470 config.floatX, 3)), 471 sp.csc_matrix(random_lil((5, 3), 472 config.floatX, 3))], 473 Dot) 474 475 def test_dot_broadcast(self): 476 for x, y in [ 477 (SparseType('csr', 'float32')(), tensor.vector()[:, None]), 478 (SparseType('csr', 'float32')(), tensor.vector()[None, :]), 479 (SparseType('csr', 'float32')(), tensor.matrix()), 480 (tensor.vector()[:, None], SparseType('csr', 'float32')()), 481 (tensor.vector()[None, :], SparseType('csr', 'float32')()), 482 (tensor.matrix(), SparseType('csr', 'float32')())]: 483 484 sparse_out = theano.dot(x, y) 485 if isinstance(x, sparse.SparseVariable): 486 x = tensor.matrix() 487 if isinstance(y, sparse.SparseVariable): 488 y = tensor.matrix() 489 dense_out = tensor.dot(x, y) 490 assert dense_out.broadcastable == sparse_out.broadcastable 491 492 def test_structured_dot(self): 493 x = SparseType('csc', dtype=config.floatX)() 494 y = SparseType('csc', dtype=config.floatX)() 495 self._compile_and_check( 496 [x, y], 497 [structured_dot(x, y)], 498 [sp.csc_matrix(random_lil((4, 5), 499 config.floatX, 3)), 500 sp.csc_matrix(random_lil((5, 3), 501 config.floatX, 3))], 502 StructuredDot) 503 504 def test_structured_dot_grad(self): 505 # We also need the grad of CSM to be implemetned. 506 raise SkipTest('infer_shape not implemented for the grad' 507 ' of structured_dot') 508 for format, op in [('csc', StructuredDotGradCSC), 509 ('csr', StructuredDotGradCSR)]: 510 x = SparseType(format, dtype=config.floatX)() 511 y = SparseType(format, dtype=config.floatX)() 512 grads = tensor.grad(dense_from_sparse(structured_dot(x, y)).sum(), 513 [x, y]) 514 self._compile_and_check( 515 [x, y], 516 [grads[0]], 517 [as_sparse_format(random_lil((4, 5), 518 config.floatX, 3), format), 519 as_sparse_format(random_lil((5, 3), 520 config.floatX, 3), format)], 521 op) 522 self._compile_and_check( 523 [x, y], 524 [grads[1]], 525 [as_sparse_format(random_lil((4, 5), 526 config.floatX, 3), format), 527 as_sparse_format(random_lil((5, 3), 528 config.floatX, 3), format)], 529 op) 530 531 def test_dense_from_sparse(self): 532 x = SparseType('csr', dtype=config.floatX)() 533 self._compile_and_check([x], 534 [dense_from_sparse(x)], 535 [sp.csr_matrix(random_lil((10, 40), 536 config.floatX, 3))], 537 dense_from_sparse.__class__) 538 539 def test_sparse_from_dense(self): 540 x = tensor.matrix() 541 self._compile_and_check([x], 542 [csc_from_dense(x)], 543 [np.random.randn(10, 40).astype( 544 config.floatX)], 545 csc_from_dense.__class__) 546 547 def test_sparse_from_list(self): 548 x = tensor.matrix('x') 549 vals = tensor.matrix('vals') 550 ilist = tensor.lvector('ilist') 551 552 out = construct_sparse_from_list(x, vals, ilist) 553 self._compile_and_check( 554 [x, vals, ilist], 555 [out], 556 [np.zeros((40, 10), dtype=config.floatX), 557 np.random.randn(12, 10).astype(config.floatX), 558 np.random.randint(low=0, high=40, size=(12,))], 559 ConstructSparseFromList 560 ) 561 562 563class TestConstructSparseFromList(unittest.TestCase): 564 def test_adv_sub1_sparse_grad(self): 565 v = theano.tensor.ivector() 566 567 # Assert we don't create a sparse grad by default 568 m = theano.tensor.matrix() 569 sub = m[v] 570 g = theano.grad(sub.sum(), m) 571 assert isinstance(g.owner.op, tensor.AdvancedIncSubtensor1) 572 573 # Test that we create a sparse grad when asked 574 # USER INTERFACE 575 m = theano.tensor.matrix() 576 v = theano.tensor.ivector() 577 sub = theano.sparse_grad(m[v]) 578 g = theano.grad(sub.sum(), m) 579 assert isinstance(g.owner.op, ConstructSparseFromList) 580 581 # Test that we create a sparse grad when asked 582 # Op INTERFACE 583 m = theano.tensor.matrix() 584 v = theano.tensor.ivector() 585 sub = theano.tensor.AdvancedSubtensor1(sparse_grad=True)(m, v) 586 g = theano.grad(sub.sum(), m) 587 assert isinstance(g.owner.op, ConstructSparseFromList) 588 589 # Test the sparse grad 590 valm = np.random.rand(5, 4).astype(config.floatX) 591 valv = np.random.randint(0, 5, 10) 592 m = theano.tensor.matrix() 593 shared_v = theano.shared(valv) 594 595 def fn(m): 596 return theano.sparse_grad(m[shared_v]) 597 verify_grad_sparse(fn, [valm]) 598 599 def test_err(self): 600 for ndim in [1, 3]: 601 t = theano.tensor.TensorType(dtype=config.floatX, 602 broadcastable=(False,) * ndim)() 603 v = theano.tensor.ivector() 604 sub = t[v] 605 606 # Assert we don't create a sparse grad by default 607 g = theano.grad(sub.sum(), t) 608 assert isinstance(g.owner.op, tensor.AdvancedIncSubtensor1) 609 610 # Test that we raise an error, as we can't create a sparse 611 # grad from tensors that don't have 2 dimensions. 612 sub = theano.sparse_grad(sub) 613 self.assertRaises(TypeError, theano.grad, sub.sum(), t) 614 615 616class T_AddMul(unittest.TestCase): 617 def testAddSS(self): 618 self._testSS(add) 619 620 def testAddSD(self): 621 self._testSD(add) 622 623 def testAddDS(self): 624 self._testDS(add) 625 626 def testMulSS(self): 627 self._testSS(mul, 628 np.array([[1., 0], [3, 0], [0, 6]]), 629 np.array([[1., 2], [3, 0], [0, 6]])) 630 631 def testMulSD(self): 632 self._testSD(mul, 633 np.array([[1., 0], [3, 0], [0, 6]]), 634 np.array([[1., 2], [3, 0], [0, 6]])) 635 636 def testMulDS(self): 637 self._testDS(mul, 638 np.array([[1., 0], [3, 0], [0, 6]]), 639 np.array([[1., 2], [3, 0], [0, 6]])) 640 641 def _testSS(self, op, array1=np.array([[1., 0], [3, 0], [0, 6]]), 642 array2=np.asarray([[0, 2.], [0, 4], [5, 0]])): 643 for mtype1, mtype2 in product(_mtypes, _mtypes): 644 for dtype1, dtype2 in [('float64', 'int8'), 645 ('int8', 'float64'), 646 ('float64', 'float64'), 647 ]: 648 a = mtype1(array1).astype(dtype1) 649 aR = as_sparse_variable(a) 650 self.assertFalse(aR.data is a) 651 self.assertTrue(_is_sparse(a)) 652 self.assertTrue(_is_sparse_variable(aR)) 653 654 b = mtype2(array2).astype(dtype2) 655 bR = as_sparse_variable(b) 656 self.assertFalse(bR.data is b) 657 self.assertTrue(_is_sparse(b)) 658 self.assertTrue(_is_sparse_variable(bR)) 659 660 apb = op(aR, bR) 661 self.assertTrue(_is_sparse_variable(apb)) 662 663 self.assertTrue(apb.type.format == aR.type.format, apb.type.format) 664 665 val = eval_outputs([apb]) 666 self.assertTrue(val.shape == (3, 2)) 667 if op is add: 668 self.assertTrue(np.all(val.todense() == (array1 + array2))) 669 if dtype1.startswith('float') and dtype2.startswith('float'): 670 verify_grad_sparse(op, [a, b], structured=False) 671 elif op is mul: 672 self.assertTrue(np.all(val.todense() 673 == (array1 * array2))) 674 if dtype1.startswith('float') and dtype2.startswith('float'): 675 verify_grad_sparse(op, [a, b], structured=False) 676 677 def _testSD(self, op, array1=np.array([[1., 0], [3, 0], [0, 6]]), 678 array2=np.asarray([[0, 2.], [0, 4], [5, 0]])): 679 for mtype in _mtypes: 680 for a in [np.array(array1), tensor.as_tensor_variable(array1), 681 theano.shared(array1)]: 682 for dtype1, dtype2 in [('float64', 'int8'), 683 ('int8', 'float64'), 684 # Needed to test the grad 685 ('float32', 'float64'), 686 ]: 687 a = a.astype(dtype1) 688 b = mtype(array2).astype(dtype2) 689 bR = as_sparse_variable(b) 690 self.assertFalse(bR.data is b) # constants are copied 691 self.assertTrue(_is_sparse(b)) 692 self.assertTrue(_is_sparse_variable(bR)) 693 694 apb = op(a, bR) 695 696 val = eval_outputs([apb]) 697 self.assertTrue(val.shape == (3, 2)) 698 if op is add: 699 self.assertTrue(_is_dense_variable(apb)) 700 self.assertTrue(np.all(val == (array1 + b))) 701 ans = np.array([[1., 2], [3, 4], [5, 6]]) 702 self.assertTrue(np.all(val == ans)) 703 if isinstance(a, theano.Constant): 704 a = a.data 705 if getattr(a, 'owner', None): 706 continue 707 if dtype1.startswith('float') and dtype2.startswith('float'): 708 verify_grad_sparse(op, [a, b], structured=True) 709 elif op is mul: 710 self.assertTrue(_is_sparse_variable(apb)) 711 self.assertTrue(np.all(val.todense() == (b.multiply(array1)))) 712 self.assertTrue(np.all(val.todense() == np.array( 713 [[1, 0], [9, 0], [0, 36]]))) 714 if isinstance(a, theano.Constant): 715 a = a.data 716 if getattr(a, 'owner', None): 717 continue 718 if dtype1.startswith('float') and dtype2.startswith('float'): 719 verify_grad_sparse(op, [a, b], structured=False) 720 721 def _testDS(self, op, array1=np.array([[1., 0], [3, 0], [0, 6]]), 722 array2=np.asarray([[0, 2.], [0, 4], [5, 0]])): 723 for mtype in _mtypes: 724 for b in [np.asarray(array2), 725 tensor.as_tensor_variable(array2), 726 theano.shared(array2)]: 727 for dtype1, dtype2 in [('float64', 'int8'), 728 ('int8', 'float64'), 729 ]: 730 a = mtype(array1).astype(dtype1) 731 aR = as_sparse_variable(a) 732 self.assertFalse(aR.data is a) 733 self.assertTrue(_is_sparse(a)) 734 self.assertTrue(_is_sparse_variable(aR)) 735 b = b.astype(dtype2) 736 737 apb = op(aR, b) 738 739 val = eval_outputs([apb]) 740 self.assertTrue(val.shape == (3, 2)) 741 if op is add: 742 self.assertTrue(_is_dense_variable(apb)) 743 self.assertTrue(np.all(val == (a + array2))) 744 ans = np.array([[1., 2], [3, 4], [5, 6]]) 745 self.assertTrue(np.all(val == ans)) 746 if isinstance(b, theano.Constant): 747 b = b.data 748 if dtype1.startswith('float') and dtype2.startswith('float'): 749 verify_grad_sparse(op, [a, b], structured=True) 750 elif op is mul: 751 self.assertTrue(_is_sparse_variable(apb)) 752 ans = np.array([[1, 0], [9, 0], [0, 36]]) 753 self.assertTrue(np.all(val.todense() == (a.multiply(array2)))) 754 self.assertTrue(np.all(val.todense() == ans)) 755 if isinstance(b, theano.Constant): 756 b = b.data 757 if dtype1.startswith('float') and dtype2.startswith('float'): 758 verify_grad_sparse(op, [a, b], structured=False) 759 760 761class test_comparison(unittest.TestCase): 762 def setUp(self): 763 utt.seed_rng() 764 765 # took from tensor basic_test.py 766 def _rand_ranged(self, min, max, shape): 767 return np.asarray(np.random.rand(*shape) * (max - min) + min, 768 dtype=config.floatX) 769 770 tests = [lambda x, y: x > y, lambda x, y: x < y, 771 lambda x, y: x >= y, lambda x, y: x <= y] 772 773 testsDic = {gt: lambda x, y: x > y, lt: lambda x, y: x < y, 774 ge: lambda x, y: x >= y, le: lambda x, y: x <= y} 775 776 def __generalized_ss_test(self, theanop, symbolicType, testOp, scipyType): 777 778 scipy_ver = [int(n) for n in scipy.__version__.split('.')[:2]] 779 780 if (bool(scipy_ver < [0, 13])): 781 raise SkipTest("comparison operators need newer release of scipy") 782 783 x = symbolicType() 784 y = symbolicType() 785 786 op = theanop(x, y) 787 788 f = theano.function([x, y], op) 789 790 m1 = scipyType(random_lil((10, 40), config.floatX, 3)) 791 m2 = scipyType(random_lil((10, 40), config.floatX, 3)) 792 793 self.assertTrue(np.array_equal(f(m1, m2).data, testOp(m1, m2).data)) 794 795 def __generalized_sd_test(self, theanop, symbolicType, testOp, scipyType): 796 797 scipy_ver = [int(n) for n in scipy.__version__.split('.')[:2]] 798 799 if (bool(scipy_ver < [0, 13])): 800 raise SkipTest("comparison operators need newer release of scipy") 801 802 x = symbolicType() 803 y = theano.tensor.matrix() 804 805 op = theanop(x, y) 806 807 f = theano.function([x, y], op) 808 809 m1 = scipyType(random_lil((10, 40), config.floatX, 3)) 810 m2 = self._rand_ranged(1000, -1000, [10, 40]) 811 812 self.assertTrue(np.array_equal(f(m1, m2).data, testOp(m1, m2).data)) 813 814 def __generalized_ds_test(self, theanop, symbolicType, testOp, scipyType): 815 816 scipy_ver = [int(n) for n in scipy.__version__.split('.')[:2]] 817 818 if (bool(scipy_ver < [0, 13])): 819 raise SkipTest("comparison operators need newer release of scipy") 820 821 x = symbolicType() 822 y = theano.tensor.matrix() 823 824 op = theanop(y, x) 825 826 f = theano.function([y, x], op) 827 828 m1 = scipyType(random_lil((10, 40), config.floatX, 3)) 829 m2 = self._rand_ranged(1000, -1000, [10, 40]) 830 831 self.assertTrue(np.array_equal(f(m2, m1).data, testOp(m2, m1).data)) 832 833 def test_ss_csr_comparison(self): 834 835 for op in self.tests: 836 self.__generalized_ss_test(op, sparse.csr_matrix, 837 op, sp.csr_matrix) 838 839 def test_ss_csc_comparison(self): 840 841 for op in self.tests: 842 self.__generalized_ss_test(op, sparse.csc_matrix, 843 op, sp.csc_matrix) 844 845 def test_sd_csr_comparison(self): 846 847 for op in self.tests: 848 self.__generalized_sd_test(op, sparse.csr_matrix, 849 op, sp.csr_matrix) 850 851 def test_sd_csc_comparison(self): 852 853 for op in self.tests: 854 self.__generalized_sd_test(op, sparse.csc_matrix, 855 op, sp.csc_matrix) 856 857 def test_ds_csc_comparison(self): 858 859 for op in self.testsDic: 860 self.__generalized_ds_test(op, sparse.csc_matrix, 861 self.testsDic[op], sp.csc_matrix) 862 863 def test_ds_csr_comparison(self): 864 865 for op in self.testsDic: 866 self.__generalized_ds_test(op, sparse.csr_matrix, 867 self.testsDic[op], sp.csr_matrix) 868 869 def test_equality_case(self): 870 # Test assuring normal behaviour when values 871 # in the matrices are equal 872 873 scipy_ver = [int(n) for n in scipy.__version__.split('.')[:2]] 874 875 if (bool(scipy_ver < [0, 13])): 876 raise SkipTest("comparison operators need newer release of scipy") 877 878 x = sparse.csc_matrix() 879 y = theano.tensor.matrix() 880 881 m1 = sp.csc_matrix((2, 2), dtype=theano.config.floatX) 882 m2 = np.asarray([[0, 0], [0, 0]], dtype=theano.config.floatX) 883 884 for func in self.testsDic: 885 886 op = func(y, x) 887 f = theano.function([y, x], op) 888 889 self.assertTrue(np.array_equal(f(m2, m1), 890 self.testsDic[func](m2, m1))) 891 892 893class T_conversion(unittest.TestCase): 894 def setUp(self): 895 utt.seed_rng() 896 897 if 0: 898 def test0(self): 899 a = tensor.as_tensor_variable(np.random.rand(5)) 900 s = csc_from_dense(a) 901 val = eval_outputs([s]) 902 self.assertTrue(str(val.dtype) == 'float64') 903 self.assertTrue(val.format == 'csc') 904 905 if 0: 906 def test1(self): 907 a = tensor.as_tensor_variable(np.random.rand(5)) 908 s = csr_from_dense(a) 909 val = eval_outputs([s]) 910 self.assertTrue(str(val.dtype) == 'float64') 911 self.assertTrue(val.format == 'csr') 912 913 def test_dense_from_sparse(self): 914 # call dense_from_sparse 915 for t in _mtypes: 916 s = t(scipy.sparse.identity(5)) 917 s = as_sparse_variable(s) 918 d = dense_from_sparse(s) 919 val = eval_outputs([d]) 920 self.assertTrue(str(val.dtype) == s.dtype) 921 self.assertTrue(np.all(val[0] == [1, 0, 0, 0, 0])) 922 923 def test_todense(self): 924 # call sparse_var.todense() 925 for t in _mtypes: 926 s = t(scipy.sparse.identity(5)) 927 s = as_sparse_variable(s) 928 d = s.toarray() 929 val = eval_outputs([d]) 930 self.assertTrue(str(val.dtype) == s.dtype) 931 self.assertTrue(np.all(val[0] == [1, 0, 0, 0, 0])) 932 933 @staticmethod 934 def check_format_ndim(format, ndim): 935 x = tensor.tensor( 936 dtype=config.floatX, 937 broadcastable=([False] * ndim), 938 name='x') 939 940 s = SparseFromDense(format)(x) 941 s_m = - s 942 d = dense_from_sparse(s_m) 943 c = d.sum() 944 g = tensor.grad(c, x) 945 f = theano.function([x], [s, g]) 946 f(np.array(0, dtype=config.floatX, ndmin=ndim)) 947 f(np.array(7, dtype=config.floatX, ndmin=ndim)) 948 949 def test_format_ndim(self): 950 for format in 'csc', 'csr': 951 for ndim in 0, 1, 2: 952 self.check_format_ndim(format, ndim) 953 954 self.assertRaises(TypeError, self.check_format_ndim, format, 3) 955 self.assertRaises(TypeError, self.check_format_ndim, format, 4) 956 957 958class test_csm_properties(unittest.TestCase): 959 def setUp(self): 960 utt.seed_rng() 961 962 def test_csm_properties_grad(self): 963 sp_types = {'csc': sp.csc_matrix, 964 'csr': sp.csr_matrix} 965 966 for format in ['csc', 'csr']: 967 for dtype in ['float32', 'float64']: 968 spmat = sp_types[format](random_lil((4, 3), dtype, 3)) 969 970 verify_grad_sparse(lambda *x: CSMProperties()(*x)[0], [spmat], 971 structured=True) 972 973 verify_grad_sparse(lambda *x: CSMProperties()(*x)[1], [spmat], 974 structured=True) 975 976 verify_grad_sparse(lambda *x: CSMProperties()(*x)[2], [spmat], 977 structured=True) 978 979 verify_grad_sparse(lambda *x: CSMProperties()(*x)[2], [spmat], 980 structured=True) 981 982 def test_csm_properties(self): 983 sp_types = {'csc': sp.csc_matrix, 984 'csr': sp.csr_matrix} 985 986 for format in ['csc', 'csr']: 987 for dtype in ['float32', 'float64']: 988 x = SparseType(format, dtype=dtype)() 989 f = theano.function([x], csm_properties(x)) 990 991 spmat = sp_types[format](random_lil((4, 3), dtype, 3)) 992 993 data, indices, indptr, shape = f(spmat) 994 995 assert np.all(data == spmat.data) 996 assert np.all(indices == spmat.indices) 997 assert np.all(indptr == spmat.indptr) 998 assert np.all(shape == spmat.shape) 999 1000 1001class test_csm(unittest.TestCase): 1002 def setUp(self): 1003 utt.seed_rng() 1004 1005 def test_csm_grad(self): 1006 sp_types = {'csc': sp.csc_matrix, 1007 'csr': sp.csr_matrix} 1008 1009 for format in ['csc', 'csr']: 1010 for dtype in ['float32', 'float64']: 1011 spmat = sp_types[format](random_lil((4, 3), dtype, 3)) 1012 1013 verify_grad_sparse(lambda x: CSM(format)(x, spmat.indices, 1014 spmat.indptr, np.asarray(spmat.shape, 'int32')), 1015 [spmat.data], structured=True) 1016 1017 def test_csm_sparser(self): 1018 # Test support for gradients sparser than the input. 1019 1020 sp_types = {'csc': sp.csc_matrix, 1021 'csr': sp.csr_matrix} 1022 1023 for format in ['csc', 'csr']: 1024 for dtype in ['float32', 'float64']: 1025 x = tensor.tensor(dtype=dtype, broadcastable=(False,)) 1026 y = tensor.ivector() 1027 z = tensor.ivector() 1028 s = tensor.ivector() 1029 1030 a = as_sparse_variable(sp_types[format](random_lil((4, 3), 1031 dtype, 1))) 1032 1033 f = theano.function([x, y, z, s], 1034 tensor.grad(dense_from_sparse( 1035 a * CSM(format)(x, y, z, s)).sum(), x)) 1036 1037 spmat = sp_types[format](random_lil((4, 3), dtype, 3)) 1038 1039 res = f(spmat.data, spmat.indices, spmat.indptr, 1040 np.asarray(spmat.shape, 'int32')) 1041 1042 assert len(spmat.data) == len(res) 1043 1044 def test_csm_unsorted(self): 1045 # Test support for gradients of unsorted inputs. 1046 1047 sp_types = {'csc': sp.csc_matrix, 1048 'csr': sp.csr_matrix} 1049 1050 for format in ['csr', 'csc', ]: 1051 for dtype in ['float32', 'float64']: 1052 x = tensor.tensor(dtype=dtype, broadcastable=(False,)) 1053 y = tensor.ivector() 1054 z = tensor.ivector() 1055 s = tensor.ivector() 1056 # Sparse advanced indexing produces unsorted sparse matrices 1057 a = sparse_random_inputs(format, (8, 6), out_dtype=dtype, 1058 unsorted_indices=True)[1][0] 1059 # Make sure it's unsorted 1060 assert not a.has_sorted_indices 1061 def my_op(x): 1062 y = tensor.constant(a.indices) 1063 z = tensor.constant(a.indptr) 1064 s = tensor.constant(a.shape) 1065 return tensor.sum( 1066 dense_from_sparse(CSM(format)(x, y, z, s) * a)) 1067 verify_grad_sparse(my_op, [a.data]) 1068 1069 def test_csm(self): 1070 sp_types = {'csc': sp.csc_matrix, 1071 'csr': sp.csr_matrix} 1072 1073 for format in ['csc', 'csr']: 1074 for dtype in ['float32', 'float64']: 1075 x = tensor.tensor(dtype=dtype, broadcastable=(False,)) 1076 y = tensor.ivector() 1077 z = tensor.ivector() 1078 s = tensor.ivector() 1079 f = theano.function([x, y, z, s], CSM(format)(x, y, z, s)) 1080 1081 spmat = sp_types[format](random_lil((4, 3), dtype, 3)) 1082 1083 res = f(spmat.data, spmat.indices, spmat.indptr, 1084 np.asarray(spmat.shape, 'int32')) 1085 1086 assert np.all(res.data == spmat.data) 1087 assert np.all(res.indices == spmat.indices) 1088 assert np.all(res.indptr == spmat.indptr) 1089 assert np.all(res.shape == spmat.shape) 1090 1091 1092class test_structureddot(unittest.TestCase): 1093 def setUp(self): 1094 utt.seed_rng() 1095 1096 def test_structureddot_csc_grad(self): 1097 1098 # shortcut: testing csc in float32, testing csr in float64 1099 1100 # allocate a random sparse matrix 1101 spmat = sp.csc_matrix(random_lil((4, 3), 'float32', 3)) 1102 1103 mat = np.asarray(np.random.randn(3, 2), 'float32') 1104 1105 verify_grad_sparse(structured_dot, [spmat, mat], structured=True) 1106 1107 def buildgraph_T(spmat, mat): 1108 return structured_dot(mat.T, spmat.T) 1109 1110 verify_grad_sparse(buildgraph_T, [spmat, mat], structured=True) 1111 1112 def test_structureddot_csr_grad(self): 1113 1114 # shortcut: testing csc in float32, testing csr in float64 1115 1116 # allocate a random sparse matrix 1117 spmat = sp.csr_matrix(random_lil((4, 3), 'float64', 3)) 1118 1119 mat = np.asarray(np.random.randn(3, 2), 'float64') 1120 1121 verify_grad_sparse(structured_dot, [spmat, mat], structured=True) 1122 1123 def buildgraph_T(spmat, mat): 1124 return structured_dot(mat.T, spmat.T) 1125 1126 verify_grad_sparse(buildgraph_T, [spmat, mat], structured=True) 1127 1128 def test_upcast(self): 1129 1130 typenames = ('float32', 'int64', 'int8', 'int32', 1131 'int16', 'float64', 'complex64', 'complex128') 1132 for dense_dtype in typenames: 1133 for sparse_dtype in typenames: 1134 correct_dtype = theano.scalar.upcast(sparse_dtype, dense_dtype) 1135 a = SparseType('csc', dtype=sparse_dtype)() 1136 b = tensor.matrix(dtype=dense_dtype) 1137 d = structured_dot(a, b) 1138 assert d.type.dtype == correct_dtype 1139 1140 # compile and run a function 1141 1142 f = theano.function([a, b], d) 1143 1144 M, N, K, nnz = (4, 3, 5, 3) 1145 spmat = sp.csc_matrix(random_lil((M, N), sparse_dtype, nnz)) 1146 # the following madness is necessary to workaround 1147 # an intc vs. int32 bug. 1148 # The lil makes an intc on my computer when sparse_dtype 1149 # is int32. 1150 spmat.dtype = np.dtype(sparse_dtype) 1151 mat = np.asarray(np.random.randn(N, K) * 9, 1152 dtype=dense_dtype) 1153 # print 'DTYPES', sparse_dtype, dense_dtype 1154 # print 'sym types', a.type, b.type 1155 # print 'dtype strings', spmat.dtype, mat.dtype 1156 # print 'numpy dtype num', mat.dtype.num 1157 # print 'scipy dtype num', spmat.data.dtype.num 1158 theano_result = f(spmat, mat) 1159 scipy_result = spmat * mat 1160 assert theano_result.shape == scipy_result.shape 1161 assert theano_result.dtype == scipy_result.dtype 1162 utt.assert_allclose(scipy_result, theano_result) 1163 1164 def test_opt_unpack(self): 1165 # 1166 # Test that a graph involving 1167 # structured_dot(assembled_csc_matrix) is optimized to be just 1168 # a structured_dot_csc Op and no assembly of a csc_matrix. 1169 # 1170 # The optimization from structured_dot -> structured_dot_csc 1171 # is currently disabled, So this test is not expected to pass 1172 1173 return 1174 # 1175 kerns = tensor.Tensor(dtype='int64', broadcastable=[False])('kerns') 1176 spmat = sp.lil_matrix((4, 6), dtype='int64') 1177 for i in range(5): 1178 # set non-zeros in random locations (row x, col y) 1179 x = np.floor(np.random.rand() * spmat.shape[0]) 1180 y = np.floor(np.random.rand() * spmat.shape[1]) 1181 spmat[x, y] = np.random.rand() * 10 1182 spmat = sp.csc_matrix(spmat) 1183 1184 images = tensor.Tensor(dtype='float32', 1185 broadcastable=[False, False])('images') 1186 1187 cscmat = CSC(kerns, spmat.indices[:spmat.size], 1188 spmat.indptr, spmat.shape) 1189 f = theano.function([kerns, images], structured_dot(cscmat, images.T)) 1190 1191 sdcscpresent = False 1192 for node in f.maker.fgraph.toposort(): 1193 # print node.op 1194 assert not isinstance(node.op, CSM) 1195 assert not isinstance(node.op, CSMProperties) 1196 if isinstance(f.maker.fgraph.toposort()[1].op, StructuredDotCSC): 1197 sdcscpresent = True 1198 assert sdcscpresent 1199 1200 kernvals = np.array(spmat.data[:spmat.size]) 1201 # print 'kdtype', kernvals.dtype, kernvals.shape, 1202 # print kernvals.ndim, kernvals.dtype.num 1203 # print 'type of kernvals = ', kernvals.dtype 1204 bsize = 3 1205 imvals = 1.0 * np.array(np.arange(bsize * spmat.shape[1]).\ 1206 reshape(bsize, spmat.shape[1]), 1207 dtype='float32') 1208 outvals = f(kernvals, imvals) 1209 # print outvals 1210 1211 def test_dot_sparse_sparse(self): 1212 # test dot for 2 input sparse matrix 1213 sparse_dtype = 'float64' 1214 sp_mat = {'csc': sp.csc_matrix, 1215 'csr': sp.csr_matrix, 1216 'bsr': sp.csr_matrix} 1217 1218 for sparse_format_a in ['csc', 'csr', 'bsr']: 1219 for sparse_format_b in ['csc', 'csr', 'bsr']: 1220 a = SparseType(sparse_format_a, dtype=sparse_dtype)() 1221 b = SparseType(sparse_format_b, dtype=sparse_dtype)() 1222 d = theano.dot(a, b) 1223 f = theano.function([a, b], theano.Out(d, borrow=True)) 1224 topo = f.maker.fgraph.toposort() 1225 for M, N, K, nnz in [(4, 3, 2, 3), 1226 (40, 30, 20, 3), 1227 (40, 30, 20, 30), 1228 (400, 3000, 200, 6000), 1229 ]: 1230 a_val = sp_mat[sparse_format_a]( 1231 random_lil((M, N), sparse_dtype, nnz)) 1232 b_val = sp_mat[sparse_format_b]( 1233 random_lil((N, K), sparse_dtype, nnz)) 1234 f(a_val, b_val) 1235 1236 def test_csc_correct_output_faster_than_scipy(self): 1237 sparse_dtype = 'float64' 1238 dense_dtype = 'float64' 1239 1240 a = SparseType('csc', dtype=sparse_dtype)() 1241 b = tensor.matrix(dtype=dense_dtype) 1242 d = theano.dot(a, b) 1243 f = theano.function([a, b], theano.Out(d, borrow=True)) 1244 1245 for M, N, K, nnz in [(4, 3, 2, 3), 1246 (40, 30, 20, 3), 1247 (40, 30, 20, 30), 1248 (400, 3000, 200, 6000), 1249 ]: 1250 spmat = sp.csc_matrix(random_lil((M, N), sparse_dtype, nnz)) 1251 mat = np.asarray(np.random.randn(N, K), dense_dtype) 1252 theano_times = [] 1253 scipy_times = [] 1254 for i in xrange(5): 1255 t0 = time.time() 1256 theano_result = f(spmat, mat) 1257 t1 = time.time() 1258 scipy_result = spmat * mat 1259 t2 = time.time() 1260 1261 theano_times.append(t1 - t0) 1262 scipy_times.append(t2 - t1) 1263 1264 theano_time = np.min(theano_times) 1265 scipy_time = np.min(scipy_times) 1266 1267 speedup = scipy_time / theano_time 1268 # print scipy_times 1269 # print theano_times 1270 # print ('M=%(M)s N=%(N)s K=%(K)s nnz=%(nnz)s theano_time' 1271 # '=%(theano_time)s speedup=%(speedup)s') % locals() 1272 1273 # fail if Theano is slower than scipy by more than a certain amount 1274 overhead_tol = 0.003 # seconds overall 1275 overhead_rtol = 1.2 # times as long 1276 utt.assert_allclose(scipy_result, theano_result) 1277 if (theano.config.mode == "FAST_RUN" and 1278 theano.config.cxx): 1279 self.assertFalse(theano_time > overhead_rtol * scipy_time + 1280 overhead_tol) 1281 1282 def test_csr_correct_output_faster_than_scipy(self): 1283 1284 # contrast with test_grad, we put csr in float32, csc in float64 1285 1286 sparse_dtype = 'float32' 1287 dense_dtype = 'float32' 1288 1289 a = SparseType('csr', dtype=sparse_dtype)() 1290 b = tensor.matrix(dtype=dense_dtype) 1291 d = theano.dot(a, b) 1292 f = theano.function([a, b], d) 1293 1294 for M, N, K, nnz in [(4, 3, 2, 3), 1295 (40, 30, 20, 3), 1296 (40, 30, 20, 30), 1297 (400, 3000, 200, 6000), 1298 ]: 1299 spmat = sp.csr_matrix(random_lil((M, N), sparse_dtype, nnz)) 1300 mat = np.asarray(np.random.randn(N, K), dense_dtype) 1301 t0 = time.time() 1302 theano_result = f(spmat, mat) 1303 t1 = time.time() 1304 scipy_result = spmat * mat 1305 t2 = time.time() 1306 1307 theano_time = t1 - t0 1308 scipy_time = t2 - t1 1309 # print 'theano took', theano_time, 1310 # print 'scipy took', scipy_time 1311 overhead_tol = 0.002 # seconds 1312 overhead_rtol = 1.1 # times as long 1313 utt.assert_allclose(scipy_result, theano_result) 1314 if (theano.config.mode == "FAST_RUN" and 1315 theano.config.cxx): 1316 self.assertFalse( 1317 theano_time > overhead_rtol * scipy_time + overhead_tol, 1318 (theano_time, 1319 overhead_rtol * scipy_time + overhead_tol, 1320 scipy_time, overhead_rtol, overhead_tol)) 1321 1322 1323class DotTests(utt.InferShapeTester): 1324 def setUp(self): 1325 super(DotTests, self).setUp() 1326 x_size = (10, 100) 1327 y_size = (100, 1000) 1328 utt.seed_rng() 1329 1330 self.x_csr = scipy.sparse.csr_matrix( 1331 np.random.binomial(1, 0.5, x_size), dtype=theano.config.floatX) 1332 self.x_csc = scipy.sparse.csc_matrix( 1333 np.random.binomial(1, 0.5, x_size), dtype=theano.config.floatX) 1334 self.y = np.asarray(np.random.uniform(-1, 1, y_size), 1335 dtype=theano.config.floatX) 1336 self.y_csr = scipy.sparse.csr_matrix( 1337 np.random.binomial(1, 0.5, y_size), dtype=theano.config.floatX) 1338 self.y_csc = scipy.sparse.csc_matrix( 1339 np.random.binomial(1, 0.5, y_size), dtype=theano.config.floatX) 1340 self.v_10 = np.asarray(np.random.uniform(-1, 1, 10), 1341 dtype=theano.config.floatX) 1342 self.v_100 = np.asarray(np.random.uniform(-1, 1, 100), 1343 dtype=theano.config.floatX) 1344 1345 def test_csr_dense(self): 1346 x = theano.sparse.csr_matrix('x') 1347 y = theano.tensor.matrix('y') 1348 v = theano.tensor.vector('v') 1349 1350 for (x, y, x_v, y_v) in [(x, y, self.x_csr, self.y), 1351 (x, v, self.x_csr, self.v_100), 1352 (v, x, self.v_10, self.x_csr)]: 1353 f_a = theano.function([x, y], theano.sparse.dot(x, y)) 1354 f_b = lambda x, y: x * y 1355 1356 utt.assert_allclose(f_a(x_v, y_v), f_b(x_v, y_v)) 1357 1358 # Test infer_shape 1359 self._compile_and_check([x, y], [theano.sparse.dot(x, y)], 1360 [x_v, y_v], 1361 (Dot, Usmm, UsmmCscDense)) 1362 1363 def test_csc_dense(self): 1364 x = theano.sparse.csc_matrix('x') 1365 y = theano.tensor.matrix('y') 1366 v = theano.tensor.vector('v') 1367 1368 for (x, y, x_v, y_v) in [(x, y, self.x_csc, self.y), 1369 (x, v, self.x_csc, self.v_100), 1370 (v, x, self.v_10, self.x_csc)]: 1371 1372 f_a = theano.function([x, y], theano.sparse.dot(x, y)) 1373 f_b = lambda x, y: x * y 1374 1375 utt.assert_allclose(f_a(x_v, y_v), f_b(x_v, y_v)) 1376 1377 # Test infer_shape 1378 self._compile_and_check([x, y], [theano.sparse.dot(x, y)], 1379 [x_v, y_v], 1380 (Dot, Usmm, UsmmCscDense)) 1381 1382 def test_sparse_sparse(self): 1383 for d1, d2 in [('float32', 'float32'), 1384 ('float32', 'float64'), 1385 ('float64', 'float32'), 1386 ('float64', 'float64'), 1387 ('float32', 'int16'), 1388 ('float32', 'complex64'), 1389 ]: 1390 for x_f, y_f in [('csc', 'csc'), 1391 ('csc', 'csr'), 1392 ('csr', 'csc'), 1393 ('csr', 'csr'), 1394 ]: 1395 x = theano.sparse.SparseType(format=x_f, dtype=d1)('x') 1396 y = theano.sparse.SparseType(format=x_f, dtype=d2)('x') 1397 1398 f_a = lambda x, y: x * y 1399 f_b = theano.function([x, y], theano.sparse.dot(x, y)) 1400 1401 vx = getattr(self, 'x_' + x_f).astype(d1) 1402 vy = getattr(self, 'y_' + y_f).astype(d2) 1403 utt.assert_allclose(f_a(vx, vy).toarray(), f_b(vx, vy)) 1404 1405 # Test infer_shape 1406 f_a = theano.function([x, y], theano.sparse.dot(x, y).shape) 1407 f_b = lambda x, y: (x * y).shape 1408 assert np.all(f_a(vx, vy) == f_b(vx, vy)) 1409 topo = f_a.maker.fgraph.toposort() 1410 if theano.config.mode != 'FAST_COMPILE': 1411 nb = 0 1412 else: 1413 nb = 1 1414 assert sum([isinstance(node.op, (Dot, Usmm, UsmmCscDense)) 1415 for node in topo]) == nb 1416 1417 def test_int32_dtype(self): 1418 # Reported on the theano-user mailing-list: 1419 # https://groups.google.com/d/msg/theano-users/MT9ui8LtTsY/rwatwEF9zWAJ 1420 size = 9 1421 intX = 'int32' 1422 1423 C = tensor.matrix('C', dtype=intX) 1424 I = tensor.matrix('I', dtype=intX) 1425 1426 fI = I.flatten() 1427 data = tensor.ones_like(fI) 1428 indptr = tensor.arange(data.shape[0] + 1, dtype='int32') 1429 1430 m1 = sparse.CSR(data, fI, indptr, (8, size)) 1431 m2 = sparse.dot(m1, C) 1432 y = m2.reshape(shape=(2, 4, 9), ndim=3) 1433 1434 f = theano.function(inputs=[I, C], outputs=y) 1435 i = np.asarray([[4, 3, 7, 7], [2, 8, 4, 5]], dtype=intX) 1436 a = np.asarray(np.random.randint(0, 100, (size, size)), 1437 dtype=intX) 1438 f(i, a) 1439 1440 def test_csr_dense_grad(self): 1441 1442 # shortcut: testing csc in float32, testing csr in float64 1443 1444 # allocate a random sparse matrix 1445 spmat = sp.csr_matrix(random_lil((4, 3), 'float64', 3)) 1446 1447 mat = np.asarray(np.random.randn(2, 4), 'float64') 1448 1449 def buildgraph_T(mat): 1450 return Dot()(mat, spmat) 1451 1452 theano.tests.unittest_tools.verify_grad(buildgraph_T, [mat]) 1453 1454 1455class UsmmTests(unittest.TestCase): 1456 """ 1457 Test the Usmm and UsmmCscDense class and related optimization 1458 """ 1459 def setUp(self): 1460 x_size = (10, 100) 1461 y_size = (100, 200) 1462 z_size = (x_size[0], y_size[1]) 1463 1464 self.rng = np.random.RandomState(seed=utt.fetch_seed()) 1465 self.x = np.asarray(self.rng.binomial(1, 0.5, x_size), 1466 dtype=theano.config.floatX) 1467 self.y = np.asarray(self.rng.uniform(-1, 1, y_size), 1468 dtype=theano.config.floatX) 1469 self.z = np.asarray(self.rng.uniform(-1, 1, z_size), 1470 dtype=theano.config.floatX) 1471 1472 # this is slow, but it's the only test for the op. 1473 def test(self): 1474 def mat(format, name, dtype): 1475 if format == 'dense': 1476 return theano.tensor.matrix(name, dtype=dtype) 1477 else: 1478 return theano.sparse.matrix(format, name, dtype=dtype) 1479 1480 params = product(*([['float32', 'float64', 'int16', 'complex64']] * 4 + 1481 [['dense', 'csc', 'csr']] * 2)) 1482 1483 # All test are too slow, so we randomly take 100 of them. 1484 # The buildbot change the seed, so we will finish by running them all. 1485 # As of this writing they where all passing. 1486 #params = self.rng.permutation(list(params))[:500] 1487 1488 for dtype1, dtype2, dtype3, dtype4, format1, format2 in params: 1489 if format1 == 'dense' and format2 == 'dense': 1490 # Usmm won't be used! 1491 continue 1492 x = mat(format1, 'x', dtype1) 1493 y = mat(format2, 'y', dtype2) 1494 a = theano.tensor.scalar('a', dtype=dtype3) 1495 z = theano.shared(np.asarray(self.z, dtype=dtype4).copy()) 1496 1497 f_b = lambda z, a, x, y: z - a * (x * y) 1498 x_data = np.asarray(self.x, dtype=dtype1) 1499 if format1 != 'dense': 1500 x_data = as_sparse_format(x_data, format1) 1501 y_data = np.asarray(self.y, dtype=dtype2) 1502 if format2 != 'dense': 1503 y_data = as_sparse_format(y_data, format2) 1504 a_data = np.asarray(1.5, dtype=dtype3) 1505 z_data = np.asarray(self.z, dtype=dtype4) 1506 1507 f_b_out = f_b(z_data, a_data, x_data, y_data) 1508 1509 # Can it work inplace? 1510 inplace = dtype4 == theano.scalar.upcast(dtype1, dtype2, dtype3) 1511 1512 # To make it easier to check the toposort 1513 mode = theano.compile.mode.get_default_mode().excluding('fusion') 1514 1515 if inplace: 1516 updates = [(z, z - a * theano.sparse.dot(x, y))] 1517 f_a = theano.function([a, x, y], [], 1518 updates=updates, 1519 mode=mode) 1520 f_a(a_data, x_data, y_data) 1521 f_a_out = z.get_value(borrow=True) 1522 else: 1523 f_a = theano.function([a, x, y], 1524 z - a * theano.sparse.dot(x, y), 1525 mode=mode) 1526 # In DebugMode there is a strange difference with complex 1527 # So we raise a little the threshold a little. 1528 try: 1529 orig_atol = theano.tensor.basic.float64_atol 1530 orig_rtol = theano.tensor.basic.float64_rtol 1531 theano.tensor.basic.float64_atol = 1e-7 1532 theano.tensor.basic.float64_rtol = 1e-6 1533 f_a_out = f_a(a_data, x_data, y_data) 1534 finally: 1535 theano.tensor.basic.float64_atol = orig_atol 1536 theano.tensor.basic.float64_rtol = orig_rtol 1537 1538 # As we do a dot product of 2 vector of 100 element, 1539 # This mean we can have 2*100*eps abs error. 1540 if f_a_out.dtype in ['float64', 'complex128']: 1541 atol = 3e-8 1542 rtol = 1e-5 1543 else: 1544 atol = None 1545 rtol = None 1546 utt.assert_allclose(f_a_out, f_b_out, rtol=rtol, atol=atol) 1547 topo = f_a.maker.fgraph.toposort() 1548 up = theano.scalar.upcast(dtype1, dtype2, dtype3, dtype4) 1549 1550 fast_compile = theano.config.mode == "FAST_COMPILE" 1551 1552 if not theano.config.blas.ldflags: 1553 # Usmm should not be inserted, because it relies on BLAS 1554 assert len(topo) == 4, topo 1555 assert isinstance(topo[0].op, theano.sparse.Dot) 1556 assert isinstance(topo[1].op, theano.tensor.DimShuffle) 1557 assert (isinstance(topo[2].op, theano.tensor.Elemwise) and 1558 isinstance(topo[2].op.scalar_op, theano.scalar.Mul)) 1559 assert (isinstance(topo[3].op, theano.tensor.Elemwise) and 1560 isinstance(topo[3].op.scalar_op, theano.scalar.Sub)) 1561 elif (y.type.dtype == up and format1 == 'csc' 1562 and format2 == 'dense' and not fast_compile 1563 and theano.config.cxx and up in ('float32', 'float64')): 1564 # The op UsmmCscDense should be inserted 1565 assert (sum([isinstance(node.op, tensor.Elemwise) and 1566 isinstance(node.op.scalar_op, 1567 theano.scalar.basic.Cast) 1568 for node in topo]) == len(topo) - 5) 1569 new_topo = [] 1570 for node in topo: 1571 if not (isinstance(node.op, tensor.Elemwise) and 1572 isinstance(node.op.scalar_op, 1573 theano.scalar.basic.Cast)): 1574 new_topo.append(node) 1575 topo = new_topo 1576 assert len(topo) == 5, topo 1577 # Usmm is tested at the same time in debugmode 1578 # Check if the optimization local_usmm and local_usmm_csx is 1579 # applied 1580 def check_once(x): 1581 assert sum([isinstance(n.op, x) for n in topo]) == 1 1582 check_once(theano.sparse.basic.CSMProperties) 1583 check_once(theano.tensor.DimShuffle) 1584 check_once(theano.tensor.Subtensor) 1585 check_once(UsmmCscDense) 1586 check_once(theano.tensor.Elemwise) 1587 if inplace: 1588 assert topo[4].op.inplace 1589 elif not fast_compile: 1590 # The op Usmm should be inserted 1591 assert len(topo) == 3, topo 1592 assert isinstance(topo[0].op, theano.tensor.DimShuffle) 1593 assert topo[1].op == theano.tensor.neg 1594 assert isinstance(topo[2].op, theano.sparse.Usmm) 1595 1596 def test_infer_shape(self): 1597 def mat(format, name, dtype): 1598 if format == 'dense': 1599 return theano.tensor.matrix(name, dtype=dtype) 1600 else: 1601 return theano.sparse.matrix(format, name, dtype=dtype) 1602 1603 params = [('float32', 'float64', 'int16', 'complex64', 'csc', 'dense'), 1604 ('float32', 'float64', 'int16', 'complex64', 'csr', 'dense')] 1605 for dtype1, dtype2, dtype3, dtype4, format1, format2 in params: 1606 if format1 == 'dense' and format2 == 'dense': 1607 # Usmm won't be used! 1608 continue 1609 x = mat(format1, 'x', dtype1) 1610 y = mat(format2, 'y', dtype2) 1611 a = theano.tensor.scalar('a', dtype=dtype3) 1612 z = theano.shared(np.asarray(self.z, dtype=dtype4).copy()) 1613 1614 f_b = lambda z, a, x, y: z - a * (x * y) 1615 x_data = np.asarray(self.x, dtype=dtype1) 1616 if format1 != 'dense': 1617 x_data = as_sparse_format(x_data, format1) 1618 y_data = np.asarray(self.y, dtype=dtype2) 1619 if format2 != 'dense': 1620 y_data = as_sparse_format(y_data, format2) 1621 a_data = np.asarray(1.5, dtype=dtype3) 1622 z_data = np.asarray(self.z, dtype=dtype4) 1623 1624 f_b_out = f_b(z_data, a_data, x_data, y_data) 1625 1626 # Can it work inplace? 1627 inplace = dtype4 == theano.scalar.upcast(dtype1, dtype2, dtype3) 1628 1629 # To make it easier to check the toposort 1630 mode = theano.compile.mode.get_default_mode().excluding('fusion') 1631 1632 # test infer_shape of Dot got applied 1633 f_shape = theano.function([a, x, y], 1634 (z - a * theano.sparse.dot(x, y)).shape, 1635 mode=mode) 1636 assert all(f_shape(a_data, x_data, y_data) == f_b_out.shape) 1637 topo = f_shape.maker.fgraph.toposort() 1638 if theano.config.mode != 'FAST_COMPILE': 1639 nb = 0 1640 else: 1641 nb = 1 1642 assert sum([isinstance(node.op, (Dot, Usmm, UsmmCscDense)) 1643 for node in topo]) == nb 1644 1645 1646class test_zeros_like(unittest.TestCase): 1647 def test(self): 1648 x = theano.sparse.csr_matrix() 1649 f = theano.function([x], theano.sparse.sp_zeros_like(x)) 1650 vx = scipy.sparse.csr_matrix(np.asarray( 1651 np.random.binomial(1, 0.5, (100, 100)), 1652 dtype=theano.config.floatX)) 1653 1654 fx = f(vx) 1655 1656 assert fx.nnz == 0 1657 assert fx.shape == vx.shape 1658 1659 1660def test_shape_i(): 1661 sparse_dtype = 'float32' 1662 1663 a = SparseType('csr', dtype=sparse_dtype)() 1664 f = theano.function([a], a.shape[1]) 1665 assert f(sp.csr_matrix(random_lil((100, 10), sparse_dtype, 3))) == 10 1666 1667 1668def test_shape(): 1669 # Test that getting the shape of a sparse variable 1670 # does not actually create a dense tensor in the process. 1671 sparse_dtype = 'float32' 1672 1673 a = SparseType('csr', dtype=sparse_dtype)() 1674 f = theano.function([a], a.shape) 1675 assert np.all(f(sp.csr_matrix(random_lil((100, 10), sparse_dtype, 3))) 1676 == (100, 10)) 1677 if theano.config.mode != 'FAST_COMPILE': 1678 topo = f.maker.fgraph.toposort() 1679 assert len(topo) == 3 1680 assert isinstance(topo[0].op, tensor.opt.Shape_i) 1681 assert isinstance(topo[1].op, tensor.opt.Shape_i) 1682 assert isinstance(topo[2].op, tensor.opt.MakeVector) 1683 1684 1685def test_may_share_memory(): 1686 a = scipy.sparse.csc_matrix(scipy.sparse.eye(5, 3)) 1687 b = scipy.sparse.csc_matrix(scipy.sparse.eye(4, 3)) 1688 as_ar = lambda a: theano._asarray(a, dtype='int32') 1689 for a_, b_, rep in [(a, a, True), 1690 (b, b, True), 1691 (a, b, False), 1692 (a, a.data, True), 1693 (a, a.indptr, True), 1694 (a, a.indices, True), 1695 (a, as_ar(a.shape), False), 1696 (a.data, a, True), 1697 (a.indptr, a, True), 1698 (a.indices, a, True), 1699 (as_ar(a.shape), a, False), 1700 (b, b.data, True), 1701 (b, b.indptr, True), 1702 (b, b.indices, True), 1703 (b, as_ar(b.shape), False), 1704 (b.data, b, True), 1705 (b.indptr, b, True), 1706 (b.indices, b, True), 1707 (as_ar(b.shape), b, False), 1708 (b.data, a, False), 1709 (b.indptr, a, False), 1710 (b.indices, a, False), 1711 (as_ar(b.shape), a, False), 1712 (a.transpose(), a, True), 1713 (b.transpose(), b, True), 1714 (a.transpose(), b, False), 1715 (b.transpose(), a, False), 1716 ]: 1717 1718 assert SparseType.may_share_memory(a_, b_) == rep 1719 1720 1721def test_sparse_shared_memory(): 1722 # Note : There are no inplace ops on sparse matrix yet. If one is 1723 # someday implemented, we could test it here. 1724 a = random_lil((3, 4), 'float32', 3).tocsr() 1725 m1 = random_lil((4, 4), 'float32', 3).tocsr() 1726 m2 = random_lil((4, 4), 'float32', 3).tocsr() 1727 x = SparseType('csr', dtype='float32')() 1728 y = SparseType('csr', dtype='float32')() 1729 1730 sdot = theano.sparse.structured_dot 1731 z = sdot(x * 3, m1) + sdot(y * 2, m2) 1732 1733 f = theano.function([theano.In(x, mutable=True), 1734 theano.In(y, mutable=True)], z, mode='FAST_RUN') 1735 1736 def f_(x, y, m1=m1, m2=m2): 1737 return ((x * 3) * m1) + ((y * 2) * m2) 1738 1739 assert SparseType.may_share_memory(a, a) # This is trivial 1740 result = f(a, a) 1741 result_ = f_(a, a) 1742 assert (result_.todense() == result.todense()).all() 1743 1744 1745def test_size(): 1746 # Ensure the `size` attribute of sparse matrices behaves as in numpy. 1747 1748 for sparse_type in ('csc_matrix', 'csr_matrix'): 1749 x = getattr(theano.sparse, sparse_type)() 1750 y = getattr(scipy.sparse, sparse_type)((5, 7)).astype(config.floatX) 1751 get_size = theano.function([x], x.size) 1752 1753 def check(): 1754 assert y.size == get_size(y) 1755 # We verify that the size is correctly updated as we store more data 1756 # into the sparse matrix (including zeros). 1757 check() 1758 y[0, 0] = 1 1759 check() 1760 y[0, 1] = 0 1761 check() 1762 1763 1764class ColScaleCSCTester(utt.InferShapeTester): 1765 def setUp(self): 1766 super(ColScaleCSCTester, self).setUp() 1767 self.op = sparse.col_scale 1768 1769 def test_op(self): 1770 for format in sparse.sparse_formats: 1771 variable, data = sparse_random_inputs(format, shape=(8, 10)) 1772 variable.append(tensor.vector()) 1773 data.append(np.random.random(10).astype(config.floatX)) 1774 1775 f = theano.function(variable, self.op(*variable)) 1776 1777 tested = f(*data) 1778 x, s = data[0].toarray(), data[1][np.newaxis, :] 1779 expected = x * s 1780 1781 assert tested.format == format 1782 utt.assert_allclose(expected, tested.toarray()) 1783 1784 def test_infer_shape(self): 1785 for format, cls in [('csc', sparse.ColScaleCSC), 1786 ('csr', sparse.RowScaleCSC)]: 1787 variable, data = sparse_random_inputs(format, shape=(8, 10)) 1788 variable.append(tensor.vector()) 1789 data.append(np.random.random(10).astype(config.floatX)) 1790 1791 self._compile_and_check(variable, 1792 [self.op(*variable)], 1793 data, 1794 cls) 1795 1796 def test_grad(self): 1797 for format in sparse.sparse_formats: 1798 variable, data = sparse_random_inputs(format, shape=(8, 10)) 1799 variable.append(tensor.vector()) 1800 data.append(np.random.random(10).astype(config.floatX)) 1801 1802 verify_grad_sparse(self.op, data, structured=True) 1803 1804 1805class RowScaleCSCTester(utt.InferShapeTester): 1806 def setUp(self): 1807 super(RowScaleCSCTester, self).setUp() 1808 self.op = sparse.row_scale 1809 1810 def test_op(self): 1811 for format in sparse.sparse_formats: 1812 variable, data = sparse_random_inputs(format, shape=(8, 10)) 1813 variable.append(tensor.vector()) 1814 data.append(np.random.random(8).astype(config.floatX)) 1815 1816 f = theano.function(variable, self.op(*variable)) 1817 1818 tested = f(*data) 1819 x, s = data[0].toarray(), data[1][:, np.newaxis] 1820 expected = x * s 1821 1822 assert tested.format == format 1823 utt.assert_allclose(expected, tested.toarray()) 1824 1825 def test_infer_shape(self): 1826 for format, cls in [('csc', sparse.RowScaleCSC), 1827 ('csr', sparse.ColScaleCSC)]: 1828 variable, data = sparse_random_inputs(format, shape=(8, 10)) 1829 variable.append(tensor.vector()) 1830 data.append(np.random.random(8).astype(config.floatX)) 1831 1832 self._compile_and_check(variable, 1833 [self.op(*variable)], 1834 data, 1835 cls) 1836 1837 def test_grad(self): 1838 for format in sparse.sparse_formats: 1839 variable, data = sparse_random_inputs(format, shape=(8, 10)) 1840 variable.append(tensor.vector()) 1841 data.append(np.random.random(8).astype(config.floatX)) 1842 1843 verify_grad_sparse(self.op, data, structured=True) 1844 1845 1846class SpSumTester(utt.InferShapeTester): 1847 possible_axis = [None, 0, 1] 1848 1849 def setUp(self): 1850 super(SpSumTester, self).setUp() 1851 self.op_class = sparse.SpSum 1852 self.op = sparse.sp_sum 1853 1854 def test_op(self): 1855 for format in sparse.sparse_formats: 1856 for axis in self.possible_axis: 1857 variable, data = sparse_random_inputs(format, 1858 shape=(10, 10)) 1859 1860 z = theano.sparse.sp_sum(variable[0], axis=axis) 1861 if axis is None: 1862 assert z.type.broadcastable == () 1863 else: 1864 assert z.type.broadcastable == (False, ) 1865 1866 f = theano.function(variable, self.op(variable[0], axis=axis)) 1867 tested = f(*data) 1868 expected = data[0].todense().sum(axis).ravel() 1869 utt.assert_allclose(expected, tested) 1870 1871 def test_infer_shape(self): 1872 for format in sparse.sparse_formats: 1873 for axis in self.possible_axis: 1874 variable, data = sparse_random_inputs(format, 1875 shape=(9, 10)) 1876 self._compile_and_check(variable, 1877 [self.op(variable[0], axis=axis)], 1878 data, 1879 self.op_class) 1880 1881 def test_grad(self): 1882 for format in sparse.sparse_formats: 1883 for axis in self.possible_axis: 1884 for struct in [True, False]: 1885 variable, data = sparse_random_inputs(format, 1886 shape=(9, 10)) 1887 verify_grad_sparse( 1888 self.op_class(axis=axis, sparse_grad=struct), 1889 data, 1890 structured=struct) 1891 1892 1893class DiagTester(utt.InferShapeTester): 1894 def setUp(self): 1895 super(DiagTester, self).setUp() 1896 self.op_class = Diag 1897 self.op = diag 1898 1899 def test_op(self): 1900 for format in sparse.sparse_formats: 1901 variable, data = sparse_random_inputs(format, 1902 shape=(10, 10)) 1903 1904 z = self.op(*variable) 1905 assert z.type.broadcastable == (False, ) 1906 1907 f = theano.function(variable, z) 1908 tested = f(*data) 1909 expected = data[0].toarray().diagonal() 1910 1911 utt.assert_allclose(expected, tested) 1912 1913 def test_infer_shape(self): 1914 for format in sparse.sparse_formats: 1915 variable, data = sparse_random_inputs(format, 1916 shape=(10, 10)) 1917 self._compile_and_check(variable, 1918 [self.op(*variable)], 1919 data, 1920 self.op_class, 1921 warn=False) 1922 1923 def test_grad(self): 1924 for format in sparse.sparse_formats: 1925 variable, data = sparse_random_inputs(format, 1926 shape=(10, 10)) 1927 verify_grad_sparse( 1928 self.op, 1929 data, 1930 structured=False) 1931 1932 1933class SquareDiagonalTester(utt.InferShapeTester): 1934 def setUp(self): 1935 super(SquareDiagonalTester, self).setUp() 1936 self.op_class = SquareDiagonal 1937 self.op = square_diagonal 1938 1939 def test_op(self): 1940 for format in sparse.sparse_formats: 1941 for size in range(5, 9): 1942 variable = [tensor.vector()] 1943 data = [np.random.random(size).astype(config.floatX)] 1944 1945 f = theano.function(variable, self.op(*variable)) 1946 tested = f(*data).toarray() 1947 1948 expected = np.diag(*data) 1949 utt.assert_allclose(expected, tested) 1950 assert tested.dtype == expected.dtype 1951 assert tested.shape == expected.shape 1952 1953 def test_infer_shape(self): 1954 for format in sparse.sparse_formats: 1955 for size in range(5, 9): 1956 variable = [tensor.vector()] 1957 data = [np.random.random(size).astype(config.floatX)] 1958 1959 self._compile_and_check(variable, 1960 [self.op(*variable)], 1961 data, 1962 self.op_class) 1963 1964 def test_grad(self): 1965 for format in sparse.sparse_formats: 1966 for size in range(5, 9): 1967 variable = [tensor.vector()] 1968 data = [np.random.random(size).astype(config.floatX)] 1969 1970 verify_grad_sparse( 1971 self.op, 1972 data, 1973 structured=False) 1974 1975 1976class EnsureSortedIndicesTester(utt.InferShapeTester): 1977 def setUp(self): 1978 super(EnsureSortedIndicesTester, self).setUp() 1979 self.op_class = EnsureSortedIndices 1980 self.op = ensure_sorted_indices 1981 1982 def test_op(self): 1983 for format in sparse.sparse_formats: 1984 for shape in zip(range(5, 9), range(3, 7)[::-1]): 1985 variable, data = sparse_random_inputs(format, shape=shape) 1986 1987 f = theano.function(variable, self.op(*variable)) 1988 tested = f(*data).toarray() 1989 expected = data[0].sorted_indices().toarray() 1990 1991 utt.assert_allclose(expected, tested) 1992 1993 def test_infer_shape(self): 1994 for format in sparse.sparse_formats: 1995 for shape in zip(range(5, 9), range(3, 7)[::-1]): 1996 variable, data = sparse_random_inputs(format, shape=shape) 1997 self._compile_and_check(variable, 1998 [self.op(*variable)], 1999 data, 2000 self.op_class) 2001 2002 def test_grad(self): 2003 for format in sparse.sparse_formats: 2004 for shape in zip(range(5, 9), range(3, 7)[::-1]): 2005 variable, data = sparse_random_inputs(format, shape=shape) 2006 verify_grad_sparse( 2007 self.op, 2008 data, 2009 structured=False) 2010 2011 2012class CleanTester(utt.InferShapeTester): 2013 def setUp(self): 2014 super(CleanTester, self).setUp() 2015 self.op = clean 2016 2017 def test_op(self): 2018 for format in sparse.sparse_formats: 2019 for shape in zip(range(5, 9), range(3, 7)[::-1]): 2020 variable, data = sparse_random_inputs(format, shape=shape) 2021 2022 data[0][0, 0] = data[0][1, 1] = 0 2023 2024 f = theano.function(variable, self.op(*variable)) 2025 tested = f(*data) 2026 expected = data[0] 2027 expected.eliminate_zeros() 2028 2029 assert all(tested.data == expected.data) 2030 assert not all(tested.data == 0) 2031 2032 tested = tested.toarray() 2033 expected = expected.toarray() 2034 utt.assert_allclose(expected, tested) 2035 2036 def test_grad(self): 2037 for format in sparse.sparse_formats: 2038 for shape in zip(range(5, 9), range(3, 7)[::-1]): 2039 variable, data = sparse_random_inputs(format, shape=shape) 2040 verify_grad_sparse( 2041 self.op, 2042 data, 2043 structured=False) 2044 2045 2046class Remove0Tester(utt.InferShapeTester): 2047 def setUp(self): 2048 super(Remove0Tester, self).setUp() 2049 self.op_class = Remove0 2050 2051 def test_remove0(self): 2052 configs = [ 2053 # structure type, numpy matching class 2054 ('csc', scipy.sparse.csc_matrix), 2055 ('csr', scipy.sparse.csr_matrix), ] 2056 2057 for format, matrix_class in configs: 2058 for zero, unsor in [(True, True), (True, False), 2059 (False, True), (False, False)]: 2060 (x,), (mat,) = sparse_random_inputs(format, (6, 8), 2061 out_dtype=config.floatX, 2062 explicit_zero=zero, 2063 unsorted_indices=unsor) 2064 assert 0 in mat.data or not zero 2065 assert not mat.has_sorted_indices or not unsor 2066 2067 # the In thingy has to be there because theano has as rule not 2068 # to optimize inputs 2069 f = theano.function([theano.In(x, borrow=True, mutable=True)], 2070 Remove0()(x)) 2071 2072 # assert optimization local_inplace_remove0 is applied in 2073 # modes with optimization 2074 if theano.config.mode not in ['FAST_COMPILE']: 2075 # list of apply nodes in the optimized graph. 2076 nodes = f.maker.fgraph.toposort() 2077 # Check there isn't any Remove0 instance not inplace. 2078 assert not any([isinstance(node.op, Remove0) and 2079 not node.op.inplace for node in nodes]), ( 2080 'Inplace optimization should have been applied') 2081 # Check there is at least one Remove0 inplace. 2082 assert any([isinstance(node.op, Remove0) and node.op.inplace 2083 for node in nodes]) 2084 # checking 2085 # makes sense to change its name 2086 target = mat 2087 result = f(mat) 2088 mat.eliminate_zeros() 2089 msg = 'Matrices sizes differ. Have zeros been removed ?' 2090 assert result.size == target.size, msg 2091 if unsor: 2092 assert not result.has_sorted_indices 2093 assert not target.has_sorted_indices 2094 else: 2095 assert result.has_sorted_indices 2096 assert target.has_sorted_indices 2097 2098 def test_infer_shape(self): 2099 mat = (np.arange(12) + 1).reshape((4, 3)) 2100 mat[0, 1] = mat[1, 0] = mat[2, 2] = 0 2101 2102 x_csc = theano.sparse.csc_matrix(dtype=theano.config.floatX) 2103 mat_csc = sp.csc_matrix(mat, dtype=theano.config.floatX) 2104 self._compile_and_check([x_csc], 2105 [Remove0()(x_csc)], 2106 [mat_csc], 2107 self.op_class) 2108 2109 x_csr = theano.sparse.csr_matrix(dtype=theano.config.floatX) 2110 mat_csr = sp.csr_matrix(mat, dtype=theano.config.floatX) 2111 self._compile_and_check([x_csr], 2112 [Remove0()(x_csr)], 2113 [mat_csr], 2114 self.op_class) 2115 2116 def test_grad(self): 2117 mat = (np.arange(9) + 1).reshape((3, 3)) 2118 mat[0, 1] = mat[1, 0] = mat[2, 2] = 0 2119 2120 mat_csc = sp.csc_matrix(mat, dtype=theano.config.floatX) 2121 verify_grad_sparse(Remove0(), [mat_csc]) 2122 2123 mat_csr = sp.csr_matrix(mat, dtype=theano.config.floatX) 2124 verify_grad_sparse(Remove0(), [mat_csr]) 2125 2126 2127class Test_getitem(unittest.TestCase): 2128 def setUp(self): 2129 self.rng = np.random.RandomState(utt.fetch_seed()) 2130 2131 def test_GetItemList(self): 2132 2133 a, A = sparse_random_inputs('csr', (4, 5)) 2134 b, B = sparse_random_inputs('csc', (4, 5)) 2135 y = a[0][[0, 1, 2, 3, 1]] 2136 z = b[0][[0, 1, 2, 3, 1]] 2137 2138 fa = theano.function([a[0]], y) 2139 fb = theano.function([b[0]], z) 2140 2141 t_geta = fa(A[0]).todense() 2142 t_getb = fb(B[0]).todense() 2143 2144 s_geta = scipy.sparse.csr_matrix(A[0])[[0, 1, 2, 3, 1]].todense() 2145 s_getb = scipy.sparse.csc_matrix(B[0])[[0, 1, 2, 3, 1]].todense() 2146 2147 utt.assert_allclose(t_geta, s_geta) 2148 utt.assert_allclose(t_getb, s_getb) 2149 2150 def test_GetItemList_wrong_index(self): 2151 a, A = sparse_random_inputs('csr', (4, 5)) 2152 y = a[0][[0, 4]] 2153 f = theano.function([a[0]], y) 2154 2155 self.assertRaises(IndexError, f, A[0]) 2156 2157 def test_get_item_list_grad(self): 2158 op = theano.sparse.basic.GetItemList() 2159 def op_with_fixed_index(x): 2160 return op(x, index=np.asarray([0, 1])) 2161 2162 x, x_val = sparse_random_inputs("csr", (4, 5)) 2163 2164 try: 2165 verify_grad_sparse(op_with_fixed_index, x_val) 2166 except NotImplementedError as e: 2167 assert "Scipy version is to old" in str(e) 2168 2169 def test_GetItem2Lists(self): 2170 2171 a, A = sparse_random_inputs('csr', (4, 5)) 2172 b, B = sparse_random_inputs('csc', (4, 5)) 2173 y = a[0][[0, 0, 1, 3], [0, 1, 2, 4]] 2174 z = b[0][[0, 0, 1, 3], [0, 1, 2, 4]] 2175 2176 fa = theano.function([a[0]], y) 2177 fb = theano.function([b[0]], z) 2178 2179 t_geta = fa(A[0]) 2180 t_getb = fb(B[0]) 2181 2182 s_geta = np.asarray(scipy.sparse.csr_matrix(A[0])[[0, 0, 1, 3], [0, 1, 2, 4]]) 2183 s_getb = np.asarray(scipy.sparse.csc_matrix(B[0])[[0, 0, 1, 3], [0, 1, 2, 4]]) 2184 2185 utt.assert_allclose(t_geta, s_geta) 2186 utt.assert_allclose(t_getb, s_getb) 2187 2188 def test_GetItem2Lists_wrong_index(self): 2189 a, A = sparse_random_inputs('csr', (4, 5)) 2190 y1 = a[0][[0, 5], [0, 3]] 2191 y2 = a[0][[0, 3], [0, 5]] 2192 2193 f1 = theano.function([a[0]], y1) 2194 f2 = theano.function([a[0]], y2) 2195 2196 self.assertRaises(IndexError, f1, A[0]) 2197 self.assertRaises(IndexError, f2, A[0]) 2198 2199 def test_get_item_2lists_grad(self): 2200 op = theano.sparse.basic.GetItem2Lists() 2201 def op_with_fixed_index(x): 2202 return op(x, ind1=np.asarray([0, 1]), ind2=np.asarray([2, 3])) 2203 2204 x, x_val = sparse_random_inputs("csr", (4, 5)) 2205 2206 verify_grad_sparse(op_with_fixed_index, x_val) 2207 2208 def test_GetItem2D(self): 2209 scipy_ver = [int(n) for n in scipy.__version__.split('.')[:2]] 2210 is_supported_version = bool(scipy_ver >= [0, 14]) 2211 2212 sparse_formats = ('csc', 'csr') 2213 for format in sparse_formats: 2214 x = theano.sparse.matrix(format, name='x') 2215 a = theano.tensor.iscalar('a') 2216 b = theano.tensor.iscalar('b') 2217 c = theano.tensor.iscalar('c') 2218 d = theano.tensor.iscalar('d') 2219 e = theano.tensor.iscalar('e') 2220 f = theano.tensor.iscalar('f') 2221 2222 # index 2223 m = 1 2224 n = 5 2225 p = 10 2226 q = 15 2227 if is_supported_version: 2228 j = 2 2229 k = 3 2230 else: 2231 j = None 2232 k = None 2233 2234 vx = as_sparse_format(self.rng.binomial(1, 0.5, (100, 97)), 2235 format).astype(theano.config.floatX) 2236 2237 #mode_no_debug = theano.compile.mode.get_default_mode() 2238 # if isinstance(mode_no_debug, theano.compile.DebugMode): 2239 # mode_no_debug = 'FAST_RUN' 2240 if is_supported_version: 2241 f1 = theano.function([x, a, b, c, d, e, f], x[a:b:e, c:d:f]) 2242 r1 = f1(vx, m, n, p, q, j, k) 2243 t1 = vx[m:n:j, p:q:k] 2244 else: 2245 f1 = theano.function([x, a, b, c, d], x[a:b, c:d]) 2246 r1 = f1(vx, m, n, p, q) 2247 t1 = vx[m:n, p:q] 2248 assert r1.shape == t1.shape 2249 assert np.all(t1.toarray() == r1.toarray()) 2250 2251 """ 2252 Important: based on a discussion with both Fred and James 2253 The following indexing methods is not supported because the rval 2254 would be a sparse matrix rather than a sparse vector, which is a 2255 deviation from numpy indexing rule. This decision is made largely 2256 for keeping the consistency between numpy and theano. 2257 2258 f2 = theano.function([x, a, b, c], x[a:b, c]) 2259 r2 = f2(vx, m, n, p) 2260 t2 = vx[m:n, p] 2261 assert r2.shape == t2.shape 2262 assert np.all(t2.toarray() == r2.toarray()) 2263 2264 f3 = theano.function([x, a, b, c], x[a, b:c]) 2265 r3 = f3(vx, m, n, p) 2266 t3 = vx[m, n:p] 2267 assert r3.shape == t3.shape 2268 assert np.all(t3.toarray() == r3.toarray()) 2269 2270 f5 = theano.function([x], x[1:2,3]) 2271 r5 = f5(vx) 2272 t5 = vx[1:2, 3] 2273 assert r5.shape == t5.shape 2274 assert np.all(r5.toarray() == t5.toarray()) 2275 2276 f7 = theano.function([x], x[50]) 2277 r7 = f7(vx) 2278 t7 = vx[50] 2279 assert r7.shape == t7.shape 2280 assert np.all(r7.toarray() == t7.toarray()) 2281 """ 2282 if is_supported_version: 2283 f4 = theano.function([x, a, b, e], x[a:b:e]) 2284 r4 = f4(vx, m, n, j) 2285 t4 = vx[m:n:j] 2286 else: 2287 f4 = theano.function([x, a, b], x[a:b]) 2288 r4 = f4(vx, m, n) 2289 t4 = vx[m:n] 2290 assert r4.shape == t4.shape 2291 assert np.all(t4.toarray() == r4.toarray()) 2292 2293 #----------------------------------------------------------- 2294 # test cases using int indexing instead of theano variable 2295 f6 = theano.function([x], x[1:10:j, 10:20:k]) 2296 r6 = f6(vx) 2297 t6 = vx[1:10:j, 10:20:k] 2298 assert r6.shape == t6.shape 2299 assert np.all(r6.toarray() == t6.toarray()) 2300 2301 #---------------------------------------------------------- 2302 # test cases with indexing both with theano variable and int 2303 if is_supported_version: 2304 f8 = theano.function([x, a, b, e], x[a:b:e, 10:20:1]) 2305 r8 = f8(vx, m, n, j) 2306 t8 = vx[m:n:j, 10:20:1] 2307 else: 2308 f8 = theano.function([x, a, b], x[a:b, 10:20]) 2309 r8 = f8(vx, m, n) 2310 t8 = vx[m:n, 10:20] 2311 assert r8.shape == t8.shape 2312 assert np.all(r8.toarray() == t8.toarray()) 2313 2314 f9 = theano.function([x, a, b], x[1:a:j, 1:b:k]) 2315 r9 = f9(vx, p, q) 2316 t9 = vx[1:p:j, 1:q:k] 2317 assert r9.shape == t9.shape 2318 assert np.all(r9.toarray() == t9.toarray()) 2319 2320 #----------------------------------------------------------- 2321 # Test mixing None and variables 2322 f10 = theano.function([x, a, b], x[:a, :b]) 2323 r10 = f10(vx, p, q) 2324 t10 = vx[:p, :q] 2325 assert r10.shape == t10.shape 2326 assert np.all(r10.toarray() == t10.toarray()) 2327 2328 f11 = theano.function([x, a], x[:, a:]) 2329 r11 = f11(vx, p) 2330 t11 = vx[:, p:] 2331 assert r11.shape == t11.shape 2332 assert np.all(r11.toarray() == t11.toarray()) 2333 2334 # Test that is work with shared variable 2335 sx = theano.shared(vx) 2336 f12 = theano.function([a], sx[:, a:]) 2337 r12 = f12(p) 2338 t12 = vx[:, p:] 2339 assert r12.shape == t12.shape 2340 assert np.all(r12.toarray() == t12.toarray()) 2341 2342 #------------------------------------------------------------ 2343 # Invalid things 2344 # The syntax is a bit awkward because assertRaises forbids 2345 # the [] shortcut for getitem. 2346 # x[a:b] is not accepted because we don't have sparse vectors 2347 self.assertRaises(NotImplementedError, 2348 x.__getitem__, (slice(a, b), c)) 2349 2350 # x[a:b:step, c:d] is not accepted because scipy silently drops 2351 # the step (!) 2352 if not is_supported_version: 2353 self.assertRaises(ValueError, 2354 x.__getitem__, (slice(a, b, -1), slice(c, d))) 2355 self.assertRaises(ValueError, 2356 x.__getitem__, (slice(a, b), slice(c, d, 2))) 2357 else: 2358 raise SkipTest("Slicing with step is supported.") 2359 2360 # Advanced indexing is not supported 2361 self.assertRaises(ValueError, 2362 x.__getitem__, 2363 (tensor.ivector('l'), slice(a, b))) 2364 2365 # Indexing with random things is not supported either 2366 self.assertRaises(ValueError, 2367 x.__getitem__, slice(tensor.fscalar('f'), None)) 2368 self.assertRaises(ValueError, 2369 x.__getitem__, 2370 (slice(None), slice([1, 3, 4], None))) 2371 2372 def test_GetItemScalar(self): 2373 sparse_formats = ('csc', 'csr') 2374 for format in sparse_formats: 2375 x = theano.sparse.csc_matrix('x') 2376 a = theano.tensor.iscalar() 2377 b = theano.tensor.iscalar() 2378 2379 m = 50 2380 n = 42 2381 2382 vx = as_sparse_format(self.rng.binomial(1, 0.5, (97, 100)), 2383 format).astype(theano.config.floatX) 2384 2385 f1 = theano.function([x, a, b], x[a, b]) 2386 r1 = f1(vx, 10, 10) 2387 t1 = vx[10, 10] 2388 assert r1.shape == t1.shape 2389 assert np.all(t1 == r1) 2390 2391 f2 = theano.function([x, a], x[50, a]) 2392 r2 = f2(vx, m) 2393 t2 = vx[50, m] 2394 assert r2.shape == t2.shape 2395 assert np.all(t2 == r2) 2396 2397 f3 = theano.function([x, a], x[a, 50]) 2398 r3 = f3(vx, m) 2399 t3 = vx[m, 50] 2400 assert r3.shape == t3.shape 2401 assert np.all(t3 == r3) 2402 2403 f4 = theano.function([x], x[50, 42]) 2404 r4 = f4(vx) 2405 t4 = vx[m, n] 2406 assert r3.shape == t3.shape 2407 assert np.all(t4 == r4) 2408 2409 # Test that is work with shared variable 2410 sx = theano.shared(vx) 2411 f1 = theano.function([a, b], sx[a, b]) 2412 r1 = f1(10, 10) 2413 t1 = vx[10, 10] 2414 assert r1.shape == t1.shape 2415 assert np.all(t1 == r1) 2416 2417 2418class CastTester(utt.InferShapeTester): 2419 def setUp(self): 2420 super(CastTester, self).setUp() 2421 2422 # slow but only test 2423 def test_cast(self): 2424 for format in sparse.sparse_formats: 2425 for i_dtype in sparse.all_dtypes: 2426 for o_dtype in sparse.all_dtypes: 2427 (variable, ), (data, ) = sparse_random_inputs( 2428 format, 2429 shape=(4, 7), 2430 out_dtype=i_dtype) 2431 2432 func = theano.function([variable], cast(variable, o_dtype)) 2433 cls = theano.function([variable], Cast(o_dtype)(variable)) 2434 prop = theano.function([variable], 2435 variable.astype(o_dtype)) 2436 2437 t_func, t_cls, t_prop = func(data), cls(data), prop(data) 2438 2439 expected = data.toarray().astype(o_dtype) 2440 2441 assert t_func.format == format 2442 assert t_cls.format == format 2443 assert t_prop.format == format 2444 2445 t_func = t_func.toarray() 2446 t_cls = t_cls.toarray() 2447 t_prop = t_prop.toarray() 2448 2449 utt.assert_allclose(expected, t_func) 2450 utt.assert_allclose(expected, t_cls) 2451 utt.assert_allclose(expected, t_prop) 2452 2453 @attr('slow') 2454 def test_infer_shape(self): 2455 for format in sparse.sparse_formats: 2456 for i_dtype in sparse.all_dtypes: 2457 for o_dtype in sparse.all_dtypes: 2458 variable, data = sparse_random_inputs( 2459 format, 2460 shape=(4, 7), 2461 out_dtype=i_dtype) 2462 self._compile_and_check(variable, 2463 [Cast(o_dtype)(*variable)], 2464 data, 2465 Cast) 2466 2467 def test_grad(self): 2468 for format in sparse.sparse_formats: 2469 for i_dtype in sparse.float_dtypes: 2470 for o_dtype in tensor.float_dtypes: 2471 if o_dtype == 'float16': 2472 # Don't test float16 output. 2473 continue 2474 _, data = sparse_random_inputs( 2475 format, 2476 shape=(4, 7), 2477 out_dtype=i_dtype) 2478 2479 eps = None 2480 if o_dtype == 'float32': 2481 eps = 1e-2 2482 2483 verify_grad_sparse(Cast(o_dtype), data, eps=eps) 2484 2485 2486def _format_info(nb): 2487 x = {} 2488 mat = {} 2489 2490 for format in sparse.sparse_formats: 2491 variable = getattr(theano.sparse, format + '_matrix') 2492 spa = getattr(sp, format + '_matrix') 2493 2494 x[format] = [variable() for t in range(nb)] 2495 mat[format] = [spa(random_lil((3, 4), theano.config.floatX, 8)) 2496 for t in range(nb)] 2497 return x, mat 2498 2499 2500class _HVStackTester(utt.InferShapeTester): 2501 """ 2502 Test for both HStack and VStack. 2503 """ 2504 nb = 3 # Number of sparse matrix to stack 2505 x, mat = _format_info(nb) 2506 2507 def test_op(self): 2508 for format in sparse.sparse_formats: 2509 for out_f in sparse.sparse_formats: 2510 for dtype in sparse.all_dtypes: 2511 blocks = self.mat[format] 2512 2513 f = theano.function( 2514 self.x[format], 2515 self.op_class( 2516 format=out_f, dtype=dtype)(*self.x[format]), 2517 allow_input_downcast=True) 2518 2519 tested = f(*blocks) 2520 expected = self.expected_f(blocks, 2521 format=out_f, 2522 dtype=dtype) 2523 2524 utt.assert_allclose(expected.toarray(), tested.toarray()) 2525 assert tested.format == expected.format 2526 assert tested.dtype == expected.dtype 2527 2528 def test_infer_shape(self): 2529 for format in sparse.sparse_formats: 2530 self._compile_and_check(self.x[format], 2531 [self.op_class(dtype='float64') 2532 (*self.x[format])], 2533 self.mat[format], 2534 self.op_class) 2535 2536 def test_grad(self): 2537 for format in sparse.sparse_formats: 2538 for out_f in sparse.sparse_formats: 2539 for dtype in sparse.float_dtypes: 2540 verify_grad_sparse( 2541 self.op_class(format=out_f, dtype=dtype), 2542 self.mat[format], 2543 structured=False, 2544 eps=1e-2, 2545 ) 2546 2547 2548def _hv_switch(op, expected_function): 2549 """ 2550 Return the right test class for HStack or VStack. 2551 2552 :Parameters: 2553 - `op`: HStack or VStack class. 2554 - `expected_function`: function from scipy for comparaison. 2555 """ 2556 2557 class XStackTester(_HVStackTester): 2558 op_class = op 2559 2560 def expected_f(self, a, format=None, dtype=None): 2561 return expected_function(a, format, dtype) 2562 XStackTester.__name__ = op.__name__ + "Tester" 2563 if hasattr(XStackTester, '__qualname__'): 2564 XStackTester.__qualname__ = XStackTester.__name__ 2565 return XStackTester 2566 2567HStackTester = _hv_switch(HStack, sp.hstack) 2568VStackTester = _hv_switch(VStack, sp.vstack) 2569 2570 2571class AddSSDataTester(utt.InferShapeTester): 2572 x = {} 2573 a = {} 2574 2575 def setUp(self): 2576 super(AddSSDataTester, self).setUp() 2577 self.op_class = AddSSData 2578 2579 for format in sparse.sparse_formats: 2580 variable = getattr(theano.sparse, format + '_matrix') 2581 2582 rand = np.array( 2583 np.random.randint(1, 4, size=(3, 4)) - 1, 2584 dtype=theano.config.floatX) 2585 constant = as_sparse_format(rand, format) 2586 2587 self.x[format] = [variable() for t in range(2)] 2588 self.a[format] = [constant for t in range(2)] 2589 2590 def test_op(self): 2591 for format in sparse.sparse_formats: 2592 f = theano.function( 2593 self.x[format], 2594 add_s_s_data(*self.x[format])) 2595 2596 tested = f(*self.a[format]) 2597 expected = 2 * self.a[format][0] 2598 2599 utt.assert_allclose(expected.toarray(), tested.toarray()) 2600 assert tested.format == expected.format 2601 assert tested.dtype == expected.dtype 2602 2603 def test_infer_shape(self): 2604 for format in sparse.sparse_formats: 2605 self._compile_and_check(self.x[format], 2606 [add_s_s_data(*self.x[format])], 2607 self.a[format], 2608 self.op_class) 2609 2610 def test_grad(self): 2611 for format in sparse.sparse_formats: 2612 verify_grad_sparse(self.op_class(), 2613 self.a[format], 2614 structured=True) 2615 2616 2617def elemwise_checker(op, expected_f, gap=None, test_dtypes=None, 2618 grad_test=True, name=None, gap_grad=None): 2619 """ 2620 Return the appropriate test class for the elemwise on sparse. 2621 2622 :param op: Op to test. 2623 :expected_f: Function use to compare. This function must act 2624 on dense matrix. If the op is structured 2625 see the `structure_function` decorator to make 2626 this function structured. 2627 :param gap: Tuple for the range of the random sample. When 2628 length is 1, it is assumed to be the exclusive 2629 max, when `gap` = (`a`, `b`) it provide a sample 2630 from [a, b[. If `None` is used, it provide [0, 1] 2631 for float dtypes and [0, 50[ for integer dtypes. 2632 :param test_dtypes: Particular dtypes for testing the op. 2633 If `None`, this is set to the most common 2634 dtypes. 2635 :param grad_test: True for testing the grad. False will 2636 skip this test. 2637 :param gap_grad: If None, we reuse gap. Otherwise it is the same as gap 2638 but for testing the gradiant of the op. 2639 2640 :return: The class that perform the tests, not an instance 2641 of the class. 2642 """ 2643 2644 if test_dtypes is None: 2645 test_dtypes = sparse.all_dtypes 2646 2647 class Tester(unittest.TestCase): 2648 2649 def setUp(self): 2650 super(Tester, self).setUp() 2651 self.op = op 2652 self.expected_f = expected_f 2653 self.gap = gap 2654 if gap_grad is not None: 2655 self.gap_grad = gap_grad 2656 else: 2657 self.gap_grad = gap 2658 # Ensure the test's name is correct. 2659 utt.seed_rng() 2660 assert eval(self.__class__.__name__) is self.__class__ 2661 2662 def test_op(self): 2663 for format in sparse.sparse_formats: 2664 for dtype in test_dtypes: 2665 if dtype == 'int8' or dtype == 'uint8': 2666 continue 2667 2668 # When testing with unsigned integers, 2669 # we must check if the gap contains 2670 # negative numbers. 2671 if dtype.startswith('uint'): 2672 if self.gap and len(self.gap) == 2 and self.gap[0] < 0: 2673 if self.gap[1] >= 1: 2674 self.gap = (0, self.gap[1]) 2675 else: 2676 raise TypeError('Gap not suitable for', 2677 dtype, self.__name__) 2678 2679 variable, data = sparse_random_inputs( 2680 format, 2681 shape=(4, 7), 2682 out_dtype=dtype, 2683 gap=self.gap) 2684 2685 f = theano.function(variable, self.op(*variable)) 2686 2687 tested = f(*data) 2688 data = [m.toarray() for m in data] 2689 expected = self.expected_f(*data) 2690 2691 assert tested.format == format 2692 tested = tested.toarray() 2693 2694 try: 2695 utt.assert_allclose(expected, tested) 2696 except AssertionError: 2697 raise AssertionError(self.__name__) 2698 2699 # Test with int8 as dtype 2700 # These tests are not in the loop for two reasons. 2701 # First, in recent version of numpy, when a numpy 2702 # function have int8 as input dtype, it returns a 2703 # float16 as output dtype. Since this does not provide 2704 # enough precision, we upcast the data before we apply the 2705 # function. 2706 # Second, the tolerance for the checkup in DebugMode 2707 # is too high. 2708 for dtype in ['int8', 'uint8']: 2709 if dtype in test_dtypes: 2710 if self.gap: 2711 domain = self.gap 2712 # When testing with unsigned integers, 2713 # we must check if the gap contains 2714 # negative numbers. 2715 if dtype == 'uint8': 2716 if len(domain) == 2 and domain[0] < 0: 2717 if domain[1] >= 1: 2718 domain = (0, domain[1]) 2719 else: 2720 raise TypeError('Gap not suitable for', 2721 dtype, self.__name__) 2722 2723 else: 2724 domain = (0, 5) 2725 2726 variable, data = sparse_random_inputs( 2727 format, 2728 shape=(4, 7), 2729 out_dtype=dtype, 2730 gap=domain) 2731 2732 f = theano.function(variable, self.op(*variable)) 2733 2734 old_value = (tensor.basic.float32_atol, 2735 tensor.basic.float32_rtol, 2736 tensor.basic.float64_atol, 2737 tensor.basic.float64_rtol) 2738 tensor.basic.float32_atol = 1e-4 2739 tensor.basic.float32_rtol = 1e-3 2740 tensor.basic.float64_atol = 1e-3 2741 tensor.basic.float64_rtol = 1e-4 2742 try: 2743 tested = f(*data) 2744 finally: 2745 (tensor.basic.float32_atol, 2746 tensor.basic.float32_rtol, 2747 tensor.basic.float64_atol, 2748 tensor.basic.float64_rtol) = old_value 2749 2750 data = [m.toarray().astype('float32') for m in data] 2751 expected = self.expected_f(*data) 2752 2753 assert tested.format == format 2754 tested = tested.toarray() 2755 2756 try: 2757 utt.assert_allclose(tested, expected, rtol=1e-2) 2758 except AssertionError: 2759 raise AssertionError(self.__name__) 2760 2761 if grad_test: 2762 def test_grad(self): 2763 for format in sparse.sparse_formats: 2764 for dtype in sparse.float_dtypes: 2765 variable, data = sparse_random_inputs( 2766 format, 2767 shape=(4, 7), 2768 out_dtype=dtype, 2769 gap=self.gap_grad) 2770 2771 verify_grad_sparse(self.op, 2772 data, 2773 structured=True) 2774 2775 # Set proper class name to uniquely identify tests. 2776 # Note that it is important to run this code *outside* of the `Tester` 2777 # class itself, otherwise it will not work properly for some reason. 2778 if name is None: 2779 name = op.__name__.capitalize() + 'Tester' 2780 Tester.__name__ = name 2781 if hasattr(Tester, '__qualname__'): 2782 Tester.__qualname__ = name 2783 assert 'Roundhalftoeven' not in Tester.__name__ 2784 2785 return Tester 2786 2787 2788def test_hstack_vstack(): 2789 # Tests sparse.hstack and sparse.vstack (as opposed to the HStack and VStack 2790 # classes that they wrap). 2791 2792 def make_block(dtype): 2793 return theano.sparse.csr_matrix(name="%s block" % dtype, 2794 dtype=dtype) 2795 2796 def get_expected_dtype(blocks, to_dtype): 2797 if to_dtype is None: 2798 block_dtypes = tuple(b.dtype for b in blocks) 2799 return theano.scalar.upcast(*block_dtypes) 2800 else: 2801 return to_dtype 2802 2803 # a deliberately weird mix of dtypes to stack 2804 dtypes = ('complex128', theano.config.floatX) 2805 2806 blocks = [make_block(dtype) for dtype in dtypes] 2807 2808 for stack_dimension, stack_function in enumerate((theano.sparse.vstack, 2809 theano.sparse.hstack)): 2810 2811 for to_dtype in (None, ) + dtypes: 2812 stacked_blocks = stack_function(blocks, dtype=to_dtype) 2813 expected_dtype = get_expected_dtype(blocks, to_dtype) 2814 assert stacked_blocks.dtype == expected_dtype 2815 2816 2817def structure_function(f, index=0): 2818 """ 2819 Decorator to structure a function which 2820 apply on dense matrix. 2821 2822 Here, the inputs of the function must be 2823 dense matrix. The sparse pattern is 2824 determined by finding the zeros. 2825 2826 :param index: The index of the parameter 2827 from which the function must 2828 be structured. 2829 2830 :return: The structured function for its 2831 `index` parameter. 2832 """ 2833 2834 def structured_function(*args): 2835 pattern = args[index] 2836 evaluated = f(*args) 2837 evaluated[pattern == 0] = 0 2838 return evaluated 2839 return structured_function 2840 2841StructuredSigmoidTester = elemwise_checker( 2842 sparse.structured_sigmoid, 2843 structure_function(lambda x: 1.0 / (1.0 + np.exp(-x))), 2844 test_dtypes=[m for m in sparse.all_dtypes 2845 if (not m in sparse.complex_dtypes and 2846 not m.startswith('uint'))], 2847 gap=(-5, 5), 2848 name='StructuredSigmoidTester') 2849 2850StructuredExpTester = elemwise_checker( 2851 sparse.structured_exp, 2852 structure_function(np.exp), 2853 name='StructuredExpTester') 2854 2855StructuredLogTester = elemwise_checker( 2856 sparse.structured_log, 2857 structure_function(np.log), 2858 gap=(0.5, 10), 2859 name='StructuredLogTester') 2860 2861StructuredPowTester = elemwise_checker( 2862 lambda x: sparse.structured_pow(x, 2), 2863 structure_function(lambda x: np.power(x, 2)), 2864 name='StructuredPowTester') 2865 2866StructuredMinimumTester = elemwise_checker( 2867 lambda x: structured_minimum(x, 2), 2868 structure_function(lambda x: np.minimum(x, 2)), 2869 name='StructuredMinimumTester') 2870 2871StructuredMaximumTester = elemwise_checker( 2872 lambda x: structured_maximum(x, 2), 2873 structure_function(lambda x: np.maximum(x, 2)), 2874 name='StructuredMaximumTester') 2875 2876StructuredAddTester = elemwise_checker( 2877 lambda x: structured_add(x, 2), 2878 structure_function(lambda x: np.add(x, 2)), 2879 name='StructuredAddTester') 2880 2881SinTester = elemwise_checker( 2882 sparse.sin, 2883 np.sin) 2884 2885TanTester = elemwise_checker( 2886 sparse.tan, 2887 np.tan, 2888 gap=(-1, 1)) 2889 2890ArcsinTester = elemwise_checker( 2891 sparse.arcsin, 2892 np.arcsin, 2893 gap=(-1, 1), 2894 gap_grad=(-0.99, 0.99)) 2895 2896ArctanTester = elemwise_checker( 2897 sparse.arctan, 2898 np.arctan) 2899 2900SinhTester = elemwise_checker( 2901 sparse.sinh, 2902 np.sinh) 2903 2904ArcsinhTester = elemwise_checker( 2905 sparse.arcsinh, 2906 np.arcsinh, 2907 gap=(-1, 1)) 2908 2909TanhTester = elemwise_checker( 2910 sparse.tanh, 2911 np.tanh, 2912 gap=(-1, 1)) 2913 2914ArctanhTester = elemwise_checker( 2915 sparse.arctanh, 2916 np.arctanh, 2917 gap=(-0.9, 1), 2918 gap_grad=(-0.9, 0.95)) 2919 2920RintTester = elemwise_checker( 2921 sparse.rint, 2922 np.rint, 2923 grad_test=False, 2924 test_dtypes=sparse.float_dtypes) 2925 2926SgnTester = elemwise_checker( 2927 sparse.sgn, 2928 np.sign, 2929 grad_test=False, 2930 test_dtypes=[m for m in sparse.all_dtypes 2931 if (not m in sparse.complex_dtypes and 2932 not m.startswith('uint'))]) 2933 2934CeilTester = elemwise_checker( 2935 sparse.ceil, 2936 np.ceil, 2937 grad_test=False, 2938 test_dtypes=[m for m in sparse.all_dtypes 2939 if not m in sparse.complex_dtypes]) 2940 2941FloorTester = elemwise_checker( 2942 sparse.floor, 2943 np.floor, 2944 grad_test=False, 2945 test_dtypes=[m for m in sparse.all_dtypes 2946 if not m in sparse.complex_dtypes]) 2947 2948Log1pTester = elemwise_checker( 2949 sparse.log1p, 2950 np.log1p, 2951 gap=(0.5, 10)) 2952 2953Expm1Tester = elemwise_checker( 2954 sparse.expm1, 2955 np.expm1) 2956 2957Deg2radTester = elemwise_checker( 2958 sparse.deg2rad, 2959 np.deg2rad, 2960 test_dtypes=[m for m in sparse.all_dtypes 2961 if not m in sparse.complex_dtypes]) 2962 2963Rad2degTester = elemwise_checker( 2964 sparse.rad2deg, 2965 np.rad2deg, 2966 test_dtypes=[m for m in sparse.all_dtypes 2967 if not m in sparse.complex_dtypes]) 2968 2969 2970TruncTester = elemwise_checker( 2971 sparse.trunc, 2972 np.trunc, 2973 test_dtypes=[m for m in sparse.all_dtypes 2974 if not m in sparse.complex_dtypes], 2975 grad_test=False) 2976 2977 2978SqrTester = elemwise_checker( 2979 sparse.sqr, 2980 lambda x: x * x) 2981 2982SqrtTester = elemwise_checker( 2983 sparse.sqrt, 2984 np.sqrt, 2985 gap=(0, 10)) 2986 2987ConjTester = elemwise_checker( 2988 sparse.conj, 2989 np.conj, 2990 grad_test=False) 2991 2992 2993class MulSVTester(unittest.TestCase): 2994 def setUp(self): 2995 utt.seed_rng() 2996 2997 def test_mul_s_v_grad(self): 2998 sp_types = {'csc': sp.csc_matrix, 2999 'csr': sp.csr_matrix} 3000 3001 for format in ['csr', 'csc']: 3002 for dtype in ['float32', 'float64']: 3003 spmat = sp_types[format](random_lil((4, 3), dtype, 3)) 3004 mat = np.asarray(np.random.rand(3), dtype=dtype) 3005 3006 verify_grad_sparse(mul_s_v, 3007 [spmat, mat], 3008 structured=True) 3009 3010 def test_mul_s_v(self): 3011 sp_types = {'csc': sp.csc_matrix, 3012 'csr': sp.csr_matrix} 3013 3014 for format in ['csr', 'csc']: 3015 for dtype in ['float32', 'float64']: 3016 x = theano.sparse.SparseType(format, dtype=dtype)() 3017 y = tensor.vector(dtype=dtype) 3018 f = theano.function([x, y], mul_s_v(x, y)) 3019 3020 spmat = sp_types[format](random_lil((4, 3), dtype, 3)) 3021 mat = np.asarray(np.random.rand(3), dtype=dtype) 3022 3023 out = f(spmat, mat) 3024 3025 utt.assert_allclose(spmat.toarray() * mat, out.toarray()) 3026 3027 3028class StructuredAddSVTester(unittest.TestCase): 3029 def setUp(self): 3030 utt.seed_rng() 3031 3032 def test_structured_add_s_v_grad(self): 3033 sp_types = {'csc': sp.csc_matrix, 3034 'csr': sp.csr_matrix} 3035 3036 for format in ['csr', 'csc']: 3037 for dtype in ['float32', 'float64']: 3038 spmat = sp_types[format](random_lil((4, 3), dtype, 3)) 3039 mat = np.asarray(np.random.rand(3), dtype=dtype) 3040 3041 verify_grad_sparse(structured_add_s_v, 3042 [spmat, mat], 3043 structured=True) 3044 3045 def test_structured_add_s_v(self): 3046 sp_types = {'csc': sp.csc_matrix, 3047 'csr': sp.csr_matrix} 3048 3049 for format in ['csr', 'csc']: 3050 for dtype in ['float32', 'float64']: 3051 x = theano.sparse.SparseType(format, dtype=dtype)() 3052 y = tensor.vector(dtype=dtype) 3053 f = theano.function([x, y], structured_add_s_v(x, y)) 3054 3055 spmat = sp_types[format](random_lil((4, 3), dtype, 3)) 3056 spones = spmat.copy() 3057 spones.data = np.ones_like(spones.data) 3058 mat = np.asarray(np.random.rand(3), dtype=dtype) 3059 3060 out = f(spmat, mat) 3061 3062 utt.assert_allclose(as_ndarray(spones.multiply(spmat + mat)), 3063 out.toarray()) 3064 3065 3066class TrueDotTester(utt.InferShapeTester): 3067 def setUp(self): 3068 super(TrueDotTester, self).setUp() 3069 self.op = true_dot 3070 self.op_class = TrueDot 3071 3072 def test_op_ss(self): 3073 for format in sparse.sparse_formats: 3074 for dtype in sparse.all_dtypes: 3075 variable, data = sparse_random_inputs(format, 3076 shape=(10, 10), 3077 out_dtype=dtype, 3078 n=2, 3079 p=0.1) 3080 3081 f = theano.function(variable, self.op(*variable)) 3082 3083 tested = f(*data) 3084 3085 x, y = [m.toarray() for m in data] 3086 expected = np.dot(x, y) 3087 3088 assert tested.format == format 3089 assert tested.dtype == expected.dtype 3090 tested = tested.toarray() 3091 utt.assert_allclose(tested, expected) 3092 3093 def test_op_sd(self): 3094 for format in sparse.sparse_formats: 3095 for dtype in sparse.all_dtypes: 3096 variable, data = sparse_random_inputs(format, 3097 shape=(10, 10), 3098 out_dtype=dtype, 3099 n=2, 3100 p=0.1) 3101 variable[1] = tensor.TensorType(dtype=dtype, 3102 broadcastable=(False, False))() 3103 data[1] = data[1].toarray() 3104 3105 f = theano.function(variable, self.op(*variable)) 3106 3107 tested = f(*data) 3108 expected = np.dot(data[0].toarray(), data[1]) 3109 3110 assert tested.format == format 3111 assert tested.dtype == expected.dtype 3112 tested = tested.toarray() 3113 utt.assert_allclose(tested, expected) 3114 3115 def test_infer_shape(self): 3116 for format in sparse.sparse_formats: 3117 for dtype in sparse.all_dtypes: 3118 (x, ), (x_value, ) = sparse_random_inputs(format, 3119 shape=(9, 10), 3120 out_dtype=dtype, 3121 p=0.1) 3122 (y, ), (y_value, ) = sparse_random_inputs(format, 3123 shape=(10, 24), 3124 out_dtype=dtype, 3125 p=0.1) 3126 variable = [x, y] 3127 data = [x_value, y_value] 3128 self._compile_and_check(variable, 3129 [self.op(*variable)], 3130 data, 3131 self.op_class) 3132 3133 def test_grad(self): 3134 for format in sparse.sparse_formats: 3135 for dtype in sparse.float_dtypes: 3136 (x, ), (x_value, ) = sparse_random_inputs(format, 3137 shape=(9, 10), 3138 out_dtype=dtype, 3139 p=0.1) 3140 (y, ), (y_value, ) = sparse_random_inputs(format, 3141 shape=(10, 24), 3142 out_dtype=dtype, 3143 p=0.1) 3144 variable = [x, y] 3145 data = [x_value, y_value] 3146 verify_grad_sparse( 3147 self.op, 3148 data, 3149 structured=False) 3150 3151 3152class SamplingDotTester(utt.InferShapeTester): 3153 x = [tensor.matrix() for t in range(2)] 3154 x.append(sparse.csr_matrix()) 3155 # unsquare shape 3156 a = [np.array(np.random.randint(1, 6, size=(4, 3)) - 1, 3157 dtype=theano.config.floatX), 3158 np.array(np.random.randint(1, 6, size=(5, 3)) - 1, 3159 dtype=theano.config.floatX), 3160 np.array(np.random.randint(1, 3, size=(4, 5)) - 1, 3161 dtype=theano.config.floatX) 3162 ] 3163 a[2] = sp.csr_matrix(a[2]) 3164 3165 def setUp(self): 3166 super(SamplingDotTester, self).setUp() 3167 self.op_class = SamplingDot 3168 3169 def test_op(self): 3170 f = theano.function( 3171 self.x, 3172 sampling_dot(*self.x)) 3173 3174 tested = f(*self.a) 3175 x, y, p = self.a 3176 expected = p.multiply(np.dot(x, y.T)) 3177 3178 utt.assert_allclose(as_ndarray(expected), tested.toarray()) 3179 assert tested.format == 'csr' 3180 assert tested.dtype == expected.dtype 3181 3182 def test_negative_stride(self): 3183 f = theano.function( 3184 self.x, 3185 sampling_dot(*self.x)) 3186 3187 a2 = [self.a[0][::-1,:], self.a[1][:,::-1], self.a[2]] 3188 tested = f(*a2) 3189 x, y, p = a2 3190 expected = p.multiply(np.dot(x, y.T)) 3191 3192 utt.assert_allclose(as_ndarray(expected), tested.toarray()) 3193 assert tested.format == 'csr' 3194 assert tested.dtype == expected.dtype 3195 3196 def test_infer_shape(self): 3197 self._compile_and_check(self.x, 3198 [sampling_dot(*self.x)], 3199 self.a, 3200 self.op_class, 3201 excluding=['local_sampling_dot_csr']) 3202 3203 def test_grad(self): 3204 def _helper(x, y): 3205 return sampling_dot(x, y, self.a[2]) 3206 verify_grad_sparse(_helper, self.a[:2]) 3207 3208 3209import theano.tensor.tests.test_sharedvar 3210@theano.tensor.tests.test_sharedvar.makeSharedTester( 3211 shared_constructor_=theano.sparse.shared, 3212 dtype_='float64', 3213 get_value_borrow_true_alias_=True, 3214 shared_borrow_true_alias_=True, 3215 set_value_borrow_true_alias_=True, 3216 set_value_inplace_=False, 3217 set_cast_value_inplace_=False, 3218 shared_constructor_accept_ndarray_=False, 3219 internal_type_=scipy.sparse.csc_matrix, 3220 test_internal_type_=scipy.sparse.issparse, 3221 theano_fct_=lambda a: dense_from_sparse(a * 2.), 3222 ref_fct_=lambda a: np.asarray((a * 2).todense()), 3223 cast_value_=scipy.sparse.csr_matrix, 3224 expect_fail_fast_shape_inplace=False, 3225) 3226class test_shared_options(object): 3227 pass 3228 3229 3230if __name__ == '__main__': 3231 unittest.main() 3232