test_seq_pool.py 11.2 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
from op_test import OpTest
T
tensor-tang 已提交
20
from test_reorder_lod_tensor import convert_to_offset
21 22


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


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

40

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


class TestSeqAvgPool(OpTest):
52 53 54
    def set_lod(self):
        return [[11]]

55 56
    def set_data(self):
        self.op_type = 'sequence_pool'
57
        x = np.random.uniform(0.1, 1, [11, 23]).astype('float32')
58
        lod = self.set_lod()
59
        self.inputs = {'X': (x, lod)}
T
tensor-tang 已提交
60
        offset = convert_to_offset(lod)
C
chengduoZH 已提交
61
        out = np.zeros((len(lod[0]), 23)).astype('float32')
62
        self.outputs = {'Out': out}
63
        return x, offset, out
64

65
    def compute(self, x, offset, out):
66 67
        self.attrs = {"pad_value": 0.0, 'pooltype': "AVERAGE"}
        compute_seqpool_avg(x, offset, out, self.attrs["pad_value"])
68

69
    def setUp(self):
70 71
        x, offset, out = self.set_data()
        self.compute(x, offset, out)
72 73 74 75 76

    def test_check_output(self):
        self.check_output()

    def test_check_grad(self):
77 78 79
        # Remove MaxIndex after check_grad is refined.
        self.outputs['MaxIndex'] = \
            np.zeros(self.outputs['Out'].shape).astype('int32')
80 81 82
        self.check_grad(["X"], "Out")


83 84 85 86 87
class TestSeqAvgPoolLen0(TestSeqAvgPool):
    def set_lod(self):
        return [[0, 4, 0, 7, 0]]


D
dzhwinter 已提交
88
class TestSeqSumPool(TestSeqAvgPool):
89
    def compute(self, x, offset, out):
90 91 92 93 94 95 96
        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 已提交
97 98 99


class TestSeqMaxPool(TestSeqAvgPool):
100 101 102
    def set_lod(self):
        return [[13]]

D
dzhwinter 已提交
103 104 105
    def set_data(self):
        self.op_type = 'sequence_pool'
        x = np.random.uniform(0.1, 1, [13, 23]).astype('float32')
106
        lod = self.set_lod()
T
tensor-tang 已提交
107
        offset = convert_to_offset(lod)
108 109
        for i in range(len(offset[0]) - 1):
            l = offset[0][i + 1] - offset[0][i]
110 111
            if l > 0:
                x[offset[0][i] + np.random.randint(l), :] += 2.0
D
dzhwinter 已提交
112 113 114

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

115
        out = np.zeros((len(lod[0]), 23)).astype('float32')
D
dzhwinter 已提交
116
        self.outputs = {'Out': out}
117
        return x, offset, out
D
dzhwinter 已提交
118

119
    def compute(self, x, offset, out):
120
        self.attrs = {"pad_value": 0.5, 'pooltype': "MAX"}
121
        for i in range(len(offset[0]) - 1):
122 123 124 125 126 127 128 129 130 131
            if offset[0][i] == offset[0][i + 1]:
                out[i] = self.attrs["pad_value"]
            else:
                sub_x = x[offset[0][i]:offset[0][i + 1], :]
                out[i] = np.amax(sub_x, axis=0)


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


class TestSeqSqrtPool(TestSeqAvgPool):
135
    def compute(self, x, offset, out):
136 137 138 139 140 141 142
        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 已提交
143 144 145


class TestSeqLastPool(TestSeqAvgPool):
146
    def compute(self, x, offset, out):
147
        self.attrs = {"pad_value": 0.0, 'pooltype': "LAST"}
148
        for i in range(len(offset[0]) - 1):
149 150 151 152 153 154 155 156 157 158
            if offset[0][i] == offset[0][i + 1]:
                out[i] = self.attrs["pad_value"]
            else:
                sub_x = x[offset[0][i]:offset[0][i + 1], :]
                out[i] = sub_x[-1, :]


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


