backprop 0.2.6.1 → 0.2.6.2
raw patch · 11 files changed
+130/−92 lines, 11 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.Backprop (GHC.Base.Maybe a)
- Numeric.Backprop.Explicit: instance (Data.Reflection.Reifies s Numeric.Backprop.Internal.W, Numeric.Backprop.Explicit.BVGroup s as i1 o1, Numeric.Backprop.Explicit.BVGroup s bs i2 o2, cs ~ (as Data.Vinyl.TypeLevel.++ bs), Data.Vinyl.Core.RecApplicative as) => Numeric.Backprop.Explicit.BVGroup s (i1 () : i2 () : cs) (i1 GHC.Generics.:*: i2) (o1 GHC.Generics.:*: o2)
- Numeric.Backprop.Explicit: instance (Data.Reflection.Reifies s Numeric.Backprop.Internal.W, Numeric.Backprop.Explicit.BVGroup s as i1 o1, Numeric.Backprop.Explicit.BVGroup s bs i2 o2, cs ~ (as Data.Vinyl.TypeLevel.++ bs), Data.Vinyl.Core.RecApplicative as) => Numeric.Backprop.Explicit.BVGroup s (i1 () : i2 () : cs) (i1 GHC.Generics.:+: i2) (o1 GHC.Generics.:+: o2)
+ Numeric.Backprop: pattern T3 :: (Backprop a, Backprop b, Backprop c, Reifies s W) => BVar s a -> BVar s b -> BVar s c -> BVar s (a, b, c)
+ Numeric.Backprop: pattern BV :: (Generic (z f), Generic (z (BVar s)), BVGroup s as (Rep (z f)) (Rep (z (BVar s))), Backprop (Rep (z f) ()), Backprop (z f), RPureConstrained Backprop as, RecApplicative as, Reifies s W) => z (BVar s) -> BVar s (z f)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.Backprop (GHC.Maybe.Maybe a)
+ Numeric.Backprop.Explicit: instance (Data.Reflection.Reifies s Numeric.Backprop.Internal.W, Numeric.Backprop.Explicit.BVGroup s as i1 o1, Numeric.Backprop.Explicit.BVGroup s bs i2 o2, cs Data.Type.Equality.~ (as Data.Vinyl.TypeLevel.++ bs), Data.Vinyl.Core.RecApplicative as) => Numeric.Backprop.Explicit.BVGroup s (i1 () : i2 () : cs) (i1 GHC.Generics.:*: i2) (o1 GHC.Generics.:*: o2)
+ Numeric.Backprop.Explicit: instance (Data.Reflection.Reifies s Numeric.Backprop.Internal.W, Numeric.Backprop.Explicit.BVGroup s as i1 o1, Numeric.Backprop.Explicit.BVGroup s bs i2 o2, cs Data.Type.Equality.~ (as Data.Vinyl.TypeLevel.++ bs), Data.Vinyl.Core.RecApplicative as) => Numeric.Backprop.Explicit.BVGroup s (i1 () : i2 () : cs) (i1 GHC.Generics.:+: i2) (o1 GHC.Generics.:+: o2)
+ Numeric.Backprop.Op: infixr 7 :&
- Numeric.Backprop: Op :: Rec Identity as -> (a, a -> Rec Identity as) -> Op as a
+ Numeric.Backprop: Op :: (Rec Identity as -> (a, a -> Rec Identity as)) -> Op as a
- Numeric.Backprop.Explicit: AF :: a -> a -> a -> AddFunc a
+ Numeric.Backprop.Explicit: AF :: (a -> a -> a) -> AddFunc a
- Numeric.Backprop.Explicit: OF :: a -> a -> OneFunc a
+ Numeric.Backprop.Explicit: OF :: (a -> a) -> OneFunc a
- Numeric.Backprop.Explicit: Op :: Rec Identity as -> (a, a -> Rec Identity as) -> Op as a
+ Numeric.Backprop.Explicit: Op :: (Rec Identity as -> (a, a -> Rec Identity as)) -> Op as a
- Numeric.Backprop.Explicit: ZF :: a -> a -> ZeroFunc a
+ Numeric.Backprop.Explicit: ZF :: (a -> a) -> ZeroFunc a
- Numeric.Backprop.Num: Op :: Rec Identity as -> (a, a -> Rec Identity as) -> Op as a
+ Numeric.Backprop.Num: Op :: (Rec Identity as -> (a, a -> Rec Identity as)) -> Op as a
- Numeric.Backprop.Op: (~.) :: (RPureConstrained Num as) => Op '[b] c -> Op as b -> Op as c
+ Numeric.Backprop.Op: (~.) :: RPureConstrained Num as => Op '[b] c -> Op as b -> Op as c
- Numeric.Backprop.Op: Op :: Rec Identity as -> (a, a -> Rec Identity as) -> Op as a
+ Numeric.Backprop.Op: Op :: (Rec Identity as -> (a, a -> Rec Identity as)) -> Op as a
- Numeric.Backprop.Op: [:&] :: Rec a r : rs
+ Numeric.Backprop.Op: [:&] :: forall u (a :: u -> Type) (b :: [u]) (r :: u) (rs :: [u]). () => !a r -> !Rec a rs -> Rec a (r : rs)
- Numeric.Backprop.Op: [RNil] :: Rec a ([] :: [u])
+ Numeric.Backprop.Op: [RNil] :: forall u (a :: u -> Type) (b :: [u]). () => Rec a ([] :: [u])
- Numeric.Backprop.Op: composeOp :: forall as bs c. (RPureConstrained Num as) => Rec (Op as) bs -> Op bs c -> Op as c
+ Numeric.Backprop.Op: composeOp :: forall as bs c. RPureConstrained Num as => Rec (Op as) bs -> Op bs c -> Op as c
- Numeric.Backprop.Op: data Rec (a :: u -> *) (b :: [u]) :: forall u. () => u -> * -> [u] -> *
+ Numeric.Backprop.Op: data Rec (a :: u -> Type) (b :: [u]) :: forall u. () => u -> Type -> [u] -> Type
Files
- Build.hs +10/−1
- CHANGELOG.md +12/−0
- README.md +1/−1
- backprop.cabal +27/−26
- doc/03-manipulating-bvars.md +1/−1
- renders/backprop-mnist.md +16/−15
- renders/backprop-mnist.pdf binary
- renders/extensible-neural.md +17/−17
- renders/extensible-neural.pdf binary
- src/Data/Type/Util.hs +2/−17
- src/Numeric/Backprop/Internal.hs +44/−14
Build.hs view
@@ -75,9 +75,18 @@ removeFilesAfter "samples" ["/*.o"] cmd "stack ghc" "--stack-yaml stack.yaml"+ "--package finite-typelits"+ "--package hmatrix-backprop"+ "--package hmatrix-vector-sized"+ "--package microlens-th" "--package mnist-idx"- "--package singletons"+ "--package mwc-random"+ "--package one-liner" "--package one-liner-instances"+ "--package random"+ "--package singletons"+ "--package split"+ "--package vector-sized" "--" ("samples" </> src) "-o" f
CHANGELOG.md view
@@ -1,6 +1,18 @@ Changelog ========= +Version 0.2.6.2+---------------++*April 7, 2019*++<https://github.com/mstksg/backprop/releases/tag/v0.2.6.2>++* Fix a numerical bug that would occur when an input is used directly as the+ result of a computation. (For example, `gradBP id` or `gradBP2 const`).+* Some internal changes to strictness which offers some performance boosts in+ computation of gradients.+ Version 0.2.6.1 ---------------
README.md view
@@ -143,7 +143,7 @@ This can be run, again: ```haskell-evalBP (netError myTarget myVector) :: Network -> Network+evalBP (netError myTarget myVector) :: Network -> Double ``` Now, we just wrote a *normal function to compute the error of our network*.
backprop.cabal view
@@ -1,11 +1,13 @@--- This file has been generated from package.yaml by hpack version 0.28.2.+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.31.1. -- -- see: https://github.com/sol/hpack ----- hash: 009a268e1d551f52673b7339f93986c16870d9402a854ad8157d133450ef7591+-- hash: fe389131c629c91aba7d98e6c95411c83f558b8fec788d0d12405bdf4db507aa name: backprop-version: 0.2.6.1+version: 0.2.6.2 synopsis: Heterogeneous automatic differentation description: Write your functions to compute your result, and the library will automatically generate functions to compute your gradient.@@ -24,10 +26,16 @@ license-file: LICENSE tested-with: GHC >= 8.0 build-type: Simple-cabal-version: >= 1.10 extra-source-files:- Build.hs+ README.md CHANGELOG.md+ Build.hs+ samples/backprop-mnist.lhs+ samples/extensible-neural.lhs+ renders/backprop-mnist.pdf+ renders/extensible-neural.pdf+ renders/backprop-mnist.md+ renders/extensible-neural.md doc/01-getting-started.md doc/02-a-detailed-look.md doc/03-manipulating-bvars.md@@ -38,19 +46,24 @@ doc/08-equipping-your-library.md doc/09-comparisons.md doc/index.md- README.md- renders/backprop-mnist.md- renders/backprop-mnist.pdf- renders/extensible-neural.md- renders/extensible-neural.pdf- samples/backprop-mnist.lhs- samples/extensible-neural.lhs source-repository head type: git location: https://github.com/mstksg/backprop library+ exposed-modules:+ Numeric.Backprop+ Numeric.Backprop.Class+ Numeric.Backprop.Explicit+ Numeric.Backprop.Num+ Numeric.Backprop.Op+ Prelude.Backprop+ Prelude.Backprop.Explicit+ Prelude.Backprop.Num+ other-modules:+ Numeric.Backprop.Internal+ Data.Type.Util hs-source-dirs: src ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wredundant-constraints@@ -64,23 +77,13 @@ , transformers , vector , vinyl >=0.9.1- exposed-modules:- Numeric.Backprop- Numeric.Backprop.Class- Numeric.Backprop.Explicit- Numeric.Backprop.Num- Numeric.Backprop.Op- Prelude.Backprop- Prelude.Backprop.Explicit- Prelude.Backprop.Num- other-modules:- Numeric.Backprop.Internal- Data.Type.Util default-language: Haskell2010 benchmark backprop-mnist-bench type: exitcode-stdio-1.0 main-is: bench.hs+ other-modules:+ Paths_backprop hs-source-dirs: bench ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N -O2@@ -96,6 +99,4 @@ , mwc-random , time , vector- other-modules:- Paths_backprop default-language: Haskell2010
doc/03-manipulating-bvars.md view
@@ -327,7 +327,7 @@ `BVar s (a, b)` to get a `BVar s a` and `BVar s b`. The `T3` pattern is also provided, which does the same thing for three-tuples. -Note that `T2` and `T2` are bidirectional pattern synonyms, and can be used to+Note that `T2` and `T3` are *bidirectional* pattern synonyms, and can be used to construct as well as deconstruct. Combining BVars
renders/backprop-mnist.md view
@@ -35,24 +35,23 @@ - split ``` {.sourceCode .literate .haskell}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE ViewPatterns #-}-{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -Wno-incomplete-patterns #-}+{-# OPTIONS_GHC -Wno-orphans #-}+{-# OPTIONS_GHC -Wno-unused-top-binds #-} import Control.DeepSeq import Control.Exception-import Control.Lens hiding ((<.>)) import Control.Monad import Control.Monad.IO.Class import Control.Monad.Trans.Maybe@@ -66,6 +65,8 @@ import Data.Tuple import GHC.Generics (Generic) import GHC.TypeLits+import Lens.Micro+import Lens.Micro.TH import Numeric.Backprop import Numeric.Backprop.Class import Numeric.LinearAlgebra.Static
renders/backprop-mnist.pdf view
binary file changed (134752 → 134705 bytes)
renders/extensible-neural.md view
@@ -24,26 +24,24 @@ - split ``` {.sourceCode .literate .haskell}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE InstanceSigs #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeInType #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE ViewPatterns #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -Wno-orphans #-} import Control.DeepSeq import Control.Exception-import Control.Lens hiding ((<.>)) import Control.Monad import Control.Monad.IO.Class import Control.Monad.Primitive@@ -61,6 +59,8 @@ import Data.Traversable import Data.Tuple import GHC.Generics (Generic)+import Lens.Micro+import Lens.Micro.TH import Numeric.Backprop import Numeric.Backprop.Class import Numeric.LinearAlgebra.Static
renders/extensible-neural.pdf view
binary file changed (108021 → 107967 bytes)
src/Data/Type/Util.hs view
@@ -15,12 +15,11 @@ runzipWith , rzipWithM_ , Replicate- , VecT(.., (:+)), Vec+ , VecT(.., (:+)) , vmap , withVec , vecToRec , fillRec- , rtraverse_ , zipVecList , splitRec , p1, p2, s1, s2@@ -53,9 +52,7 @@ VNil :: VecT 'Z f a (:*) :: !(f a) -> VecT n f a -> VecT ('S n) f a -type Vec n = VecT n Identity--pattern (:+) :: a -> Vec n a -> Vec ('S n) a+pattern (:+) :: a -> VecT n Identity a -> VecT ('S n) Identity a pattern x :+ xs = Identity x :* xs vmap@@ -105,18 +102,6 @@ [] -> Nothing y:ys -> (f x y :&) <$> go xs ys {-# INLINE fillRec #-}--rtraverse_- :: forall f g. Applicative g- => (forall x. f x -> g ())- -> (forall xs. Rec f xs -> g ())-rtraverse_ f = go- where- go :: Rec f ys -> g ()- go = \case- RNil -> pure ()- x :& xs -> f x *> go xs-{-# INLINE rtraverse_ #-} rzipWithM_ :: forall h f g as. Applicative h
src/Numeric/Backprop/Internal.hs view
@@ -242,6 +242,9 @@ } -> SomeTapeNode +forceSomeTapeNode :: SomeTapeNode -> ()+forceSomeTapeNode (STN n) = forceTapeNode n+ -- | Debugging string for a 'SomeTapeMode'. debugSTN :: SomeTapeNode -> String debugSTN (STN TN{..}) = show . VR.rfoldMap ((:[]) . debugIR) $ _tnInputs@@ -628,6 +631,11 @@ Just y -> Just (x +* y) {-# INLINE bumpMaybe #-} +seqEither :: Either a (b, [SomeTapeNode]) -> Either a (b, [SomeTapeNode])+seqEither e@(Left !_) = e+seqEither e@(Right (!_,foldMap forceSomeTapeNode->(!_))) = e+{-# INLINE seqEither #-}+ -- | 'Numeric.Backprop.backpropWithN', but with explicit 'zero' and 'one'. -- -- Note that argument order changed in v0.2.4.@@ -639,14 +647,19 @@ -> (forall s. Reifies s W => Rec (BVar s) as -> BVar s b) -> Rec Identity as -> (b, b -> Rec Identity as)-backpropWithN zfs f !xs = (y, g)+backpropWithN zfs f !xs = (y, g') where- !(!tp@(!_,!_),!y) = unsafePerformIO $ fillWengert f xs- g :: b -> Rec Identity as- g o = runST $ do- r <- initRunner tp $ bimap getSum (`appEndo` [])- . fst- $ rtraverse_ go xs+ !(seqEither->(!tp0),!y) = unsafePerformIO $ fillWengert f xs+ g' :: b -> Rec Identity as+ g' = case tp0 of+ Left i -> setInput i+ Right tp -> g tp+ {-# INLINE g' #-}+ g :: (Int, [SomeTapeNode]) -> b -> Rec Identity as+ g tp o = runST $ do+ r <- initRunner tp . bimap getSum (`appEndo` [])+ . VR.rfoldMap go -- TODO: use strict tuple?+ $ xs gradRunner o r tp delts <- toList <$> V.freeze (_rInputs r) return . fromMaybe (internalError "backpropN") $@@ -654,9 +667,21 @@ (VR.rzipWith (fmap . runZF) zfs xs) delts where- go :: forall a. Identity a -> ((Sum Int, Endo [Maybe Any]),())- go _ = ((1, Endo (unsafeCoerce (Nothing @a) :)), ())+ go :: forall a. Identity a -> (Sum Int, Endo [Maybe Any])+ go _ = (1, Endo (unsafeCoerce (Nothing @a) :)) {-# INLINE go #-}+ setInput :: Int -> b -> Rec Identity as+ setInput !i !x = go zfs xs 0+ where+ go :: Rec ZeroFunc bs -> Rec Identity bs -> Int -> Rec Identity bs+ go = \case+ RNil -> \_ _ -> RNil+ z :& zs -> \case+ q :& qs -> \(!j) ->+ if j == i+ then Identity (unsafeCoerce x) :& VR.rzipWith coerce zs qs+ else coerce z q :& go zs qs (j + 1)+ {-# INLINE setInput #-} {-# INLINE backpropWithN #-} -- | 'evalBP' generalized to multiple inputs of different types. See@@ -673,15 +698,20 @@ :: forall as b. () => (forall s. Reifies s W => Rec (BVar s) as -> BVar s b) -> Rec Identity as- -> IO ((Int, [SomeTapeNode]), b)+ -> IO (Either Int (Int, [SomeTapeNode]), b) fillWengert f xs = do w <- initWengert- o <- reify w $ \(Proxy :: Proxy s) -> do+ (i, o) <- reify w $ \(Proxy :: Proxy s) -> do let oVar = f (inpRec @s) evaluate (forceBVar oVar)- return (_bvVal oVar)- t <- readIORef (wRef w)- return (t, o)+ let isInput = case _bvRef oVar of+ BRInp i -> Just i+ _ -> Nothing+ pure (isInput, _bvVal oVar)+ t <- case i of+ Nothing -> Right <$> readIORef (wRef w)+ Just i' -> pure $ Left i'+ pure (t, o) where inpRec :: forall s. Rec (BVar s) as inpRec = evalState (rtraverse (state . go . runIdentity) xs) 0