You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
433 lines
14 KiB
433 lines
14 KiB
# Copyright (c) 2018 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
|
|
from op_test import OpTest
|
|
from test_reorder_lod_tensor import convert_to_offset
|
|
|
|
|
|
def compute_seqpool_sum(x, offset, out, pad_value=0.0):
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = pad_value
|
|
else:
|
|
sub_x = x[offset[level][i]:offset[level][i + 1], :]
|
|
out[i] = sub_x.sum(axis=0)
|
|
|
|
|
|
def compute_seqpool_avg(x, offset, out, pad_value=0.0):
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = pad_value
|
|
else:
|
|
sub_x = x[offset[level][i]:offset[level][i + 1], :]
|
|
out[i] = sub_x.mean(axis=0)
|
|
|
|
|
|
def compute_seqpool_sqrt(x, offset, out, pad_value=0.0):
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = pad_value
|
|
else:
|
|
sub_x = x[offset[level][i]:offset[level][i + 1], :]
|
|
seq_len = offset[level][i + 1] - offset[level][i]
|
|
out[i] = sub_x.sum(axis=0) / np.sqrt(seq_len)
|
|
|
|
|
|
class TestSeqAvgPool(OpTest):
|
|
def set_lod(self):
|
|
return [[11]]
|
|
|
|
def set_data(self):
|
|
self.op_type = 'sequence_pool'
|
|
x = np.random.uniform(0.1, 1, [11, 23]).astype('float32')
|
|
lod = self.set_lod()
|
|
level = len(lod) - 1
|
|
self.inputs = {'X': (x, lod)}
|
|
offset = convert_to_offset(lod)
|
|
out = np.zeros((len(lod[level]), 23)).astype('float32')
|
|
self.outputs = {'Out': out}
|
|
return x, offset, out
|
|
|
|
def compute(self, x, offset, out):
|
|
self.attrs = {"pad_value": 0.0, 'pooltype': "AVERAGE"}
|
|
compute_seqpool_avg(x, offset, out, self.attrs["pad_value"])
|
|
|
|
def setUp(self):
|
|
x, offset, out = self.set_data()
|
|
self.compute(x, offset, out)
|
|
if len(offset) > 1:
|
|
self.outputs = {'Out': (out, [self.set_lod()[0]])}
|
|
|
|
def test_check_output(self):
|
|
self.check_output()
|
|
|
|
def test_check_grad(self):
|
|
# Remove MaxIndex after check_grad is refined.
|
|
out = self.outputs['Out']
|
|
if isinstance(out, tuple): out = out[0]
|
|
self.outputs['MaxIndex'] = \
|
|
np.zeros(out.shape).astype('int32')
|
|
self.check_grad(["X"], "Out")
|
|
|
|
|
|
class TestSeqAvgPoolLen0(TestSeqAvgPool):
|
|
def set_lod(self):
|
|
return [[0, 4, 0, 7, 0]]
|
|
|
|
|
|
class TestSeqAvgPoolLen0LoDLevel2(TestSeqAvgPool):
|
|
def set_lod(self):
|
|
return [[2, 0, 1, 2], [0, 4, 0, 7, 0]]
|
|
|
|
|
|
class TestSeqSumPool(TestSeqAvgPool):
|
|
def compute(self, x, offset, out):
|
|
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]]
|
|
|
|
|
|
class TestSeqSumPoolLen0LoDLevel2(TestSeqSumPool):
|
|
def set_lod(self):
|
|
return [[2, 0, 1, 2], [0, 4, 0, 7, 0]]
|
|
|
|
|
|
class TestSeqMaxPool(TestSeqAvgPool):
|
|
def set_lod(self):
|
|
return [[13]]
|
|
|
|
def set_data(self):
|
|
self.op_type = 'sequence_pool'
|
|
x = np.random.uniform(0.1, 1, [13, 23]).astype('float32')
|
|
lod = self.set_lod()
|
|
level = len(lod) - 1
|
|
offset = convert_to_offset(lod)
|
|
for i in range(len(offset[level]) - 1):
|
|
l = offset[level][i + 1] - offset[level][i]
|
|
if l > 0:
|
|
x[offset[level][i] + np.random.randint(l), :] += 2.0
|
|
|
|
self.inputs = {'X': (x, lod)}
|
|
|
|
out = np.zeros((len(lod[level]), 23)).astype('float32')
|
|
self.outputs = {'Out': out}
|
|
return x, offset, out
|
|
|
|
def compute(self, x, offset, out):
|
|
self.attrs = {"pad_value": 0.5, 'pooltype': "MAX"}
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = self.attrs["pad_value"]
|
|
else:
|
|
sub_x = x[offset[level][i]:offset[level][i + 1], :]
|
|
out[i] = np.amax(sub_x, axis=0)
|
|
|
|
|
|
class TestSeqMaxPoolLen0(TestSeqMaxPool):
|
|
def set_lod(self):
|
|
return [[0, 1, 1, 5, 6, 0]]
|
|
|
|
|
|
class TestSeqMaxPoolLen0LoDLevel2(TestSeqMaxPool):
|
|
def set_lod(self):
|
|
return [[2, 0, 3, 1], [0, 1, 1, 5, 6, 0]]
|
|
|
|
|
|
class TestSeqSqrtPool(TestSeqAvgPool):
|
|
def compute(self, x, offset, out):
|
|
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]]
|
|
|
|
|
|
class TestSeqSqrtPoolLen0LoDLevel2(TestSeqSqrtPool):
|
|
def set_lod(self):
|
|
return [[1, 2, 0, 3], [0, 7, 0, 2, 2, 0]]
|
|
|
|
|
|
class TestSeqLastPool(TestSeqAvgPool):
|
|
def compute(self, x, offset, out):
|
|
self.attrs = {"pad_value": 0.0, 'pooltype': "LAST"}
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = self.attrs["pad_value"]
|
|
else:
|
|
sub_x = x[offset[level][i]:offset[level][i + 1], :]
|
|
out[i] = sub_x[-1, :]
|
|
|
|
|
|
class TestSeqLastPoolLen0(TestSeqLastPool):
|
|
def set_lod(self):
|
|
return [[0, 3, 4, 0, 4, 0]]
|
|
|
|
|
|
class TestSeqLastPoolLen0LoDLevel2(TestSeqLastPool):
|
|
def set_lod(self):
|
|
return [[1, 0, 2, 3], [0, 3, 4, 0, 4, 0]]
|
|
|
|
|
|
class TestSeqFirstPool(TestSeqAvgPool):
|
|
def compute(self, x, offset, out):
|
|
self.attrs = {"pad_value": 0.3, 'pooltype': "FIRST"}
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = self.attrs["pad_value"]
|
|
else:
|
|
sub_x = x[offset[level][i]:offset[level][i + 1], :]
|
|
out[i] = sub_x[0, :]
|
|
|
|
|
|
class TestSeqFirstPoolLen0(TestSeqFirstPool):
|
|
def set_lod(self):
|
|
return [[0, 2, 0, 3, 6, 0]]
|
|
|
|
|
|
class TestSeqFirstPoolLen0LoDLevel2(TestSeqFirstPool):
|
|
def set_lod(self):
|
|
return [[1, 0, 2, 3], [0, 2, 0, 3, 6, 0]]
|
|
|
|
|
|
class TestSeqAvgPool2D(TestSeqAvgPool):
|
|
def set_lod(self):
|
|
return [[4, 1, 3, 5]]
|
|
|
|
def set_data(self):
|
|
self.op_type = 'sequence_pool'
|
|
x = np.random.uniform(0.1, 1, [13, 3, 17]).astype('float32')
|
|
lod = self.set_lod()
|
|
level = len(lod) - 1
|
|
self.inputs = {'X': (x, lod)}
|
|
offset = convert_to_offset(lod)
|
|
|
|
out = np.zeros((len(lod[level]), 3, 17)).astype('float32')
|
|
self.outputs = {'Out': out}
|
|
return x, offset, out
|
|
|
|
def compute(self, x, offset, out):
|
|
self.attrs = {"pad_value": 0.0, 'pooltype': "AVERAGE"}
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = self.attrs["pad_value"] * np.ones((3, 17))
|
|
else:
|
|
sub_x = np.reshape(x[offset[level][i]:offset[level][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]]
|
|
|
|
|
|
class TestSeqAvgPool2DLen0LoDLevel2(TestSeqAvgPool2D):
|
|
def set_lod(self):
|
|
return [[1, 0, 4], [0, 5, 0, 8, 0]]
|
|
|
|
|
|
class TestSeqSumPool2D(TestSeqAvgPool2D):
|
|
def compute(self, x, offset, out):
|
|
self.attrs = {"pad_value": 0.2, 'pooltype': "SUM"}
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = self.attrs["pad_value"] * np.ones((3, 17))
|
|
else:
|
|
sub_x = np.reshape(x[offset[level][i]:offset[level][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]]
|
|
|
|
|
|
class TestSeqSumPool2DLen0LoDLevel2(TestSeqSumPool2D):
|
|
def set_lod(self):
|
|
return [[1, 0, 4], [0, 8, 0, 5, 0]]
|
|
|
|
|
|
class TestSeqSqrtPool2D(TestSeqAvgPool2D):
|
|
def compute(self, x, offset, out):
|
|
self.attrs = {"pad_value": 0.0, 'pooltype': "SQRT"}
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = self.attrs["pad_value"] * np.ones((3, 17))
|
|
else:
|
|
sub_x = np.reshape(x[offset[level][i]:offset[level][i + 1], :],
|
|
(-1, 3 * 17))
|
|
seq_len = offset[level][i + 1] - offset[level][i]
|
|
out[i] = np.reshape(
|
|
sub_x.sum(axis=0) / np.sqrt(seq_len), (3, 17))
|
|
|
|
def test_check_grad(self):
|
|
# Remove MaxIndex after check_grad is refined.
|
|
out = self.outputs['Out']
|
|
if isinstance(out, tuple):
|
|
out = out[0]
|
|
self.outputs['MaxIndex'] = \
|
|
np.zeros(out.shape).astype('int32')
|
|
self.check_grad(["X"], "Out", max_relative_error=0.06)
|
|
|
|
|
|
class TestSeqSqrtPool2DLen0(TestSeqSqrtPool2D):
|
|
def set_lod(self):
|
|
return [[0, 8, 0, 5, 0]]
|
|
|
|
|
|
class TestSeqSqrtPool2DLen0LoDLevel2(TestSeqSqrtPool2D):
|
|
def set_lod(self):
|
|
return [[1, 0, 2, 2], [0, 8, 0, 5, 0]]
|
|
|
|
|
|
class TestSeqMaxPool2D(TestSeqAvgPool2D):
|
|
def set_lod(self):
|
|
return [[4, 1, 3, 5]]
|
|
|
|
def set_data(self):
|
|
self.op_type = 'sequence_pool'
|
|
x = np.random.uniform(0.1, 1, [13, 3, 11]).astype('float32')
|
|
self.lod = self.set_lod()
|
|
level = len(self.lod) - 1
|
|
self.inputs = {'X': (x, self.lod)}
|
|
offset = convert_to_offset(self.lod)
|
|
for i in range(len(offset[level]) - 1):
|
|
l = offset[level][i + 1] - offset[level][i]
|
|
if l == 0:
|
|
continue
|
|
x[offset[level][i] + np.random.randint(l), :] += 1.0
|
|
|
|
out = np.zeros((len(self.lod[level]), 3, 11)).astype('float32')
|
|
self.outputs = {'Out': out}
|
|
return x, offset, out
|
|
|
|
def compute(self, x, offset, out):
|
|
self.attrs = {"pad_value": 0.0, 'pooltype': "MAX"}
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = self.attrs["pad_value"] * np.ones((3, 11))
|
|
continue
|
|
sub_x = np.reshape(x[offset[level][i]:offset[level][i + 1], :],
|
|
(-1, 3 * 11))
|
|
out[i] = np.reshape(np.amax(sub_x, axis=0), (3, 11))
|
|
|
|
|
|
class TestSeqMaxPool2DLen0(TestSeqMaxPool2D):
|
|
def set_lod(self):
|
|
return [[0, 3, 0, 10, 0]]
|
|
|
|
|
|
class TestSeqMaxPool2DLen0LoDLevel2(TestSeqMaxPool2D):
|
|
def set_lod(self):
|
|
return [[1, 0, 2, 2], [0, 3, 0, 10, 0]]
|
|
|
|
|
|
class TestSeqMaxPool2DInference(TestSeqMaxPool2D):
|
|
def compute(self, x, offset, out):
|
|
self.attrs = {"pad_value": 1.0, 'pooltype': "MAX", 'is_test': True}
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = self.attrs["pad_value"] * np.ones((3, 11))
|
|
else:
|
|
sub_x = np.reshape(x[offset[level][i]:offset[level][i + 1], :],
|
|
(-1, 3 * 11))
|
|
out[i] = np.reshape(np.amax(sub_x, axis=0), (3, 11))
|
|
|
|
def test_check_grad(self):
|
|
"""Grad computation does not apply to Sequence MAX
|
|
Pool executed when is_test is true """
|
|
return
|
|
|
|
|
|
class TestSeqMaxPool2DInferenceLen0(TestSeqMaxPool2DInference):
|
|
def set_lod(self):
|
|
return [[0, 3, 0, 10, 0]]
|
|
|
|
|
|
class TestSeqMaxPool2DInferenceLen0LoDLevel2(TestSeqMaxPool2DInference):
|
|
def set_lod(self):
|
|
return [[1, 0, 2, 2], [0, 3, 0, 10, 0]]
|
|
|
|
|
|
class TestSeqLastPool2D(TestSeqAvgPool2D):
|
|
def compute(self, x, offset, out):
|
|
self.attrs = {"pad_value": 0.0, 'pooltype': "LAST"}
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = self.attrs["pad_value"] * np.ones((3, 17))
|
|
else:
|
|
sub_x = np.reshape(x[offset[level][i]:offset[level][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]]
|
|
|
|
|
|
class TestSeqLastPool2DLen0LoDLevel2(TestSeqLastPool2D):
|
|
def set_lod(self):
|
|
return [[1, 0, 2, 3], [0, 3, 0, 1, 9, 0]]
|
|
|
|
|
|
class TestSeqFirstPool2D(TestSeqAvgPool2D):
|
|
def compute(self, x, offset, out):
|
|
self.attrs = {"pad_value": 0.0, 'pooltype': "FIRST"}
|
|
level = len(offset) - 1
|
|
for i in range(len(offset[level]) - 1):
|
|
if offset[level][i] == offset[level][i + 1]:
|
|
out[i] = self.attrs["pad_value"] * np.ones((3, 17))
|
|
else:
|
|
sub_x = np.reshape(x[offset[level][i]:offset[level][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]]
|
|
|
|
|
|
class TestSeqFirstPool2DLen0LoDLevel2(TestSeqFirstPool2D):
|
|
def set_lod(self):
|
|
return [[1, 0, 2, 3], [0, 3, 0, 3, 7, 0]]
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|