test_fusion_lstm_op.py 4.2 KB
Newer Older
T
tensor-tang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
#   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.

import unittest
import numpy as np
from op_test import OpTest
from test_lstm_op import lstm, ACTIVATION


def fc(x, w, b):
    return np.dot(x, w) + b


def fusion_lstm(
        x,  # T x M
        lod,  # 1 x N
        wx=None,  # M x 4D
        bx=None,  # 1 x 4D
        h0=None,  # N x D
        c0=None,  # N x D
        w_h=None,  # D x 4D
        w_b=None,  # 1 x 4D
        w_c=None,  # 1 x 3D
        is_reverse=False,
        act_gate=None,
        act_cell=None,
        act_cand=None):
    return lstm(
        fc(x, wx, bx), lod, h0, c0, w_h, w_b, w_c, is_reverse, act_gate,
        act_cell, act_cand)


class TestLstmOp(OpTest):
    def set_argument(self):
        self.lod = [[2, 3, 2]]

    def setUp(self):
        self.op_type = 'fusion_lstm'
        self.lod = [[2, 3, 2]]
        self.M = 8
        self.D = 16
        self.has_initial_state = False
        self.is_reverse = False
        self.act_gate = 'sigmoid'
        self.act_cell = 'tanh'
        self.act_cand = 'tanh'
        self.use_peepholes = False
        self.set_argument()

        T = sum(self.lod[0])
        bs = len(self.lod[0])

T
tensor-tang 已提交
64
        x = np.random.normal(size=(T, self.M)).astype('float64')
T
tensor-tang 已提交
65
        if self.has_initial_state:
T
tensor-tang 已提交
66 67
            h0 = np.random.normal(size=(bs, self.D)).astype('float64')
            c0 = np.random.normal(size=(bs, self.D)).astype('float64')
T
tensor-tang 已提交
68
        else:
T
tensor-tang 已提交
69 70
            h0 = np.zeros((bs, self.D)).astype('float64')
            c0 = np.zeros((bs, self.D)).astype('float64')
T
tensor-tang 已提交
71

T
tensor-tang 已提交
72
        wh = np.random.normal(size=(self.D, 4 * self.D)).astype('float64')
T
tensor-tang 已提交
73 74

        if self.use_peepholes:
T
tensor-tang 已提交
75
            b = np.random.normal(size=(1, 7 * self.D)).astype('float64')
T
tensor-tang 已提交
76
        else:
T
tensor-tang 已提交
77
            b = np.random.normal(size=(1, 4 * self.D)).astype('float64')
T
tensor-tang 已提交
78 79 80 81
        w_b = np.copy(b[:, 0:4 * self.D])
        w_c = b[:, 4 * self.D:] if self.use_peepholes else None

        # this is the weight of fc
T
tensor-tang 已提交
82
        wx = np.random.normal(size=(self.M, 4 * self.D)).astype('float64')
T
tensor-tang 已提交
83 84
        # this is the bias of fc
        # and it should be manually added into the bias of this fusion LSTM
T
tensor-tang 已提交
85
        bx = np.random.normal(size=(1, 4 * self.D)).astype('float64')
T
tensor-tang 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
        b[0, 0:4 * self.D] += bx[0, :]
        h, c = fusion_lstm(x, self.lod, wx, bx, h0, c0, wh, w_b, w_c,
                           self.is_reverse, ACTIVATION[self.act_gate],
                           ACTIVATION[self.act_cell], ACTIVATION[self.act_cand])

        self.inputs = {
            'X': (x, self.lod),
            'WeightX': wx,
            'WeightH': wh,
            'Bias': b
        }

        if self.has_initial_state:
            self.inputs['H0'] = h0
            self.inputs['C0'] = c0

        self.outputs = {
            'Hidden': (h, self.lod),
            'Cell': (c, self.lod),
        }
        self.attrs = {
            'use_peepholes': self.use_peepholes,
            'is_reverse': self.is_reverse,
            'gate_activation': self.act_gate,
            'cell_activation': self.act_cell,
            'candidate_activation': self.act_cand
        }

    def test_check_output(self):
T
tensor-tang 已提交
115
        self.check_output(atol=1e-8)
T
tensor-tang 已提交
116 117 118 119 120 121 122 123 124 125


class TestLstmOpInitReverse(TestLstmOp):
    def set_argument(self):
        self.has_initial_state = True
        self.is_reverse = True


class TestLstmOpMD1(TestLstmOp):
    def set_argument(self):
T
tensor-tang 已提交
126
        self.M = 36
T
tensor-tang 已提交
127 128 129 130 131
        self.D = 8


class TestLstmOpMD2(TestLstmOp):
    def set_argument(self):
T
tensor-tang 已提交
132
        self.M = 8
T
tensor-tang 已提交
133 134 135
        self.D = 8


T
tensor-tang 已提交
136 137 138 139 140 141
class TestLstmOpMD3(TestLstmOp):
    def set_argument(self):
        self.M = 15
        self.D = 3


T
tensor-tang 已提交
142 143 144 145 146 147 148 149
class TestLstmOpBS1(TestLstmOp):
    def set_argument(self):
        self.lod = [[3]]
        self.D = 16


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