# AutodiffComposition¶

## Overview¶

Warning

As of PsyNeuLink 0.7.5, the API for using AutodiffCompositions has been slightly changed! Please see this link for more details!

AutodiffComposition is a subclass of Composition used to train feedforward neural network models through integration with PyTorch, a popular machine learning library, which executes considerably more quickly than using the standard implementation of learning in a Composition, using its learning methods. An AutodiffComposition is configured and run similarly to a standard Composition, with some exceptions that are described below.

## Creating an AutodiffComposition¶

An AutodiffComposition can be created by calling its constructor, and then adding Components using the standard Composition methods for doing so. The constructor also includes an number of parameters that are specific to the AutodiffComposition. See the <class reference AutodiffComposition> for a list of these parameters.

Warning

Mechanisms or Projections should not be added to or deleted from an AutodiffComposition after it has been run for the first time. Unlike an ordinary Composition, AutodiffComposition does not support this functionality.

Warning

When comparing models built in PyTorch to those using AutodiffComposition, the bias parameter of PyTorch modules should be set to False, as AutodiffComposition does not currently support trainable biases.

## Execution¶

An AutodiffComposition’s run, execute, and learn methods are the same as for a Composition.

The following is an example showing how to create a simple AutodiffComposition, specify its inputs and targets, and run it with learning enabled and disabled.

>>> import psyneulink as pnl
>>> # Set up PsyNeuLink Components
>>> my_mech_1 = pnl.TransferMechanism(function=pnl.Linear, size = 3)
>>> my_mech_2 = pnl.TransferMechanism(function=pnl.Linear, size = 2)
>>> my_projection = pnl.MappingProjection(matrix=np.random.randn(3,2),
...                     sender=my_mech_1,
>>> # Create AutodiffComposition
>>> my_autodiff = pnl.AutodiffComposition()
>>> # Specify inputs and targets
>>> my_inputs = {my_mech_1: [[1, 2, 3]]}
>>> my_targets = {my_mech_2: [[4, 5]]}
>>> input_dict = {"inputs": my_inputs, "targets": my_targets, "epochs": 2}
>>> # Run Composition in learnng mode
>>> my_autodiff.learn(inputs = input_dict)
>>> # Run Composition in test mode
>>> my_autodiff.run(inputs = input_dict['inputs'])


### Logging¶

Logging in AutodiffCompositions follows the same procedure as logging in a Composition. However, since an AutodiffComposition internally converts all of its mechanisms to an equivalent PyTorch model, then its inner components are not actually executed. This means that there is limited support for logging parameters of components inside an AutodiffComposition; Currently, the only supported parameters are:

1. the matrix parameter of Projections
2. the value parameter of its inner components

### Nested Execution¶

Like any other Composition, an AutodiffComposition may be nested inside another.

The following shows how the AutodiffComposition created in the previous example can be nested and run inside another Composition:

>>> # Create outer composition
>>> my_outer_composition = pnl.Composition()
>>> # Specify dict containing inputs and targets for nested Composition
>>> training_input = {my_autodiff: input_dict}
>>> # Run in learning mode
>>> result1 = my_outer_composition.learn(inputs=training_input)


## Class Reference¶

class psyneulink.library.compositions.autodiffcomposition.AutodiffComposition(learning_rate=None, optimizer_type='sgd', weight_decay=0, loss_spec='mse', disable_learning=False, refresh_losses=False, disable_cuda=True, cuda_index=None, force_no_retain_graph=False, name='autodiff_composition')

Subclass of Composition that trains models using PyTorch. See Composition for additional arguments and attributes.

Parameters: learning_rate (float : default 0.001) – the learning rate, which is passed to the optimizer. disable_learning (bool: default False) – specifies whether the AutodiffComposition should disable learning when run in learning mode. optimizer_type (str : default 'sgd') – the kind of optimizer used in training. The current options are ‘sgd’ or ‘adam’. weight_decay (float : default 0) – specifies the L2 penalty (which discourages large weights) used by the optimizer. loss_spec (str or PyTorch loss function : default 'mse') – specifies the loss function for training. The current string options are ‘mse’ (the default), ‘crossentropy’, ‘l1’, ‘nll’, ‘poissonnll’, and ‘kldiv’. Any PyTorch loss function can work here, such as ones from https://pytorch.org/docs/stable/nn.html#loss-functions losses (list of floats) – tracks the average for each weight update (i.e. each minibatch) optimizer (PyTorch optimizer function) – the optimizer used for training. Depends on the optimizer_type, learning_rate, and weight_decay arguments from initialization. loss (PyTorch loss function) – the loss function used for training. Depends on the loss_spec argument from initialization.
_infer_input_nodes(nodes)

Maps targets onto target mechanisms (as needed by learning)

Returns: A dict mapping TargetMechanisms -> target values
_infer_output_nodes(nodes)

Maps targets onto target mechanisms (as needed by learning)

Returns: A dict mapping TargetMechanisms -> target values
_update_learning_parameters(context)

Updates parameters based on trials ran since last update.