test_sequence_pool.py 14.8 KB
Newer Older
1
#   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
D
dzhwinter 已提交
2
#
D
dzhwinter 已提交
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
D
dzhwinter 已提交
6
#
D
dzhwinter 已提交
7
#     http://www.apache.org/licenses/LICENSE-2.0
D
dzhwinter 已提交
8
#
D
dzhwinter 已提交
9 10 11 12 13 14
# 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.

15 16
from __future__ import print_function

17 18
import unittest
import numpy as np
19 20
import sys
sys.path.append("../")
21
from op_test import OpTest, skip_check_grad_ci
T
tensor-tang 已提交
22
from test_reorder_lod_tensor import convert_to_offset
23 24


25
def compute_seqpool_sum(x, offset, out, pad_value=0.0):
26 27 28
    level = len(offset) - 1
    for i in range(len(offset[level]) - 1):
        if offset[level][i] == offset[level][i + 1]:
29 30
            out[i] = pad_value
        else:
31
            sub_x = x[offset[level][i]:offset[level][i + 1], :]
32
            out[i] = sub_x.sum(axis=0)
T
tensor-tang 已提交
33 34


35
def compute_seqpool_avg(x, offset, out, pad_value=0.0):
36 37 38
    level = len(offset) - 1
    for i in range(len(offset[level]) - 1):
        if offset[level][i] == offset[level][i + 1]:
39 40
            out[i] = pad_value
        else:
41
            sub_x = x[offset[level][i]:offset[level][i + 1], :]
42
            out[i] = sub_x.mean(axis=0)
T
tensor-tang 已提交
43

44

45
def compute_seqpool_sqrt(x, offset, out, pad_value=0.0):
46 47 48
    level = len(offset) - 1
    for i in range(len(offset[level]) - 1):
        if offset[level][i] == offset[level][i + 1]:
49 50
            out[i] = pad_value
        else:
51 52
            sub_x = x[offset[level][i]:offset[level][i + 1], :]
            seq_len = offset[level][i + 1] - offset[level][i]
53
            out[i] = sub_x.sum(axis=0) / np.sqrt(seq_len)
T
tensor-tang 已提交
54 55 56


class TestSeqAvgPool(OpTest):
57 58 59
    def set_lod(self):
        return [[11]]

60
    def set_lod_data(self):
61
        x = np.random.uniform(0.1, 1, [11, 23]).astype('float32')
62 63 64 65
        return x

    def set_data(self):
        x = self.set_lod_data()
66
        lod = self.set_lod()
67
        level = len(lod) - 1
68
        self.inputs = {'X': (x, lod)}
T
tensor-tang 已提交
69
        offset = convert_to_offset(lod)
70
        out = np.zeros((len(lod[level]), x.shape[1])).astype('float32')
71
        self.outputs = {'Out': out}
72
        return x, lod, offset, out
73

74
    def compute(self, x, offset, out):
75 76
        self.attrs = {"pad_value": 0.0, 'pooltype': "AVERAGE"}
        compute_seqpool_avg(x, offset, out, self.attrs["pad_value"])
77

78
    def setUp(self):
79 80
        self.op_type = 'sequence_pool'
        x, lod, offset, out = self.set_data()
81
        self.compute(x, offset, out)
82
        if len(offset) > 1:
83
            self.outputs = {'Out': (out, [lod[0]])}
84 85

    def test_check_output(self):
H
hong 已提交
86
        self.check_output(check_dygraph=False)
87 88

    def test_check_grad(self):
89
        # Remove MaxIndex after check_grad is refined.
90 91
        out = self.outputs['Out']
        if isinstance(out, tuple): out = out[0]
92
        self.outputs['MaxIndex'] = \
93
            np.zeros(out.shape).astype('int32')
H
hong 已提交
94
        self.check_grad(["X"], "Out", check_dygraph=False)
95 96


97 98 99 100 101 102 103 104 105 106 107
class TestSeqAvgPoolBatch1(TestSeqAvgPool):
    def set_lod(self):
        return [[11]]

    def set_lod_data(self):
        lod = self.set_lod()
        x, _ = self.get_sequence_batch_size_1_input(
            lod=lod, shape=[lod[0][0], 23])
        return x


