---
title: "GatedRecurrentLayer"
language: "en"
type: "Symbol"
summary: "GatedRecurrentLayer[n] represents a trainable recurrent layer that takes a sequence of vectors and produces a sequence of vectors each of size n. GatedRecurrentLayer[n, opts] includes options for initial weights and other parameters."
keywords: 
- gated recurrent layer
- gru
- gru layer
- gated recurrent neural networks
- gated layer
canonical_url: "https://reference.wolfram.com/language/ref/GatedRecurrentLayer.html"
source: "Wolfram Language Documentation"
related_guides: 
  - 
    title: "Neural Network Layers"
    link: "https://reference.wolfram.com/language/guide/NeuralNetworkLayers.en.md"
  - 
    title: "Speech Computation"
    link: "https://reference.wolfram.com/language/guide/SpeechComputation.en.md"
related_functions: 
  - 
    title: "NetStateObject"
    link: "https://reference.wolfram.com/language/ref/NetStateObject.en.md"
  - 
    title: "BasicRecurrentLayer"
    link: "https://reference.wolfram.com/language/ref/BasicRecurrentLayer.en.md"
  - 
    title: "LongShortTermMemoryLayer"
    link: "https://reference.wolfram.com/language/ref/LongShortTermMemoryLayer.en.md"
  - 
    title: "NetBidirectionalOperator"
    link: "https://reference.wolfram.com/language/ref/NetBidirectionalOperator.en.md"
  - 
    title: "NetFoldOperator"
    link: "https://reference.wolfram.com/language/ref/NetFoldOperator.en.md"
  - 
    title: "NetMapOperator"
    link: "https://reference.wolfram.com/language/ref/NetMapOperator.en.md"
  - 
    title: "SequenceLastLayer"
    link: "https://reference.wolfram.com/language/ref/SequenceLastLayer.en.md"
  - 
    title: "LinearLayer"
    link: "https://reference.wolfram.com/language/ref/LinearLayer.en.md"
  - 
    title: "NetChain"
    link: "https://reference.wolfram.com/language/ref/NetChain.en.md"
  - 
    title: "NetGraph"
    link: "https://reference.wolfram.com/language/ref/NetGraph.en.md"
  - 
    title: "NetExtract"
    link: "https://reference.wolfram.com/language/ref/NetExtract.en.md"
related_tutorials: 
  - 
    title: "Neural Networks in the Wolfram Language"
    link: "https://reference.wolfram.com/language/tutorial/NeuralNetworksOverview.en.md"
---
[EXPERIMENTAL]

# GatedRecurrentLayer

GatedRecurrentLayer[n] represents a trainable recurrent layer that takes a sequence of vectors and produces a sequence of vectors each of size n.

GatedRecurrentLayer[n, opts] includes options for initial weights and other parameters.

## Details and Options

* ``GatedRecurrentLayer[n]`` represents a net that takes an input matrix representing a sequence of vectors and outputs a sequence of the same length.

* Each element of the input sequence is a vector of size ``k``, and each element of the output sequence is a vector of size ``n``.

* The size ``k`` of the input vectors is usually inferred automatically within a ``NetGraph``, ``NetChain``, etc.

* The input and output ports of the net represented by ``GatedRecurrentLayer[n]`` are:

|          |                                 |
| -------- | ------------------------------- |
| "Input"  | a sequence of vectors of size k |
| "Output" | a sequence of vectors of size n |

* Given an input sequence ``{x1, x2, …, xT}``, a ``GatedRecurrentLayer`` outputs a sequence of states ``{s1, s2, …, sT}`` using the following recurrence relation:

|             |                                                |
| ----------- | ---------------------------------------------- |
| input gate  | it = LogisticSigmoid[Wix.xt + Wis.st - 1 + bi] |
| reset gate  | rt = LogisticSigmoid[Wrx.xt + Wrs.st - 1 + br] |
| memory gate | mt = Tanh[Wmx.xt + rt * (Wms.st - 1) + bm]     |
| state       | st = (1 - it) * mt + it * st - 1               |

* The above definition of ``GatedRecurrentLayer`` is based on the variant described in Chung et al., *Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling*, 2014.

