test_sparse_utils_op.py 19.9 KB
Newer Older
1
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2
#
3 4 5
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
6
#
7
#     http://www.apache.org/licenses/LICENSE-2.0
8
#
9 10 11 12 13 14 15 16 17 18
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function
import unittest
import numpy as np
import paddle
19
import paddle.fluid as fluid
20
import paddle.fluid.core as core
21 22
from paddle.fluid.framework import _test_eager_guard

23 24
devices = ['cpu', 'gpu']

25

26
class TestSparseCreate(unittest.TestCase):
27

28
    def test_create_coo_by_tensor(self):
29
        with _test_eager_guard():
30 31
            indices = [[0, 0, 1, 2, 2], [1, 3, 2, 0, 1]]
            values = [1, 2, 3, 4, 5]
32
            dense_shape = [3, 4]
33 34
            dense_indices = paddle.to_tensor(indices)
            dense_elements = paddle.to_tensor(values, dtype='float32')
35 36 37 38
            coo = paddle.sparse.sparse_coo_tensor(dense_indices,
                                                  dense_elements,
                                                  dense_shape,
                                                  stop_gradient=False)
39
            # test the to_string.py
40 41
            assert np.array_equal(indices, coo.indices().numpy())
            assert np.array_equal(values, coo.values().numpy())
42

43 44 45 46
    def test_create_coo_by_np(self):
        with _test_eager_guard():
            indices = [[0, 1, 2], [1, 2, 0]]
            values = [1.0, 2.0, 3.0]
47
            dense_shape = [3, 3]
48
            coo = paddle.sparse.sparse_coo_tensor(indices, values, dense_shape)
49
            assert np.array_equal(3, coo.nnz())
50 51
            assert np.array_equal(indices, coo.indices().numpy())
            assert np.array_equal(values, coo.values().numpy())
52

53
    def test_create_csr_by_tensor(self):
54
        with _test_eager_guard():
55 56 57
            crows = [0, 2, 3, 5]
            cols = [1, 3, 2, 0, 1]
            values = [1, 2, 3, 4, 5]
58
            dense_shape = [3, 4]
59 60 61
            dense_crows = paddle.to_tensor(crows)
            dense_cols = paddle.to_tensor(cols)
            dense_elements = paddle.to_tensor(values, dtype='float32')
62
            stop_gradient = False
63 64 65 66 67
            csr = paddle.sparse.sparse_csr_tensor(dense_crows,
                                                  dense_cols,
                                                  dense_elements,
                                                  dense_shape,
                                                  stop_gradient=stop_gradient)
68

69 70 71 72 73 74
    def test_create_csr_by_np(self):
        with _test_eager_guard():
            crows = [0, 2, 3, 5]
            cols = [1, 3, 2, 0, 1]
            values = [1, 2, 3, 4, 5]
            dense_shape = [3, 4]
75 76
            csr = paddle.sparse.sparse_csr_tensor(crows, cols, values,
                                                  dense_shape)
77
            # test the to_string.py
78
            assert np.array_equal(5, csr.nnz())
79 80 81
            assert np.array_equal(crows, csr.crows().numpy())
            assert np.array_equal(cols, csr.cols().numpy())
            assert np.array_equal(values, csr.values().numpy())
82 83 84 85 86 87 88

    def test_place(self):
        with _test_eager_guard():
            place = core.CPUPlace()
            indices = [[0, 1], [0, 1]]
            values = [1.0, 2.0]
            dense_shape = [2, 2]
89 90 91 92
            coo = paddle.sparse.sparse_coo_tensor(indices,
                                                  values,
                                                  dense_shape,
                                                  place=place)
93
            assert coo.place.is_cpu_place()
94 95
            assert coo.values().place.is_cpu_place()
            assert coo.indices().place.is_cpu_place()
96 97 98 99

            crows = [0, 2, 3, 5]
            cols = [1, 3, 2, 0, 1]
            values = [1.0, 2.0, 3.0, 4.0, 5.0]
100 101 102 103
            csr = paddle.sparse.sparse_csr_tensor(crows,
                                                  cols,
                                                  values, [3, 5],
                                                  place=place)
104
            assert csr.place.is_cpu_place()
105 106 107
            assert csr.crows().place.is_cpu_place()
            assert csr.cols().place.is_cpu_place()
            assert csr.values().place.is_cpu_place()