108 109 110 111 112 113 114 115 116 117 118
class TestSeqAvgPoolInstance0(TestSeqAvgPool):
    def set_lod(self):
        return [[0, 0, 4, 0, 3, 0, 0, 5, 0, 0]]

    def set_lod_data(self):
        lod = self.set_lod()
        x, _ = self.get_sequence_instance_size_0_input(
            lod=lod, shape=[sum(lod[0]), 10])
        return x


119 120 121 122 123
class TestSeqAvgPoolLen0(TestSeqAvgPool):
    def set_lod(self):
        return [[0, 4, 0, 7, 0]]


124 125 126 127 128
class TestSeqAvgPoolLen0LoDLevel2(TestSeqAvgPool):
    def set_lod(self):
        return [[2, 0, 1, 2], [0, 4, 0, 7, 0]]


D
dzhwinter 已提交
129
class TestSeqSumPool(TestSeqAvgPool):
130
    def compute(self, x, offset, out):
131 132 133 134 135 136 137
        self.attrs = {"pad_value": 0.1, 'pooltype': "SUM"}
        compute_seqpool_sum(x, offset, out, self.attrs["pad_value"])


class TestSeqSumPoolLen0(TestSeqSumPool):
    def set_lod(self):
        return [[0, 4, 0, 7, 0]]
D
dzhwinter 已提交
138 139


140 141 142 143 144
class TestSeqSumPoolLen0LoDLevel2(TestSeqSumPool):
    def set_lod(self):
        return [[2, 0, 1, 2], [0, 4, 0, 7, 0]]


D
dzhwinter 已提交
145
class TestSeqMaxPool(TestSeqAvgPool):
146 147 148
    def set_lod(self):
        return [[13]]

D
dzhwinter 已提交
149 150 151
    def set_data(self):
        self.op_type = 'sequence_pool'
        x = np.random.uniform(0.1, 1, [13, 23]).astype('float32')
152
        lod = self.set_lod()
153
        level = len(lod) - 1
T
tensor-tang 已提交
154
        offset = convert_to_offset(lod)
155 156
        for i in range(len(offset[level]) - 1):
            l = offset[level][i + 1] - offset[level][i]
157
            if l > 0:
158
                x[offset[level][i] + np.random.randint(l), :] += 2.0
D
dzhwinter 已提交
159 160 161

        self.inputs = {'X': (x, lod)}

162
        out = np.zeros((len(lod[level]), 23)).astype('float32')
D
dzhwinter 已提交
163
        self.outputs = {'Out': out}
164
        return x, lod, offset, out
D
dzhwinter 已提交
165

166
    def compute(self, x, offset, out):
167
        self.attrs = {"pad_value": 0.5, 'pooltype': "MAX"}
168 169 170
        level = len(offset) - 1
        for i in range(len(offset[level]) - 1):
            if offset[level][i] == offset[level][i + 1]:
171 172
                out[i] = self.attrs["pad_value"]
            else:
173
                sub_x = x[offset[level][i]:offset[level][i + 1], :]
174 175 176 177 178 179
                out[i] = np.amax(sub_x, axis=0)


class TestSeqMaxPoolLen0(TestSeqMaxPool):
    def set_lod(self):
        return [[0, 1, 1, 5, 6, 0]]
D
dzhwinter 已提交
180 181


182 183 184 185 186
class TestSeqMaxPoolLen0LoDLevel2(TestSeqMaxPool):
    def set_lod(self):
        return [[2, 0, 3, 1], [0, 1, 1, 5, 6, 0]]


D
dzhwinter 已提交
187
class TestSeqSqrtPool(TestSeqAvgPool):
188
    def compute(self, x, offset, out):
189 190 191 192 193 194 195
        self.attrs = {"pad_value": 0.0, 'pooltype': "SQRT"}
        compute_seqpool_sqrt(x, offset, out, self.attrs["pad_value"])


class TestSeqSqrtPoolLen0(TestSeqSqrtPool):
    def set_lod(self):
        return [[0, 7, 0, 2, 2, 0]]
D
dzhwinter 已提交
196 197


