Synapse-0.1.0.0: test/NNTest.hs
-- | Tests "Synapse.NN" module and its submodules.
module NNTest
( tests
)
where
import Synapse.Tensors
import qualified Synapse.Tensors.Vec as V
import Synapse.NN.Models
import Synapse.NN.Layers
import Synapse.NN.Optimizers
import Synapse.NN.LearningRates
import Synapse.NN.Losses
import Synapse.NN.Batching
import Synapse.NN.Training
import System.Random
import Graphics.EasyPlot
import Test.HUnit
testSin :: Test -- -3 sin (x + 5)
testSin = TestLabel "testSin" $ TestCase $ do
let sinFn x = (-3.0) * sin (x + 5.0)
let model = buildSequentialModel (InputSize 1) [ Layer . layerDense 1
, Layer . layerActivation (Activation cos)
, Layer . layerDense 1
] :: SequentialModel Double
let dataset = Dataset $ V.fromList $ [Sample (singleton x) (sinFn $ singleton x) | x <- [-pi, -pi+0.2 .. pi]]
(trainedModel, _, losses, _) <- train model
(SGD 0.2 False)
(Hyperparameters 500 16 dataset (LearningRate $ const 0.01) (Loss mse) V.empty)
emptyCallbacks
(mkStdGen 1)
_ <- plot (PNG "test/plots/sin.png")
[ Data2D [Title "predicted sin", Style Lines, Color Red] [Range (-pi) pi] [(x, unSingleton $ forward (singleton x) trainedModel) | x <- [-pi, -pi+0.05 .. pi]]
, Data2D [Title "true sin", Style Lines, Color Green] [Range (-pi) pi] [(x, sinFn x) | x <- [-pi, -pi+0.05 .. pi]]
]
let unpackedLosses = unRecordedMetric (unsafeIndex losses 0)
let lastLoss = unsafeIndex unpackedLosses (V.size unpackedLosses - 1)
assertBool "trained well enough" (lastLoss < 0.01)
testSqrt :: Test -- sqrt(x)
testSqrt = TestLabel "testSqrt" $ TestCase $ do
let sqrtFn x = sqrt x
let model = buildSequentialModel (InputSize 1) [ Layer . layerDense 1
, Layer . layerActivation (Activation tanh)
, Layer . layerDense 1
] :: SequentialModel Double
let dataset = Dataset $ V.fromList $ [Sample (singleton x) (sqrtFn $ singleton x) | x <- [0.0, 0.2 .. 4.0]]
(trainedModel, _, losses, _) <- train model
(SGD 0.2 True)
(Hyperparameters 500 16 dataset (LearningRate $ const 0.01) (Loss mse) V.empty)
emptyCallbacks
(mkStdGen 1)
_ <- plot (PNG "test/plots/sqrt.png")
[ Data2D [Title "predicted sqrt", Style Lines, Color Red] [Range 0.0 6.0] $ [(x, unSingleton $ forward (singleton x) trainedModel) | x <- [0.0, 0.05 .. 4.0]]
, Data2D [Title "true sqrt", Style Lines, Color Green] [Range 0.0 6.0] $ [(x, sqrtFn x) | x <- [0.0, 0.05 .. 4.0]]
]
let unpackedLosses = unRecordedMetric (unsafeIndex losses 0)
let lastLoss = unsafeIndex unpackedLosses (V.size unpackedLosses - 1)
assertBool "trained well enough" (lastLoss < 0.01)
testTrigonometry :: Test -- sin(2.0 * cos(x) + 3.0) + 2.5
testTrigonometry = TestLabel "testTrigonometry" $ TestCase $ do
let trigonometryFn x = sin (2.0 * cos x + 3.0) + 2.5
let model = buildSequentialModel (InputSize 1) [ Layer . layerDense 1
, Layer . layerActivation (Activation sin)
, Layer . layerDense 1
, Layer . layerActivation (Activation sin)
, Layer . layerDense 1
] :: SequentialModel Double
let dataset = Dataset $ V.fromList $ [Sample (singleton x) (trigonometryFn $ singleton x) | x <- [-(2.0 * pi),((-(2.0 * pi)) + 0.1)..(2.0 * pi)]]
(trainedModel, _, losses, _) <- train model
(SGD 0.3 True)
(Hyperparameters 1000 1 dataset (LearningRate $ const 0.001) (Loss mse) V.empty)
emptyCallbacks
(mkStdGen 1)
_ <- plot (PNG "test/plots/trigonometry.png")
[ Data2D [Title "predicted trigonometry", Style Lines, Color Red] [Range ((-2.0) * pi) (2.0 * pi)] $ [(x, unSingleton $ forward (singleton x) trainedModel) | x <- [-(2.0 * pi),((-(2.0 * pi)) + 0.1)..(2.0 * pi)]]
, Data2D [Title "true trigonometry", Style Lines, Color Green] [Range ((-2.0) * pi) (2.0 * pi)] $ [(x, trigonometryFn x) | x <- [-(2.0 * pi),((-(2.0 * pi)) + 0.1)..(2.0 * pi)]]
]
let unpackedLosses = unRecordedMetric (unsafeIndex losses 0)
let lastLoss = unsafeIndex unpackedLosses (V.size unpackedLosses - 1)
assertBool "trained well enough" (lastLoss < 0.01)
tests :: Test
tests = TestLabel "NNTest" $ TestList
[ testSin
, testSqrt
, testTrigonometry
]