108 109 110 111 112 113 114 115

    def test_dtype(self):
        with _test_eager_guard():
            indices = [[0, 1], [0, 1]]
            values = [1.0, 2.0]
            dense_shape = [2, 2]
            indices = paddle.to_tensor(indices, dtype='int32')
            values = paddle.to_tensor(values, dtype='float32')
116 117 118 119
            coo = paddle.sparse.sparse_coo_tensor(indices,
                                                  values,
                                                  dense_shape,
                                                  dtype='float64')
120 121 122 123 124
            assert coo.dtype == paddle.float64

            crows = [0, 2, 3, 5]
            cols = [1, 3, 2, 0, 1]
            values = [1.0, 2.0, 3.0, 4.0, 5.0]
125 126 127 128
            csr = paddle.sparse.sparse_csr_tensor(crows,
                                                  cols,
                                                  values, [3, 5],
                                                  dtype='float16')
129 130 131 132 133 134 135 136
            assert csr.dtype == paddle.float16

    def test_create_coo_no_shape(self):
        with _test_eager_guard():
            indices = [[0, 1], [0, 1]]
            values = [1.0, 2.0]
            indices = paddle.to_tensor(indices, dtype='int32')
            values = paddle.to_tensor(values, dtype='float32')
137
            coo = paddle.sparse.sparse_coo_tensor(indices, values)
138 139 140 141
            assert [2, 2] == coo.shape


class TestSparseConvert(unittest.TestCase):
142

143 144 145
    def test_to_sparse_coo(self):
        with _test_eager_guard():
            x = [[0, 1, 0, 2], [0, 0, 3, 0], [4, 5, 0, 0]]
146 147 148
            indices = [[0, 0, 1, 2, 2], [1, 3, 2, 0, 1]]
            values = [1.0, 2.0, 3.0, 4.0, 5.0]
            dense_x = paddle.to_tensor(x, dtype='float32', stop_gradient=False)
149
            out = dense_x.to_sparse_coo(2)
150 151 152 153 154
            assert np.array_equal(out.indices().numpy(), indices)
            assert np.array_equal(out.values().numpy(), values)
            #test to_sparse_coo_grad backward
            out_grad_indices = [[0, 1], [0, 1]]
            out_grad_values = [2.0, 3.0]
155
            out_grad = paddle.sparse.sparse_coo_tensor(
156
                paddle.to_tensor(out_grad_indices),
157 158 159
                paddle.to_tensor(out_grad_values),
                shape=out.shape,
                stop_gradient=True)
160 161 162 163 164
            out.backward(out_grad)
            assert np.array_equal(dense_x.grad.numpy(),
                                  out_grad.to_dense().numpy())

    def test_coo_to_dense(self):
165
        fluid.set_flags({"FLAGS_retain_grad_for_all_tensor": True})
166 167 168
        with _test_eager_guard():
            indices = [[0, 0, 1, 2, 2], [1, 3, 2, 0, 1]]
            values = [1.0, 2.0, 3.0, 4.0, 5.0]
169 170
            indices_dtypes = ['int32', 'int64']
            for indices_dtype in indices_dtypes:
171
                sparse_x = paddle.sparse.sparse_coo_tensor(
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
                    paddle.to_tensor(indices, dtype=indices_dtype),
                    paddle.to_tensor(values),
                    shape=[3, 4],
                    stop_gradient=False)
                dense_tensor = sparse_x.to_dense()
                #test to_dense_grad backward
                out_grad = [[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0],
                            [9.0, 10.0, 11.0, 12.0]]
                dense_tensor.backward(paddle.to_tensor(out_grad))
                #mask the out_grad by sparse_x.indices()
                correct_x_grad = [2.0, 4.0, 7.0, 9.0, 10.0]
                assert np.array_equal(correct_x_grad,
                                      sparse_x.grad.values().numpy())

                paddle.device.set_device("cpu")
187
                sparse_x_cpu = paddle.sparse.sparse_coo_tensor(
188 189 190 191 192 193 194 195
                    paddle.to_tensor(indices, dtype=indices_dtype),
                    paddle.to_tensor(values),
                    shape=[3, 4],
                    stop_gradient=False)
                dense_tensor_cpu = sparse_x_cpu.to_dense()
                dense_tensor_cpu.backward(paddle.to_tensor(out_grad))
                assert np.array_equal(correct_x_grad,
                                      sparse_x_cpu.grad.values().numpy())