class TestSeqFirstPool(TestSeqAvgPool):
162
    def compute(self, x, offset, out):
163
        self.attrs = {"pad_value": 0.3, 'pooltype': "FIRST"}
164
        for i in range(len(offset[0]) - 1):
165 166 167 168 169 170 171 172 173 174
            if offset[0][i] == offset[0][i + 1]:
                out[i] = self.attrs["pad_value"]
            else:
                sub_x = x[offset[0][i]:offset[0][i + 1], :]
                out[i] = sub_x[0, :]


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


177
class TestSeqAvgPool2D(TestSeqAvgPool):
178 179 180
    def set_lod(self):
        return [[4, 1, 3, 5]]

181 182
    def set_data(self):
        self.op_type = 'sequence_pool'
183
        x = np.random.uniform(0.1, 1, [13, 3, 17]).astype('float32')
184
        lod = self.set_lod()
185
        self.inputs = {'X': (x, lod)}
T
tensor-tang 已提交
186
        offset = convert_to_offset(lod)
187

188
        out = np.zeros((len(lod[0]), 3, 17)).astype('float32')
189
        self.outputs = {'Out': out}
190
        return x, offset, out
191

192
    def compute(self, x, offset, out):
193
        self.attrs = {"pad_value": 0.0, 'pooltype': "AVERAGE"}
194
        for i in range(len(offset[0]) - 1):
195 196 197 198 199 200 201 202 203 204 205
            if offset[0][i] == offset[0][i + 1]:
                out[i] = self.attrs["pad_value"] * np.ones((3, 17))
            else:
                sub_x = np.reshape(x[offset[0][i]:offset[0][i + 1], :],
                                   (-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]]
206 207


208
class TestSeqSumPool2D(TestSeqAvgPool2D):
209
    def compute(self, x, offset, out):
210
        self.attrs = {"pad_value": 0.2, 'pooltype': "SUM"}
211
        for i in range(len(offset[0]) - 1):
212 213 214 215 216 217 218 219 220 221 222
            if offset[0][i] == offset[0][i + 1]:
                out[i] = self.attrs["pad_value"] * np.ones((3, 17))
            else:
                sub_x = np.reshape(x[offset[0][i]:offset[0][i + 1], :],
                                   (-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]]
223 224


L
Luo Tao 已提交
225
class TestSeqSqrtPool2D(TestSeqAvgPool2D):
226
    def compute(self, x, offset, out):
227
        self.attrs = {"pad_value": 0.0, 'pooltype': "SQRT"}
228
        for i in range(len(offset[0]) - 1):
229 230 231 232 233 234 235 236
            if offset[0][i] == offset[0][i + 1]:
                out[i] = self.attrs["pad_value"] * np.ones((3, 17))
            else:
                sub_x = np.reshape(x[offset[0][i]:offset[0][i + 1], :],
                                   (-1, 3 * 17))
                seq_len = offset[0][i + 1] - offset[0][i]
                out[i] = np.reshape(
                    sub_x.sum(axis=0) / np.sqrt(seq_len), (3, 17))
L
Luo Tao 已提交
237 238

    def test_check_grad(self):
239 240 241
        # Remove MaxIndex after check_grad is refined.
        self.outputs['MaxIndex'] = \
            np.zeros(self.outputs['Out'].shape).astype('int32')
L
Luo Tao 已提交
242 243 244
        self.check_grad(["X"], "Out", max_relative_error=0.06)


245 246 247 248 249
class TestSeqSqrtPool2DLen0(TestSeqSqrtPool2D):
    def set_lod(self):
        return [[0, 8, 0, 5, 0]]


L
Luo Tao 已提交
250
class TestSeqMaxPool2D(TestSeqAvgPool2D):
251 252 253
    def set_lod(self):
        return [[4, 1, 3, 5]]

