**Recursive Layers**

## TensorTree

TensorTree class is used to decode a tensor to a tree structure.
The given input `content`

is a tensor which encodes a constituency parse tree.
The tensor should have the following structure:

Each row of the tensor represents a tree node and the row number is node number.
For each row, except the last column, all other columns represent the children
node number of this node. Assume the value of a certain column of the row is not zero,
the value `p`

means this node has a child whose node number is `p`

(lies in the `p`

-th)
row. Each leaf has a leaf number, in the tensor, the last column represents the leaf number.
Each leaf does not have any children, so all the columns of a leaf except the last should
be zero. If a node is the root, the last column should equal to `-1`

.

Note: if any row for padding, the padding rows should be placed at the last rows with all
elements equal to `-1`

.

eg. a tensor represents a binary tree:

```
[11, 10, -1;
0, 0, 1;
0, 0, 2;
0, 0, 3;
0, 0, 4;
0, 0, 5;
0, 0, 6;
4, 5, 0;
6, 7, 0;
8, 9, 0;
2, 3, 0;
-1, -1, -1;
-1, -1, -1]
```

Parameters:
* `content`

the tensor to be encoded

## TreeLSTM

TreeLSTM is a base class of all other kinds of tree lstms, , as described in the paper Improved Semantic Representations From Tree-Structured Long Short-Term Memory Networks by Kai Sheng Tai, Richard Socher, and Christopher Manning.

## BinaryTreeLSTM

**Scala:**

```
val treeLSTM = BinaryTreeLSTM(
inputSize,
hiddenSize,
gateOutput,
withGraph)
```

**Python:**

```
tree_lstm = BinaryTreeLSTM(
input_size,
hidden_size,
gate_output,
with_graph)
```

This class is an implementation of Binary TreeLSTM (Constituency Tree LSTM) receiving Constituency-based parse trees. Tree-LSTM is a kind of recursive neural networks, as described in the paper Improved Semantic Representations From Tree-Structured Long Short-Term Memory Networks by Kai Sheng Tai, Richard Socher, and Christopher Manning.

The input tensor in `forward(input)`

is expected to be a table, in which the first element is a 3D tensor (`batch x leaf number x inputSize`

) and the second elment is the 3D embedding tensor tree
(`batch x tree node number x (number of branches + 1)`

]. output of
`forward(input)`

is expected to be a 3D tensor (`batch x tree node number x hiddenSize`

).

Parameters:
* inputSize the size of each input vector
*

`hiddenSize`

hidden unit size in GRU

`gateOutput`

whether gate the output. Default is `true`

`withGraph`

whether create lstms with `com.intel.analytics.bigdl.nn.Graph`

. Default is `true`

.**Scala example:**

```
import com.intel.analytics.bigdl.numeric.NumericFloat
import com.intel.analytics.bigdl.utils.RandomGenerator.RNG
RNG.setSeed(100)
val hiddenSize = 2
val inputSize = 2
val inputs =
Tensor(
T(T(T(1f, 2f),
T(2f, 3f),
T(4f, 5f))))
val tree =
Tensor(
T(T(T(2f, 5f, -1f),
T(0f, 0f, 1f),
T(0f, 0f, 2f),
T(0f, 0f, 3f),
T(3f, 4f, 0f))))
val input = T(inputs, tree)
val gradOutput =
Tensor(
T(T(T(2f, 5f),
T(2f, 3f),
T(4f, 5f),
T(2f, 3f),
T(4f, 5f),
T(6f, 7f))))
val model = BinaryTreeLSTM(inputSize, hiddenSize)
val output = model.forward(input)
println(output)
(1,.,.) =
-0.07799375 -0.14419462
-0.23495524 -0.04679072
-0.15945151 -0.026039641
-0.0454074 -0.007066241
-0.058696028 -0.13559057
[com.intel.analytics.bigdl.tensor.DenseTensor of size 1x5x2]
val gradInput = model.backward(input, gradOutput)
println(gradInput)
{
2: (1,.,.) =
0.0 0.0 0.0
0.0 0.0 0.0
0.0 0.0 0.0
0.0 0.0 0.0
0.0 0.0 0.0
[com.intel.analytics.bigdl.tensor.DenseTensor of size 1x5x3]
1: (1,.,.) =
0.56145966 -0.3383652
0.81720364 -0.46767634
0.37739626 -0.23355529
[com.intel.analytics.bigdl.tensor.DenseTensor of size 1x3x2]
}
```

**Python example:**

```
from bigdl.nn.layer import *
from bigdl.nn.criterion import *
import numpy as np
hidden_size = 2
input_size = 2
inputs = np.array([[
[1.0, 2.0],
[2.0, 3.0],
[4.0, 5.0]
]])
tree = np.array([[
[2.0, 5.0, -1.0],
[0.0, 0.0, 1.0],
[0.0, 0.0, 2.0],
[0.0, 0.0, 3.0],
[3.0, 4.0, 0.0]
]])
input = [inputs, tree]
grad_output = np.array([[
[2.0, 3.0],
[4.0, 5.0],
[2.0, 3.0],
[4.0, 5.0],
[6.0, 7.0]
]])
model = BinaryTreeLSTM(input_size, hidden_size)
output = model.forward(input)
print output
[[[-0.08113038 -0.0289295 ]
[ 0.1378704 0.00550814]
[ 0.33053339 -0.02395477]
[ 0.26895314 -0.02019646]
[ 0.34085754 -0.12480961]]]
gradient = model.backward(input, grad_output)
print gradient
[array([[[ 0.43623093, 0.97416967],
[-0.02283204, 0.99245077],
[-1.11290622, 0.84173977]]], dtype=float32), array([[[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]]], dtype=float32)]
```