polycirc.learner

Circuits for gradient-based machine learning.

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 = [0]*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]