254 255 256
    def set_data(self):
        self.op_type = 'sequence_pool'
        x = np.random.uniform(0.1, 1, [13, 3, 11]).astype('float32')
257 258 259
        self.lod = self.set_lod()
        self.inputs = {'X': (x, self.lod)}
        offset = convert_to_offset(self.lod)
260 261
        for i in range(len(offset[0]) - 1):
            l = offset[0][i + 1] - offset[0][i]
262 263
            if l == 0:
                continue
264
            x[offset[0][i] + np.random.randint(l), :] += 1.0
265

266
        out = np.zeros((len(self.lod[0]), 3, 11)).astype('float32')
267
        self.outputs = {'Out': out}
268
        return x, offset, out
269

270
    def compute(self, x, offset, out):
271
        self.attrs = {"pad_value": 0.0, 'pooltype': "MAX"}
272
        for i in range(len(offset[0]) - 1):
273 274 275
            if offset[0][i] == offset[0][i + 1]:
                out[i] = self.attrs["pad_value"] * np.ones((3, 11))
                continue
276 277
            sub_x = np.reshape(x[offset[0][i]:offset[0][i + 1], :],
                               (-1, 3 * 11))
278
            out[i] = np.reshape(np.amax(sub_x, axis=0), (3, 11))
L
Luo Tao 已提交
279 280


281 282 283 284 285
class TestSeqMaxPool2DLen0(TestSeqMaxPool2D):
    def set_lod(self):
        return [[0, 3, 0, 10, 0]]


J
Jacek Czaja 已提交
286 287
class TestSeqMaxPool2DInference(TestSeqMaxPool2D):
    def compute(self, x, offset, out):
288
        self.attrs = {"pad_value": 1.0, 'pooltype': "MAX", 'is_test': True}
J
Jacek Czaja 已提交
289
        for i in range(len(offset[0]) - 1):
290 291 292 293 294 295
            if offset[0][i] == offset[0][i + 1]:
                out[i] = self.attrs["pad_value"] * np.ones((3, 11))
            else:
                sub_x = np.reshape(x[offset[0][i]:offset[0][i + 1], :],
                                   (-1, 3 * 11))
                out[i] = np.reshape(np.amax(sub_x, axis=0), (3, 11))
J
Jacek Czaja 已提交
296 297 298 299 300 301 302

    def test_check_grad(self):
        """Grad computation does not apply to Sequence MAX 
            Pool executed when is_test is true """
        return


303 304 305 306 307
class TestSeqMaxPool2DInferenceLen0(TestSeqMaxPool2DInference):
    def set_lod(self):
        return [[0, 3, 0, 10, 0]]


L
Luo Tao 已提交
308
class TestSeqLastPool2D(TestSeqAvgPool2D):
309
    def compute(self, x, offset, out):
310
        self.attrs = {"pad_value": 0.0, 'pooltype': "LAST"}
311
        for i in range(len(offset[0]) - 1):
312 313 314 315 316 317 318 319 320 321 322
            if offset[0][i] == offset[0][i + 1]:
                out[i] = self.attrs["pad_value"] * np.ones((3, 17))
            else:
                sub_x = np.reshape(x[offset[0][i]:offset[0][i + 1], :],
                                   (-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 已提交
323 324 325


class TestSeqFirstPool2D(TestSeqAvgPool2D):
326
    def compute(self, x, offset, out):
327
        self.attrs = {"pad_value": 0.0, 'pooltype': "FIRST"}
328
        for i in range(len(offset[0]) - 1):
329 330 331 332 333 334 335 336 337 338 339
            if offset[0][i] == offset[0][i + 1]:
                out[i] = self.attrs["pad_value"] * np.ones((3, 17))
            else:
                sub_x = np.reshape(x[offset[0][i]:offset[0][i + 1], :],
                                   (-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 已提交
340 341


342 343
if __name__ == '__main__':
    unittest.main()