198 199 200 201 202
class TestSeqSqrtPoolLen0LoDLevel2(TestSeqSqrtPool):
    def set_lod(self):
        return [[1, 2, 0, 3], [0, 7, 0, 2, 2, 0]]


D
dzhwinter 已提交
203
class TestSeqLastPool(TestSeqAvgPool):
204
    def compute(self, x, offset, out):
205
        self.attrs = {"pad_value": 0.0, 'pooltype': "LAST"}
206 207 208
        level = len(offset) - 1
        for i in range(len(offset[level]) - 1):
            if offset[level][i] == offset[level][i + 1]:
209 210
                out[i] = self.attrs["pad_value"]
            else:
211
                sub_x = x[offset[level][i]:offset[level][i + 1], :]
212 213 214 215 216 217
                out[i] = sub_x[-1, :]


class TestSeqLastPoolLen0(TestSeqLastPool):
    def set_lod(self):
        return [[0, 3, 4, 0, 4, 0]]
D
dzhwinter 已提交
218 219


220 221 222 223 224
class TestSeqLastPoolLen0LoDLevel2(TestSeqLastPool):
    def set_lod(self):
        return [[1, 0, 2, 3], [0, 3, 4, 0, 4, 0]]


D
dzhwinter 已提交
225
class TestSeqFirstPool(TestSeqAvgPool):
226
    def compute(self, x, offset, out):
227
        self.attrs = {"pad_value": 0.3, 'pooltype': "FIRST"}
228 229 230
        level = len(offset) - 1
        for i in range(len(offset[level]) - 1):
            if offset[level][i] == offset[level][i + 1]:
231 232
                out[i] = self.attrs["pad_value"]
            else:
233
                sub_x = x[offset[level][i]:offset[level][i + 1], :]
234 235 236 237 238 239
                out[i] = sub_x[0, :]


class TestSeqFirstPoolLen0(TestSeqFirstPool):
    def set_lod(self):
        return [[0, 2, 0, 3, 6, 0]]
D
dzhwinter 已提交
240 241


242 243 244 245 246
class TestSeqFirstPoolLen0LoDLevel2(TestSeqFirstPool):
    def set_lod(self):
        return [[1, 0, 2, 3], [0, 2, 0, 3, 6, 0]]


247
class TestSeqAvgPool2D(TestSeqAvgPool):
248 249 250
    def set_lod(self):
        return [[4, 1, 3, 5]]

251 252
    def set_data(self):
        self.op_type = 'sequence_pool'
253
        x = np.random.uniform(0.1, 1, [13, 3, 17]).astype('float32')
254
        lod = self.set_lod()
255
        level = len(lod) - 1
256
        self.inputs = {'X': (x, lod)}
T
tensor-tang 已提交
257
        offset = convert_to_offset(lod)
258

259
        out = np.zeros((len(lod[level]), 3, 17)).astype('float32')
260
        self.outputs = {'Out': out}
261
        return x, lod, offset, out
262

263
    def compute(self, x, offset, out):
264
        self.attrs = {"pad_value": 0.0, 'pooltype': "AVERAGE"}
265 266 267
        level = len(offset) - 1
        for i in range(len(offset[level]) - 1):
            if offset[level][i] == offset[level][i + 1]:
268 269
                out[i] = self.attrs["pad_value"] * np.ones((3, 17))
            else:
270
                sub_x = np.reshape(x[offset[level][i]:offset[level][i + 1], :],
271 272 273 274 275 276 277
                                   (-1, 3 * 17))
                out[i] = np.reshape(sub_x.mean(axis=0), (3, 17))


class TestSeqAvgPool2DLen0(TestSeqAvgPool2D):
    def set_lod(self):
        return [[0, 5, 0, 8, 0]]
278 279


280 281 282 283 284
class TestSeqAvgPool2DLen0LoDLevel2(TestSeqAvgPool2D):
    def set_lod(self):
        return [[1, 0, 4], [0, 5, 0, 8, 0]]


285
class TestSeqSumPool2D(TestSeqAvgPool2D):
286
    def compute(self, x, offset, out):
287
        self.attrs = {"pad_value": 0.2, 'pooltype': "SUM"}
288 289 290
        level = len(offset) - 1
        for i in range(len(offset[level]) - 1):
            if offset[level][i] == offset[level][i + 1]:
