@@ -7,52 +7,64 @@
77
88module Grenade.Core.Runner (
99 train
10+ , backPropagate
1011 , runNet
12+ , applyUpdate
1113 ) where
1214
1315import Data.Singletons.Prelude
1416import Grenade.Core.Network
1517import Grenade.Core.Shape
1618
17−-- | Update a network with new weights after training with an instance.
18−train :: forall i o hs. (Head hs ~ i, Last hs ~ o, KnownShape i, KnownShape o)
19− => LearningParameters -- ^ learning rate
20− -> S' i -- ^ input vector
21− -> S' o -- ^ target vector
22− -> Network hs -- ^ network to train
23− -> Network hs
24−train rate x0 target = fst . go x0
19+-- | Drive and network and collect it's back propogated gradients.
20+backPropagate :: forall input output shapes layers. (Head shapes ~ input, Last shapes ~ output)
21+ => Network layers shapes -> S' input -> S' output -> Gradients layers
22+backPropagate network input target =
23+ fst $ go input network
2524 where
26− go :: forall j js. (Head js ~ j, Last js ~ o, KnownShape j)
27− => S' j -- ^ input vector
28− -> Network js -- ^ network to train
29− -> (Network js, S' j)
25+ go :: forall j js sublayers. (Head js ~ j, Last js ~ output)
26+ => S' j -- ^ input vector
27+ -> Network sublayers js -- ^ network to train
28+ -> (Gradients sublayers, S' j)
3029 -- handle input from the beginning, feeding upwards.
3130 go !x (layer :~> n)
3231 = let y = runForwards layer x
33− -- run the rest of the network, and get the layer from above.
32+ -- recursively run the rest of the network, and get the layer from above.
3433 (n', dWs') = go y n
3534 -- calculate the gradient for this layer to pass down,
3635 (layer', dWs) = runBackards layer x dWs'
3736
38− -- Update this layer using the gradient
39− newLayer = runUpdate rate layer layer'
40−
41− in (newLayer :~> n', dWs)
37+ in (layer' :/> n', dWs)
4238
4339 -- handle the output layer, bouncing the derivatives back down.
4440 go !x (O layer)
4541 = let y = runForwards layer x
46− -- the gradient (how much y affects the error)
42+ -- the gradient (how much y affects the error)
4743 (layer', dWs) = runBackards layer x (y - target)
48− newLayer = runUpdate rate layer layer'
4944
50− in (O newLayer, dWs)
45+ in (OG layer', dWs)
46+
47+-- | Update a network with new weights after training with an instance.
48+train :: forall input output shapes layers. (Head shapes ~ input, Last shapes ~ output)
49+ => LearningParameters -- ^ learning rate
50+ -> Network layers shapes -- ^ network to train
51+ -> S' input -> S' output -- ^ target vector
52+ -> Network layers shapes
53+train rate network input output =
54+ let grads = backPropagate network input output
55+ in applyUpdate rate network grads
56+
57+applyUpdate :: LearningParameters -> Network ls ss -> Gradients ls -> Network ls ss
58+applyUpdate rate (O layer) (OG gradient)
59+ = O (runUpdate rate layer gradient)
60+applyUpdate rate (layer :~> rest) (gradient :/> grest)
61+ = runUpdate rate layer gradient :~> applyUpdate rate rest grest
62+applyUpdate _ _ _
63+ = error "Impossible for the gradients of a network to have a different length to the network"
5164
5265-- | Just forwards propagation with no training.
53−runNet :: Network hs
66+runNet :: Network layers hs
5467 -> S' (Head hs) -- ^ input vector
5568 -> S' (Last hs) -- ^ target vector
56−runNet (layer :~> n) !x = let y = runForwards layer x
57− in runNet n y
69+runNet (layer :~> n) !x = let y = runForwards layer x in runNet n y
5870runNet (O layer) !x = runForwards layer x