* ``GatedRecurrentLayer[n]`` also has a single state port, ``"State"``, which is a vector of size ``n``.

* Within a ``NetGraph``, a connection of the form ``src -> NetPort[layer, "State"]`` can be used to provide the initial value of the state for a ``GatedRecurrentLayer``, corresponding to ``s0`` in the recurrence relation. The default initial value is a zero vector.

* Within a ``NetGraph``, a connection of the form ``NetPort[layer, "State"] -> dst`` can be used to obtain the final value of the state for a ``GatedRecurrentLayer``, corresponding to ``sT`` in the recurrence relation.

* ``NetStateObject`` can be used to create a net that will remember values for the state of ``GatedRecurrentLayer`` that update when the net is applied to inputs.

* An initialized ``GatedRecurrentLayer[…]`` that operates on vectors of size ``k`` contains the following trainable arrays:

|                          |     |                    |
| ------------------------ | --- | ------------------ |
| "InputGateInputWeights"  | Wix | matrix of size n×k |
| "InputGateStateWeights"  | Wis | matrix of size n×n |
| "InputGateBiases"        | bi  | vector of size n   |
| "ResetGateInputWeights"  | Wrx | matrix of size n×k |
| "ResetGateStateWeights"  | Wrs | matrix of size n×n |
| "ResetGateBiases"        | br  | vector of size n   |
| "MemoryGateInputWeights" | Wmx | matrix of size n×k |
| "MemoryGateStateWeights" | Wms | matrix of size n×n |
| "MemoryGateBiases"       | bm  | vector of size n   |

* In ``GatedRecurrentLayer[n, opts]``, initial values can be given to the trainable arrays using a rule of the form ``"array" -> value``.

* The following training parameters can be included:

|                         |           |                                                                          |
| ----------------------- | --------- | ------------------------------------------------------------------------ |
| "Dropout"               | None      | dropout regularization, in which units are probabilistically set to zero |
| LearningRateMultipliers | Automatic | learning rate multipliers for the trainable arrays                       |

* Specifying ``"Dropout" -> None`` disables dropout during training.

* Specifying ``"Dropout" -> p`` applies an automatically chosen dropout method with dropout probability ``p``.

* Specifying "Dropout"->{"Subscript[method, 1]"->Subscript[p, 1],"Subscript[method, 2]"->Subscript[p, 2],\[Ellipsis]} can be used to combine specific methods of dropout with the corresponding dropout probabilities. Possible methods include:

|     |     |
| --- | --- |
| "VariationalWeights" | dropout applied to the recurrent connections between weight matrices (default) |
| "VariationalInput" | dropout applied to the gate contributions from the input, using the same pattern of units at each sequence step |
| "VariationalState" | dropout applied to the gate contributions from the previous state, using the same pattern of units at each sequence step |
| "StateUpdate" | dropout applied to the state update vector prior to it being added to the previous state, using a different pattern of units at each sequence step |

* The dropout methods ``"VariationalInput"`` and ``"VariationalState"`` are based on the Gal et al. 2016 method, while ``"StateUpdate"`` is based on the Semeniuta et al. 2016 method and ``"VariationalWeights"`` is based on the Merity et al. 2017 method.

* ``GatedRecurrentLayer[n, "Input" -> shape]`` allows the shape of the input to be specified. Possible forms for ``shape`` are:

|                        |                                                   |
| ---------------------- | ------------------------------------------------- |
| NetEncoder[…]          | encoder producing a sequence of vectors           |
| {len, k}               | sequence of len length-k vectors                  |
| {len, Automatic}       | sequence of len vectors whose length is inferred  |
| {"Varying", k}         | varying number of vectors each of length k        |
| {"Varying", Automatic} | varying number of vectors each of inferred length |

* When given a ``NumericArray`` as input, the output will be a ``NumericArray``.

* ``Options[GatedRecurrentLayer]`` gives the list of default options to construct the layer. ``Options[GatedRecurrentLayer[…]]`` gives the list of default options to evaluate the layer on some data.

* ``Information[GatedRecurrentLayer[…]]`` gives a report about the layer.