291 292
                out[i] = self.attrs["pad_value"] * np.ones((3, 17))
            else:
293
                sub_x = np.reshape(x[offset[level][i]:offset[level][i + 1], :],
294 295 296 297 298 299 300
                                   (-1, 3 * 17))
                out[i] = np.reshape(sub_x.sum(axis=0), (3, 17))


class TestSeqSumPool2DLen0(TestSeqSumPool2D):
    def set_lod(self):
        return [[0, 8, 0, 5, 0]]
301 302


303 304 305 306 307
class TestSeqSumPool2DLen0LoDLevel2(TestSeqSumPool2D):
    def set_lod(self):
        return [[1, 0, 4], [0, 8, 0, 5, 0]]


L
Luo Tao 已提交
308
class TestSeqSqrtPool2D(TestSeqAvgPool2D):
309
    def compute(self, x, offset, out):
310
        self.attrs = {"pad_value": 0.0, 'pooltype': "SQRT"}
311 312 313
        level = len(offset) - 1
        for i in range(len(offset[level]) - 1):
            if offset[level][i] == offset[level][i + 1]:
314 315
                out[i] = self.attrs["pad_value"] * np.ones((3, 17))
            else:
316
                sub_x = np.reshape(x[offset[level][i]:offset[level][i + 1], :],
317
                                   (-1, 3 * 17))
318
                seq_len = offset[level][i + 1] - offset[level][i]
319 320
                out[i] = np.reshape(
                    sub_x.sum(axis=0) / np.sqrt(seq_len), (3, 17))
L
Luo Tao 已提交
321 322

    def test_check_grad(self):
323
        # Remove MaxIndex after check_grad is refined.
324 325 326
        out = self.outputs['Out']
        if isinstance(out, tuple):
            out = out[0]
327
        self.outputs['MaxIndex'] = \
328
            np.zeros(out.shape).astype('int32')
H
hong 已提交
329 330
        self.check_grad(
            ["X"], "Out", max_relative_error=0.06, check_dygraph=False)
L
Luo Tao 已提交
331 332


333 334 335 336 337
class TestSeqSqrtPool2DLen0(TestSeqSqrtPool2D):
    def set_lod(self):
        return [[0, 8, 0, 5, 0]]


338 339 340 341 342
class TestSeqSqrtPool2DLen0LoDLevel2(TestSeqSqrtPool2D):
    def set_lod(self):
        return [[1, 0, 2, 2], [0, 8, 0, 5, 0]]


L
Luo Tao 已提交
343
class TestSeqMaxPool2D(TestSeqAvgPool2D):
344 345 346
    def set_lod(self):
        return [[4, 1, 3, 5]]

347 348 349
    def set_data(self):
        self.op_type = 'sequence_pool'
        x = np.random.uniform(0.1, 1, [13, 3, 11]).astype('float32')
350 351 352 353
        lod = self.set_lod()
        level = len(lod) - 1
        self.inputs = {'X': (x, lod)}
        offset = convert_to_offset(lod)
354 355
        for i in range(len(offset[level]) - 1):
            l = offset[level][i + 1] - offset[level][i]
356 357
            if l == 0:
                continue
358
            x[offset[level][i] + np.random.randint(l), :] += 1.0
359

360
        out = np.zeros((len(lod[level]), 3, 11)).astype('float32')
361
        self.outputs = {'Out': out}
362
        return x, lod, offset, out
363

364
    def compute(self, x, offset, out):
365
        self.attrs = {"pad_value": 0.0, 'pooltype': "MAX"}
366 367 368
        level = len(offset) - 1
        for i in range(len(offset[level]) - 1):
            if offset[level][i] == offset[level][i + 1]:
369 370
                out[i] = self.attrs["pad_value"] * np.ones((3, 11))
                continue
371
            sub_x = np.reshape(x[offset[level][i]:offset[level][i + 1], :],
372
                               (-1, 3 * 11))
373
            out[i] = np.reshape(np.amax(sub_x, axis=0), (3, 11))
L
Luo Tao 已提交
374 375


376 377 378 379 380
class TestSeqMaxPool2DLen0(TestSeqMaxPool2D):
    def set_lod(self):
        return [[0, 3, 0, 10, 0]]