196
        fluid.set_flags({"FLAGS_retain_grad_for_all_tensor": False})
197

198 199 200
    def test_to_sparse_csr(self):
        with _test_eager_guard():
            x = [[0, 1, 0, 2], [0, 0, 3, 0], [4, 5, 0, 0]]
201 202 203
            crows = [0, 2, 3, 5]
            cols = [1, 3, 2, 0, 1]
            values = [1, 2, 3, 4, 5]
204
            dense_x = paddle.to_tensor(x)
205
            out = dense_x.to_sparse_csr()
206 207 208
            assert np.array_equal(out.crows().numpy(), crows)
            assert np.array_equal(out.cols().numpy(), cols)
            assert np.array_equal(out.values().numpy(), values)
209

210
            dense_tensor = out.to_dense()
211 212
            assert np.array_equal(dense_tensor.numpy(), x)

213
    def test_coo_values_grad(self):
214
        fluid.set_flags({"FLAGS_retain_grad_for_all_tensor": True})
215 216 217
        with _test_eager_guard():
            indices = [[0, 0, 1, 2, 2], [1, 3, 2, 0, 1]]
            values = [1.0, 2.0, 3.0, 4.0, 5.0]
218
            sparse_x = paddle.sparse.sparse_coo_tensor(
219
                paddle.to_tensor(indices),
220 221 222
                paddle.to_tensor(values),
                shape=[3, 4],
                stop_gradient=False)
223 224 225 226 227
            values_tensor = sparse_x.values()
            out_grad = [2.0, 3.0, 5.0, 8.0, 9.0]
            # test coo_values_grad
            values_tensor.backward(paddle.to_tensor(out_grad))
            assert np.array_equal(out_grad, sparse_x.grad.values().numpy())
228 229 230
            indices = [[0, 0, 1, 2, 2], [1, 3, 2, 0, 1]]
            values = [[1.0, 1.0], [2.0, 2.0], [3.0, 3.0], [4.0, 4.0],
                      [5.0, 5.0]]
231
            sparse_x = paddle.sparse.sparse_coo_tensor(
232 233 234 235 236 237 238 239 240 241
                paddle.to_tensor(indices),
                paddle.to_tensor(values),
                shape=[3, 4, 2],
                stop_gradient=False)
            values_tensor = sparse_x.values()
            out_grad = [[2.0, 2.0], [3.0, 3.0], [5.0, 5.0], [8.0, 8.0],
                        [9.0, 9.0]]
            # test coo_values_grad
            values_tensor.backward(paddle.to_tensor(out_grad))
            assert np.array_equal(out_grad, sparse_x.grad.values().numpy())
242
        fluid.set_flags({"FLAGS_retain_grad_for_all_tensor": False})
243

244 245
    def test_sparse_coo_tensor_grad(self):
        with _test_eager_guard():
246
            for device in devices:
247 248
                if device == 'cpu' or (device == 'gpu'
                                       and paddle.is_compiled_with_cuda()):
249 250 251 252
                    paddle.device.set_device(device)
                    indices = [[0, 1], [0, 1]]
                    values = [1, 2]
                    indices = paddle.to_tensor(indices, dtype='int32')
253 254 255
                    values = paddle.to_tensor(values,
                                              dtype='float32',
                                              stop_gradient=False)
256
                    sparse_x = paddle.sparse.sparse_coo_tensor(
257 258 259 260 261
                        indices, values, shape=[2, 2], stop_gradient=False)
                    grad_indices = [[0, 1], [1, 1]]
                    grad_values = [2, 3]
                    grad_indices = paddle.to_tensor(grad_indices, dtype='int32')
                    grad_values = paddle.to_tensor(grad_values, dtype='float32')
262
                    sparse_out_grad = paddle.sparse.sparse_coo_tensor(
263 264 265 266 267
                        grad_indices, grad_values, shape=[2, 2])
                    sparse_x.backward(sparse_out_grad)
                    correct_values_grad = [0, 3]
                    assert np.array_equal(correct_values_grad,
                                          values.grad.numpy())
268

