@@ -10,7 +10,7 @@
10{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
10{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
11module Test.Grenade.Recurrent.Layers.LSTM where
11module Test.Grenade.Recurrent.Layers.LSTM where
13−import Disorder.Jack
13+import Hedgehog
15import Data.Foldable ( toList )
15import Data.Foldable ( toList )
16import Data.Singletons.TypeLits
16import Data.Singletons.TypeLits
@@ -24,6 +24,7 @@ import qualified Numeric.LinearAlgebra.Static as S
25import qualified Test.Grenade.Recurrent.Layers.LSTM.Reference as Reference
25import qualified Test.Grenade.Recurrent.Layers.LSTM.Reference as Reference
26import Test.Jack.Hmatrix
26import Test.Jack.Hmatrix
27+import Test.Jack.Compat
28genLSTM :: forall i o. (KnownNat i, KnownNat o) => Jack (LSTM i o)
29genLSTM :: forall i o. (KnownNat i, KnownNat o) => Jack (LSTM i o)
29genLSTM = do
30genLSTM = do
@@ -39,63 +40,69 @@ genLSTM = do
39 <*> pure (LSTMWeights w0 u0 v0 w0 u0 v0 w0 u0 v0 w0 v0)
40 <*> pure (LSTMWeights w0 u0 v0 w0 u0 v0 w0 u0 v0 w0 v0)
41prop_lstm_reference_forwards =
42prop_lstm_reference_forwards =
42− gamble randomVector $ \(input :: S.R 3) ->
43+ property $ do
43− gamble randomVector $ \(cell :: S.R 2) ->
44+ input :: S.R 3 <- forAll randomVector
44− gamble genLSTM $ \(net@(LSTM lstmWeights _) :: LSTM 3 2) ->
45+ cell :: S.R 2 <- forAll randomVector
46+ net@(LSTM lstmWeights _) :: LSTM 3 2 <- forAll genLSTM
45− let actual = runRecurrentForwards net (S1D cell) (S1D input)
48+ let actual = runRecurrentForwards net (S1D cell) (S1D input)
46− in case actual of
49+ case actual of
47− (_, (S1D cellOut) :: S ('D1 2), (S1D output) :: S ('D1 2)) ->
50+ (_, (S1D cellOut) :: S ('D1 2), (S1D output) :: S ('D1 2)) ->
48− let cellOut' = Reference.Vector . H.toList . S.extract $ cellOut
51+ let cellOut' = Reference.Vector . H.toList . S.extract $ cellOut
49− output' = Reference.Vector . H.toList . S.extract $ output
52+ output' = Reference.Vector . H.toList . S.extract $ output
50− refNet = Reference.lstmToReference lstmWeights
53+ refNet = Reference.lstmToReference lstmWeights
51− refCell = Reference.Vector . H.toList . S.extract $ cell
54+ refCell = Reference.Vector . H.toList . S.extract $ cell
52− refInput = Reference.Vector . H.toList . S.extract $ input
55+ refInput = Reference.Vector . H.toList . S.extract $ input
53− (refCO, refO) = Reference.runLSTM refNet refCell refInput
56+ (refCO, refO) = Reference.runLSTM refNet refCell refInput
54− in toList refCO ~~~ toList cellOut' .&&. toList refO ~~~ toList output'
57+ in do assert (toList refCO ~~~ toList cellOut')
58+ assert (toList refO ~~~ toList output')
56prop_lstm_reference_backwards =
61prop_lstm_reference_backwards =
57− gamble randomVector $ \(input :: S.R 3) ->
62+ property $ do
58− gamble randomVector $ \(cell :: S.R 2) ->
63+ input :: S.R 3 <- forAll randomVector
59− gamble genLSTM $ \(net@(LSTM lstmWeights _) :: LSTM 3 2) ->
64+ cell :: S.R 2 <- forAll randomVector
65+ net@(LSTM lstmWeights _) :: LSTM 3 2 <- forAll genLSTM
60− let actualBacks = runRecurrentBackwards net (S1D cell, S1D input) (S1D (S.konst 1) :: S ('D1 2)) (S1D (S.konst 1) :: S ('D1 2))
66+ let actualBacks = runRecurrentBackwards net (S1D cell, S1D input) (S1D (S.konst 1) :: S ('D1 2)) (S1D (S.konst 1) :: S ('D1 2))
61− in case actualBacks of
67+ case actualBacks of
62− (actualGradients, _, _ :: S ('D1 3)) ->
68+ (actualGradients, _, _ :: S ('D1 3)) ->
63− let refNet = Reference.lstmToReference lstmWeights
69+ let refNet = Reference.lstmToReference lstmWeights
64− refCell = Reference.Vector . H.toList . S.extract $ cell
70+ refCell = Reference.Vector . H.toList . S.extract $ cell
65− refInput = Reference.Vector . H.toList . S.extract $ input
71+ refInput = Reference.Vector . H.toList . S.extract $ input
66− refGradients = Reference.runLSTMback refCell refInput refNet
72+ refGradients = Reference.runLSTMback refCell refInput refNet
67− in toList refGradients ~~~ toList (Reference.lstmToReference actualGradients)
73+ in assert $ toList refGradients ~~~ toList (Reference.lstmToReference actualGradients)
69prop_lstm_reference_backwards_input =
75prop_lstm_reference_backwards_input =
70− gamble randomVector $ \(input :: S.R 3) ->
76+ property $ do
71− gamble randomVector $ \(cell :: S.R 2) ->
77+ input :: S.R 3 <- forAll randomVector
72− gamble genLSTM $ \(net@(LSTM lstmWeights _) :: LSTM 3 2) ->
78+ cell :: S.R 2 <- forAll randomVector
79+ net@(LSTM lstmWeights _) :: LSTM 3 2 <- forAll genLSTM
73− let actualBacks = runRecurrentBackwards net (S1D cell, S1D input) (S1D (S.konst 1) :: S ('D1 2)) (S1D (S.konst 1) :: S ('D1 2))
80+ let actualBacks = runRecurrentBackwards net (S1D cell, S1D input) (S1D (S.konst 1) :: S ('D1 2)) (S1D (S.konst 1) :: S ('D1 2))
74− in case actualBacks of
81+ case actualBacks of
75− (_, _, S1D actualGradients :: S ('D1 3)) ->
82+ (_, _, S1D actualGradients :: S ('D1 3)) ->
76− let refNet = Reference.lstmToReference lstmWeights
83+ let refNet = Reference.lstmToReference lstmWeights
77− refCell = Reference.Vector . H.toList . S.extract $ cell
84+ refCell = Reference.Vector . H.toList . S.extract $ cell
78− refInput = Reference.Vector . H.toList . S.extract $ input
85+ refInput = Reference.Vector . H.toList . S.extract $ input
79− refGradients = Reference.runLSTMbackOnInput refCell refNet refInput
86+ refGradients = Reference.runLSTMbackOnInput refCell refNet refInput
80− in toList refGradients ~~~ H.toList (S.extract actualGradients)
87+ in assert $ toList refGradients ~~~ H.toList (S.extract actualGradients)
82prop_lstm_reference_backwards_cell =
89prop_lstm_reference_backwards_cell =
83− gamble randomVector $ \(input :: S.R 3) ->
90+ property $ do
84− gamble randomVector $ \(cell :: S.R 2) ->
91+ input :: S.R 3 <- forAll randomVector
85− gamble genLSTM $ \(net@(LSTM lstmWeights _) :: LSTM 3 2) ->
92+ cell :: S.R 2 <- forAll randomVector
93+ net@(LSTM lstmWeights _) :: LSTM 3 2 <- forAll genLSTM
86− let actualBacks = runRecurrentBackwards net (S1D cell, S1D input) (S1D (S.konst 1) :: S ('D1 2)) (S1D (S.konst 1) :: S ('D1 2))
94+ let actualBacks = runRecurrentBackwards net (S1D cell, S1D input) (S1D (S.konst 1) :: S ('D1 2)) (S1D (S.konst 1) :: S ('D1 2))
87− in case actualBacks of
95+ case actualBacks of
88− (_, S1D actualGradients, _ :: S ('D1 3)) ->
96+ (_, S1D actualGradients, _ :: S ('D1 3)) ->
89− let refNet = Reference.lstmToReference lstmWeights
97+ let refNet = Reference.lstmToReference lstmWeights
90− refCell = Reference.Vector . H.toList . S.extract $ cell
98+ refCell = Reference.Vector . H.toList . S.extract $ cell
91− refInput = Reference.Vector . H.toList . S.extract $ input
99+ refInput = Reference.Vector . H.toList . S.extract $ input
92− refGradients = Reference.runLSTMbackOnCell refInput refNet refCell
100+ refGradients = Reference.runLSTMbackOnCell refInput refNet refCell
93− in toList refGradients ~~~ H.toList (S.extract actualGradients)
101+ in assert $ toList refGradients ~~~ H.toList (S.extract actualGradients)
96(~~~) as bs = all (< 1e-8) (zipWith (-) as bs)
104(~~~) as bs = all (< 1e-8) (zipWith (-) as bs)
97infix 4 ~~~
105infix 4 ~~~
100tests :: IO Bool
107tests :: IO Bool
101−tests = $quickCheckAll
108+tests = $$(checkConcurrent)