DeepDarkFantasy 0.2017.8.8 → 0.2017.8.9
raw patch · 9 files changed
+307/−308 lines, 9 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- DDF.Poly: comp :: Lang r => r h (Double -> Double)
- DDF.Poly: l2 :: Lang r => r h (Double -> Double)
- DDF.Poly: main :: IO ()
- DDF.Poly: poly :: forall repr h. Lang repr => repr h (Double -> Double)
- DDF.Poly: solve :: forall m. Monad m => (AST -> m ()) -> (Integer -> Double -> m ()) -> m Double
- DDF.Util: vars :: [[Char]]
- DDF.Xor: dataset :: Lang repr => repr h [((Double, Double), Double)]
- DDF.Xor: doubleWeight :: Lang repr => ImpW repr h Double
- DDF.Xor: eval :: Lang repr => repr h (XOR -> ((Double, Double), Double) -> Double)
- DDF.Xor: findXor :: forall g m. (RandomGen g, Monad m) => g -> (AST -> m ()) -> (Int -> Double -> String -> m ()) -> m XOR
- DDF.Xor: hidden :: Lang repr => ImpW repr h ((Double, Double) -> ((Double, Double), (Double, Double)))
- DDF.Xor: l2 :: Lang repr => repr h (Double -> Double -> Double)
- DDF.Xor: l22 :: Lang r => r h Double -> r h Double -> r h Double
- DDF.Xor: loss :: Lang repr => repr h (XOR -> Double)
- DDF.Xor: main :: IO ()
- DDF.Xor: neuron :: Lang repr => ImpW repr h ((Double, Double) -> Double)
- DDF.Xor: neuron1 :: Lang repr => ImpW repr h (Double, Double) -> ImpW repr h Double
- DDF.Xor: scaleAdd :: Lang repr => ImpW repr h ((Double, Double) -> Double)
- DDF.Xor: sigmoid :: Lang r => r h (Double -> Double)
- DDF.Xor: sigmoid1 :: Lang r => r h Double -> r h Double
- DDF.Xor: type XOR = (Double, Double) -> Double
- DDF.Xor: withBias :: Lang repr => ImpW repr h (Double -> Double)
- DDF.Xor: xorNet :: Lang repr => ImpW repr h XOR
+ DDF.Sam.Poly: comp :: Lang r => r h (Double -> Double)
+ DDF.Sam.Poly: l2 :: Lang r => r h (Double -> Double)
+ DDF.Sam.Poly: main :: IO ()
+ DDF.Sam.Poly: poly :: forall repr h. Lang repr => repr h (Double -> Double)
+ DDF.Sam.Poly: solve :: forall m. Monad m => (AST -> m ()) -> (Integer -> Double -> m ()) -> m Double
+ DDF.Sam.Xor: dataset :: Lang repr => repr h [((Double, Double), Double)]
+ DDF.Sam.Xor: doubleWeight :: Lang repr => ImpW repr h Double
+ DDF.Sam.Xor: eval :: Lang repr => repr h (XOR -> ((Double, Double), Double) -> Double)
+ DDF.Sam.Xor: findXor :: forall g m. (RandomGen g, Monad m) => g -> (AST -> m ()) -> (Int -> Double -> String -> m ()) -> m XOR
+ DDF.Sam.Xor: hidden :: Lang repr => ImpW repr h ((Double, Double) -> ((Double, Double), (Double, Double)))
+ DDF.Sam.Xor: l2 :: Lang repr => repr h (Double -> Double -> Double)
+ DDF.Sam.Xor: l22 :: Lang r => r h Double -> r h Double -> r h Double
+ DDF.Sam.Xor: loss :: Lang repr => repr h (XOR -> Double)
+ DDF.Sam.Xor: main :: IO ()
+ DDF.Sam.Xor: neuron :: Lang repr => ImpW repr h ((Double, Double) -> Double)
+ DDF.Sam.Xor: neuron1 :: Lang repr => ImpW repr h (Double, Double) -> ImpW repr h Double
+ DDF.Sam.Xor: scaleAdd :: Lang repr => ImpW repr h ((Double, Double) -> Double)
+ DDF.Sam.Xor: sigmoid :: Lang r => r h (Double -> Double)
+ DDF.Sam.Xor: sigmoid1 :: Lang r => r h Double -> r h Double
+ DDF.Sam.Xor: type XOR = (Double, Double) -> Double
+ DDF.Sam.Xor: withBias :: Lang repr => ImpW repr h (Double -> Double)
+ DDF.Sam.Xor: xorNet :: Lang repr => ImpW repr h XOR
+ DDF.Show: vars :: [[Char]]
Files
- DDF/Poly.lhs +0/−114
- DDF/Sam/Poly.lhs +114/−0
- DDF/Sam/Xor.lhs +138/−0
- DDF/Show.hs +2/−0
- DDF/Util.hs +0/−2
- DDF/Xor.lhs +0/−138
- DeepDarkFantasy.cabal +51/−52
- test/TestPoly.hs +1/−1
- test/TestXor.hs +1/−1
− DDF/Poly.lhs
@@ -1,114 +0,0 @@-> {-# LANGUAGE -> NoImplicitPrelude, -> MultiParamTypeClasses, -> RankNTypes, -> ScopedTypeVariables, -> FlexibleInstances, -> FlexibleContexts, -> UndecidableInstances, -> IncoherentInstances, -> PolyKinds, -> LambdaCase, -> NoMonomorphismRestriction, -> TypeFamilies, -> LiberalTypeSynonyms, -> EmptyCase -> #-} - -> module DDF.Poly where -> import Control.Monad (when) -> import DDF.Util -> import DDF.Lang -> import DDF.Show -> import DDF.Diff () -> import qualified Control.Monad as M -> import Prelude (Integer) -> import qualified Prelude as M -> import qualified DDF.Meta.Dual as M -> import DDF.Eval - -Importing files and opening language extension... -So, our goal is to find x, where x * x + 2 * x + 3 = 27. -To do so, we try to minimize their difference squared (l2 norm). - -> poly :: forall repr h. Lang repr => repr h (M.Double -> M.Double) -> poly = lam $ \x -> plus2 (mult2 x x) (plus2 (mult2 (double 2.0) x) (double 3.0)) - -poly x = x * x + (2 * x + 3) - -> l2 = lam $ \x -> mult2 (minus2 x (double 27)) (minus2 x (double 27)) - -l2 x = (x - 27) * (x - 27) -l2 measure how far is the input from 27 - -> comp = com2 l2 poly - -By composing the two, we can measure how far is x * x + 2 * x + 3 from 27. -We want to minimize this distance. - -Now write a generic function that calculate x and return it. - -> solve :: forall m. M.Monad m => (AST -> m ()) -> (Integer -> M.Double -> m ()) -> m M.Double -> solve doAST doIter = do - -Let's begin by trying to print poly - -> doAST $ runShow poly vars 0 -> go 0 0 -> where - -The main loop. i is step and w is weight (our current estimate of x). -We start by assuming x = 0 is the solution, -and minimize (comp x) by taking derivative of x, and decrease it whenever it is positive (and vice versa). - -> go :: Integer -> M.Double -> m M.Double -> go i w | i < 200 = do -> doIter i w -> go (1 + i) $ w - 0.001 * M.dualDiff (runEval (runDiff $ noEnv comp) () $ M.Dual (w, 1)) - -noEnv comp assume the term (which is a De Brujin Index term) need no environment (is free) -and it is a finally tagless term, with WDiff interpreter being implicitly applied, -which return another finally tagless term, but taking derivative of x. -it is then applied to Eval interpreter (which eval it in the meta language, haskell). -similar to runWDiff, we use runEval to take out the term from a newtype -now we apply the environment (remember it has no environment? so just stick a unit) -and a pair, the zeroth being x, the first being derivative of x, which is 1. -the whole computation return a pair of (x * x + (2 * x + 3) - 27)^2, and it's derivative. -we modify w using the derivative. - -> go _ w = M.return w - -By running the program, you shall see -(\a -> (plus (mult a a) (plus (mult 2.0 a) 3.0))) -since we pretty print poly -followed by something like -0.0 -9.6e-2 -0.43573084645674215 -1.1890033104995505 -2.498644212525056 -3.652210805402036 -3.9662181049468925 -3.9981203814732154 -3.9999338218043157 -3.999998509763363 -3.9999999785234146 -3.9999999998019136 -3.9999999999988307 -3.9999999999999956 -3.999999999999999 -which mean we found 4 as a soultion. -plugging it back to the equation, we can verify that (4 * 4) + 2 * 4 + 3 is indeed 27! - -Now the main function: - -> main :: M.IO () -> main = do -> d <- solve print printSquare -> M.putStrLn $ "x is: " ++ (show d) -> M.return () -> where -> printSquare i x = when (isSquare i) (print x) - -the only thing worth noting is that we print the weight in increasing interval, -so initially more weight is printed
+ DDF/Sam/Poly.lhs view
@@ -0,0 +1,114 @@+> {-# LANGUAGE +> NoImplicitPrelude, +> MultiParamTypeClasses, +> RankNTypes, +> ScopedTypeVariables, +> FlexibleInstances, +> FlexibleContexts, +> UndecidableInstances, +> IncoherentInstances, +> PolyKinds, +> LambdaCase, +> NoMonomorphismRestriction, +> TypeFamilies, +> LiberalTypeSynonyms, +> EmptyCase +> #-} + +> module DDF.Sam.Poly where +> import Control.Monad (when) +> import DDF.Util +> import DDF.Lang +> import DDF.Show +> import DDF.Diff () +> import qualified Control.Monad as M +> import Prelude (Integer) +> import qualified Prelude as M +> import qualified DDF.Meta.Dual as M +> import DDF.Eval + +Importing files and opening language extension... +So, our goal is to find x, where x * x + 2 * x + 3 = 27. +To do so, we try to minimize their difference squared (l2 norm). + +> poly :: forall repr h. Lang repr => repr h (M.Double -> M.Double) +> poly = lam $ \x -> plus2 (mult2 x x) (plus2 (mult2 (double 2.0) x) (double 3.0)) + +poly x = x * x + (2 * x + 3) + +> l2 = lam $ \x -> mult2 (minus2 x (double 27)) (minus2 x (double 27)) + +l2 x = (x - 27) * (x - 27) +l2 measure how far is the input from 27 + +> comp = com2 l2 poly + +By composing the two, we can measure how far is x * x + 2 * x + 3 from 27. +We want to minimize this distance. + +Now write a generic function that calculate x and return it. + +> solve :: forall m. M.Monad m => (AST -> m ()) -> (Integer -> M.Double -> m ()) -> m M.Double +> solve doAST doIter = do + +Let's begin by trying to print poly + +> doAST $ runShow poly vars 0 +> go 0 0 +> where + +The main loop. i is step and w is weight (our current estimate of x). +We start by assuming x = 0 is the solution, +and minimize (comp x) by taking derivative of x, and decrease it whenever it is positive (and vice versa). + +> go :: Integer -> M.Double -> m M.Double +> go i w | i < 200 = do +> doIter i w +> go (1 + i) $ w - 0.001 * M.dualDiff (runEval (runDiff $ noEnv comp) () $ M.Dual (w, 1)) + +noEnv comp assume the term (which is a De Brujin Index term) need no environment (is free) +and it is a finally tagless term, with WDiff interpreter being implicitly applied, +which return another finally tagless term, but taking derivative of x. +it is then applied to Eval interpreter (which eval it in the meta language, haskell). +similar to runWDiff, we use runEval to take out the term from a newtype +now we apply the environment (remember it has no environment? so just stick a unit) +and a pair, the zeroth being x, the first being derivative of x, which is 1. +the whole computation return a pair of (x * x + (2 * x + 3) - 27)^2, and it's derivative. +we modify w using the derivative. + +> go _ w = M.return w + +By running the program, you shall see +(\a -> (plus (mult a a) (plus (mult 2.0 a) 3.0))) +since we pretty print poly +followed by something like +0.0 +9.6e-2 +0.43573084645674215 +1.1890033104995505 +2.498644212525056 +3.652210805402036 +3.9662181049468925 +3.9981203814732154 +3.9999338218043157 +3.999998509763363 +3.9999999785234146 +3.9999999998019136 +3.9999999999988307 +3.9999999999999956 +3.999999999999999 +which mean we found 4 as a soultion. +plugging it back to the equation, we can verify that (4 * 4) + 2 * 4 + 3 is indeed 27! + +Now the main function: + +> main :: M.IO () +> main = do +> d <- solve print printSquare +> M.putStrLn $ "x is: " ++ (show d) +> M.return () +> where +> printSquare i x = when (isSquare i) (print x) + +the only thing worth noting is that we print the weight in increasing interval, +so initially more weight is printed
+ DDF/Sam/Xor.lhs view
@@ -0,0 +1,138 @@+> {-# LANGUAGE+> ScopedTypeVariables,+> NoMonomorphismRestriction,+> TypeApplications,+> RankNTypes,+> NoImplicitPrelude,+> ScopedTypeVariables+> #-}++This is the classical example of using sigmoid NN to approximate Xor.+You should already read DDF.Poly before this.++> module DDF.Sam.Xor where+> import qualified Prelude as M+> import System.Random+> import Control.Monad (when)+> import Data.Constraint+> import DDF.Util+> import DDF.Lang+> import DDF.Show+> import DDF.Eval ()+> import DDF.Term+> import DDF.ImpW+> import DDF.WithDiff+> import DDF.Eval+> import qualified DDF.Meta.Dual as M++Recall in poly, we constructed a function Double -> Double,+with argument being the weight, and do gradient descend to found a solution.++However, most of the time, there wil be more than one weight (or no weight at all).+Also, when we are composing a Neural Network to approximate a value, we dont really care how much weight it use.+So, we use existential type to hide the actual weight.++data ImpW repr h x = forall w. Weight w => ImpW (repr h (w -> x))++ImpW stands for implicit weights.+The existential w is weight, and a Neural Network of type x is just a function from w to x!+We require that the weight can be constructed randomly, so we have random initialization.+Weight also form a Vector so we can combine weights (update it), scale it (to control the learning rate).++Let's start by constructing a weight.++> doubleWeight :: Lang repr => ImpW repr h M.Double+> doubleWeight = ImpW id++Note that we are just manipulating AST.+If you wanna do weight sharing, you need to use let(in DDF) yourself.++Obviously, we just need to take the implicit argument.++We have the weight, now we need the activation function, sigmoid.++> sigmoid = lam $ \x -> recip1 (plus2 doubleOne (doubleExp1 (invert1 x)))+> sigmoid1 = app sigmoid++With weight and sigmoid we can construct a neuron of type ((M.Double, M.Double) -> M.Double)+The weight should be a pair of M.Double, each as a scale on the actual input, with a bias.+We then add the two scaled input, with the bias, and pass them into sigmoid.++> scaleAdd :: Lang repr => ImpW repr h ((M.Double, M.Double) -> M.Double)+> scaleAdd = ImpW $ lam2 $ \w p -> plus2 (mult2 (zro1 w) (zro1 p)) (plus2 (fst1 w) (fst1 p))++> withBias :: Lang repr => ImpW repr h (M.Double -> M.Double)+> withBias = ImpW $ plus++> neuron :: Lang repr => ImpW repr h ((M.Double, M.Double) -> M.Double)+> neuron = com2 (com2 sigmoid withBias) scaleAdd+> neuron1 = app neuron++Now, the hidden layer of type (M.Double, M.Double) -> ((M.Double, M.Double), (M.Double, M.Double))++> hidden = lam $ \p -> mkProd2 (mkProd2 (neuron1 p) (neuron1 p)) (mkProd2 (neuron1 p) (neuron1 p))++And finally, the whole NN:++> type XOR = (M.Double, M.Double) -> M.Double+> xorNet :: Lang repr => ImpW repr h XOR+> xorNet = neuron `com2` (bimap2 scaleAdd scaleAdd) `com2` hidden++But before we can train it, we need to define the dataset and the loss function.++> l2 :: Lang repr => repr h (M.Double -> M.Double -> M.Double)+> l2 = lam2 $ \l r -> (mult2 (minus2 l r) (minus2 l r))+> l22 = app2 l2++> eval :: Lang repr => repr h (XOR -> ((M.Double, M.Double), M.Double) -> M.Double)+> eval = lam2 $ \xor p -> l22 (app xor (zro1 p)) (fst1 p)++> dataset :: Lang repr => repr h [((M.Double, M.Double), M.Double)]+> dataset = cons2 (build 0 0 0) (cons2 (build 0 1 1) (cons2 (build 1 0 1) (cons2 (build 1 1 0) nil)))+> where build l r ret = mkProd2 (mkProd2 (double l) (double r)) (double ret)++However, unlike Poly, there are more than one datapoint, so we need to use a list, and map xor onto it.++> loss :: Lang repr => repr h (XOR -> M.Double)+> loss = lam $ \xor -> y2 (lam $ \self -> listMatch2 doubleZero (lam2 $ \x xs -> plus2 x (app self xs))) (map2 (app eval xor) dataset)++Now we are good to implement the train function!++> findXor :: forall g m. (RandomGen g, M.Monad m) => g -> (AST -> m ()) -> (M.Int -> M.Double -> M.String -> m ()) -> m XOR+> findXor rand doAST doIter = case runImpW $ noEnv xorNet of+> RunImpW ((Term net) :: Weight w => Term Lang () (w -> XOR)) -> do+> doAST $ runShow net vars 0++printing weights. now you will see a list of gibberish++> let initWeight :: w = M.fst $ ((randomR (randRange (-0.01, 0.01)) \\ weightCon @w @Random) \\ weightCon @w @RandRange) rand++Getting random weights...++> (go (diff net) initWeight (runEval selfWithDiff () \\ weightCon @w @(WithDiff Eval)) (diff loss)+> ((runEval (lam3 $ \d o n -> minus2 o (mult2 d n)) ()) \\ weightCon @w @(Vector Eval)) 0 (runEval net ())) \\ weightCon @w @M.Show+> where+> diff :: forall x. Term Lang () x -> DiffType w x+> diff (Term x) = runEval (runDiff @_ @w (noEnv x)) () \\ weightCon @w @(Vector Eval)+> go :: M.Show w => (DiffType w (w -> XOR)) -> w -> (w -> DiffType w w) -> (DiffType w (XOR -> M.Double)) -> (M.Double -> w -> w -> w) -> M.Int -> (w -> XOR) -> m XOR+> go xor weight reifyE lossE updateW i orig | i <= 2500 = do+> doIter i lossVal (M.show weight)+> go xor (updateW 0.3 weight lossDiff) reifyE lossE updateW (1 + i) orig+> where+> M.Dual (lossVal, lossDiff) = lossE $ xor (reifyE weight)+> go _ weight _ _ _ _ orig = M.return $ orig weight++> main :: M.IO ()+> main = do+> g <- getStdGen+> xorTrained <- findXor g print (\i d w -> when (isSquare i) $ do+> print d+> M.putStrLn w+> M.putStrLn "")+> let doXor :: M.Double -> M.Double -> M.IO ()+> doXor l r = M.putStrLn $ M.show l ++ " xor " ++ M.show r ++ " is " ++ (M.show $ xorTrained (l, r))+> doXor 0 0+> doXor 0 1+> doXor 1 0+> doXor 1 1+> M.return ()
DDF/Show.hs view
@@ -16,6 +16,8 @@ lamAST str (Lam st l t) = Lam str (st:l) t lamAST str r = Lam str [] r +vars = [pre : suf | suf <- "":M.map show [0..], pre <- ['a'..'z']]+ instance M.Show AST where show (Leaf f) = f show (App f x l) = "(" ++ f ++ " " ++ show x ++ M.concatMap ((" " ++) . show) l ++ ")"
DDF/Util.hs view
@@ -5,8 +5,6 @@ import System.Random import GHC.Float -vars = [pre : suf | suf <- "":map show [0..], pre <- ['a'..'z']] - isSquare n = sq * sq == n where sq = floor $ sqrt (fromIntegral n::Double)
− DDF/Xor.lhs
@@ -1,138 +0,0 @@-> {-# LANGUAGE-> ScopedTypeVariables,-> NoMonomorphismRestriction,-> TypeApplications,-> RankNTypes,-> NoImplicitPrelude,-> ScopedTypeVariables-> #-}--This is the classical example of using sigmoid NN to approximate Xor.-You should already read DDF.Poly before this.--> module DDF.Xor where-> import qualified Prelude as M-> import System.Random-> import Control.Monad (when)-> import Data.Constraint-> import DDF.Util-> import DDF.Lang-> import DDF.Show-> import DDF.Eval ()-> import DDF.Term-> import DDF.ImpW-> import DDF.WithDiff-> import DDF.Eval-> import qualified DDF.Meta.Dual as M--Recall in poly, we constructed a function Double -> Double,-with argument being the weight, and do gradient descend to found a solution.--However, most of the time, there wil be more than one weight (or no weight at all).-Also, when we are composing a Neural Network to approximate a value, we dont really care how much weight it use.-So, we use existential type to hide the actual weight.--data ImpW repr h x = forall w. Weight w => ImpW (repr h (w -> x))--ImpW stands for implicit weights.-The existential w is weight, and a Neural Network of type x is just a function from w to x!-We require that the weight can be constructed randomly, so we have random initialization.-Weight also form a Vector so we can combine weights (update it), scale it (to control the learning rate).--Let's start by constructing a weight.--> doubleWeight :: Lang repr => ImpW repr h M.Double-> doubleWeight = ImpW id--Note that we are just manipulating AST.-If you wanna do weight sharing, you need to use let(in DDF) yourself.--Obviously, we just need to take the implicit argument.--We have the weight, now we need the activation function, sigmoid.--> sigmoid = lam $ \x -> recip1 (plus2 doubleOne (doubleExp1 (invert1 x)))-> sigmoid1 = app sigmoid--With weight and sigmoid we can construct a neuron of type ((M.Double, M.Double) -> M.Double)-The weight should be a pair of M.Double, each as a scale on the actual input, with a bias.-We then add the two scaled input, with the bias, and pass them into sigmoid.--> scaleAdd :: Lang repr => ImpW repr h ((M.Double, M.Double) -> M.Double)-> scaleAdd = ImpW $ lam2 $ \w p -> plus2 (mult2 (zro1 w) (zro1 p)) (plus2 (fst1 w) (fst1 p))--> withBias :: Lang repr => ImpW repr h (M.Double -> M.Double)-> withBias = ImpW $ plus--> neuron :: Lang repr => ImpW repr h ((M.Double, M.Double) -> M.Double)-> neuron = com2 (com2 sigmoid withBias) scaleAdd-> neuron1 = app neuron--Now, the hidden layer of type (M.Double, M.Double) -> ((M.Double, M.Double), (M.Double, M.Double))--> hidden = lam $ \p -> mkProd2 (mkProd2 (neuron1 p) (neuron1 p)) (mkProd2 (neuron1 p) (neuron1 p))--And finally, the whole NN:--> type XOR = (M.Double, M.Double) -> M.Double-> xorNet :: Lang repr => ImpW repr h XOR-> xorNet = neuron `com2` (bimap2 scaleAdd scaleAdd) `com2` hidden--But before we can train it, we need to define the dataset and the loss function.--> l2 :: Lang repr => repr h (M.Double -> M.Double -> M.Double)-> l2 = lam2 $ \l r -> (mult2 (minus2 l r) (minus2 l r))-> l22 = app2 l2--> eval :: Lang repr => repr h (XOR -> ((M.Double, M.Double), M.Double) -> M.Double)-> eval = lam2 $ \xor p -> l22 (app xor (zro1 p)) (fst1 p)--> dataset :: Lang repr => repr h [((M.Double, M.Double), M.Double)]-> dataset = cons2 (build 0 0 0) (cons2 (build 0 1 1) (cons2 (build 1 0 1) (cons2 (build 1 1 0) nil)))-> where build l r ret = mkProd2 (mkProd2 (double l) (double r)) (double ret)--However, unlike Poly, there are more than one datapoint, so we need to use a list, and map xor onto it.--> loss :: Lang repr => repr h (XOR -> M.Double)-> loss = lam $ \xor -> y2 (lam $ \self -> listMatch2 doubleZero (lam2 $ \x xs -> plus2 x (app self xs))) (map2 (app eval xor) dataset)--Now we are good to implement the train function!--> findXor :: forall g m. (RandomGen g, M.Monad m) => g -> (AST -> m ()) -> (M.Int -> M.Double -> M.String -> m ()) -> m XOR-> findXor rand doAST doIter = case runImpW $ noEnv xorNet of-> RunImpW ((Term net) :: Weight w => Term Lang () (w -> XOR)) -> do-> doAST $ runShow net vars 0--printing weights. now you will see a list of gibberish--> let initWeight :: w = M.fst $ ((randomR (randRange (-0.01, 0.01)) \\ weightCon @w @Random) \\ weightCon @w @RandRange) rand--Getting random weights...--> (go (diff net) initWeight (runEval selfWithDiff () \\ weightCon @w @(WithDiff Eval)) (diff loss)-> ((runEval (lam3 $ \d o n -> minus2 o (mult2 d n)) ()) \\ weightCon @w @(Vector Eval)) 0 (runEval net ())) \\ weightCon @w @M.Show-> where-> diff :: forall x. Term Lang () x -> DiffType w x-> diff (Term x) = runEval (runDiff @_ @w (noEnv x)) () \\ weightCon @w @(Vector Eval)-> go :: M.Show w => (DiffType w (w -> XOR)) -> w -> (w -> DiffType w w) -> (DiffType w (XOR -> M.Double)) -> (M.Double -> w -> w -> w) -> M.Int -> (w -> XOR) -> m XOR-> go xor weight reifyE lossE updateW i orig | i <= 2500 = do-> doIter i lossVal (M.show weight)-> go xor (updateW 0.3 weight lossDiff) reifyE lossE updateW (1 + i) orig-> where-> M.Dual (lossVal, lossDiff) = lossE $ xor (reifyE weight)-> go _ weight _ _ _ _ orig = M.return $ orig weight--> main :: M.IO ()-> main = do-> g <- getStdGen-> xorTrained <- findXor g print (\i d w -> when (isSquare i) $ do-> print d-> M.putStrLn w-> M.putStrLn "")-> let doXor :: M.Double -> M.Double -> M.IO ()-> doXor l r = M.putStrLn $ M.show l ++ " xor " ++ M.show r ++ " is " ++ (M.show $ xorTrained (l, r))-> doXor 0 0-> doXor 0 1-> doXor 1 0-> doXor 1 1-> M.return ()
DeepDarkFantasy.cabal view
@@ -1,5 +1,5 @@ name: DeepDarkFantasy-version: 0.2017.8.8+version: 0.2017.8.9 cabal-version: 1.12 build-type: Simple license: Apache@@ -20,50 +20,49 @@ location: https://github.com/ThoughtWorksInc/DeepDarkFantasy library- exposed-modules:- DDF.Bimap- DDF.Bool- DDF.Char- DDF.DBI- DDF.Diff- DDF.DiffWrapper- DDF.Double- DDF.Dual- DDF.Eval- DDF.Fix- DDF.Float- DDF.FreeVector- DDF.ImportMeta- DDF.ImpW- DDF.Int- DDF.IO- DDF.Lang- DDF.List- DDF.Map- DDF.Meta.Diff- DDF.Meta.DiffWrapper- DDF.Meta.Dual- DDF.Meta.FreeVector- DDF.Meta.VectorTF- DDF.Option- DDF.PE- DDF.Poly- DDF.Prod- DDF.Show- DDF.Size- DDF.Sum- DDF.Term- DDF.TermGen- DDF.UInt- DDF.UnHOAS- DDF.Unit- DDF.UnLiftEnv- DDF.Util- DDF.Vector- DDF.VectorTF- DDF.WithDiff- DDF.Xor- DDF.Y+ exposed-modules: DDF.Bimap+ DDF.Bool+ DDF.Char+ DDF.DBI+ DDF.Diff+ DDF.DiffWrapper+ DDF.Double+ DDF.Dual+ DDF.Eval+ DDF.Fix+ DDF.Float+ DDF.FreeVector+ DDF.ImportMeta+ DDF.ImpW+ DDF.Int+ DDF.IO+ DDF.Lang+ DDF.List+ DDF.Map+ DDF.Meta.Diff+ DDF.Meta.DiffWrapper+ DDF.Meta.Dual+ DDF.Meta.FreeVector+ DDF.Meta.VectorTF+ DDF.Option+ DDF.PE+ DDF.Prod+ DDF.Sam.Poly+ DDF.Sam.Xor+ DDF.Show+ DDF.Size+ DDF.Sum+ DDF.Term+ DDF.TermGen+ DDF.UInt+ DDF.UnHOAS+ DDF.Unit+ DDF.UnLiftEnv+ DDF.Util+ DDF.Vector+ DDF.VectorTF+ DDF.WithDiff+ DDF.Y build-depends: base >= 4.9.0.0 && <= 4.9.1.0, mtl -any,@@ -78,7 +77,7 @@ ghc-options: -Werror default-language: Haskell2010 -Test-Suite TestPoly+test-Suite TestPoly type: exitcode-stdio-1.0 default-language: Haskell2010 hs-source-dirs: test@@ -88,9 +87,9 @@ mtl -any, random -any, constraints -any,- DeepDarkFantasy+ DeepDarkFantasy -any -Test-Suite TestXor+test-Suite TestXor type: exitcode-stdio-1.0 default-language: Haskell2010 hs-source-dirs: test@@ -100,9 +99,9 @@ mtl -any, random -any, constraints -any,- DeepDarkFantasy+ DeepDarkFantasy -any -Test-Suite TestPE+test-Suite TestPE type: exitcode-stdio-1.0 default-language: Haskell2010 hs-source-dirs: test@@ -112,5 +111,5 @@ mtl -any, random -any, constraints -any,- QuickCheck,- DeepDarkFantasy+ QuickCheck -any,+ DeepDarkFantasy -any
test/TestPoly.hs view
@@ -1,6 +1,6 @@ module Main where -import DDF.Poly hiding (main)+import DDF.Sam.Poly hiding (main) import Control.Monad import System.Exit (exitFailure)
test/TestXor.hs view
@@ -1,6 +1,6 @@ module Main where -import DDF.Xor hiding (main)+import DDF.Sam.Xor hiding (main) import Control.Monad import System.Exit (exitFailure) import System.Random