381 382 383 384 385
class TestSeqMaxPool2DLen0LoDLevel2(TestSeqMaxPool2D):
    def set_lod(self):
        return [[1, 0, 2, 2], [0, 3, 0, 10, 0]]


386 387
@skip_check_grad_ci(reason="Grad computation does not apply to Sequence MAX "
                    "Pool executed when is_test is true.")
J
Jacek Czaja 已提交
388 389
class TestSeqMaxPool2DInference(TestSeqMaxPool2D):
    def compute(self, x, offset, out):
390
        self.attrs = {"pad_value": 1.0, 'pooltype': "MAX", 'is_test': True}
391 392 393
        level = len(offset) - 1
        for i in range(len(offset[level]) - 1):
            if offset[level][i] == offset[level][i + 1]:
394 395
                out[i] = self.attrs["pad_value"] * np.ones((3, 11))
            else:
396
                sub_x = np.reshape(x[offset[level][i]:offset[level][i + 1], :],
397 398
                                   (-1, 3 * 11))
                out[i] = np.reshape(np.amax(sub_x, axis=0), (3, 11))
J
Jacek Czaja 已提交
399 400

    def test_check_grad(self):
401
        """Grad computation does not apply to Sequence MAX
J
Jacek Czaja 已提交
402 403 404 405
            Pool executed when is_test is true """
        return


406 407 408 409 410
class TestSeqMaxPool2DInferenceLen0(TestSeqMaxPool2DInference):
    def set_lod(self):
        return [[0, 3, 0, 10, 0]]


411 412 413 414 415
class TestSeqMaxPool2DInferenceLen0LoDLevel2(TestSeqMaxPool2DInference):
    def set_lod(self):
        return [[1, 0, 2, 2], [0, 3, 0, 10, 0]]


L
Luo Tao 已提交
416
class TestSeqLastPool2D(TestSeqAvgPool2D):
417
    def compute(self, x, offset, out):
418
        self.attrs = {"pad_value": 0.0, 'pooltype': "LAST"}
419 420 421
        level = len(offset) - 1
        for i in range(len(offset[level]) - 1):
            if offset[level][i] == offset[level][i + 1]:
422 423
                out[i] = self.attrs["pad_value"] * np.ones((3, 17))
            else:
424
                sub_x = np.reshape(x[offset[level][i]:offset[level][i + 1], :],
425 426 427 428 429 430 431
                                   (-1, 3 * 17))
                out[i] = np.reshape(sub_x[-1, :], (3, 17))


class TestSeqLastPool2DLen0(TestSeqLastPool2D):
    def set_lod(self):
        return [[0, 3, 0, 1, 9, 0]]
L
Luo Tao 已提交
432 433


434 435 436 437 438
class TestSeqLastPool2DLen0LoDLevel2(TestSeqLastPool2D):
    def set_lod(self):
        return [[1, 0, 2, 3], [0, 3, 0, 1, 9, 0]]


L
Luo Tao 已提交
439
class TestSeqFirstPool2D(TestSeqAvgPool2D):
440
    def compute(self, x, offset, out):
441
        self.attrs = {"pad_value": 0.0, 'pooltype': "FIRST"}
442 443 444
        level = len(offset) - 1
        for i in range(len(offset[level]) - 1):
            if offset[level][i] == offset[level][i + 1]:
445 446
                out[i] = self.attrs["pad_value"] * np.ones((3, 17))
            else:
447
                sub_x = np.reshape(x[offset[level][i]:offset[level][i + 1], :],
448 449 450 451 452 453 454
                                   (-1, 3 * 17))
                out[i] = np.reshape(sub_x[0, :], (3, 17))


class TestSeqFirstPool2DLen0(TestSeqFirstPool2D):
    def set_lod(self):
        return [[0, 3, 0, 3, 7, 0]]
L
Luo Tao 已提交
455 456


457 458 459 460 461
class TestSeqFirstPool2DLen0LoDLevel2(TestSeqFirstPool2D):
    def set_lod(self):
        return [[1, 0, 2, 3], [0, 3, 0, 3, 7, 0]]


462 463
if __name__ == '__main__':
    unittest.main()