synapse-0.1.0.0: test/AutogradTest.hs
-- | Tests @Synapse.Autograd@ module and its submodules.
module AutogradTest
( tests
) where
import Synapse.Autograd
import Synapse.Tensors (MatOps(..))
import qualified Synapse.Tensors.Vec as V
import qualified Synapse.Tensors.Mat as M
import Test.HUnit
testNumOps :: Test
testNumOps = TestLabel "testIntOps" $ TestList
[ TestCase $ assertEqual "zero gradient" 0 (unSymbol $ getGradientsOf a `wrt` b)
, TestCase $ assertEqual "identity gradient" 1 (unSymbol $ getGradientsOf a `wrt` a)
, TestCase $ assertEqual "composited identity gradient" 1 (unSymbol $ getGradientsOf c `wrt` c)
, TestCase $ assertEqual "addition gradient" 1 (unSymbol $ getGradientsOf (a + b) `wrt` a)
, TestCase $ assertEqual "subtraction gradient" (-1) (unSymbol $ getGradientsOf (a - b) `wrt` b)
, TestCase $ assertEqual "multiplication gradient" 3 (unSymbol $ getGradientsOf (a * b) `wrt` a)
, TestCase $ assertEqual "composed operations gradient" (4 * 4 * 3) (unSymbol $ getGradientsOf (a * (b + b) * a) `wrt` a)
, TestCase $ assertEqual "renamed symbol gradient" (2 * 25) (unSymbol $ getGradientsOf (c * c) `wrt` c)
]
where
a = symbol (SymbolIdentifier "a") 4 :: Symbol Int
b = symbol (SymbolIdentifier "b") 3 :: Symbol Int
c = renameSymbol (SymbolIdentifier "c") ((a * a) + (b * b)) :: Symbol Int
testNthOrderGradients :: Test
testNthOrderGradients = TestLabel "testNthOrderGradients" $ TestList
[ TestCase $ assertEqual "identity 2nd gradient" 0 (unSymbol $ nthGradient 2 a a)
, TestCase $ assertEqual "composed operations 2nd gradient" (4 * 3) (unSymbol $ nthGradient 2 (a * (b + b) * a) a)
, TestCase $ assertEqual "4th gradient" (unSymbol $ sin c) (unSymbol $ nthGradient 4 (sin c) c)
]
where
a = symbol (SymbolIdentifier "a") 4 :: Symbol Int
b = symbol (SymbolIdentifier "b") 3 :: Symbol Int
c = symbol (SymbolIdentifier "c") 0.5 :: Symbol Float
testVecOps :: Test
testVecOps = TestLabel "testVecOps" $ TestList
[ TestCase $ assertEqual "vector addition gradient" (V.replicate 3 1.0) (unSymbol $ getGradientsOf (a + b) `wrt` a)
, TestCase $ assertEqual "vector elementwise multiplication gradient" (unSymbol b) (unSymbol $ getGradientsOf (a * b) `wrt` a)
, TestCase $ assertEqual "vector op gradient" (V.map cos $ unSymbol a) (unSymbol $ getGradientsOf (sin a) `wrt` a)
]
where
a = symbol (SymbolIdentifier "a") (V.fromList [1.0, 2.0, 3.0]) :: SymbolVec Float
b = symbol (SymbolIdentifier "b") (V.fromList [3.0, 2.0, 1.0]) :: SymbolVec Float
testMatOps :: Test
testMatOps = TestLabel "testMatOps" $ TestList
[ TestCase $ assertEqual "matrix addition gradient" (M.replicate (3, 3) 1.0) (unSymbol $ getGradientsOf (a + b) `wrt` a)
, TestCase $ assertEqual "matrix elementwise multiplication gradient" (unSymbol b) (unSymbol $ getGradientsOf (a * b) `wrt` a)
, TestCase $ assertEqual "matrix op gradient" (M.map cos $ unSymbol a) (unSymbol $ getGradientsOf (sin a) `wrt` a)
, TestCase $ assertEqual "matrix transposing gradient" (M.transpose $ unSymbol c) (unSymbol $ getGradientsOf (transpose c) `wrt` c)
, TestCase $ assertEqual "matrix multiplication+addition gradient" (M.transpose $ unSymbol c) (unSymbol $ getGradientsOf (c `matMul` d + e) `wrt` d)
, TestCase $ assertEqual "matrix composed multiplication gradient" (M.transpose $ unSymbol c) (unSymbol $ getGradientsOf (c `matMul` d `matMul` e) `wrt` d)
]
where
a = symbol (SymbolIdentifier "a") (M.replicate (3, 3) 3.0) :: SymbolMat Float
b = symbol (SymbolIdentifier "b") (M.replicate (3, 3) (-3.0)) :: SymbolMat Float
c = symbol (SymbolIdentifier "c") (M.fromLists (1, 2) [[5.0, 3.0]]) :: SymbolMat Float
d = symbol (SymbolIdentifier "d") (M.fromLists (2, 1) [[1.0], [-2.0]]) :: SymbolMat Float
e = symbol (SymbolIdentifier "e") (M.fromLists (1, 1) [[1.0]]) :: SymbolMat Float
tests :: Test
tests = TestLabel "AutogradTest" $ TestList
[ testNumOps
, testNthOrderGradients
, testVecOps
, testMatOps
]