| 25 | namespace MNN { |
| 26 | |
| 27 | class BlstmComputer { |
| 28 | /** |
| 29 | Blstm: |
| 30 | Xt = input at timestep t |
| 31 | Ct-1 = cell state of last time step |
| 32 | O = sigmoid activation |
| 33 | x = matrix product |
| 34 | * = matrix dot product |
| 35 | Input gate: It = Og(Xt x Wi + Ht-1 x Ui + Bi) |
| 36 | Next gate: Nt = tanh(Xt x Wn + Ht-1 x Un + Bn) |
| 37 | Forget gate: Ft = Og(Xt x Wf + Ht-1 x Uf + Bf) |
| 38 | Output gate: Ot = Og(Xt x Wo + Ht-1 x Uo + Bo) |
| 39 | Cell state: Ct = Nt * It + Ct-1 * Ft |
| 40 | Hidden state: Ht = tanh(Ct) * Ot |
| 41 | output : Ht |
| 42 | |
| 43 | Suppose input is a (Batch, Timestep, Feature) tensor |
| 44 | General usage: |
| 45 | (1). Construct a BlstmComputer* blstm = new BlstmComputer(); |
| 46 | (2). Call blstm.importWeights() to import weight into this blstm. |
| 47 | (3). Upon every execution, first blstm.onResize(), then |
| 48 | blstm.onExecute() This is a single layer blstm. If you want to construct a |
| 49 | multi-layer blstm, you can just construct multiple blstm instances with |
| 50 | proper args and connect them together. |
| 51 | */ |
| 52 | |
| 53 | public: |
| 54 | /** |
| 55 | * @brief construct the BlstmComputer instance. |
| 56 | * @param inDim input dimension, correspond to 'Feature' in input(Batch, |
| 57 | * Timestep, Feature) |
| 58 | * @param stateSize hidden state & cell state size. |
| 59 | * @param bidirectional if this is a bidirectional or unidirectional lstm |
| 60 | * @param backend backend |
| 61 | */ |
| 62 | BlstmComputer(int inDim, int stateSize, bool bidirectional, |
| 63 | MNN::CPUBackend *backend); |
| 64 | virtual ~BlstmComputer(); |
| 65 | /** |
| 66 | * @brief sigmoid activation function |
| 67 | */ |
| 68 | static float sigmoid(float x); |
| 69 | |
| 70 | /** |
| 71 | * @brief trim tensor into correct storage order. For NCHW and NHWC, data will |
| 72 | * be directly copied, interal storage order will not be changed. For NC4HW4, |
| 73 | * onCopyBuffer() will be used, interal storage order will be changed. |
| 74 | */ |
| 75 | void trimTensor(Tensor *src_tensor, Tensor *tgt_tensor); |
| 76 | |
| 77 | /** |
| 78 | * @brief allocate space for all the weights and bias. And import data from |
| 79 | weightsVec. |
| 80 | * @param weightsVec |
| 81 | WeightsVec must has the same order as mWeights. This method will copy each |
| 82 | tensor in WeightsVec to corresponding mWeight. for weightsVec[0-3, 12-15], |
| 83 | shape = (mInDim, mStateSize) for weightsVec[4-7, 16-19], shape = (mStateSize, |
| 84 | mStateSize) for weightsVec[8-11, 20-23], shape = (mStateSize) For |