proarrow
Safe HaskellNone
LanguageGHC2024

Proarrow.Category.Instance.Diff

Description

Differentiable maps between products of real vector spaces, with their reverse derivatives. An object is a list of dimensions, DF '[n, m] for ℝⁿ × ℝᵐ, and an arrow is a map together with its reverse derivative: given a point and a change of the output, the change of the input it comes from. Running an arrow at a point gives the image together with the reverse derivative there, so the backward pass reuses what the forward pass computed, as in Elliott's The simple essence of automatic differentiation. Composition runs the maps forward and chains the reverse derivatives backward, which is the chain rule, so a reverse derivative is never more than a change of vectors passed back through each step.

The category is cartesian: copying a point is adding the changes that come back, and discarding one is the zero change. Every object is a commutative monoid by adding vectors. toLens gives an arrow as a lens, with the map as the view and the reverse derivative as the update.

The reverse derivative is a function rather than an arrow of the category itself, so this is the first-order part of a reverse derivative category: the derivative cannot be differentiated again.

Synopsis

Documentation

data DIFF Source Github #

Objects are lists of dimensions, the product of the spaces of those dimensions.

Constructors

DF [Nat] 

Instances

Instances details
Monoidal DIFF Source Github #

The product of spaces as the tensor.

Instance details

Defined in Proarrow.Category.Instance.Diff

Associated Types

type Unit 
Instance details

Defined in Proarrow.Category.Instance.Diff

type Unit = 'DF ('[] :: [Nat])
type (a :: DIFF) ** (b :: DIFF) 
Instance details

Defined in Proarrow.Category.Instance.Diff

type (a :: DIFF) ** (b :: DIFF) = 'DF (UN 'DF a ++ UN 'DF b)

Methods

withOb2 :: forall (a :: DIFF) (b :: DIFF) r. (Ob a, Ob b) => (Ob (a ** b) => r) -> r Source Github #

leftUnitor :: forall (a :: DIFF). Ob a => ((Unit :: DIFF) ** a) ~> a Source Github #

leftUnitorInv :: forall (a :: DIFF). Ob a => a ~> ((Unit :: DIFF) ** a) Source Github #

rightUnitor :: forall (a :: DIFF). Ob a => (a ** (Unit :: DIFF)) ~> a Source Github #

rightUnitorInv :: forall (a :: DIFF). Ob a => a ~> (a ** (Unit :: DIFF)) Source Github #

associator :: forall (a :: DIFF) (b :: DIFF) (c :: DIFF). (Ob a, Ob b, Ob c) => ((a ** b) ** c) ~> (a ** (b ** c)) Source Github #

associatorInv :: forall (a :: DIFF) (b :: DIFF) (c :: DIFF). (Ob a, Ob b, Ob c) => (a ** (b ** c)) ~> ((a ** b) ** c) Source Github #

SymMonoidal DIFF Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

Methods

swap :: forall (a :: DIFF) (b :: DIFF). (Ob a, Ob b) => (a ** b) ~> (b ** a) Source Github #

CopyDiscard DIFF Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

Methods

copy :: forall (a :: DIFF). Ob a => a ~> (a ** a) Source Github #

discard :: forall (a :: DIFF). Ob a => a ~> (Unit :: DIFF) Source Github #

CategoryOf DIFF Source Github #

Differentiable maps between products of real vector spaces.

Instance details

Defined in Proarrow.Category.Instance.Diff

Associated Types

type (~>) 
Instance details

Defined in Proarrow.Category.Instance.Diff

type (~>) = Diff
type Ob (a :: DIFF) 
Instance details

Defined in Proarrow.Category.Instance.Diff

type Ob (a :: DIFF) = (Is 'DF a, KnownListOf KnownNat (UN 'DF a))
HasBinaryProducts DIFF Source Github #

The product of spaces: the reverse derivative of a pairing adds the changes of both parts.

Instance details

Defined in Proarrow.Category.Instance.Diff

Associated Types

type (a :: DIFF) && (b :: DIFF) 
Instance details