269 270
                    # test the non-zero values is a vector
                    values = [[1, 1], [2, 2]]
271 272 273
                    values = paddle.to_tensor(values,
                                              dtype='float32',
                                              stop_gradient=False)
274
                    sparse_x = paddle.sparse.sparse_coo_tensor(
275 276 277
                        indices, values, shape=[2, 2, 2], stop_gradient=False)
                    grad_values = [[2, 2], [3, 3]]
                    grad_values = paddle.to_tensor(grad_values, dtype='float32')
278
                    sparse_out_grad = paddle.sparse.sparse_coo_tensor(
279 280 281 282 283 284
                        grad_indices, grad_values, shape=[2, 2, 2])
                    sparse_x.backward(sparse_out_grad)
                    correct_values_grad = [[0, 0], [3, 3]]
                    assert np.array_equal(correct_values_grad,
                                          values.grad.numpy())

285 286 287
    def test_sparse_coo_tensor_sorted(self):
        with _test_eager_guard():
            for device in devices:
288 289
                if device == 'cpu' or (device == 'gpu'
                                       and paddle.is_compiled_with_cuda()):
290
                    paddle.device.set_device(device)
291
                    #test unsorted and duplicate indices
292 293 294 295
                    indices = [[1, 0, 0], [0, 1, 1]]
                    values = [1.0, 2.0, 3.0]
                    indices = paddle.to_tensor(indices, dtype='int32')
                    values = paddle.to_tensor(values, dtype='float32')
296 297
                    sparse_x = paddle.sparse.sparse_coo_tensor(indices, values)
                    sparse_x = paddle.sparse.coalesce(sparse_x)
298 299 300 301 302 303 304
                    indices_sorted = [[0, 1], [1, 0]]
                    values_sorted = [5.0, 1.0]
                    assert np.array_equal(indices_sorted,
                                          sparse_x.indices().numpy())
                    assert np.array_equal(values_sorted,
                                          sparse_x.values().numpy())

305 306 307
                    # test the non-zero values is a vector
                    values = [[1.0, 1.0], [2.0, 2.0], [3.0, 3.0]]
                    values = paddle.to_tensor(values, dtype='float32')
308 309
                    sparse_x = paddle.sparse.sparse_coo_tensor(indices, values)
                    sparse_x = paddle.sparse.coalesce(sparse_x)
310 311 312 313 314 315
                    values_sorted = [[5.0, 5.0], [1.0, 1.0]]
                    assert np.array_equal(indices_sorted,
                                          sparse_x.indices().numpy())
                    assert np.array_equal(values_sorted,
                                          sparse_x.values().numpy())

Z
zhangkaihuo 已提交
316 317
    def test_batch_csr(self):
        with _test_eager_guard():
Z
zhangkaihuo 已提交
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335

            def verify(dense_x):
                sparse_x = dense_x.to_sparse_csr()
                out = sparse_x.to_dense()
                assert np.allclose(out.numpy(), dense_x.numpy())

            shape = np.random.randint(low=1, high=10, size=3)
            shape = list(shape)
            dense_x = paddle.randn(shape)
            dense_x = paddle.nn.functional.dropout(dense_x, p=0.5)
            verify(dense_x)

            #test batchs=1
            shape[0] = 1
            dense_x = paddle.randn(shape)
            dense_x = paddle.nn.functional.dropout(dense_x, p=0.5)
            verify(dense_x)

Z
zhangkaihuo 已提交
336
            shape = np.random.randint(low=3, high=10, size=3)
Z
zhangkaihuo 已提交
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
            shape = list(shape)
            dense_x = paddle.randn(shape)
            #set the 0th batch to zero
            dense_x[0] = 0
            verify(dense_x)

            dense_x = paddle.randn(shape)
            #set the 1th batch to zero
            dense_x[1] = 0
            verify(dense_x)

            dense_x = paddle.randn(shape)
            #set the 2th batch to zero
            dense_x[2] = 0
            verify(dense_x)
Z
zhangkaihuo 已提交
352

353 354

class TestCooError(unittest.TestCase):
355

356 357 358 359 360 361 362
    def test_small_shape(self):
        with _test_eager_guard():
            with self.assertRaises(ValueError):
                indices = [[2, 3], [0, 2]]
                values = [1, 2]
                # 1. the shape too small
                dense_shape = [2, 2]
