test_sparse_utils_op.py 17.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
# 
# 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
# 
#     http://www.apache.org/licenses/LICENSE-2.0
# 
# 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.core as core
20 21
from paddle.fluid.framework import _test_eager_guard

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

24

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

40 41 42 43
    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]
44
            dense_shape = [3, 3]
45 46
            coo = paddle.incubate.sparse.sparse_coo_tensor(indices, values,
                                                           dense_shape)
47 48
            assert np.array_equal(indices, coo.indices().numpy())
            assert np.array_equal(values, coo.values().numpy())
49

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

67 68 69 70 71 72
    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]
73 74
            csr = paddle.incubate.sparse.sparse_csr_tensor(crows, cols, values,
                                                           dense_shape)
75 76
            # test the to_string.py
            print(csr)
77 78 79
            assert np.array_equal(crows, csr.crows().numpy())
            assert np.array_equal(cols, csr.cols().numpy())
            assert np.array_equal(values, csr.values().numpy())
80 81 82 83 84 85 86

    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]
87
            coo = paddle.incubate.sparse.sparse_coo_tensor(
88 89
                indices, values, dense_shape, place=place)
            assert coo.place.is_cpu_place()
90 91
            assert coo.values().place.is_cpu_place()
            assert coo.indices().place.is_cpu_place()
92 93 94 95

            crows = [0, 2, 3, 5]
            cols = [1, 3, 2, 0, 1]
            values = [1.0, 2.0, 3.0, 4.0, 5.0]
96
            csr = paddle.incubate.sparse.sparse_csr_tensor(
97 98
                crows, cols, values, [3, 5], place=place)
            assert csr.place.is_cpu_place()
99 100 101
            assert csr.crows().place.is_cpu_place()
            assert csr.cols().place.is_cpu_place()
            assert csr.values().place.is_cpu_place()
102 103 104 105 106 107 108 109

    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')
110
            coo = paddle.incubate.sparse.sparse_coo_tensor(
111 112 113 114 115 116
                indices, values, dense_shape, dtype='float64')
            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]
117
            csr = paddle.incubate.sparse.sparse_csr_tensor(
118 119 120 121 122 123 124 125 126
                crows, cols, values, [3, 5], dtype='float16')
            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')
127
            coo = paddle.incubate.sparse.sparse_coo_tensor(indices, values)
128 129 130 131
            assert [2, 2] == coo.shape


class TestSparseConvert(unittest.TestCase):
132 133 134
    def test_to_sparse_coo(self):
        with _test_eager_guard():
            x = [[0, 1, 0, 2], [0, 0, 3, 0], [4, 5, 0, 0]]
135 136 137
            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)
138
            out = dense_x.to_sparse_coo(2)
139 140 141 142 143
            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]
144
            out_grad = paddle.incubate.sparse.sparse_coo_tensor(
145
                paddle.to_tensor(out_grad_indices),
146 147 148
                paddle.to_tensor(out_grad_values),
                shape=out.shape,
                stop_gradient=True)
149 150 151 152 153 154 155 156
            out.backward(out_grad)
            assert np.array_equal(dense_x.grad.numpy(),
                                  out_grad.to_dense().numpy())

    def test_coo_to_dense(self):
        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]
157
            sparse_x = paddle.incubate.sparse.sparse_coo_tensor(
158
                paddle.to_tensor(indices),
159 160 161
                paddle.to_tensor(values),
                shape=[3, 4],
                stop_gradient=False)
162 163 164 165 166 167 168 169 170
            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())
171

172
            paddle.device.set_device("cpu")
173
            sparse_x_cpu = paddle.incubate.sparse.sparse_coo_tensor(
174 175 176 177 178 179 180 181 182
                paddle.to_tensor(indices),
                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())

183 184 185
    def test_to_sparse_csr(self):
        with _test_eager_guard():
            x = [[0, 1, 0, 2], [0, 0, 3, 0], [4, 5, 0, 0]]
186 187 188
            crows = [0, 2, 3, 5]
            cols = [1, 3, 2, 0, 1]
            values = [1, 2, 3, 4, 5]
189
            dense_x = paddle.to_tensor(x)
190
            out = dense_x.to_sparse_csr()
191 192 193
            assert np.array_equal(out.crows().numpy(), crows)
            assert np.array_equal(out.cols().numpy(), cols)
            assert np.array_equal(out.values().numpy(), values)
194

195
            dense_tensor = out.to_dense()
196 197
            assert np.array_equal(dense_tensor.numpy(), x)

198 199 200 201
    def test_coo_values_grad(self):
        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]
