(l-onnx-docai-onnx-preview-training-Adam)=
# ai.onnx.preview.training - Adam
(l-onnx-opai-onnx-preview-training-adam-1)=
## Adam - 1 (ai.onnx.preview.training)
### Version
- **name**: [Adam (GitHub)](https://github.com/onnx/onnx/blob/main/docs/Operators.md#ai.onnx.preview.training.Adam)
- **domain**: `ai.onnx.preview.training`
- **since_version**: `1`
- **function**: `False`
- **support_level**: `SupportType.COMMON`
- **shape inference**: `True`
This version of the operator has been available
**since version 1 of domain ai.onnx.preview.training**.
### Summary
Compute one iteration of Adam, a stochastic gradient based optimization
algorithm. This operator can conduct the optimization of multiple tensor variables.
Let's define the behavior of this operator. First of all, Adam requires
some parameters:
- The learning-rate "R".
- The update count "T". That is, the number of training iterations conducted.
- A L2-norm regularization coefficient "norm_coefficient".
- A small constant "epsilon" to avoid dividing-by-zero.
- Two coefficients, "alpha" and "beta".
At each Adam iteration, the optimized tensors are moved along a direction
computed based on their exponentially-averaged historical gradient and
exponentially-averaged historical squared gradient. Assume that only a tensor
"X" is being optimized. The rest of required information is
- the value of "X",
- "X"'s gradient (denoted by "G"),
- "X"'s exponentially-averaged historical gradient (denoted by "V"), and
- "X"'s exponentially-averaged historical squared gradient (denoted by "H").
Some of those parameters are passed into this operator as input tensors and others
are stored as this operator's attributes. Specifically, this operator's input tensor
list is ["R", "T", "X", "G", "V", "H"]. That is, "R" is the first input, "T" is
the second input, and so on. Other parameters are given as attributes because they
are constants. Moreover, the corresponding output tensors are
- the new value of "X" (called "X_new"),
- the new exponentially-averaged historical gradient (denoted by "V_new"), and
- the new exponentially-averaged historical squared gradient (denoted by "H_new").
Those outputs are computed following the pseudo code below.
Let "+", "-", "*", and "/" are all element-wise arithmetic operations with
numpy-style broadcasting support. The pseudo code to compute those outputs is:
// Add gradient of 0.5 * norm_coefficient * ||X||_2^2, where ||X||_2 is the 2-norm.
G_regularized = norm_coefficient * X + G
// Update exponentially-averaged historical gradient.
V_new = alpha * V + (1 - alpha) * G_regularized
// Update exponentially-averaged historical squared gradient.
H_new = beta * H + (1 - beta) * G_regularized * G_regularized
// Compute the element-wise square-root of H_new. V_new will be element-wisely
// divided by H_sqrt for a better update direction.
H_sqrt = Sqrt(H_new) + epsilon
// Compute learning-rate. Note that "alpha**T"/"beta**T" is alpha's/beta's T-th power.
R_adjusted = T > 0 ? R * Sqrt(1 - beta**T) / (1 - alpha**T) : R
// Compute new value of "X".
X_new = X - R_adjusted * V_new / H_sqrt
// Post-update regularization.
X_final = (1 - norm_coefficient_post) * X_new
If there are multiple inputs to be optimized, the pseudo code will be applied
independently to each of them.
### Attributes
* **alpha - FLOAT** (default is `'0.9'`):
Coefficient of previously accumulated gradient in running average. Default to 0.9.
* **beta - FLOAT** (default is `'0.999'`):
Coefficient of previously accumulated squared-gradient in running average. Default to 0.999.
* **epsilon - FLOAT** (default is `'0.0'`):
Small scalar to avoid dividing by zero.
* **norm_coefficient - FLOAT** (default is `'0.0'`):
Regularization coefficient of 0.5 * norm_coefficient * ||X||_2^2. Default to 0, which means no regularization.
* **norm_coefficient_post - FLOAT** (default is `'0.0'`):
Regularization coefficient of 0.5 * norm_coefficient * ||X||_2^2. Default to 0, which means no regularization.
### Inputs
Between 3 and 2147483647 inputs.
- **R** (heterogeneous) - **T1**:
The initial learning rate.
- **T** (heterogeneous) - **T2**:
The update count of "X". It should be a scalar.
- **inputs** (variadic) - **T3**:
The tensors to be optimized, followed by their respective gradients, followed by their respective accumulated gradients (aka momentum), followed by their respective accumulated squared gradients. For example, to optimize tensors "X_1" and "X_2,", the input list would be ["X_1", "X_2", gradient of "X_1", gradient of "X_2", accumulated gradient of "X_1", accumulated gradient of "X_2", accumulated squared gradient of "X_1", accumulated squared gradient of "X_2"].
### Outputs
Between 1 and 2147483647 outputs.
- **outputs** (variadic) - **T3**:
New values of optimized tensors, followed by their respective new accumulated gradients, followed by their respective new accumulated squared gradients. For example, if two tensors "X_1" and "X_2" are optimized, the outputs list would be [new value of "X_1", new value of "X_2", new accumulated gradient of "X_1", new accumulated gradient of "X_2", new accumulated squared gradient of "X_1", new accumulated squared gradient of "X_2"].
### Type Constraints
* **T1** in ( `tensor(double)`, `tensor(float)` ):
Constrain input types to float scalars.
* **T2** in ( `tensor(int64)` ):
Constrain input types to 64-bit integer scalars.
* **T3** in ( `tensor(double)`, `tensor(float)` ):
Constrain input and output types to float tensors.