Defined in Proarrow.Category.Instance.Diff

type (a :: DIFF) && (b :: DIFF) = 'DF (UN 'DF a ++ UN 'DF b)

Methods

withObProd :: forall (a :: DIFF) (b :: DIFF) r. (Ob a, Ob b) => (Ob (a && b) => r) -> r Source Github #

fst :: forall (a :: DIFF) (b :: DIFF). (Ob a, Ob b) => (a && b) ~> a Source Github #

snd :: forall (a :: DIFF) (b :: DIFF). (Ob a, Ob b) => (a && b) ~> b Source Github #

(&&&) :: forall (a :: DIFF) (x :: DIFF) (y :: DIFF). (a ~> x) -> (a ~> y) -> a ~> (x && y) Source Github #

(***) :: forall (a :: DIFF) (b :: DIFF) (x :: DIFF) (y :: DIFF). (a ~> x) -> (b ~> y) -> (a && b) ~> (x && y) Source Github #

HasTerminalObject DIFF Source Github #

The one-point space.

Instance details

Defined in Proarrow.Category.Instance.Diff

Associated Types

type TerminalObject 
Instance details

Defined in Proarrow.Category.Instance.Diff

type TerminalObject = 'DF ('[] :: [Nat])

Methods

terminate :: forall (a :: DIFF). Ob a => a ~> (TerminalObject :: DIFF) Source Github #

Promonad Diff Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

Methods

id :: forall (a :: DIFF). Ob a => Diff a a Source Github #

(.) :: forall (b :: DIFF) (c :: DIFF) (a :: DIFF). Diff b c -> Diff a b -> Diff a c Source Github #

MonoidalProfunctor Diff Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

Methods

one :: Diff (Unit :: DIFF) (Unit :: DIFF) Source Github #

(**) :: forall (x1 :: DIFF) (x2 :: DIFF) (y1 :: DIFF) (y2 :: DIFF). Diff x1 x2 -> Diff y1 y2 -> Diff (x1 ** y1) (x2 ** y2) Source Github #

Profunctor Diff Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

Methods

dimap :: forall (c :: DIFF) (a :: DIFF) (b :: DIFF) (d :: DIFF). (c ~> a) -> (b ~> d) -> Diff a b -> Diff c d Source Github #

lmap :: forall (c :: DIFF) (a :: DIFF) (b :: DIFF). (c ~> a) -> Diff a b -> Diff c b Source Github #

rmap :: forall (b :: DIFF) (d :: DIFF) (a :: DIFF). (b ~> d) -> Diff a b -> Diff a d Source Github #

(\\) :: forall (a :: DIFF) (b :: DIFF) r. ((Ob a, Ob b) => r) -> Diff a b -> r Source Github #

FunctorForRep Forget Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

Associated Types

type Forget @ (a :: DIFF) 
Instance details

Defined in Proarrow.Category.Instance.Diff

