| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Proarrow.Category.Instance.Diff
Description
Differentiable maps between products of real vector spaces, with their reverse derivatives.
An object is a list of dimensions, 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.DF '[n, m]
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
- data DIFF = DF [Nat]
- data Diff (a :: DIFF) (b :: DIFF) where
- Diff :: forall (as :: [Nat]) (bs :: [Nat]). (KnownListOf KnownNat as, KnownListOf KnownNat bs) => {..} -> Diff ('DF as) ('DF bs)
- forward :: forall (as :: [Nat]) (bs :: [Nat]). ('DF as ~> 'DF bs) -> Point as -> Point bs
- backward :: forall (as :: [Nat]) (bs :: [Nat]). ('DF as ~> 'DF bs) -> Point as -> Point bs -> Point as
- 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
- newtype Point (ns :: [Nat]) = Point {}
- pattern Vector :: forall (n :: Nat). Vector Double -> Point '[n]
- coordinates :: forall (ns :: [Nat]). Point ns -> Vector Double
- fromCoordinates :: forall (ns :: [Nat]). KnownListOf KnownNat ns => Vector Double -> Point ns
- zero :: forall (ns :: [Nat]). KnownListOf KnownNat ns => Point ns
- add :: forall (ns :: [Nat]). Point ns -> Point ns -> Point ns
- scale :: forall (ns :: [Nat]). Double -> Point ns -> Point ns
- split :: forall (as :: [Nat]) (bs :: [Nat]). KnownListOf KnownNat as => Point (as ++ bs) -> (Point as, Point bs)
- append :: forall (as :: [Nat]) (bs :: [Nat]). Point as -> Point bs -> Point (as ++ bs)
- 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]
- pointwise :: forall (n :: Nat). KnownNat n => (Double -> Double) -> (Double -> Double) -> 'DF '[n] ~> 'DF '[n]
- times :: forall (n :: Nat). KnownNat n => 'DF '[n, n] ~> 'DF '[n]
- dot :: forall (n :: Nat). KnownNat n => 'DF '[n, n] ~> 'DF '[1]
- matVec :: forall (m :: Nat) (n :: Nat). (KnownNat m, KnownNat n, KnownNat (m * n)) => 'DF '[m * n, n] ~> 'DF '[m]
- 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]
- broadcast :: forall (m :: Nat) (b :: Nat). (KnownNat m, KnownNat b, KnownNat (b * m)) => 'DF '[m] ~> 'DF '[b * m]
- softmax :: forall (k :: Nat) (b :: Nat). (KnownNat k, KnownNat b, KnownNat (b * k)) => 'DF '[b * k] ~> 'DF '[b * k]
- softmaxCrossEntropy :: forall (k :: Nat) (b :: Nat). (KnownNat k, KnownNat b, KnownNat (b * k)) => 'DF '[b * k, b * k] ~> 'DF '[1]
- 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]
- constant :: forall (as :: [Nat]) (bs :: [Nat]). (KnownListOf KnownNat as, KnownListOf KnownNat bs) => Point bs -> 'DF as ~> 'DF bs
- toLens :: forall (as :: [Nat]) (bs :: [Nat]). ('DF as ~> 'DF bs) -> Lens (Point as) (Point as) (Point bs) (Point bs)
- data family Forget :: DIFF +-> Type
- data family AsLens :: DIFF +-> OPPOSITE (OPTIC Type Type (Prostrong (LensFl :: (Type +-> Type) -> (Type +-> Type) -> Constraint)))
Documentation
Objects are lists of dimensions, the product of the spaces of those dimensions.
Instances
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 | |
Instances
| Promonad Diff Source Github # | |
| MonoidalProfunctor Diff Source Github # | |
| Profunctor Diff Source Github # | |
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.
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 #
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.
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.