0 | module Data.Autodiff.Ops
2 | import public System.Random
5 | import Data.Tensor.Utils
6 | import Data.Container.Additive
7 | import Data.Container.Additive.Quantifiers
9 | import Data.Autodiff.Model
10 | import Control.Monad.Distribution
11 | import Data.ComMonoid
12 | import Data.Materialise
26 | mulModel : {t : Type} -> Num t => Neg t => Random t =>
27 | Const t -\-> Const t
28 | mulModel = fromPara (binaryOpToPara {p = Const t} mul) DefaultInit
31 | addModel : {t : Type} -> Num t => Neg t => Random t =>
32 | Const t -\-> Const t
33 | addModel = fromPara (binaryOpToPara {p = Const t} sum) DefaultInit
36 | scalarAffine : {t : Type} -> Num t => Neg t => Random t => Materialise t =>
37 | Const t -\-> Const t
38 | scalarAffine = mulModel >>> addModel
42 | parallelTensor : {a, b : Type} -> Num a => Num b =>
43 | {shape : TensorShape rank} ->
44 | AllC TensorMonoid shape => AllC IsConcrete shape =>
45 | (f : Const a =%+> Const b) ->
46 | Const (Tensor shape a) =%+> Const (Tensor shape b)
47 | parallelTensor f = !%+ \x =>
48 | let outs : Tensor shape (y : b ** (b -> a))
49 | outs = materialise ((%!+) f <$> x)
50 | in (
materialise (fst <$> outs) ** \ys' => materialise [| snd outs ys' |])
54 | parallelTensorModel : {a, b : Type} -> Num a => Num b =>
55 | {shape : TensorShape rank} -> AllC TensorMonoid shape => AllC IsConcrete shape =>
56 | Traversable (Tensor shape) =>
57 | (m : Const a -\-> Const b) -> Const (Tensor shape a) -\-> Const (Tensor shape b)
58 | parallelTensorModel m = MkModel (Tensor shape m.Params) @{tensorComMonoid m.pMon}
59 | (sequence (pure m.init)) $
61 | let outs : Tensor shape (y : b ** b -> (a, m.Params))
62 | outs = materialise ([| (x, ps) |] <&> (%!+) m.run)
63 | in (
materialise (fst <$> outs) ** \ys' =>
64 | let grads : Tensor shape (a, m.Params)
65 | grads = materialise [| snd outs ys' |]
66 | in (fst <$> grads, snd <$> grads))
69 | copyN : {a : Type} -> Num a => {n : Nat} -> {axisName : AxisName} ->
70 | Const a =%+> Const (Tensor [axisName ~~> n] a)
71 | copyN = !%+ \x => (
pure x ** reduce)
74 | sameFromTensorN : {a, b : Type} -> Num a => Num b => {n : Nat} ->
75 | {axisName : AxisName} ->
76 | Traversable (Tensor [axisName ~~> n]) =>
77 | (m : Const a -\-> Const b) -> Const a -\-> Const (Tensor [axisName ~~> n] b)
78 | sameFromTensorN m = precomposeLens copyN (parallelTensorModel m)
82 | sumAxis : {n : Axis} -> IsCubical n => Num a =>
83 | TensorMonoid n.cont =>
84 | Const (Tensor [n] a) =%+> Const (Tensor [] a)
85 | sumAxis @{MkIsCubical _ n} = !%+ \t => (
># reduce t ** \a' => fill (#> a'))
89 | divBy : {a : Type} -> Num a => Fractional a =>
91 | Const (Tensor [] a) =%+> Const (Tensor [] a)
92 | divBy d = !%+ \x => (
x <&> (/ d) ** \x' => x' <&> (/ d))
95 | meanSquaredDifference : IsCubical n => TensorMonoid n.cont =>
96 | {a : Type} -> Num a => Neg a => Fractional a => Cast Nat a =>
97 | Const (Tensor [n] a) >*< Const (Tensor [n] a) =%+> Const (Tensor [] a)
98 | meanSquaredDifference @{MkIsCubical _ n}
99 | = SquaredDifference %+>> sumAxis %+>> divBy (cast n)
106 | leakyReLU : {a : Type} -> Num a => Ord a =>
108 | Const a =%+> Const a
109 | leakyReLU alpha = !%+ \x =>
110 | (
if x > 0 then x else alpha * x ** \x' => if x > 0 then x' else alpha * x')
113 | leakyReLUModel : {a : Type} -> Num a => Ord a =>
115 | {shape : TensorShape rank} -> AllC TensorMonoid shape => AllC IsConcrete shape =>
116 | Const (Tensor shape a) -\-> Const (Tensor shape a)
117 | leakyReLUModel alpha = trivialParam (parallelTensor (leakyReLU alpha))
120 | reluModel : {a : Type} -> Num a => Ord a =>
121 | {shape : TensorShape rank} -> AllC TensorMonoid shape => AllC IsConcrete shape =>
122 | Const (Tensor shape a) -\-> Const (Tensor shape a)
123 | reluModel = leakyReLUModel 0
130 | fromLogits : {a : Axis} -> TensorMonoid a.cont =>
131 | Const (Tensor [a] Double) =%+> Simplex a
132 | fromLogits = !%+ \xs => (
MkDist xs ** unrestrict)
135 | fromLogitsModel : {a : Axis} -> TensorMonoid a.cont =>
136 | Const (Tensor [a] Double) -\-> Simplex a
137 | fromLogitsModel = trivialParam fromLogits