* ``Information[GatedRecurrentLayer[…], prop]`` gives the value of the property ``prop`` of ``GatedRecurrentLayer[…]``. [Possible properties](https://reference.wolfram.com/language/ref/NetGraph.en.md#495200340) are the same as for ``NetGraph``.

---

## Examples (12)

### Basic Examples (2)

Create a ``GatedRecurrentLayer`` that produces a sequence of length-3 vectors:

```wl
In[1]:= GatedRecurrentLayer[3]

Out[1]=
GatedRecurrentLayer[Association["Type" -> "GatedRecurrent", 
  "Arrays" -> Association["InputGateInputWeights" -> NeuralNetworks`TensorT[
      {3, NeuralNetworks`SizeT}, NeuralNetworks`RealT], "InputGateStateWeights" -> 
     NeuralNetworks`Tensor ...  NeuralNetworks`TensorT[
      {NeuralNetworks`LengthVar[1066052189], 3}, NeuralNetworks`RealT]], 
  "States" -> Association["State" -> NeuralNetworks`TensorT[{3}, NeuralNetworks`RealT]]], 
 Association["Version" -> "14.1.1", "Unstable" -> False]]
```

---

Create a randomly initialized ``GatedRecurrentLayer`` that takes a sequence of length-2 vectors and produces a sequence of length-3 vectors:

```wl
In[1]:= gru = NetInitialize@GatedRecurrentLayer[3, "Input" -> {"Varying", 2}]

