backprop 0.1.3.0 → 0.1.4.0
raw patch · 7 files changed
+165/−25 lines, 7 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Numeric.Backprop: isoVar :: (Num a, Num b, Reifies s W) => (a -> b) -> (b -> a) -> BVar s a -> BVar s b
+ Numeric.Backprop: isoVar2 :: (Num a, Num b, Num c, Reifies s W) => (a -> b -> c) -> (c -> (a, b)) -> BVar s a -> BVar s b -> BVar s c
+ Numeric.Backprop: isoVar3 :: (Num a, Num b, Num c, Num d, Reifies s W) => (a -> b -> c -> d) -> (d -> (a, b, c)) -> BVar s a -> BVar s b -> BVar s c -> BVar s d
+ Numeric.Backprop: isoVarN :: (Every Num as, Num b, Reifies s W) => (Tuple as -> b) -> (b -> Tuple as) -> Prod (BVar s) as -> BVar s b
+ Numeric.Backprop.Op: opIso2 :: (a -> b -> c) -> (c -> (a, b)) -> Op '[a, b] c
+ Numeric.Backprop.Op: opIso3 :: (a -> b -> c -> d) -> (d -> (a, b, c)) -> Op '[a, b, c] d
+ Numeric.Backprop.Tuple: T0 :: T0
+ Numeric.Backprop.Tuple: data T0
+ Numeric.Backprop.Tuple: instance Control.DeepSeq.NFData Numeric.Backprop.Tuple.T0
+ Numeric.Backprop.Tuple: instance Data.Data.Data Numeric.Backprop.Tuple.T0
+ Numeric.Backprop.Tuple: instance GHC.Classes.Eq Numeric.Backprop.Tuple.T0
+ Numeric.Backprop.Tuple: instance GHC.Classes.Ord Numeric.Backprop.Tuple.T0
+ Numeric.Backprop.Tuple: instance GHC.Float.Floating Numeric.Backprop.Tuple.T0
+ Numeric.Backprop.Tuple: instance GHC.Generics.Generic Numeric.Backprop.Tuple.T0
+ Numeric.Backprop.Tuple: instance GHC.Num.Num Numeric.Backprop.Tuple.T0
+ Numeric.Backprop.Tuple: instance GHC.Read.Read Numeric.Backprop.Tuple.T0
+ Numeric.Backprop.Tuple: instance GHC.Real.Fractional Numeric.Backprop.Tuple.T0
+ Numeric.Backprop.Tuple: instance GHC.Show.Show Numeric.Backprop.Tuple.T0
Files
- CHANGELOG.md +20/−0
- backprop.cabal +2/−2
- renders/backprop-mnist.pdf binary
- src/Numeric/Backprop.hs +63/−1
- src/Numeric/Backprop/Internal.hs +0/−5
- src/Numeric/Backprop/Op.hs +21/−11
- src/Numeric/Backprop/Tuple.hs +59/−6
CHANGELOG.md view
@@ -1,6 +1,26 @@ Changelog ========= +Version 0.1.4.0+---------------++*Mar 25, 2018*++<https://github.com/mstksg/backprop/releases/tag/v0.1.4.0>++* `isoVar`, `isoVar2`, `isoVar3`, and `isoVarN`: convenient aliases for+ applying isomorphisms to `BVar`s. Helpful for use with constructors and+ deconstructors.+* `opIso2` and `opIso3` added to *Numeric.Backprop.Op*, for convenience.+* `T0` (Unit with numeric instances) added to *Numeric.Backprop.Tuple".++*Internal*++* Completely decoupled the internal implementation from `Num`, which showed+ some performance benefits. Mostly just to make the code slightly cleaner,+ and to prepare for some day potentially decoupling the external API from+ `Num` as well.+ Version 0.1.3.0 ---------------
backprop.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: a179c83822a97b40195355e48510d1b31057e23a68d04abb6966e24bd4b9d6f0+-- hash: 29db4e10ba34d97fcc6fd087831de6d57d581d92e0cb33d6088380834faccda4 name: backprop-version: 0.1.3.0+version: 0.1.4.0 synopsis: Heterogeneous automatic differentation (backpropagation) description: Write your functions to compute your result, and the library will automatically generate functions to compute your gradient.
renders/backprop-mnist.pdf view
binary file changed (133763 → 133763 bytes)
src/Numeric/Backprop.hs view
@@ -61,6 +61,8 @@ , viewVar, setVar , sequenceVar, collectVar , previewVar, toListOfVar+ -- ** With Isomorphisms+ , isoVar, isoVar2, isoVar3, isoVarN -- ** With 'Op's#liftops# -- $liftops , liftOp@@ -369,7 +371,7 @@ -- which do have 'Num' instances. -- -- @--- myPrism :: 'Prism'' c (a, b)+-- myPrism :: 'Prism'' c (a, b) -- myPrism . 'iso' 'tupT2' 't2Tup' :: 'Prism'' c ('T2' a b) -- @ (^^?)@@ -408,3 +410,63 @@ -> [BVar s a] v ^^.. t = toListOfVar t v {-# INLINE (^^..) #-}++-- | Convert the value inside a 'BVar' using a given isomorphism. Useful+-- for things like constructors.+--+-- Warning: This is unsafe! It assumes that the isomorphisms themselves+-- have derivative 1, so will break for things like 'exp' & 'log'.+-- Basically, don't use this for any "numeric" isomorphisms.+--+-- @since 0.1.4.0+isoVar+ :: (Num a, Num b, Reifies s W)+ => (a -> b)+ -> (b -> a)+ -> BVar s a+ -> BVar s b+isoVar f g = liftOp1 (opIso f g)+{-# INLINE isoVar #-}++-- | Convert the values inside two 'BVar's using a given isomorphism.+-- Useful for things like constructors. See 'isoVar' for caveats.+--+-- @since 0.1.4.0+isoVar2+ :: (Num a, Num b, Num c, Reifies s W)+ => (a -> b -> c)+ -> (c -> (a, b))+ -> BVar s a+ -> BVar s b+ -> BVar s c+isoVar2 f g = liftOp2 (opIso2 f g)+{-# INLINE isoVar2 #-}++-- | Convert the values inside three 'BVar's using a given isomorphism.+-- Useful for things like constructors. See 'isoVar' for caveats.+--+-- @since 0.1.4.0+isoVar3+ :: (Num a, Num b, Num c, Num d, Reifies s W)+ => (a -> b -> c -> d)+ -> (d -> (a, b, c))+ -> BVar s a+ -> BVar s b+ -> BVar s c+ -> BVar s d+isoVar3 f g = liftOp3 (opIso3 f g)+{-# INLINE isoVar3 #-}++-- | Convert the values inside a tuple of 'BVar's using a given+-- isomorphism. Useful for things like constructors. See 'isoVar' for+-- caveats.+--+-- @since 0.1.4.0+isoVarN+ :: (Every Num as, Num b, Reifies s W)+ => (Tuple as -> b)+ -> (b -> Tuple as)+ -> Prod (BVar s) as+ -> BVar s b+isoVarN f g = liftOp (opIsoN f g)+{-# INLINE isoVarN #-}
src/Numeric/Backprop/Internal.hs view
@@ -158,10 +158,6 @@ } -> SomeTapeNode -forceSomeTapeNode :: SomeTapeNode -> ()-forceSomeTapeNode (STN !_ tn) = forceTapeNode tn `seq` ()-{-# INLINE forceSomeTapeNode #-}- -- | Debugging string for a 'SomeTapeMode'. debugSTN :: SomeTapeNode -> String debugSTN (STN _ TN{..}) = show . foldMap1 ((:[]) . debugIR) $ _tnInputs@@ -596,7 +592,6 @@ evaluate (forceBVar oVar) return (_bvVal oVar) t <- readIORef (wRef w)- traverse_ (evaluate . forceSomeTapeNode) (snd t) return (t, o) where inpProd :: forall s. Prod (BVar s) as
src/Numeric/Backprop/Op.hs view
@@ -47,11 +47,11 @@ , runOp, evalOp, gradOp, gradOpWith -- * Creation , op0, opConst, idOp- , opConst'+ , opConst', opLens -- ** Giving gradients directly , op1, op2, op3 -- ** From Isomorphisms- , opCoerce, opTup, opIso, opIsoN, opLens+ , opCoerce, opTup, opIso, opIso2, opIso3, opIsoN -- ** No gradient , noGrad1, noGrad -- * Manipulation@@ -390,20 +390,30 @@ -- | An 'Op' that runs the input value through an isomorphism. -- -- Warning: This is unsafe! It assumes that the isomorphisms themselves--- have derivative 1, so will break for things like--- 'Numeric.Lens.exponentiating'. Basically, don't use this for any--- "numeric" isomorphisms.+-- have derivative 1, so will break for things like 'exp' & 'log'.+-- Basically, don't use this for any "numeric" isomorphisms. opIso :: (a -> b) -> (b -> a) -> Op '[ a ] b opIso to' from' = op1 $ \x -> (to' x, from') {-# INLINE opIso #-} --- | An 'Op' that runs the input value through an isomorphism between--- a tuple of values and a value.+-- | An 'Op' that runs the two input values through an isomorphism. Useful+-- for things like constructors. See 'opIso' for caveats. ----- Warning: This is unsafe! It assumes that the isomorphisms themselves--- have derivative 1, so will break for things like--- 'Numeric.Lens.exponentiating'. Basically, don't use this for any--- "numeric" isomorphisms.+-- @since 0.1.4.0+opIso2 :: (a -> b -> c) -> (c -> (a, b)) -> Op '[a, b] c+opIso2 to' from' = op2 $ \x y -> (to' x y, from')+{-# INLINE opIso2 #-}++-- | An 'Op' that runs the three input values through an isomorphism.+-- Useful for things like constructors. See 'opIso' for caveats.+--+-- @since 0.1.4.0+opIso3 :: (a -> b -> c -> d) -> (d -> (a, b, c)) -> Op '[a, b, c] d+opIso3 to' from' = op3 $ \x y z -> (to' x y z, from')+{-# INLINE opIso3 #-}++-- | An 'Op' that runs the input value through an isomorphism between+-- a tuple of values and a value. See 'opIso' for caveats. -- -- In "Numeric.Backprop.Op" since version 0.1.2.0, but only exported from -- "Numeric.Backprop" since version 0.1.3.0.
src/Numeric/Backprop/Tuple.hs view
@@ -13,9 +13,9 @@ -- Stability : experimental -- Portability : non-portable ----- Canonical strict tuples with 'Num' instances for usage with /backprop/.--- This is here to solve the problem of orphan instances in libraries and--- potential mismatched tuple types.+-- Canonical strict tuples (and unit) with 'Num' instances for usage with+-- /backprop/. This is here to solve the problem of orphan instances in+-- libraries and potential mismatched tuple types. -- -- If you are writing a library that needs to export 'BVar's of tuples, -- consider using the tuples in this module so that your library can have@@ -47,13 +47,18 @@ -- and '_3' from "Lens.Micro". However, note that these are incompatible -- with '_1', '_2', and '_3' from "Control.Lens". --+-- You can "construct" a @'BVar' s ('T2' a b)@ with functions like+-- 'isoVar'.+-- -- @since 0.1.1.0 -- module Numeric.Backprop.Tuple (+ -- * Zero-tuples (unit)+ T0(..) -- * Two-tuples- T2(..)+ , T2(..) -- ** Conversions -- $t2iso , t2Tup, tupT2@@ -80,13 +85,29 @@ import Lens.Micro import Lens.Micro.Internal --- | Strict 2-tuple with a 'Num' instance.+-- | Unit ('()') with 'Num', 'Fractional', and 'Floating' instances. --+-- Be aware that the methods in its numerical instances are all non-strict:+--+-- @@+-- _ + _ = 'T0'+-- 'negate' _ = 'T0'+-- 'fromIntegral' _ = 'T0'+-- @@+--+-- @since 0.1.4.0+data T0 = T0+ deriving (Show, Read, Eq, Ord, Generic, Data)++instance NFData T0++-- | Strict 2-tuple with 'Num', 'Fractional', and 'Floating' instances.+-- -- @since 0.1.1.0 data T2 a b = T2 !a !b deriving (Show, Read, Eq, Ord, Generic, Functor, Data) --- | Strict 3-tuple with a 'Num' instance.+-- | Strict 3-tuple with a 'Num', 'Fractional', and 'Floating' instances. -- -- @since 0.1.1.0 data T3 a b c = T3 !a !b !c@@ -188,6 +209,38 @@ -- "Lens.Micro". t3_3 :: Lens (T3 a b c) (T3 a b c') c c' t3_3 = _3++instance Num T0 where+ _ + _ = T0+ _ - _ = T0+ _ * _ = T0+ negate _ = T0+ abs _ = T0+ signum _ = T0+ fromInteger _ = T0++instance Fractional T0 where+ _ / _ = T0+ recip _ = T0+ fromRational _ = T0++instance Floating T0 where+ pi = T0+ _ ** _ = T0+ logBase _ _ = T0+ exp _ = T0+ log _ = T0+ sqrt _ = T0+ sin _ = T0+ cos _ = T0+ asin _ = T0+ acos _ = T0+ atan _ = T0+ sinh _ = T0+ cosh _ = T0+ asinh _ = T0+ acosh _ = T0+ atanh _ = T0 instance (Num a, Num b) => Num (T2 a b) where T2 x1 y1 + T2 x2 y2 = T2 (x1 + x2) (y1 + y2)