packages feed

backprop 0.1.5.1 → 0.1.5.2

raw patch · 8 files changed

+420/−351 lines, 8 filesdep +randomPVP: minor bump suggested

API additions: PVP suggests at least a minor version bump

Dependencies added: random

API changes (from Hackage documentation)

+ Numeric.Backprop: coerceVar :: Coercible a b => BVar s a -> BVar s b
+ Numeric.Backprop.Tuple: instance (System.Random.Random a, System.Random.Random b) => System.Random.Random (Numeric.Backprop.Tuple.T2 a b)
+ Numeric.Backprop.Tuple: instance (System.Random.Random a, System.Random.Random b, System.Random.Random c) => System.Random.Random (Numeric.Backprop.Tuple.T3 a b c)
+ Numeric.Backprop.Tuple: instance (Type.Class.Known.Known [*] (Data.Type.Length.Length *) as, Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint System.Random.Random as)) => System.Random.Random (Numeric.Backprop.Tuple.T as)
+ Numeric.Backprop.Tuple: instance System.Random.Random Numeric.Backprop.Tuple.T0

Files

CHANGELOG.md view
@@ -1,10 +1,23 @@ Changelog ========= +Version 0.1.5.2+---------------++*Apr 26, 2018*++<https://github.com/mstksg/backprop/releases/tag/v0.1.5.2>++*   Added `coerceVar` to *Numeric.Backprop*+*   Added `Random` instaces for all tuple types.  Same as for `Binary`, this+    does incur a *random* and *time* dependency only from the tuple types.+    Again, because these packages are a part of GHC's boot libraries, this+    is hopefully not too bad.+ Version 0.1.5.1 --------------- -*Apr 8, 2018*+*Apr 9, 2018*  <https://github.com/mstksg/backprop/releases/tag/v0.1.5.1> 
backprop.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 27ad120cc4fb815335e1be622df84ce63c95b38332af173a6898e59a80a7c0ad+-- hash: 1a3823df38b9b0fe0ecb1481bea9f4b591e24a0abe5f96c21bf88c2b6055851b  name:           backprop-version:        0.1.5.1+version:        0.1.5.2 synopsis:       Heterogeneous automatic differentation (backpropagation) description:    Write your functions to compute your result, and the library will                 automatically generate functions to compute your gradient.@@ -51,6 +51,7 @@     , deepseq     , microlens     , primitive+    , random     , reflection     , transformers     , type-combinators@@ -67,7 +68,7 @@  benchmark backprop-mnist-bench   type: exitcode-stdio-1.0-  main-is: MNISTBench.hs+  main-is: bench.hs   hs-source-dirs:       bench   ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wredundant-constraints -fprint-explicit-kinds -threaded -rtsopts -with-rtsopts=-N -O2
− bench/MNISTBench.hs
@@ -1,334 +0,0 @@-{-# LANGUAGE BangPatterns         #-}-{-# LANGUAGE DataKinds            #-}-{-# LANGUAGE DeriveGeneric        #-}-{-# LANGUAGE FlexibleContexts     #-}-{-# LANGUAGE GADTs                #-}-{-# LANGUAGE LambdaCase           #-}-{-# LANGUAGE ScopedTypeVariables  #-}-{-# LANGUAGE TemplateHaskell      #-}-{-# LANGUAGE TypeApplications     #-}-{-# LANGUAGE ViewPatterns         #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--import           Control.DeepSeq-import           Control.Exception-import           Control.Lens hiding          ((:<), (<.>))-import           Control.Monad.IO.Class-import           Control.Monad.Trans.Maybe-import           Criterion.Main-import           Criterion.Types-import           Data.Bitraversable-import           Data.IDX-import           Data.Time-import           Data.Traversable-import           Data.Tuple-import           GHC.Generics                 (Generic)-import           GHC.TypeLits-import           Numeric.Backprop-import           Numeric.LinearAlgebra.Static-import           System.Directory-import qualified Data.Vector.Generic          as VG-import qualified Data.Vector.Unboxed          as VU-import qualified Numeric.LinearAlgebra        as HM-import qualified System.Random.MWC            as MWC--data Layer i o =-    Layer { _lWeights :: !(L o i)-          , _lBiases  :: !(R o)-          }-  deriving (Show, Generic)--instance NFData (Layer i o)--makeLenses ''Layer--data Network i h1 h2 o =-    Net { _nLayer1 :: !(Layer i  h1)-        , _nLayer2 :: !(Layer h1 h2)-        , _nLayer3 :: !(Layer h2 o)-        }-  deriving (Show, Generic)--instance NFData (Network i h1 h2 o)--makeLenses ''Network--infixr 8 #>!-(#>!)-    :: (KnownNat m, KnownNat n, Reifies s W)-    => BVar s (L m n)-    -> BVar s (R n)-    -> BVar s (R m)-(#>!) = liftOp2 . op2 $ \m v ->-  ( m #> v, \g -> (g `outer` v, tr m #> g) )---infixr 8 <.>!-(<.>!)-    :: (KnownNat n, Reifies s W)-    => BVar s (R n)-    -> BVar s (R n)-    -> BVar s Double-(<.>!) = liftOp2 . op2 $ \x y ->-  ( x <.> y, \g -> (konst g * y, x * konst g)-  )--konst'-    :: (KnownNat n, Reifies s W)-    => BVar s Double-    -> BVar s (R n)-konst' = liftOp1 . op1 $ \c -> (konst c, HM.sumElements . extract)--sumElements :: KnownNat n => R n -> Double-sumElements = HM.sumElements . extract--sumElements'-    :: (KnownNat n, Reifies s W)-    => BVar s (R n)-    -> BVar s Double-sumElements' = liftOp1 . op1 $ \x -> (sumElements x, konst)--logistic :: Floating a => a -> a-logistic x = 1 / (1 + exp (-x))-{-# INLINE logistic #-}--runLayer-    :: (KnownNat i, KnownNat o, Reifies s W)-    => BVar s (Layer i o)-    -> BVar s (R i)-    -> BVar s (R o)-runLayer l x = (l ^^. lWeights) #>! x + (l ^^. lBiases)-{-# INLINE runLayer #-}--softMax :: (KnownNat n, Reifies s W) => BVar s (R n) -> BVar s (R n)-softMax x = konst' (1 / sumElements' expx) * expx-  where-    expx = exp x-{-# INLINE softMax #-}--runNetwork-    :: (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o, Reifies s W)-    => BVar s (Network i h1 h2 o)-    -> R i-    -> BVar s (R o)-runNetwork n = softMax-             . runLayer (n ^^. nLayer3)-             . logistic-             . runLayer (n ^^. nLayer2)-             . logistic-             . runLayer (n ^^. nLayer1)-             . constVar-{-# INLINE runNetwork #-}--crossEntropy :: (KnownNat n, Reifies s W) => R n -> BVar s (R n) -> BVar s Double-crossEntropy t r = negate $ log r <.>! constVar t-{-# INLINE crossEntropy #-}--netErr-    :: (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o, Reifies s W)-    => R i-    -> R o-    -> BVar s (Network i h1 h2 o)-    -> BVar s Double-netErr x t n = crossEntropy t (runNetwork n x)-{-# INLINE netErr #-}--trainStep-    :: forall i h1 h2 o. (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o)-    => Double-    -> R i-    -> R o-    -> Network i h1 h2 o-    -> Network i h1 h2 o-trainStep r !x !t !n = n - realToFrac r * gradBP (netErr x t) n-{-# INLINE trainStep #-}--runLayerManual-    :: (KnownNat i, KnownNat o)-    => Layer i o-    -> R i-    -> R o-runLayerManual l x = (l ^. lWeights) #> x + (l ^. lBiases)-{-# INLINE runLayerManual #-}--softMaxManual :: KnownNat n => R n -> R n-softMaxManual x = konst (1 / sumElements expx) * expx-  where-    expx = exp x-{-# INLINE softMaxManual #-}--runNetManual-    :: (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o)-    => Network i h1 h2 o-    -> R i-    -> R o-runNetManual n = softMaxManual-               . runLayerManual (n ^. nLayer3)-               . logistic-               . runLayerManual (n ^. nLayer2)-               . logistic-               . runLayerManual (n ^. nLayer1)-{-# INLINE runNetManual #-}--gradNetManual-    :: forall i h1 h2 o. (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o)-    => R i-    -> R o-    -> Network i h1 h2 o-    -> Network i h1 h2 o-gradNetManual x t (Net (Layer w1 b1) (Layer w2 b2) (Layer w3 b3)) =-    let y1 = w1 #> x-        z1 = y1 + b1-        x2 = logistic z1-        y2 = w2 #> x2-        z2 = y2 + b2-        x3 = logistic z2-        y3 = w3 #> x3-        z3 = y3 + b3-        o0 = exp z3-        o1 = HM.sumElements (extract o0)-        o2 = o0 / konst o1-        -- o3 = - (log o2 <.> t)-        dEdO3 = 1-        dEdO2 = dEdO3 * (- t / o2)-        dEdO1 = - (dEdO2 <.> o0) / (o1 ** 2)-        dEdO0 = konst dEdO1 + dEdO2 / konst o1-        dEdZ3 = dEdO0 * o0-        dEdY3 = dEdZ3-        dEdX3 = tr w3 #> dEdY3-        dEdZ2 = dEdX3 * (x3 * (1 - x3))-        dEdY2 = dEdZ2-        dEdX2 = tr w2 #> dEdY2-        dEdZ1 = dEdX2 * (x2 * (1 - x2))-        dEdY1 = dEdZ1-        dEdB3 = dEdZ3-        dEdW3 = dEdY3 `outer` x3-        dEdB2 = dEdZ2-        dEdW2 = dEdY2 `outer` x2-        dEdB1 = dEdZ1-        dEdW1 = dEdY1 `outer` x-    in  Net (Layer dEdW1 dEdB1) (Layer dEdW2 dEdB2) (Layer dEdW3 dEdB3)-{-# INLINE gradNetManual #-}--trainStepManual-    :: forall i h1 h2 o. (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o)-    => Double-    -> R i-    -> R o-    -> Network i h1 h2 o-    -> Network i h1 h2 o-trainStepManual r !x !t !n =-    let gN = gradNetManual x t n-    in  n - (realToFrac r * gN)--main :: IO ()-main = MWC.withSystemRandom $ \g -> do-    Just test  <- loadMNIST "data/t10k-images-idx3-ubyte"  "data/t10k-labels-idx1-ubyte"-    putStrLn "Loaded data."-    net0 <- MWC.uniformR @(Network 784 300 100 9) (-0.5, 0.5) g-    createDirectoryIfMissing True "bench-results"-    t <- getZonedTime-    let test0   = head test-        tstr    = formatTime defaultTimeLocale "%Y%m%d-%H%M%S" t-    defaultMainWith defaultConfig-          { reportFile = Just $ "bench-results/mnist-bench_" ++ tstr ++ ".html"-          , timeLimit  = 10-          } [-        bgroup "gradient" [-            let testManual x y = gradNetManual x y net0-            in  bench "manual" $ nf (uncurry testManual) test0-          , let testBP     x y = gradBP (netErr x y) net0-            in  bench "bp"     $ nf (uncurry testBP) test0-          ]-      , bgroup "descent" [-            let testManual x y = trainStepManual 0.02 x y net0-            in  bench "manual" $ nf (uncurry testManual) test0-          , let testBP     x y = trainStep 0.02 x y net0-            in  bench "bp"     $ nf (uncurry testBP) test0-          ]-      , bgroup "run" [-            let testManual     = runNetManual net0-            in  bench "manual" $ nf testManual (fst test0)-          , let testBP     x   = evalBP (`runNetwork` x) net0-            in  bench "bp"     $ nf testBP (fst test0)-          ]-      ]--loadMNIST-    :: FilePath-    -> FilePath-    -> IO (Maybe [(R 784, R 9)])-loadMNIST fpI fpL = runMaybeT $ do-    i <- MaybeT          $ decodeIDXFile       fpI-    l <- MaybeT          $ decodeIDXLabelsFile fpL-    d <- MaybeT . return $ labeledIntData l i-    r <- MaybeT . return $ for d (bitraverse mkImage mkLabel . swap)-    liftIO . evaluate $ force r-  where-    mkImage :: VU.Vector Int -> Maybe (R 784)-    mkImage = create . VG.convert . VG.map (\i -> fromIntegral i / 255)-    mkLabel :: Int -> Maybe (R 9)-    mkLabel n = create $ HM.build 9 (\i -> if round i == n then 1 else 0)--instance (KnownNat i, KnownNat o) => Num (Layer i o) where-    Layer w1 b1 + Layer w2 b2 = Layer (w1 + w2) (b1 + b2)-    Layer w1 b1 - Layer w2 b2 = Layer (w1 - w2) (b1 - b2)-    Layer w1 b1 * Layer w2 b2 = Layer (w1 * w2) (b1 * b2)-    abs    (Layer w b)        = Layer (abs    w) (abs    b)-    signum (Layer w b)        = Layer (signum w) (signum b)-    negate (Layer w b)        = Layer (negate w) (negate b)-    fromInteger x             = Layer (fromInteger x) (fromInteger x)--instance (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o) => Num (Network i h1 h2 o) where-    Net a b c + Net d e f = Net (a + d) (b + e) (c + f)-    Net a b c - Net d e f = Net (a - d) (b - e) (c - f)-    Net a b c * Net d e f = Net (a * d) (b * e) (c * f)-    abs    (Net a b c)    = Net (abs    a) (abs    b) (abs    c)-    signum (Net a b c)    = Net (signum a) (signum b) (signum c)-    negate (Net a b c)    = Net (negate a) (negate b) (negate c)-    fromInteger x         = Net (fromInteger x) (fromInteger x) (fromInteger x)--instance (KnownNat i, KnownNat o) => Fractional (Layer i o) where-    Layer w1 b1 / Layer w2 b2 = Layer (w1 / w2) (b1 / b2)-    recip (Layer w b)         = Layer (recip w) (recip b)-    fromRational x            = Layer (fromRational x) (fromRational x)--instance (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o) => Fractional (Network i h1 h2 o) where-    Net a b c / Net d e f = Net (a / d) (b / e) (c / f)-    recip (Net a b c)     = Net (recip a) (recip b) (recip c)-    fromRational x        = Net (fromRational x) (fromRational x) (fromRational x)--instance KnownNat n => MWC.Variate (R n) where-    uniform g = randomVector <$> MWC.uniform g <*> pure Uniform-    uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g--instance (KnownNat m, KnownNat n) => MWC.Variate (L m n) where-    uniform g = uniformSample <$> MWC.uniform g <*> pure 0 <*> pure 1-    uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g--instance (KnownNat i, KnownNat o) => MWC.Variate (Layer i o) where-    uniform g = Layer <$> MWC.uniform g <*> MWC.uniform g-    uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g--instance (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o) => MWC.Variate (Network i h1 h2 o) where-    uniform g = Net <$> MWC.uniform g <*> MWC.uniform g <*> MWC.uniform g-    uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g--instance (Num a, Num b) => Num (a, b) where-    (x1,y1) + (x2,y2) = (x1 + x2, y1 + y2)-    (x1,y1) * (x2,y2) = (x1 * x2, y1 * y2)-    (x1,y1) - (x2,y2) = (x1 - x2, y1 - y2)-    abs (x, y)        = (abs x, abs y)-    signum (x, y)     = (signum x, signum y)-    fromInteger x     = (fromInteger x, fromInteger x)---- softMaxCrossEntropy---     :: KnownNat n---     => R n---     -> BPOpI s '[ R n ] Double--- softMaxCrossEntropy targ (r :< Ø) =  realToFrac tsum * log (vsum .$ (r :< Ø))---                                        - (dot .$ (r :< t :< Ø))---   where---     tsum = HM.sumElements . extract $ targ---     t    = constVar targ-
+ bench/bench.hs view
@@ -0,0 +1,334 @@+{-# LANGUAGE BangPatterns         #-}+{-# LANGUAGE DataKinds            #-}+{-# LANGUAGE DeriveGeneric        #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE GADTs                #-}+{-# LANGUAGE LambdaCase           #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE TemplateHaskell      #-}+{-# LANGUAGE TypeApplications     #-}+{-# LANGUAGE ViewPatterns         #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++import           Control.DeepSeq+import           Control.Exception+import           Control.Lens hiding          ((:<), (<.>))+import           Control.Monad.IO.Class+import           Control.Monad.Trans.Maybe+import           Criterion.Main+import           Criterion.Types+import           Data.Bitraversable+import           Data.IDX+import           Data.Time+import           Data.Traversable+import           Data.Tuple+import           GHC.Generics                 (Generic)+import           GHC.TypeLits+import           Numeric.Backprop+import           Numeric.LinearAlgebra.Static+import           System.Directory+import qualified Data.Vector.Generic          as VG+import qualified Data.Vector.Unboxed          as VU+import qualified Numeric.LinearAlgebra        as HM+import qualified System.Random.MWC            as MWC++data Layer i o =+    Layer { _lWeights :: !(L o i)+          , _lBiases  :: !(R o)+          }+  deriving (Show, Generic)++instance NFData (Layer i o)++makeLenses ''Layer++data Network i h1 h2 o =+    Net { _nLayer1 :: !(Layer i  h1)+        , _nLayer2 :: !(Layer h1 h2)+        , _nLayer3 :: !(Layer h2 o)+        }+  deriving (Show, Generic)++instance NFData (Network i h1 h2 o)++makeLenses ''Network++infixr 8 #>!+(#>!)+    :: (KnownNat m, KnownNat n, Reifies s W)+    => BVar s (L m n)+    -> BVar s (R n)+    -> BVar s (R m)+(#>!) = liftOp2 . op2 $ \m v ->+  ( m #> v, \g -> (g `outer` v, tr m #> g) )+++infixr 8 <.>!+(<.>!)+    :: (KnownNat n, Reifies s W)+    => BVar s (R n)+    -> BVar s (R n)+    -> BVar s Double+(<.>!) = liftOp2 . op2 $ \x y ->+  ( x <.> y, \g -> (konst g * y, x * konst g)+  )++konst'+    :: (KnownNat n, Reifies s W)+    => BVar s Double+    -> BVar s (R n)+konst' = liftOp1 . op1 $ \c -> (konst c, HM.sumElements . extract)++sumElements :: KnownNat n => R n -> Double+sumElements = HM.sumElements . extract++sumElements'+    :: (KnownNat n, Reifies s W)+    => BVar s (R n)+    -> BVar s Double+sumElements' = liftOp1 . op1 $ \x -> (sumElements x, konst)++logistic :: Floating a => a -> a+logistic x = 1 / (1 + exp (-x))+{-# INLINE logistic #-}++runLayer+    :: (KnownNat i, KnownNat o, Reifies s W)+    => BVar s (Layer i o)+    -> BVar s (R i)+    -> BVar s (R o)+runLayer l x = (l ^^. lWeights) #>! x + (l ^^. lBiases)+{-# INLINE runLayer #-}++softMax :: (KnownNat n, Reifies s W) => BVar s (R n) -> BVar s (R n)+softMax x = konst' (1 / sumElements' expx) * expx+  where+    expx = exp x+{-# INLINE softMax #-}++runNetwork+    :: (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o, Reifies s W)+    => BVar s (Network i h1 h2 o)+    -> R i+    -> BVar s (R o)+runNetwork n = softMax+             . runLayer (n ^^. nLayer3)+             . logistic+             . runLayer (n ^^. nLayer2)+             . logistic+             . runLayer (n ^^. nLayer1)+             . constVar+{-# INLINE runNetwork #-}++crossEntropy :: (KnownNat n, Reifies s W) => R n -> BVar s (R n) -> BVar s Double+crossEntropy t r = negate $ log r <.>! constVar t+{-# INLINE crossEntropy #-}++netErr+    :: (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o, Reifies s W)+    => R i+    -> R o+    -> BVar s (Network i h1 h2 o)+    -> BVar s Double+netErr x t n = crossEntropy t (runNetwork n x)+{-# INLINE netErr #-}++trainStep+    :: forall i h1 h2 o. (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o)+    => Double+    -> R i+    -> R o+    -> Network i h1 h2 o+    -> Network i h1 h2 o+trainStep r !x !t !n = n - realToFrac r * gradBP (netErr x t) n+{-# INLINE trainStep #-}++runLayerManual+    :: (KnownNat i, KnownNat o)+    => Layer i o+    -> R i+    -> R o+runLayerManual l x = (l ^. lWeights) #> x + (l ^. lBiases)+{-# INLINE runLayerManual #-}++softMaxManual :: KnownNat n => R n -> R n+softMaxManual x = konst (1 / sumElements expx) * expx+  where+    expx = exp x+{-# INLINE softMaxManual #-}++runNetManual+    :: (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o)+    => Network i h1 h2 o+    -> R i+    -> R o+runNetManual n = softMaxManual+               . runLayerManual (n ^. nLayer3)+               . logistic+               . runLayerManual (n ^. nLayer2)+               . logistic+               . runLayerManual (n ^. nLayer1)+{-# INLINE runNetManual #-}++gradNetManual+    :: forall i h1 h2 o. (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o)+    => R i+    -> R o+    -> Network i h1 h2 o+    -> Network i h1 h2 o+gradNetManual x t (Net (Layer w1 b1) (Layer w2 b2) (Layer w3 b3)) =+    let y1 = w1 #> x+        z1 = y1 + b1+        x2 = logistic z1+        y2 = w2 #> x2+        z2 = y2 + b2+        x3 = logistic z2+        y3 = w3 #> x3+        z3 = y3 + b3+        o0 = exp z3+        o1 = HM.sumElements (extract o0)+        o2 = o0 / konst o1+        -- o3 = - (log o2 <.> t)+        dEdO3 = 1+        dEdO2 = dEdO3 * (- t / o2)+        dEdO1 = - (dEdO2 <.> o0) / (o1 ** 2)+        dEdO0 = konst dEdO1 + dEdO2 / konst o1+        dEdZ3 = dEdO0 * o0+        dEdY3 = dEdZ3+        dEdX3 = tr w3 #> dEdY3+        dEdZ2 = dEdX3 * (x3 * (1 - x3))+        dEdY2 = dEdZ2+        dEdX2 = tr w2 #> dEdY2+        dEdZ1 = dEdX2 * (x2 * (1 - x2))+        dEdY1 = dEdZ1+        dEdB3 = dEdZ3+        dEdW3 = dEdY3 `outer` x3+        dEdB2 = dEdZ2+        dEdW2 = dEdY2 `outer` x2+        dEdB1 = dEdZ1+        dEdW1 = dEdY1 `outer` x+    in  Net (Layer dEdW1 dEdB1) (Layer dEdW2 dEdB2) (Layer dEdW3 dEdB3)+{-# INLINE gradNetManual #-}++trainStepManual+    :: forall i h1 h2 o. (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o)+    => Double+    -> R i+    -> R o+    -> Network i h1 h2 o+    -> Network i h1 h2 o+trainStepManual r !x !t !n =+    let gN = gradNetManual x t n+    in  n - (realToFrac r * gN)++main :: IO ()+main = MWC.withSystemRandom $ \g -> do+    Just test  <- loadMNIST "data/t10k-images-idx3-ubyte"  "data/t10k-labels-idx1-ubyte"+    putStrLn "Loaded data."+    net0 <- MWC.uniformR @(Network 784 300 100 9) (-0.5, 0.5) g+    createDirectoryIfMissing True "bench-results"+    t <- getZonedTime+    let test0   = head test+        tstr    = formatTime defaultTimeLocale "%Y%m%d-%H%M%S" t+    defaultMainWith defaultConfig+          { reportFile = Just $ "bench-results/mnist-bench_" ++ tstr ++ ".html"+          , timeLimit  = 10+          } [+        bgroup "gradient" [+            let testManual x y = gradNetManual x y net0+            in  bench "manual" $ nf (uncurry testManual) test0+          , let testBP     x y = gradBP (netErr x y) net0+            in  bench "bp"     $ nf (uncurry testBP) test0+          ]+      , bgroup "descent" [+            let testManual x y = trainStepManual 0.02 x y net0+            in  bench "manual" $ nf (uncurry testManual) test0+          , let testBP     x y = trainStep 0.02 x y net0+            in  bench "bp"     $ nf (uncurry testBP) test0+          ]+      , bgroup "run" [+            let testManual     = runNetManual net0+            in  bench "manual" $ nf testManual (fst test0)+          , let testBP     x   = evalBP (`runNetwork` x) net0+            in  bench "bp"     $ nf testBP (fst test0)+          ]+      ]++loadMNIST+    :: FilePath+    -> FilePath+    -> IO (Maybe [(R 784, R 9)])+loadMNIST fpI fpL = runMaybeT $ do+    i <- MaybeT          $ decodeIDXFile       fpI+    l <- MaybeT          $ decodeIDXLabelsFile fpL+    d <- MaybeT . return $ labeledIntData l i+    r <- MaybeT . return $ for d (bitraverse mkImage mkLabel . swap)+    liftIO . evaluate $ force r+  where+    mkImage :: VU.Vector Int -> Maybe (R 784)+    mkImage = create . VG.convert . VG.map (\i -> fromIntegral i / 255)+    mkLabel :: Int -> Maybe (R 9)+    mkLabel n = create $ HM.build 9 (\i -> if round i == n then 1 else 0)++instance (KnownNat i, KnownNat o) => Num (Layer i o) where+    Layer w1 b1 + Layer w2 b2 = Layer (w1 + w2) (b1 + b2)+    Layer w1 b1 - Layer w2 b2 = Layer (w1 - w2) (b1 - b2)+    Layer w1 b1 * Layer w2 b2 = Layer (w1 * w2) (b1 * b2)+    abs    (Layer w b)        = Layer (abs    w) (abs    b)+    signum (Layer w b)        = Layer (signum w) (signum b)+    negate (Layer w b)        = Layer (negate w) (negate b)+    fromInteger x             = Layer (fromInteger x) (fromInteger x)++instance (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o) => Num (Network i h1 h2 o) where+    Net a b c + Net d e f = Net (a + d) (b + e) (c + f)+    Net a b c - Net d e f = Net (a - d) (b - e) (c - f)+    Net a b c * Net d e f = Net (a * d) (b * e) (c * f)+    abs    (Net a b c)    = Net (abs    a) (abs    b) (abs    c)+    signum (Net a b c)    = Net (signum a) (signum b) (signum c)+    negate (Net a b c)    = Net (negate a) (negate b) (negate c)+    fromInteger x         = Net (fromInteger x) (fromInteger x) (fromInteger x)++instance (KnownNat i, KnownNat o) => Fractional (Layer i o) where+    Layer w1 b1 / Layer w2 b2 = Layer (w1 / w2) (b1 / b2)+    recip (Layer w b)         = Layer (recip w) (recip b)+    fromRational x            = Layer (fromRational x) (fromRational x)++instance (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o) => Fractional (Network i h1 h2 o) where+    Net a b c / Net d e f = Net (a / d) (b / e) (c / f)+    recip (Net a b c)     = Net (recip a) (recip b) (recip c)+    fromRational x        = Net (fromRational x) (fromRational x) (fromRational x)++instance KnownNat n => MWC.Variate (R n) where+    uniform g = randomVector <$> MWC.uniform g <*> pure Uniform+    uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g++instance (KnownNat m, KnownNat n) => MWC.Variate (L m n) where+    uniform g = uniformSample <$> MWC.uniform g <*> pure 0 <*> pure 1+    uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g++instance (KnownNat i, KnownNat o) => MWC.Variate (Layer i o) where+    uniform g = Layer <$> MWC.uniform g <*> MWC.uniform g+    uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g++instance (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o) => MWC.Variate (Network i h1 h2 o) where+    uniform g = Net <$> MWC.uniform g <*> MWC.uniform g <*> MWC.uniform g+    uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g++instance (Num a, Num b) => Num (a, b) where+    (x1,y1) + (x2,y2) = (x1 + x2, y1 + y2)+    (x1,y1) * (x2,y2) = (x1 * x2, y1 * y2)+    (x1,y1) - (x2,y2) = (x1 - x2, y1 - y2)+    abs (x, y)        = (abs x, abs y)+    signum (x, y)     = (signum x, signum y)+    fromInteger x     = (fromInteger x, fromInteger x)++-- softMaxCrossEntropy+--     :: KnownNat n+--     => R n+--     -> BPOpI s '[ R n ] Double+-- softMaxCrossEntropy targ (r :< Ø) =  realToFrac tsum * log (vsum .$ (r :< Ø))+--                                        - (dot .$ (r :< t :< Ø))+--   where+--     tsum = HM.sumElements . extract $ targ+--     t    = constVar targ+
src/Data/Type/Util.hs view
@@ -13,7 +13,6 @@   , zipWithPM_   , vecToProd   , vecLen-  , prodToVec'   , lengthProd   , listToVecDef   , fillProd@@ -51,16 +50,6 @@ vecLen = \case     ØV      -> Z_     _ :* xs -> S_ (vecLen xs)--prodToVec'-    :: Nat n-    -> Prod f (Replicate n a)-    -> VecT n f a-prodToVec' = \case-    Z_   -> \case-      Ø       -> ØV-    S_ n -> \case-      x :< xs -> x :* prodToVec' n xs  zipWithPM_     :: forall h f g as. Applicative h
src/Numeric/Backprop.hs view
@@ -56,7 +56,7 @@   , backprop2, evalBP2, gradBP2   , backpropN, evalBPN, gradBPN, Every     -- * Manipulating 'BVar'-  , constVar+  , constVar, coerceVar   , (^^.), (.~~), (^^?), (^^..)   , viewVar, setVar   , sequenceVar, collectVar
src/Numeric/Backprop/Internal.hs view
@@ -31,6 +31,7 @@   , constVar   , liftOp, liftOp1, liftOp2, liftOp3   , viewVar, setVar, sequenceVar, collectVar, previewVar, toListOfVar+  , coerceVar   -- * Debug   , debugSTN   , debugIR@@ -43,6 +44,7 @@ import           Control.Monad.ST import           Control.Monad.Trans.State import           Data.Bifunctor+import           Data.Coerce import           Data.Foldable import           Data.Function import           Data.IORef@@ -483,6 +485,15 @@ toListOfVar t !v = unsafePerformIO $ traverseVar' (toListOf t) t v {-# INLINE toListOfVar #-} +-- | Coerce a 'BVar' contents.  Useful for things like newtype wrappers.+--+-- @since 0.1.5.2+coerceVar+    :: Coercible a b+    => BVar s a+    -> BVar s b+coerceVar v@(BV r x) = forceBVar v `seq` BV r (coerce x)+ data Runner s = R { _rDelta  :: !(MV.MVector s Any)                   , _rInputs :: !(MV.MVector s Any)                   }@@ -716,3 +727,4 @@         go []     = error "asList"         go (y:ys) = (y, ys) {-# INLINE ixt #-}+
src/Numeric/Backprop/Tuple.hs view
@@ -12,6 +12,7 @@ {-# LANGUAGE RankNTypes            #-} {-# LANGUAGE ScopedTypeVariables   #-} {-# LANGUAGE StandaloneDeriving    #-}+{-# LANGUAGE TupleSections         #-} {-# LANGUAGE TypeApplications      #-} {-# LANGUAGE TypeInType            #-} {-# LANGUAGE TypeOperators         #-}@@ -102,6 +103,7 @@   ) where  import           Control.DeepSeq+import           Control.Monad.Trans.State import           Data.Bifunctor import           Data.Data import           Data.Kind@@ -112,6 +114,7 @@ import           GHC.Generics               (Generic) import           Lens.Micro import           Lens.Micro.Internal hiding (Index)+import           System.Random import           Type.Class.Known import           Type.Family.List import qualified Data.Binary                as Bi@@ -188,8 +191,35 @@       TNil    -> ()       x :& xs -> rnf x `seq` rnf xs --- TODO: optimize+-- | @since 0.1.5.2+instance Random T0 where+    randomR  _   = (T0,)+    random       = (T0,)+    randomRs _ _ = repeat T0+    randoms  _   = repeat T0+    randomIO     = pure T0 +-- | @since 0.1.5.2+instance (Random a, Random b) => Random (T2 a b) where+    randomR (T2 lx ly, T2 ux uy) = runState $+        T2 <$> state (randomR (lx, ux))+           <*> state (randomR (ly, uy))+    random = runState $+        T2 <$> state random <*> state random++-- | @since 0.1.5.2+instance (Random a, Random b, Random c) => Random (T3 a b c) where+    randomR (T3 lx ly lz, T3 ux uy uz) = runState $+        T3 <$> state (randomR (lx, ux))+           <*> state (randomR (ly, uy))+           <*> state (randomR (lz, uz))+    random = runState $+        T3 <$> state random <*> state random <*> state random++++-- TODO: optimize?+ -- | @since 0.1.5.1 instance Bi.Binary T0 -- | @since 0.1.5.1@@ -629,6 +659,30 @@       x  <- Bi.get       xs <- getT l       pure (x :& xs)++-- | @since 0.1.5.2+instance (Known Length as, ListC (Random <$> as)) => Random (T as) where+    randomR (l, u) = runState (randomRT l u)+    random         = runState (randomT known)++randomRT+    :: (ListC (Random <$> as), RandomGen g)+    => T as+    -> T as+    -> State g (T as)+randomRT = \case+    TNil -> \case+      TNil -> pure TNil+    lx :& lxs -> \case+      ux :& uxs -> (:&) <$> state (randomR (lx, ux)) <*> randomRT lxs uxs++randomT+    :: (ListC (Random <$> as), RandomGen g)+    => Length as+    -> State g (T as)+randomT = \case+    LZ   -> pure TNil+    LS l -> (:&) <$> state random <*> randomT l  -- $t2iso --