Out[1]=
GatedRecurrentLayer[Association["Type" -> "GatedRecurrent", 
  "Arrays" -> Association["InputGateInputWeights" -> RawArray["Real32", 
      {{-0.3594474792480469, -0.04992305114865303}, {-1.127055048942566, 1.086535930633545}, 
       {1.8936456441 ... NeuralNetworks`TensorT[{NeuralNetworks`LengthVar[1907867702], 3}, 
      NeuralNetworks`RealT]], "States" -> 
   Association["State" -> NeuralNetworks`TensorT[{3}, NeuralNetworks`RealT]]], 
 Association["Version" -> "14.1.1", "Unstable" -> False]]
```

Apply the layer to an input sequence:

```wl
In[2]:= gru[{{1, 2}, {0, 1}, {2, 1}, {1, 2}}]//MatrixForm

Out[2]//MatrixForm=
(⁠|           |           |           |
| --------- | --------- | --------- |
| -0.11167  | 0.153902  | -0.667927 |
| -0.319126 | -0.151816 | -0.514283 |
| -0.402155 | 0.481529  | -0.839676 |
| -0.474362 | 0.282905  | -0.912102 |⁠)
```

### Scope (5)

#### Arguments (1)

Create a ``GatedRecurrentLayer`` that produces a sequence of length-3 vectors:

```wl
In[1]:= GatedRecurrentLayer[2]

Out[1]=
GatedRecurrentLayer[Association["Type" -> "GatedRecurrent", 
  "Arrays" -> Association["InputGateInputWeights" -> NeuralNetworks`TensorT[
      {2, NeuralNetworks`SizeT}, NeuralNetworks`RealT], "InputGateStateWeights" -> 
     NeuralNetworks`Tensor ...  NeuralNetworks`TensorT[{NeuralNetworks`LengthVar[715248120], 
       2}, NeuralNetworks`RealT]], 
  "States" -> Association["State" -> NeuralNetworks`TensorT[{2}, NeuralNetworks`RealT]]], 
 Association["Version" -> "14.1.1", "Unstable" -> False]]
```

---

#### Ports (4)

Create a randomly initialized ``GatedRecurrentLayer`` that takes a string and produces a sequence of length-2 vectors:

```wl
In[1]:=
gru = 
	NetInitialize@GatedRecurrentLayer[2, "Input" -> NetEncoder[{"Characters", Automatic, "UnitVector"}]]

Out[1]=
GatedRecurrentLayer[Association["Type" -> "GatedRecurrent", 
  "Arrays" -> Association["InputGateInputWeights" -> CompressedData["«1177»"], "InputGateStateWeights" -> 
     RawArray["Real32", {{-0.36914902925491333, -0.9783514142036438}, 
       {0 ...  NeuralNetworks`TensorT[{NeuralNetworks`LengthVar[546843100], 
       2}, NeuralNetworks`RealT]], 
  "States" -> Association["State" -> NeuralNetworks`TensorT[{2}, NeuralNetworks`RealT]]], 
 Association["Version" -> "14.1.1", "Unstable" -> False]]
```

Apply the layer to an input string:

```wl
In[2]:= gru["hello world"]//MatrixForm

Out[2]//MatrixForm=
(⁠|             |              |
| ----------- | ------------ |
| -0.00706724 | -0.0212493   |
| 0.0842391   | 0.0819901    |
| -0.0650938  | 0.125202     |
| -0.128755   | 0.123828     |
| 0.035452    | -0.00742704  |
| -0.0588478  | -0.000947591 |
| -0.0218402  | -0.0868912   |
| 0.0768812   | -0.128498    |
| -0.0566253  | 0.0086757    |
| -0.125302   | 0.051791     |
| -0.113944   | -0.0698482   |⁠)
```

Thread the layer over a batch of inputs:

```wl
In[3]:= gru[{"good", "bye"}]//Map[MatrixForm]

Out[3]=
{(⁠|             |            |
| ----------- | ---------- |
| 0.0555968   | -0.0426992 |
| 0.111025    | -0.0859098 |
| 0.133056    | -0.10199   |
| -0.00316393 | -0.131629  |⁠), (⁠|            |            |
| ---------- | ---------- |
| -0.0369498 | -0.101278  |
| -0.137397  | -0.191033  |
| 0.00475381 | -0.0604297 |⁠)}
```

---

Create a randomly initialized net that takes a sequence of length-2 vectors and produces a single length-3 vector:

```wl
In[1]:=
net = NetInitialize@NetChain[{
	GatedRecurrentLayer[3, "Input" -> {"Varying", 2}], 
	SequenceLastLayer[]
	}]

Out[1]=
NetChain[Association["Type" -> "Chain", 
  "Nodes" -> Association["1" -> Association["Type" -> "GatedRecurrent", 
      "Arrays" -> Association["InputGateInputWeights" -> RawArray["Real32", 
          {{-0.3594474792480469, -0.04992305114865303}, { ... sociation["Output" -> NeuralNetworks`TensorT[{3}, NeuralNetworks`RealT]], 
  "InteriorStates" -> Association[{1, "State"} -> NeuralNetworks`NetPath["Nodes", "1", "States", 
      "State"]]], Association["Version" -> "14.1.1", "Unstable" -> False]]
```

Apply the layer to an input:

```wl
In[2]:= net[{{1, 2}, {2, 1}, {3, 0}}]

Out[2]= {-0.902088, 0.0991775, -0.29804}
```

Thread the layer across a batch of inputs:

```wl
In[3]:= net[{{{1, 2}, {2, 1}, {3, 0}}, {{3, 3}, {0, 0}}}]

Out[3]= {{-0.902088, 0.0991775, -0.29804}, {-0.23724, 0.0568412, -0.0665627}}
```

---

Create a ``NetGraph`` that allows the initial state of a ``GatedRecurrentLayer`` to be set:

```wl
In[1]:=
graph = NetInitialize@NetGraph[
	{GatedRecurrentLayer[2, "Input" -> {"Varying", 2}]}, 
	{NetPort["InitialState"] -> NetPort[1, "State"]}]

Out[1]=
NetGraph[Association["Type" -> "Graph", 
  "Inputs" -> Association["InitialState" -> NeuralNetworks`TensorT[{2}, NeuralNetworks`RealT], 
    "Input" -> NeuralNetworks`TensorT[{NeuralNetworks`LengthVar[261246272], 2}, 
      NeuralNetworks`AtomT]],  ... 1", "Inputs", "Input"] -> NeuralNetworks`NetPath["Inputs", 
      "Input"], NeuralNetworks`NetPath["Outputs", "Output"] -> NeuralNetworks`NetPath["Nodes", "1", 
      "Outputs", "Output"]}], Association["Version" -> "14.1.1", "Unstable" -> False]]

In[2]:= graph[<|"Input" -> {{1, 2}, {2, 0}, {3, 1}}, "InitialState" -> {1, 1}|>]

Out[2]= {{0.996846, 0.998839}, {0.993675, 0.945083}, {0.993673, 0.994089}}
```

---

Create a ``NetGraph`` that allows the final state of a ``GatedRecurrentLayer`` to be obtained:

```wl
In[1]:=
graph = NetInitialize@NetGraph[
	{GatedRecurrentLayer[2, "Input" -> {"Varying", 2}]}, 
	{NetPort[1, "State"] -> NetPort["FinalState"]}]

Out[1]=
NetGraph[Association["Type" -> "Graph", 
  "Inputs" -> Association["Input" -> NeuralNetworks`TensorT[{NeuralNetworks`LengthVar[1394897790], 
       2}, NeuralNetworks`AtomT]], "Outputs" -> 
   Association["Output" -> NeuralNetworks`TensorT[{NeuralN ... tput"] -> NeuralNetworks`NetPath["Nodes", "1", "Outputs", 
      "Output"]}, "InteriorStates" -> Association[{1, "State"} -> NeuralNetworks`NetPath["Nodes", 
      "1", "States", "State"]]], Association["Version" -> "14.1.1", "Unstable" -> False]]

In[2]:= graph[{{1, 2}, {2, 0}, {3, 1}}]

Out[2]= <|"FinalState" -> {-0.181389, -0.945833}, "Output" -> {{0.383668, -0.3965}, {-0.0393807, -0.77669}, {-0.181389, -0.945833}}|>
```

The final state is the last element of the output sequence:

```wl
In[3]:= %[["FinalState"]] == %[["Output", -1]]

Out[3]= True
```

### Options (2)

#### "Dropout" (2)

Create a ``GatedRecurrentLayer`` with the dropout method specified:

```wl
In[1]:= net = GatedRecurrentLayer[2, "Dropout" -> {"VariationalInput" -> 0.2, "VariationalState" -> 0.5}]

Out[1]=
GatedRecurrentLayer[Association["Type" -> "GatedRecurrent", 
  "Arrays" -> Association["InputGateInputWeights" -> NeuralNetworks`TensorT[
      {2, NeuralNetworks`SizeT}, NeuralNetworks`RealT], "InputGateStateWeights" -> 
     NeuralNetworks`Tensor ...  NeuralNetworks`TensorT[{NeuralNetworks`LengthVar[358411299], 
       2}, NeuralNetworks`RealT]], 
  "States" -> Association["State" -> NeuralNetworks`TensorT[{2}, NeuralNetworks`RealT]]], 
 Association["Version" -> "14.1.1", "Unstable" -> False]]
```

---

Create a randomly initialized ``GatedRecurrentLayer`` with specified dropout probability:

```wl
In[1]:= gru = NetInitialize@GatedRecurrentLayer[2, "Dropout" -> 0.5, "Input" -> {"Varying", 2}]

Out[1]=
GatedRecurrentLayer[Association["Type" -> "GatedRecurrent", 
  "Arrays" -> Association["InputGateInputWeights" -> RawArray["Real32", 
      {{-0.3594474792480469, -0.04992305114865303}, {-1.127055048942566, 1.086535930633545}}], 
    "InputGateStat ... NeuralNetworks`TensorT[{NeuralNetworks`LengthVar[2036851800], 2}, 
      NeuralNetworks`RealT]], "States" -> 
   Association["State" -> NeuralNetworks`TensorT[{2}, NeuralNetworks`RealT]]], 
 Association["Version" -> "14.1.1", "Unstable" -> False]]
```

Evaluate the layer on a sequence of vectors:

```wl
In[2]:=
data = {{1, 2}, {3, 4}, {1, 0}, {2, 2}};
gru[data]//MatrixForm

Out[2]//MatrixForm=
(⁠|           |           |
| --------- | --------- |
| -0.110076 | 0.0512703 |
| -0.126292 | 0.695913  |
| -0.39989  | 0.77401   |
| -0.464781 | 0.77515   |⁠)
```

Dropout has no effect during evaluation:

```wl
In[3]:=
gru2 = NetReplacePart[gru, "Dropout" -> 0];
gru[data] == gru2[data]

Out[3]= True
```

Use ``NetEvaluationMode`` to force the training behavior of dropout:

```wl
In[4]:= gru[data, NetEvaluationMode -> "Train"]//MatrixForm

Out[4]//MatrixForm=
(⁠|            |          |
| ---------- | -------- |
| -0.0956161 | 0.120176 |
| -0.228879  | 0.954463 |
| -0.166764  | 0.975522 |
| -0.179216  | 0.972073 |⁠)
```

Multiple evaluations on the same input can give different results:

```wl
In[5]:= Table[gru[{{1, 2}, {3, 4}, {5, 6}, {7, 8}}, NetEvaluationMode -> "Train"], 5]//Map[MatrixPlot[#, ImageSize -> 30, FrameTicks -> None]&]

Out[5]= {[image], [image], [image], [image], [image]}
```

### Applications (2)

Create training data consisting of strings that describe two-digit additions and the corresponding numeric result:

```wl
In[1]:=
enc = NetEncoder[{"Characters", {DigitCharacter, "+"}}];
makeRule[a_, b_] := IntegerString[a] <> "+" <> IntegerString[b] -> a + b;
trainingData = Flatten@Table[makeRule[i, j], {i, 0, 99}, {j, 0, 99}];
RandomSample[trainingData, 4]//InputForm
```

Out[1]//InputForm= {"18+41" -> 59, "19+75" -> 94, "16+34" -> 50, "31+66" -> 97}

Create a network using stacked ``GatedRecurrentLayer`` layers that reads the input string and predicts the numeric result:

```wl
In[2]:= net = NetChain[{UnitVectorLayer[], GatedRecurrentLayer[40], GatedRecurrentLayer[30], SequenceLastLayer[], LinearLayer[1]}, "Input" -> enc, "Output" -> "Scalar"];
```

Train the network:

```wl
In[3]:= trained = NetTrain[net, trainingData, BatchSize -> 64, MaxTrainingRounds -> 200, ValidationSet -> Scaled[0.1]]

Out[3]=
NetChain[Association["Type" -> "Chain", 
  "Nodes" -> Association["1" -> Association["Type" -> "UnitVector", "Arrays" -> Association[], 
      "Parameters" -> Association["ClassCount" -> 11, "$Dimensions" -> 
         {NeuralNetworks`LengthVar[1437 ...   "InteriorStates" -> Association[{2, "State"} -> NeuralNetworks`NetPath["Nodes", "2", "States", 
      "State"], {3, "State"} -> NeuralNetworks`NetPath["Nodes", "3", "States", "State"]]], 
 Association["Version" -> "14.1.1", "Unstable" -> False]]
```

Apply the trained network to a list of inputs:

```wl
In[4]:= Round@trained[{"5+2", "10+25", "9+11", "44+44"}]

Out[4]= {7, 35, 20, 88}
```

---

Create training data based on strings containing x's and y's, and either ``Less``, ``Greater`` or ``Equal`` by comparing the number of x's and y's. The training data consists of all possible sentences up to length 8:

```wl
In[1]:=
alphabet = {"x", "y", " "};
inputs = Flatten@Table[StringJoin /@ Tuples[alphabet, n], {n, 1, 8}];
cmpXY[str_] := Switch[Sign[StringCount[str, "x"] - StringCount[str, "y"]], -1, Less, 0, Equal, 1, Greater];
outputs = cmpXY /@ inputs;
trainingData = Thread[inputs -> outputs];
RandomSample[trainingData, 4]//InputForm
```

Out[1]//InputForm=
{" xy   " -> Equal, " xx y  y" -> Equal, "xxxxxyyy" -> Greater, 
 "x xxxxyx" -> Greater}

Create a network containing a ``GatedRecurrentLayer`` to read an input string and predict one of ``Less``, ``Greater`` or ``Equal`` :

```wl
In[2]:= net = NetChain[{UnitVectorLayer[], GatedRecurrentLayer[5], SequenceLastLayer[], LinearLayer[3], SoftmaxLayer[]}, "Input" -> NetEncoder[{"Characters", alphabet}], "Output" -> NetDecoder[{"Class", {Less, Equal, Greater}}]];
```

Train the network:

```wl
In[3]:= trained = NetTrain[net, trainingData, BatchSize -> 64, MaxTrainingRounds -> 100, ValidationSet -> Scaled[0.2]]

Out[3]=
NetChain[Association["Type" -> "Chain", 
  "Nodes" -> Association["1" -> Association["Type" -> "UnitVector", "Arrays" -> Association[], 
      "Parameters" -> Association["ClassCount" -> 3, "$Dimensions" -> 
         {NeuralNetworks`LengthVar[63169 ... n" -> "14.1.1"], NeuralNetworks`TensorT[{3}, 
       NeuralNetworks`RealT]]], "InteriorStates" -> 
   Association[{2, "State"} -> NeuralNetworks`NetPath["Nodes", "2", "States", "State"]]], 
 Association["Version" -> "14.1.1", "Unstable" -> False]]
```

Apply the trained network to a list of inputs:

```wl
In[4]:= trained[{"xxy", "xyy", "xyxy"}]

Out[4]= {Greater, Less, Equal}
```

Measure the accuracy on the entire training set:

```wl
In[5]:= NetMeasurements[trained, trainingData, "Accuracy"]

Out[5]= 1.
```

### Properties & Relations (1)

``NetStateObject`` can be used to create a net that remembers the state of ``GatedRecurrentLayer`` :

```wl
In[1]:= sobj = NetStateObject[NetInitialize@GatedRecurrentLayer[2, "Input" -> {"Varying", 2}]]

Out[1]=
NetStateObject[Association["Net" -> GatedRecurrentLayer[Association["Type" -> "GatedRecurrent", 
     "Arrays" -> Association["InputGateInputWeights" -> RawArray["Real32", 
         {{-0.3594474792480469, -0.04992305114865303}, {-1.127055048942566, ... , "SessionID" -> 25650838974352026468, 
  "RecurrentStateKeys" -> {{"State"}}, "RecurrentStateArrays" -> 
   Hold[NeuralNetworks`Private`NetStateObject`state$19496], 
  "EvaluationCount" -> Hold[NeuralNetworks`Private`NetStateObject`evals$19496]]]
```

Each evaluation modifies the state stored inside the ``NetStateObject`` :

```wl
In[2]:= sobj[{{0, 0}, {1, 1}}]

Out[2]= {{0., 0.}, {-0.0734226, -0.0967464}}

In[3]:= sobj[{{0, 0}, {1, 1}}]

Out[3]= {{-0.0202983, -0.0292139}, {-0.087523, -0.100702}}

In[4]:= sobj[{{0, 0}, {1, 1}}]

Out[4]= {{-0.0232148, -0.0291619}, {-0.0892748, -0.100358}}
```

## See Also

* [`NetStateObject`](https://reference.wolfram.com/language/ref/NetStateObject.en.md)
* [`BasicRecurrentLayer`](https://reference.wolfram.com/language/ref/BasicRecurrentLayer.en.md)
* [`LongShortTermMemoryLayer`](https://reference.wolfram.com/language/ref/LongShortTermMemoryLayer.en.md)
* [`NetBidirectionalOperator`](https://reference.wolfram.com/language/ref/NetBidirectionalOperator.en.md)
* [`NetFoldOperator`](https://reference.wolfram.com/language/ref/NetFoldOperator.en.md)
* [`NetMapOperator`](https://reference.wolfram.com/language/ref/NetMapOperator.en.md)
* [`SequenceLastLayer`](https://reference.wolfram.com/language/ref/SequenceLastLayer.en.md)
* [`LinearLayer`](https://reference.wolfram.com/language/ref/LinearLayer.en.md)
* [`NetChain`](https://reference.wolfram.com/language/ref/NetChain.en.md)
* [`NetGraph`](https://reference.wolfram.com/language/ref/NetGraph.en.md)
* [`NetExtract`](https://reference.wolfram.com/language/ref/NetExtract.en.md)

## Tech Notes

* [Neural Networks in the Wolfram Language](https://reference.wolfram.com/language/tutorial/NeuralNetworksOverview.en.md)

## Related Guides

* [Neural Network Layers](https://reference.wolfram.com/language/guide/NeuralNetworkLayers.en.md)
* [Speech Computation](https://reference.wolfram.com/language/guide/SpeechComputation.en.md)

## History

* [Introduced in 2017 (11.1)](https://reference.wolfram.com/language/guide/SummaryOfNewFeaturesIn111.en.md)