0 | module NN.Training.Training
5 | import Data.Container.Additive as Additive
6 | import public Data.ScientificNotation
10 | import NN.Training.DataLoader
11 | import NN.Architectures.LossFunctions
13 | import Data.Autodiff.Model
44 | optimiseStep : {p, l : AddCont} -> {e : Cont} ->
45 | InterfaceOnPositions l Num =>
46 | (f : p =%+> e >-+@ l) ->
47 | (handleEffect : Costate (IO <!> e)) ->
48 | (optimiser : Optimiser p stateTy) ->
49 | Costate (IO <!> (Const (p.Shp, stateTy)))
50 | optimiseStep f handleEffect (MkOptimiser opt _) =
51 | let closeFunction : p =%+> e >-+@ Scalar
52 | closeFunction = f %+>> (id >-+@ constantOne)
54 | closeFunctionT : UC p =%> e
55 | closeFunctionT = adjL closeFunction
56 | in (IO <!> (opt %>> closeFunctionT)) %>> handleEffect
60 | evalFw : {0 e : Cont} ->
61 | (f : a -> Ext e b) ->
62 | (handleEffect : Costate (IO <!> e)) ->
63 | Costate (IO <!> (Const2 a b))
64 | evalFw f handleEffect = toCostate $
\ps => do
65 | let (eInp <| outGivenEffect) = f ps
66 | e <- fromCostate handleEffect eInp
67 | pure $
outGivenEffect e
72 | optimise : {p, l : AddCont} -> {e : Cont} ->
73 | InterfaceOnPositions l Num =>
74 | {default 100 printEvery : Nat} ->
75 | Materialise p.Shp => Materialise stateTy =>
76 | ScientificDisplay p.Shp => ScientificDisplay l.Shp => ScientificDisplay stateTy =>
77 | (f : p =%+> e >-+@ l) ->
78 | (handleEffect : Costate (IO <!> e)) ->
79 | (initParam : IO p.Shp) ->
80 | (opt : Optimiser p stateTy) ->
83 | optimise f handleEffect initParam opt numSteps = do
84 | currentValue <- initParam
85 | currentState <- opt.initState
86 | runActionUntilMaxSteps
88 | {printEvery=printEvery}
89 | (fromCostate $
optimiseStep f handleEffect opt)
92 | (currentValue, currentState)
93 | (fromCostate $
evalFw (f.fwd . opt.fwd) handleEffect)
99 | buildSupervisedLearningSystem : (f : x =\\=> y) -> (loss : y =\\=> l) ->
100 | Materialise (Param f).Shp => InterfaceOnPositions (Param f) Materialise =>
101 | Param f =%+> (SupervisedData x.Shp (Param loss).Shp) >-+@ l
102 | buildSupervisedLearningSystem f loss =
103 | let supplied : (a >*< b) >*< c =%+> a >*< (c >*< b)
104 | supplied = assocL %+>> (id >*< swap)
105 | in materialiseCont %+>> pushIntoContinuation {d=x>*<Param loss}
106 | (supplied %+>> (composePara f loss).Run)
109 | namespace WithEffect
113 | (f : x =\\=> e >-+@ y) ->
114 | (loss : y =\\=> l) ->
115 | (p : (Param f).Shp) ->
116 | (handleEffect : Costate (IO <!> e)) ->
117 | Costate (IO <!> Const2 (x.Shp, (Param loss).Shp) l.Shp)
118 | computeLoss f loss p handleEffect = toCostate $
\(x, yTrue) => do
119 | yPred <- fromCostate (evalFw (Run f).fwd handleEffect) (x, p)
120 | pure ((Run loss).fwd (yPred, yTrue))
128 | totalLoss : Num l.Shp =>
129 | (f : x =\\=> e >-+@ y) ->
130 | (loss : y =\\=> l) ->
131 | (p : (Param f).Shp) ->
132 | (handleEffect : Costate (IO <!> e)) ->
133 | Costate (IO <!> (Const2 (Vect n (x.Shp, Label loss)) l.Shp))
134 | totalLoss (MkPara pCont f) (MkPara z loss) p handleEffect
135 | = let evalFWithLoss : (x.Shp, z.Shp) -> IO l.Shp
136 | evalFWithLoss (x, yTrue) = do
137 | yPred <- fromCostate (evalFw f.fwd handleEffect) (x, p)
138 | pure $
loss.fwd (yPred, yTrue)
140 | in toCostate $
\testData => do
141 | losses <- traverse evalFWithLoss testData
142 | pure $
Prelude.sum losses
147 | averageLoss : {n : Nat} ->
148 | Num l.Shp => Fractional l.Shp => Cast Nat l.Shp =>
149 | (f : x =\\=> e >-+@ y) ->
150 | (loss : y =\\=> l) ->
151 | (p : (Param f).Shp) ->
152 | (handleEffect : Costate (IO <!> e)) ->
153 | Costate (IO <!> (Const2 (Vect n (x.Shp, Label loss)) l.Shp))
154 | averageLoss f loss p handleEffect = toCostate $
\testData => do
155 | lossSum <- fromCostate (totalLoss f loss p handleEffect) testData
156 | pure (lossSum / cast n)
161 | evalPrint : {0 a, y : AddCont} -> {0 e : Cont} ->
162 | {default True printEffect : Bool} ->
163 | Show a.Shp => Show e.Shp => Show y.Shp =>
164 | (m : a -\-> e >-+@ y) -> (p : m.Params) ->
165 | (handleEffect : Costate (IO <!> e)) ->
166 | Dataset a.Shp lab -> IO ()
167 | evalPrint {printEffect} m p handleEffect dl = for_ dl $
\(x, _) => do
168 | let out = m.fwd x p
169 | answer <- fromCostate handleEffect (shapeExt out)
171 | asked = if printEffect then ", Effect out: \{show (shapeExt out)}" else ""
172 | putStrLn "Input: \{show x}\{asked}, Predicted: \{show (index out answer)}"
175 | evalLoss : {0 a, y, l : AddCont} -> {0 e : Cont} ->
176 | (m : a -\-> e >-+@ y) -> (loss : Loss y l) -> (p : m.Params) ->
177 | (handleEffect : Costate (IO <!> e)) ->
178 | Dataset a.Shp (Label loss) -> IO (Tensor [DatasetAxis] l.Shp)
179 | evalLoss m loss p handleEffect
180 | = traverse (fromCostate (computeLoss (toPara m) loss p handleEffect))
184 | matchRate : Foldable t => t (Either e l) -> Double
185 | matchRate xs = cast (count isRight xs) / cast (count (const True) xs)
189 | averageMatched : Foldable t => Fractional l => Cast Nat l =>
190 | t (Either e l) -> Maybe l
191 | averageMatched xs = case rights (toList xs) of
193 | ls => Just (Prelude.sum ls / cast (length ls))
197 | train : {a, b : AddCont} -> {l : AddCont} ->
198 | {default 100 printEvery : Nat} ->
200 | (loss : Loss b l) ->
201 | InterfaceOnPositions l Num =>
202 | ScientificDisplay l.Shp =>
203 | Materialise m.Params => Materialise stateTy =>
204 | ScientificDisplay m.Params => ScientificDisplay stateTy =>
205 | (trainData : Dataset a.Shp (Label loss)) ->
206 | (opt : Optimiser (ParamCont m) stateTy) ->
207 | (numSteps : Nat) ->
208 | IO (m.Params, stateTy)
209 | train m loss trainData opt numSteps = optimise {printEvery}
210 | (buildSupervisedLearningSystem (toPara m) loss)
211 | (handleDataFor trainData)
218 | averageLoss : {0 a, b, l : AddCont} ->
220 | (loss : b =\\=> l) ->
221 | Fractional l.Shp => Cast Nat l.Shp =>
223 | (dl : Dataset a.Shp (Label loss)) ->
225 | averageLoss m (MkPara z loss) p dl =
226 | let pointLoss : (a.Shp, z.Shp) -> l.Shp
227 | pointLoss (x, yTrue) = loss.fwd (m.fwd x p, yTrue)
228 | in Prelude.sum (pointLoss <$> dl) / cast (datasetSize dl)
233 | evalPrint : {0 a, b : AddCont} -> {dataset : Axis} ->
234 | IsFoldable dataset.cont =>
235 | ScientificDisplay a.Shp => ScientificDisplay b.Shp =>
236 | (m : a -\-> b) -> (p : m.Params) ->
237 | Tensor [dataset] a.Shp -> IO ()
238 | evalPrint m p dl = do
239 | putStrLn "Model's predictions on inputs:"
240 | let input = "Input"
241 | predicted = "Predicted"
243 | putStrLn " \{dim input}: \{showSci x}, \{dim predicted}: \{bold $ showSci (m.fwd x p)}"