@@ -3,7 +3,6 @@
3{-# LANGUAGE DataKinds #-}
3{-# LANGUAGE DataKinds #-}
4{-# LANGUAGE GADTs #-}
4{-# LANGUAGE GADTs #-}
5{-# LANGUAGE RankNTypes #-}
5{-# LANGUAGE RankNTypes #-}
6−{-# LANGUAGE RecordWildCards #-}
7{-# LANGUAGE TypeOperators #-}
6{-# LANGUAGE TypeOperators #-}
8{-# LANGUAGE TypeFamilies #-}
7{-# LANGUAGE TypeFamilies #-}
9{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE MultiParamTypeClasses #-}
@@ -75,7 +74,7 @@ instance (KnownNat i, KnownNat o) => UpdateLayer (LSTM i o) where
76 -- Run the update function for each group matrix/vector of weights, momentums and gradients.
75 -- Run the update function for each group matrix/vector of weights, momentums and gradients.
77 -- Hmm, maybe the function should be used instead of passing in the learning parameters.
76 -- Hmm, maybe the function should be used instead of passing in the learning parameters.
78− runUpdate LearningParameters {..} (LSTM w m) g =
77+ runUpdate lp (LSTM w m) g =
79 let (wf, wf') = u lstmWf w m g
78 let (wf, wf') = u lstmWf w m g
80 (uf, uf') = u lstmUf w m g
79 (uf, uf') = u lstmUf w m g
81 (bf, bf') = v lstmBf w m g
80 (bf, bf') = v lstmBf w m g
@@ -92,11 +91,11 @@ instance (KnownNat i, KnownNat o) => UpdateLayer (LSTM i o) where
92 -- Utility function for updating with the momentum, gradients, and weights.
91 -- Utility function for updating with the momentum, gradients, and weights.
93 u :: forall x ix out. (KnownNat ix, KnownNat out) => (x -> (L out ix)) -> x -> x -> x -> ((L out ix), (L out ix))
92 u :: forall x ix out. (KnownNat ix, KnownNat out) => (x -> (L out ix)) -> x -> x -> x -> ((L out ix), (L out ix))
94 u e (e -> weights) (e -> momentum) (e -> gradient) =
93 u e (e -> weights) (e -> momentum) (e -> gradient) =
95− descendMatrix learningRate learningMomentum learningRegulariser weights gradient momentum
94+ descendMatrix (learningRate lp) (learningMomentum lp) (learningRegulariser lp) weights gradient momentum
97 v :: forall x ix. (KnownNat ix) => (x -> (R ix)) -> x -> x -> x -> ((R ix), (R ix))
96 v :: forall x ix. (KnownNat ix) => (x -> (R ix)) -> x -> x -> x -> ((R ix), (R ix))
98 v e (e -> weights) (e -> momentum) (e -> gradient) =
97 v e (e -> weights) (e -> momentum) (e -> gradient) =
99− descendVector learningRate learningMomentum learningRegulariser weights gradient momentum
98+ descendVector (learningRate lp) (learningMomentum lp) (learningRegulariser lp) weights gradient momentum
101 -- There's a lot of updates here, so to try and minimise the number of data copies
100 -- There's a lot of updates here, so to try and minimise the number of data copies
102 -- we'll create a mutable bucket for each.
101 -- we'll create a mutable bucket for each.
@@ -137,18 +136,18 @@ instance (KnownNat i, KnownNat o) => RecurrentLayer (LSTM i o) ('D1 i) ('D1 o) w
137 type RecTape (LSTM i o) ('D1 i) ('D1 o) = (R o, R i, R o, R o, R o, R o, R o, R o, R o, R o, R o)
136 type RecTape (LSTM i o) ('D1 i) ('D1 o) = (R o, R i, R o, R o, R o, R o, R o, R o, R o, R o, R o)
138 -- Forward propagation for the LSTM layer.
137 -- Forward propagation for the LSTM layer.
139 -- The size of the cell state is also the size of the output.
138 -- The size of the cell state is also the size of the output.
140− runRecurrentForwards (LSTM (LSTMWeights {..}) _) (S1D cell) (S1D input) =
139+ runRecurrentForwards (LSTM lw _) (S1D cell) (S1D input) =
141 let -- Forget state vector
140 let -- Forget state vector
142− f_s = lstmBf + lstmWf #> input + lstmUf #> cell
141+ f_s = lstmBf lw + lstmWf lw #> input + lstmUf lw #> cell
143 f_t = sigmoid f_s
142 f_t = sigmoid f_s
144 -- Input state vector
143 -- Input state vector
145− i_s = lstmBi + lstmWi #> input + lstmUi #> cell
144+ i_s = lstmBi lw + lstmWi lw #> input + lstmUi lw #> cell
146 i_t = sigmoid i_s
145 i_t = sigmoid i_s
147 -- Output state vector
146 -- Output state vector
148− o_s = lstmBo + lstmWo #> input + lstmUo #> cell
147+ o_s = lstmBo lw + lstmWo lw #> input + lstmUo lw #> cell
149 o_t = sigmoid o_s
148 o_t = sigmoid o_s
150 -- Cell input state vector
149 -- Cell input state vector
151− c_s = lstmBc + lstmWc #> input
150+ c_s = lstmBc lw + lstmWc lw #> input
152 c_x = tanh c_s
151 c_x = tanh c_s
153 -- Cell state
152 -- Cell state
154 c_t = f_t * cell + i_t * c_x
153 c_t = f_t * cell + i_t * c_x
@@ -162,7 +161,7 @@ instance (KnownNat i, KnownNat o) => RecurrentLayer (LSTM i o) ('D1 i) ('D1 o) w
163 -- There's a test version using the AD library without hmatrix in the test
162 -- There's a test version using the AD library without hmatrix in the test
164 -- suite. These should match always.
163 -- suite. These should match always.
165− runRecurrentBackwards (LSTM (LSTMWeights {..}) _) (cell, input, f_s, f_t, i_s, i_t, o_s, o_t, c_s, c_x, c_t) (S1D cellGrad) (S1D h_t') =
164+ runRecurrentBackwards (LSTM lw _) (cell, input, f_s, f_t, i_s, i_t, o_s, o_t, c_s, c_x, c_t) (S1D cellGrad) (S1D h_t') =
166 let -- Reverse Mode AD Derivitives
165 let -- Reverse Mode AD Derivitives
167 c_t' = h_t' * o_t + cellGrad
166 c_t' = h_t' * o_t + cellGrad
@@ -179,8 +178,8 @@ instance (KnownNat i, KnownNat o) => RecurrentLayer (LSTM i o) ('D1 i) ('D1 o) w
179 c_s' = tanh' c_s * c_x'
178 c_s' = tanh' c_s * c_x'
181 -- The derivatives to pass sideways (recurrent) and downwards
180 -- The derivatives to pass sideways (recurrent) and downwards
182− cell' = tr lstmUf #> f_s' + tr lstmUo #> o_s' + tr lstmUi #> i_s' + c_t' * f_t
181+ cell' = tr (lstmUf lw) #> f_s' + tr (lstmUo lw) #> o_s' + tr (lstmUi lw) #> i_s' + c_t' * f_t
183− input' = tr lstmWf #> f_s' + tr lstmWo #> o_s' + tr lstmWi #> i_s' + tr lstmWc #> c_s'
182+ input' = tr (lstmWf lw) #> f_s' + tr (lstmWo lw) #> o_s' + tr (lstmWi lw) #> i_s' + tr (lstmWc lw) #> c_s'
185 -- Calculate the gradient Matricies for the input
184 -- Calculate the gradient Matricies for the input
186 lstmWf' = f_s' `outer` input
185 lstmWf' = f_s' `outer` input
@@ -239,44 +238,34 @@ tanh' :: (Floating a) => a -> a
239tanh' t = 1 - s ^ (2 :: Int) where s = tanh t
238tanh' t = 1 - s ^ (2 :: Int) where s = tanh t
241instance (KnownNat i, KnownNat o) => Serialize (LSTM i o) where
240instance (KnownNat i, KnownNat o) => Serialize (LSTM i o) where
242− put (LSTM LSTMWeights {..} _) = do
241+ put (LSTM lw _) = do
243− u lstmWf
242+ u (lstmWf lw)
244− u lstmUf
243+ u (lstmUf lw)
245− v lstmBf
244+ v (lstmBf lw)
246− u lstmWi
245+ u (lstmWi lw)
247− u lstmUi
246+ u (lstmUi lw)
248− v lstmBi
247+ v (lstmBi lw)
249− u lstmWo
248+ u (lstmWo lw)
250− u lstmUo
249+ u (lstmUo lw)
251− v lstmBo
250+ v (lstmBo lw)
252− u lstmWc
251+ u (lstmWc lw)
253− v lstmBc
252+ v (lstmBc lw)
255− u :: forall a b. (KnownNat a, KnownNat b) => Putter (L b a)
254+ u :: forall a b. (KnownNat a, KnownNat b) => Putter (L b a)
256− u = putListOf put . LA.toList . LA.flatten . extract
255+ u = putListOf put . LA.toList . LA.flatten . extract
257− v :: forall a. (KnownNat a) => Putter (R a)
256+ v :: forall a. (KnownNat a) => Putter (R a)
258− v = putListOf put . LA.toList . extract
257+ v = putListOf put . LA.toList . extract
261− lstmWf <- u
260+ w <- LSTMWeights <$> u <*> u <*> v <*> u <*> u <*> v <*> u <*> u <*> v <*> u <*> v
272− return $ LSTM (LSTMWeights {..}) (LSTMWeights w0 u0 v0 w0 u0 v0 w0 u0 v0 w0 v0)
261+ return $ LSTM w (LSTMWeights w0 u0 v0 w0 u0 v0 w0 u0 v0 w0 v0)
274− u :: forall a b. (KnownNat a, KnownNat b) => Get (L b a)
263+ u :: forall a b. (KnownNat a, KnownNat b) => Get (L b a)
275− u = let f = fromIntegral $ natVal (Proxy :: Proxy a)
264+ u = let f = fromIntegral $ natVal (Proxy :: Proxy a)
276− in maybe (fail "Vector of incorrect size") return . create . LA.reshape f . LA.fromList =<< getListOf get
265+ in maybe (fail "Vector of incorrect size") return . create . LA.reshape f . LA.fromList =<< getListOf get
277− v :: forall a. (KnownNat a) => Get (R a)
266+ v :: forall a. (KnownNat a) => Get (R a)
278− v = maybe (fail "Vector of incorrect size") return . create . LA.fromList =<< getListOf get
267+ v = maybe (fail "Vector of incorrect size") return . create . LA.fromList =<< getListOf get
280− w0 = konst 0
269+ w0 = konst 0
281− u0 = konst 0
270+ u0 = konst 0
282− v0 = konst 0
271+ v0 = konst 0