type Forget @ (a :: DIFF) = Point (UN 'DF a)

Methods

fmap :: forall (a :: DIFF) (b :: DIFF). (a ~> b) -> (Forget @ a) ~> (Forget @ b) Source Github #

KnownListOf KnownNat ns => CocommutativeComonoid ('DF ns :: DIFF) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

KnownListOf KnownNat ns => CommutativeMonoid ('DF ns :: DIFF) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

KnownListOf KnownNat ns => Comonoid ('DF ns :: DIFF) Source Github #

Copying a point: the changes that come back are added.

Instance details

Defined in Proarrow.Category.Instance.Diff

Methods

counit :: 'DF ns ~> (Unit :: DIFF) Source Github #

comult :: 'DF ns ~> ('DF ns ** 'DF ns) Source Github #

KnownListOf KnownNat ns => Monoid ('DF ns :: DIFF) Source Github #

Adding vectors: the change of a sum is passed back to both terms.

Instance details

Defined in Proarrow.Category.Instance.Diff

Methods

mempty :: (Unit :: DIFF) ~> 'DF ns Source Github #

mappend :: ('DF ns ** 'DF ns) ~> 'DF ns Source Github #

FunctorForRep AsLens Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

Associated Types

type AsLens @ (a :: DIFF) 
Instance details

Defined in Proarrow.Category.Instance.Diff

type AsLens @ (a :: DIFF) = 'OP ('OPT (Point (UN 'DF a)) (Point (UN 'DF a)) :: OPTIC Type Type (Prostrong (LensFl :: (Type +-> Type) -> (Type +-> Type) -> Constraint)))

Methods

fmap :: forall (a :: DIFF) (b :: DIFF). (a ~> b) -> (AsLens @ a) ~> (AsLens @ b) Source Github #

type Unit Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

type Unit = 'DF ('[] :: [Nat])
type (~>) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

type (~>) = Diff
type TerminalObject Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

type TerminalObject = 'DF ('[] :: [Nat])
type Ob (a :: DIFF) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

type Ob (a :: DIFF) = (Is 'DF a, KnownListOf KnownNat (UN 'DF a))
type (a :: DIFF) ** (b :: DIFF) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

type (a :: DIFF) ** (b :: DIFF) = 'DF (UN 'DF a ++ UN 'DF b)
type (a :: DIFF) && (b :: DIFF) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

type (a :: DIFF) && (b :: DIFF) = 'DF (UN 'DF a ++ UN 'DF b)
type Forget @ (a :: DIFF) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

type Forget @ (a :: DIFF) = Point (UN 'DF a)
type AsLens @ (a :: DIFF) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

type AsLens @ (a :: DIFF) = 'OP ('OPT (Point (UN 'DF a)) (Point (UN 'DF a)) :: OPTIC Type Type (Prostrong (LensFl :: (Type +-> Type) -> (Type +-> Type) -> Constraint)))

data Diff (a :: DIFF) (b :: DIFF) where Source Github #

A differentiable map: at a point, its image and its reverse derivative there, which takes a change of the image to the change of the point it comes from.

Constructors

Diff 

Fields

Instances

Instances details
Promonad Diff Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

Methods

id :: forall (a :: DIFF). Ob a => Diff a a Source Github #

(.) :: forall (b :: DIFF) (c :: DIFF) (a :: DIFF). Diff b c -> Diff a b -> Diff a c Source Github #

MonoidalProfunctor Diff Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

Methods

one :: Diff (Unit :: DIFF) (Unit :: DIFF) Source Github #

(**) :: forall (x1 :: DIFF) (x2 :: DIFF) (y1 :: DIFF) (y2 :: DIFF). Diff x1 x2 -> Diff y1 y2 -> Diff (x1 ** y1) (x2 ** y2) Source Github #

Profunctor Diff Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

Methods

dimap :: forall (c :: DIFF) (a :: DIFF) (b :: DIFF) (d :: DIFF). (c ~> a) -> (b ~> d) -> Diff a b -> Diff c d Source Github #

lmap :: forall (c :: DIFF) (a :: DIFF) (b :: DIFF). (c ~> a) -> Diff a b -> Diff c b Source Github #

rmap :: forall (b :: DIFF) (d :: DIFF) (a :: DIFF). (b ~> d) -> Diff a b -> Diff a d Source Github #

(\\) :: forall (a :: DIFF) (b :: DIFF) r. ((Ob a, Ob b) => r) -> Diff a b -> r Source Github #

forward :: forall (as :: [Nat]) (bs :: [Nat]). ('DF as ~> 'DF bs) -> Point as -> Point bs Source Github #

The map of an arrow.

backward :: forall (as :: [Nat]) (bs :: [Nat]). ('DF as ~> 'DF bs) -> Point as -> Point bs -> Point as Source Github #

The reverse derivative of an arrow at a point.

diff :: forall (as :: [Nat]) (bs :: [Nat]). (KnownListOf KnownNat as, KnownListOf KnownNat bs) => (Point as -> Point bs) -> (Point as -> Point bs -> Point as) -> 'DF as ~> 'DF bs Source Github #

The arrow with the given map and reverse derivative, for when the two share no work.

newtype Point (ns :: [Nat]) Source Github #

A point of a product of spaces, or a change of one: a vector of coordinates for each space. Taking a point of a product apart and putting it together handles the vectors without copying their coordinates.

Constructors

Point 

Fields

pattern Vector :: forall (n :: Nat). Vector Double -> Point '[n] Source Github #

A point of a single space.

coordinates :: forall (ns :: [Nat]). Point ns -> Vector Double Source Github #

The coordinates of a point, one space after the other.

fromCoordinates :: forall (ns :: [Nat]). KnownListOf KnownNat ns => Vector Double -> Point ns Source Github #

The point with the given coordinates, one space after the other.

zero :: forall (ns :: [Nat]). KnownListOf KnownNat ns => Point ns Source Github #

The origin, which is also the change that changes nothing.

add :: forall (ns :: [Nat]). Point ns -> Point ns -> Point ns Source Github #

The sum of two points, or two changes.

scale :: forall (ns :: [Nat]). Double -> Point ns -> Point ns Source Github #

A point, or a change, multiplied by a number.

split :: forall (as :: [Nat]) (bs :: [Nat]). KnownListOf KnownNat as => Point (as ++ bs) -> (Point as, Point bs) Source Github #

A point of a product as its two parts.

append :: forall (as :: [Nat]) (bs :: [Nat]). Point as -> Point bs -> Point (as ++ bs) Source Github #

The point of a product with the given parts.

linear :: forall (as :: [Nat]) (bs :: [Nat]). (KnownListOf KnownNat as, KnownListOf KnownNat bs, KnownNat (Size as), KnownNat (Size bs)) => (('TN as :: TNET Double) ~> ('TN bs :: TNET Double)) -> 'DF '[Size as] ~> 'DF '[Size bs] Source Github #

A linear map, given as a tensor network, its input and result each the vector of a tensor's entries. The change of the input is the change of the result through the dual of the map.

pointwise :: forall (n :: Nat). KnownNat n => (Double -> Double) -> (Double -> Double) -> 'DF '[n] ~> 'DF '[n] Source Github #

A function applied to each coordinate, given with its derivative.

times :: forall (n :: Nat). KnownNat n => 'DF '[n, n] ~> 'DF '[n] Source Github #

The coordinatewise product of two vectors: bilinear with the merging spider, written out.

dot :: forall (n :: Nat). KnownNat n => 'DF '[n, n] ~> 'DF '[1] Source Github #

The dot product of two vectors: bilinear with the cap, which sums the products.

matVec :: forall (m :: Nat) (n :: Nat). (KnownNat m, KnownNat n, KnownNat (m * n)) => 'DF '[m * n, n] ~> 'DF '[m] Source Github #

The product of an m by n matrix, given row by row, with a vector: matMat with a single column.

matMat :: forall (m :: Nat) (n :: Nat) (k :: Nat). (KnownNat m, KnownNat n, KnownNat k, KnownNat (m * n), KnownNat (n * k), KnownNat (m * k)) => 'DF '[m * n, n * k] ~> 'DF '[m * k] Source Github #

The product of an m by n matrix with an n by k matrix, both given row by row. With a batch of m vectors as the rows of the first, the second is a linear map applied to each of them. It is bilinear with the cap on the summed index, written out with matMul: the change of the first matrix is the change of the result times the transposed second, and the change of the second is the transposed first times the change of the result, which adds up the changes from the whole batch.

broadcast :: forall (m :: Nat) (b :: Nat). (KnownNat m, KnownNat b, KnownNat (b * m)) => 'DF '[m] ~> 'DF '[b * m] Source Github #

A vector copied to each of the b rows of a matrix, given row by row: for adding the same vector to each of a batch of b vectors. The change of the vector adds up the rows of the change of the matrix.

softmax :: forall (k :: Nat) (b :: Nat). (KnownNat k, KnownNat b, KnownNat (b * k)) => 'DF '[b * k] ~> 'DF '[b * k] Source Github #

The softmax of each of the b rows of a matrix of scores, given row by row: the exponentials of a row divided by their sum, for each of a batch of b vectors a probability for each of k classes. The change of a row of scores is the probabilities times the change of the row minus its average under them.

softmaxCrossEntropy :: forall (k :: Nat) (b :: Nat). (KnownNat k, KnownNat b, KnownNat (b * k)) => 'DF '[b * k, b * k] ~> 'DF '[1] Source Github #

The cross-entropy of the softmax of each of the b rows of a matrix of scores against the same row of a matrix of target probabilities, both given row by row, summed over the rows: the loss of a classifier on a batch. With the softmax computed along, the change of the scores is the probabilities minus the targets, for targets that sum to 1, and the change of the targets is minus the logarithms of the probabilities.

bilinear :: forall (as :: [Nat]) (bs :: [Nat]) (cs :: [Nat]). (KnownListOf KnownNat as, KnownListOf KnownNat bs, KnownListOf KnownNat cs, KnownNat (Size as), KnownNat (Size bs), KnownNat (Size cs)) => (('TN (as ++ bs) :: TNET Double) ~> ('TN cs :: TNET Double)) -> 'DF '[Size as, Size bs] ~> 'DF '[Size cs] Source Github #

A bilinear map, given as a tensor network from the tensor product of its two inputs, each input and the result the vector of a tensor's entries: linear in each input. The change of one input is the change of the result through the dual of the map with the other input fixed.

constant :: forall (as :: [Nat]) (bs :: [Nat]). (KnownListOf KnownNat as, KnownListOf KnownNat bs) => Point bs -> 'DF as ~> 'DF bs Source Github #

The map to a fixed point, whose reverse derivative is the zero change.

toLens :: forall (as :: [Nat]) (bs :: [Nat]). ('DF as ~> 'DF bs) -> Lens (Point as) (Point as) (Point bs) (Point bs) Source Github #

An arrow as a lens: the map is the view, and the reverse derivative the update. Composing arrows and composing their lenses agree, which is the chain rule; AsLens is the functor. A lens views and updates separately, so the update runs the map again.

data family Forget :: DIFF +-> Type Source Github #

The underlying functions: a differentiable map as a function from the points of its source to those of its target, forgetting the reverse derivative.

Instances

Instances details
FunctorForRep Forget Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

Associated Types

type Forget @ (a :: DIFF) 
Instance details

Defined in Proarrow.Category.Instance.Diff

type Forget @ (a :: DIFF) = Point (UN 'DF a)

Methods

fmap :: forall (a :: DIFF) (b :: DIFF). (a ~> b) -> (Forget @ a) ~> (Forget @ b) Source Github #

type Forget @ (a :: DIFF) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

type Forget @ (a :: DIFF) = Point (UN 'DF a)

data family AsLens :: DIFF +-> OPPOSITE (OPTIC Type Type (Prostrong (LensFl :: (Type +-> Type) -> (Type +-> Type) -> Constraint))) Source Github #

Arrows as lenses, by toLens. The lens of an arrow goes the other way, so this is a functor into the opposite of the category of lenses, and that it is a functor is the chain rule.

Instances

Instances details
FunctorForRep AsLens Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

Associated Types

type AsLens @ (a :: DIFF) 
Instance details

Defined in Proarrow.Category.Instance.Diff

type AsLens @ (a :: DIFF) = 'OP ('OPT (Point (UN 'DF a)) (Point (UN 'DF a)) :: OPTIC Type Type (Prostrong (LensFl :: (Type +-> Type) -> (Type +-> Type) -> Constraint)))

Methods

fmap :: forall (a :: DIFF) (b :: DIFF). (a ~> b) -> (AsLens @ a) ~> (AsLens @ b) Source Github #

type AsLens @ (a :: DIFF) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.Diff

type AsLens @ (a :: DIFF) = 'OP ('OPT (Point (UN 'DF a)) (Point (UN 'DF a)) :: OPTIC Type Type (Prostrong (LensFl :: (Type +-> Type) -> (Type +-> Type) -> Constraint)))