363 364 365
                sparse_x = paddle.sparse.sparse_coo_tensor(indices,
                                                           values,
                                                           shape=dense_shape)
366 367 368 369 370 371 372

    def test_same_nnz(self):
        with _test_eager_guard():
            with self.assertRaises(ValueError):
                # 2. test the nnz of indices must same as nnz of values
                indices = [[1, 2], [1, 0]]
                values = [1, 2, 3]
373
                sparse_x = paddle.sparse.sparse_coo_tensor(indices, values)
374 375 376 377 378 379 380

    def test_same_dimensions(self):
        with _test_eager_guard():
            with self.assertRaises(ValueError):
                indices = [[1, 2], [1, 0]]
                values = [1, 2, 3]
                shape = [2, 3, 4]
381 382 383
                sparse_x = paddle.sparse.sparse_coo_tensor(indices,
                                                           values,
                                                           shape=shape)
384 385 386 387 388 389

    def test_indices_dtype(self):
        with _test_eager_guard():
            with self.assertRaises(TypeError):
                indices = [[1.0, 2.0], [0, 1]]
                values = [1, 2]
390
                sparse_x = paddle.sparse.sparse_coo_tensor(indices, values)
391 392 393


class TestCsrError(unittest.TestCase):
394

395 396 397 398 399 400 401
    def test_dimension1(self):
        with _test_eager_guard():
            with self.assertRaises(ValueError):
                crows = [0, 1, 2, 3]
                cols = [0, 1, 2]
                values = [1, 2, 3]
                shape = [3]
402
                sparse_x = paddle.sparse.sparse_csr_tensor(
403
                    crows, cols, values, shape)
404 405 406 407 408 409 410 411

    def test_dimension2(self):
        with _test_eager_guard():
            with self.assertRaises(ValueError):
                crows = [0, 1, 2, 3]
                cols = [0, 1, 2]
                values = [1, 2, 3]
                shape = [3, 3, 3, 3]
412
                sparse_x = paddle.sparse.sparse_csr_tensor(
413
                    crows, cols, values, shape)
414 415 416 417 418 419 420 421

    def test_same_shape1(self):
        with _test_eager_guard():
            with self.assertRaises(ValueError):
                crows = [0, 1, 2, 3]
                cols = [0, 1, 2, 3]
                values = [1, 2, 3]
                shape = [3, 4]
422
                sparse_x = paddle.sparse.sparse_csr_tensor(
423
                    crows, cols, values, shape)
424

425 426 427 428 429 430 431
    def test_same_shape2(self):
        with _test_eager_guard():
            with self.assertRaises(ValueError):
                crows = [0, 1, 2, 3]
                cols = [0, 1, 2, 3]
                values = [1, 2, 3, 4]
                shape = [3, 4]
432
                sparse_x = paddle.sparse.sparse_csr_tensor(
433
                    crows, cols, values, shape)
434 435 436 437 438 439 440 441

    def test_same_shape3(self):
        with _test_eager_guard():
            with self.assertRaises(ValueError):
                crows = [0, 1, 2, 3, 0, 1, 2]
                cols = [0, 1, 2, 3, 0, 1, 2]
                values = [1, 2, 3, 4, 0, 1, 2]
                shape = [2, 3, 4]
442
                sparse_x = paddle.sparse.sparse_csr_tensor(
443
                    crows, cols, values, shape)
444 445 446 447 448 449 450 451

    def test_crows_first_value(self):
        with _test_eager_guard():
            with self.assertRaises(ValueError):
                crows = [1, 1, 2, 3]
                cols = [0, 1, 2]
                values = [1, 2, 3]
                shape = [3, 4]
452
                sparse_x = paddle.sparse.sparse_csr_tensor(
453
                    crows, cols, values, shape)
454 455 456 457 458 459 460 461

    def test_dtype(self):
        with _test_eager_guard():
            with self.assertRaises(TypeError):
                crows = [0, 1, 2, 3.0]
                cols = [0, 1, 2]
                values = [1, 2, 3]
                shape = [3]
462
                sparse_x = paddle.sparse.sparse_csr_tensor(
463
                    crows, cols, values, shape)
464

465 466 467

if __name__ == "__main__":
    unittest.main()