parent
83627d3efd
commit
2a8dbd130d
@ -1,44 +0,0 @@
|
|||||||
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
|
|
||||||
|
|
||||||
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. */
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "/paddle/operators/math/detail/hl_functions.h"
|
|
||||||
|
|
||||||
namespace hppl {
|
|
||||||
|
|
||||||
real relu(const real a) { return a > 0.0f ? a : 0.0f; }
|
|
||||||
|
|
||||||
real sigmoid(const real a) {
|
|
||||||
const real min = SIGMOID_THRESHOLD_MIN;
|
|
||||||
const real max = SIGMOID_THRESHOLD_MAX;
|
|
||||||
real tmp = (a < min) ? min : ((a > max) ? max : a);
|
|
||||||
return 1.0 / (1.0 + exp(-tmp));
|
|
||||||
}
|
|
||||||
|
|
||||||
real tanh(const real a) {
|
|
||||||
real tmp = -2.0 * a;
|
|
||||||
tmp = (tmp > EXP_MAX_INPUT) ? EXP_MAX_INPUT : tmp;
|
|
||||||
return (2.0 / (1.0 + exp(tmp))) - 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
real linear(const real a) { return a; }
|
|
||||||
|
|
||||||
real relu(const real a, const real b) { return a * (b > 0.0f ? 1.0f : 0.0f); }
|
|
||||||
|
|
||||||
real sigmoid(const real a, const real b) { return a * b * (1 - b); }
|
|
||||||
|
|
||||||
real tanh(const real a, const real b) { return a * (1.0f - b * b); }
|
|
||||||
|
|
||||||
real linear(const real a, const real b) { return a; }
|
|
||||||
} // namespace hppl
|
|
@ -0,0 +1,116 @@
|
|||||||
|
import unittest
|
||||||
|
import numpy as np
|
||||||
|
from op_test import OpTest
|
||||||
|
|
||||||
|
|
||||||
|
def identity(x):
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
def sigmoid(x):
|
||||||
|
return 1. / (1. + np.exp(-x))
|
||||||
|
|
||||||
|
|
||||||
|
def tanh(x):
|
||||||
|
return 2. * sigmoid(2. * x) - 1.
|
||||||
|
|
||||||
|
|
||||||
|
def relu(x):
|
||||||
|
return np.maximum(x, 0)
|
||||||
|
|
||||||
|
|
||||||
|
def lstm(
|
||||||
|
input, # T x 4D
|
||||||
|
lod, # 1 x N
|
||||||
|
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,
|
||||||
|
gate_act=None,
|
||||||
|
cell_act=None,
|
||||||
|
cand_act=None):
|
||||||
|
def _step(x, w_h, w_c, h_pre, c_pre, gate_act, cell_act, cand_act):
|
||||||
|
g = np.dot(h_pre, w_h) # 1 x 4D
|
||||||
|
g = g + x
|
||||||
|
g = np.reshape(g, (1, g.size))
|
||||||
|
c, g_i, g_f, g_o = np.split(g, 4, axis=1)
|
||||||
|
if w_c is None:
|
||||||
|
g_i = gate_act(g_i) # 1 x D
|
||||||
|
g_f = gate_act(g_f) # 1 x D
|
||||||
|
else:
|
||||||
|
w_ic, w_fc, w_oc = np.split(w_c, 3, axis=1)
|
||||||
|
g_i = gate_act(g_i + w_ic * c_pre) # 1 x D
|
||||||
|
g_f = gate_act(g_f + w_fc * c_pre) # 1 x D
|
||||||
|
c = g_f * c_pre + g_i * cand_act(c) # 1 x D
|
||||||
|
|
||||||
|
if w_c is None:
|
||||||
|
g_o = gate_act(g_o) # 1 x D
|
||||||
|
else:
|
||||||
|
_, _, w_oc = np.split(w_c, 3, axis=1)
|
||||||
|
g_o = gate_act(g_o + w_oc * c) # 1 x D
|
||||||
|
h = g_o * cell_act(c)
|
||||||
|
return h, c
|
||||||
|
|
||||||
|
offset = lod[0]
|
||||||
|
batch_size = len(offset) - 1
|
||||||
|
hidden = []
|
||||||
|
cell = []
|
||||||
|
if w_b is not None:
|
||||||
|
input = input + np.tile(w_b, (offset[-1], 1))
|
||||||
|
for i in range(batch_size):
|
||||||
|
# compute one sequence
|
||||||
|
seq_len = offset[i + 1] - offset[i]
|
||||||
|
x = input[offset[i]:offset[i + 1], :]
|
||||||
|
h_pre = h0[i] # 1 x D
|
||||||
|
c_pre = h0[i] # 1 x D
|
||||||
|
for j in range(seq_len):
|
||||||
|
# compute one step
|
||||||
|
h_pre, c_pre = _step(x[j], w_h, w_c, h_pre, c_pre, gate_act,
|
||||||
|
cell_act, cand_act)
|
||||||
|
hidden.append(h_pre.flatten())
|
||||||
|
cell.append(c_pre.flatten())
|
||||||
|
|
||||||
|
hidden = np.array(hidden).astype("float64")
|
||||||
|
cell = np.array(cell).astype("float64")
|
||||||
|
assert hidden.shape == (input.shape[0], input.shape[1] / 4)
|
||||||
|
assert cell.shape == (input.shape[0], input.shape[1] / 4)
|
||||||
|
return hidden, cell
|
||||||
|
|
||||||
|
|
||||||
|
class LstmUnitTest(OpTest):
|
||||||
|
def set_data(self):
|
||||||
|
lod = [[0, 2, 6, 9]]
|
||||||
|
shape = (9, 64)
|
||||||
|
|
||||||
|
x = np.random.normal(size=(9, 4 * 64)).astype("float64")
|
||||||
|
h0 = np.random.normal(size=(4, 64)).astype("float64")
|
||||||
|
c0 = np.random.normal(size=(4, 64)).astype("float64")
|
||||||
|
w = np.random.normal(size=(64, 4 * 64)).astype("float64")
|
||||||
|
b = np.random.normal(size=(1, 7 * 64)).astype("float64")
|
||||||
|
|
||||||
|
w_b = b[:, 4 * 64]
|
||||||
|
w_c = b[:, 4 * 64:]
|
||||||
|
h, c = lstm(x, lod, h0, c0, w, w_b, w_c, False, sigmoid, tanh, tanh)
|
||||||
|
|
||||||
|
self.inputs = {'Input': x, 'H0': h0, 'C0': c0, 'Weight': w, 'Bias': b}
|
||||||
|
self.inputs = {'Hidden': h, 'Cell': c}
|
||||||
|
self.attrs = {
|
||||||
|
'usePeepholes': True,
|
||||||
|
'isReverse': False,
|
||||||
|
'gateActivation': 'sigmoid',
|
||||||
|
'cellActivation': 'tanh',
|
||||||
|
'candidateActivation': 'tanh'
|
||||||
|
}
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.set_data()
|
||||||
|
self.op_type = "lstm"
|
||||||
|
|
||||||
|
def test_check_output(self):
|
||||||
|
self.check_output()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
Loading…
Reference in new issue