202
            sparse_x = paddle.incubate.sparse.sparse_coo_tensor(
203
                paddle.to_tensor(indices),
204 205 206
                paddle.to_tensor(values),
                shape=[3, 4],
                stop_gradient=False)
207 208 209 210 211
            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())
212 213 214
            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]]
215
            sparse_x = paddle.incubate.sparse.sparse_coo_tensor(
216 217 218 219 220 221 222 223 224 225
                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())
226

227 228
    def test_sparse_coo_tensor_grad(self):
        with _test_eager_guard():
229 230 231 232 233 234 235 236 237
            for device in devices:
                if device == 'cpu' or (device == 'gpu' and
                                       paddle.is_compiled_with_cuda()):
                    paddle.device.set_device(device)
                    indices = [[0, 1], [0, 1]]
                    values = [1, 2]
                    indices = paddle.to_tensor(indices, dtype='int32')
                    values = paddle.to_tensor(
                        values, dtype='float32', stop_gradient=False)
238
                    sparse_x = paddle.incubate.sparse.sparse_coo_tensor(
239 240 241 242 243
                        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')
244
                    sparse_out_grad = paddle.incubate.sparse.sparse_coo_tensor(
245 246 247 248 249
                        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())
250

251 252 253 254
                    # test the non-zero values is a vector
                    values = [[1, 1], [2, 2]]
                    values = paddle.to_tensor(
                        values, dtype='float32', stop_gradient=False)
255
                    sparse_x = paddle.incubate.sparse.sparse_coo_tensor(
256 257 258
                        indices, values, shape=[2, 2, 2], stop_gradient=False)
                    grad_values = [[2, 2], [3, 3]]
                    grad_values = paddle.to_tensor(grad_values, dtype='float32')
259
                    sparse_out_grad = paddle.incubate.sparse.sparse_coo_tensor(
260 261 262 263 264 265
                        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())

266 267 268 269 270 271 272 273 274 275 276
    def test_sparse_coo_tensor_sorted(self):
        with _test_eager_guard():
            for device in devices:
                if device == 'cpu' or (device == 'gpu' and
                                       paddle.is_compiled_with_cuda()):
                    paddle.device.set_device(device)
                    #test unsorted and duplicate indices 
                    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')
277 278
                    sparse_x = paddle.incubate.sparse.sparse_coo_tensor(indices,
                                                                        values)
279 280 281 282 283 284 285
                    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())

286 287 288
                    # 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')
289 290
                    sparse_x = paddle.incubate.sparse.sparse_coo_tensor(indices,
                                                                        values)
291 292 293 294 295 296
                    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())

297 298 299 300 301 302 303 304 305

class TestCooError(unittest.TestCase):
    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]
306
                sparse_x = paddle.incubate.sparse.sparse_coo_tensor(
307 308 309 310 311 312 313 314
                    indices, values, shape=dense_shape)

    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]
315 316
                sparse_x = paddle.incubate.sparse.sparse_coo_tensor(indices,
                                                                    values)
317 318 319 320 321 322 323

    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]
324
                sparse_x = paddle.incubate.sparse.sparse_coo_tensor(
325 326 327 328 329 330 331
                    indices, values, shape=shape)

    def test_indices_dtype(self):
        with _test_eager_guard():
            with self.assertRaises(TypeError):
                indices = [[1.0, 2.0], [0, 1]]
                values = [1, 2]
332 333
                sparse_x = paddle.incubate.sparse.sparse_coo_tensor(indices,
                                                                    values)
334 335 336 337 338 339 340 341 342 343


class TestCsrError(unittest.TestCase):
    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]
344 345
                sparse_x = paddle.incubate.sparse.sparse_csr_tensor(
                    crows, cols, values, shape)
346 347 348 349 350 351 352 353

    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]
354 355
                sparse_x = paddle.incubate.sparse.sparse_csr_tensor(
                    crows, cols, values, shape)
356 357 358 359 360 361 362 363

    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]
364 365
                sparse_x = paddle.incubate.sparse.sparse_csr_tensor(
                    crows, cols, values, shape)
366

367 368 369 370 371 372 373
    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]
374 375
                sparse_x = paddle.incubate.sparse.sparse_csr_tensor(
                    crows, cols, values, shape)
376 377 378 379 380 381 382 383

    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]
384 385
                sparse_x = paddle.incubate.sparse.sparse_csr_tensor(
                    crows, cols, values, shape)
386 387 388 389 390 391 392 393

    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]
394 395
                sparse_x = paddle.incubate.sparse.sparse_csr_tensor(
                    crows, cols, values, shape)
396 397 398 399 400 401 402 403

    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]
404 405
                sparse_x = paddle.incubate.sparse.sparse_csr_tensor(
                    crows, cols, values, shape)
406

407 408 409

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