# polycirc.learner

Suppose you have the following:

• A dataset of input/output examples `(a, b)`, which are pairs of `A`- and `B`-dimensional vectors.

• An initial `P`-dimensional parameter `θ ∈ P`

• A circuit `model : P + A → B` which maps parameters and inputs to outputs

Using the `make_learner()` and `rdiff()` functions in this module, you can obtain a circuit `step : P + A + B → P` mapping a parameter `θ` and example datum `(a, b)` to an updated parameter. Iterating the `step` function amounts to learning with gradient descent.

For a step-by-step explanation, see the User Guide. For a complete end-to-end example, see the included example.

For mathematical background, see Cruttwell et al. [CGG+21].

Warning

Note that the example update/displacement maps given in this file don’t work well for integer-valued learning.

See the examples directory for a full example of integer-valued training using fixed-point operations.

polycirc.learner.gd(lr: int)

Gradient descent update map with learning rate `lr`.

```>>> from yarrow import Diagram
>>> u = gd(0.01)
>>> type(u(p = 10)) is Diagram # 10-dimensional parameter vector
True
```
polycirc.learner.mse(b: int)

Mean-squared error displacement map for `b`-dimensional predictions. Computes model error as the pointwise difference `ŷ - y` between prediction `ŷ` and true label `y`.

polycirc.learner.rdiff(c: Diagram)

Transform a circuit into an optic computing the forward and reverse passes

polycirc.learner.make_learner(model_optic, update, displacement, P: int, A: int)

Construct a circuit `step : P + A + B → B + P + A` which computes both model output (dimension `B`) and new parameter vector (dimension `P`). Iterate this `step` function to train your model.

```>>> import polycirc.ir as ir
>>> from polycirc.ast import diagram_to_function
>>> A = 4 # input dimension
>>> B = 3 # output dimension
>>> P = 3*4 # parameter dimension
>>> model = ir.mat_mul(B, A)
>>> f = rdiff(model) # compute derivative of model
>>> u = gd(lr=1)(P) # update circuit
>>> d = mse(B) # displacement circuit
>>> step = diagram_to_function(make_learner(f, u, d, P, A))
>>> params = *P # initial params
>>> x = [1, 2, 3, 4] # example input
>>> y = [0, 1, 0] # example output
>>> new_params = step(*params, *x, *y)[B:B+P] # compute parameter change: a 3×4 matrix.
>>> new_params
[0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0]
```