commit 5c275852a155c1189b9bc12f8fecd0a627b18d4a
parent ad7925d2aa33a7ed0f6822370ddc12a746e40f03
Author: Jared Tobin <jared@jtobin.ca>
Date: Sun, 13 Oct 2013 21:48:20 +1300
Remove working directory from tree.
Diffstat:
D | working/HMC.hs | | | 224 | ------------------------------------------------------------------------------- |
D | working/daNUTS.hs | | | 199 | ------------------------------------------------------------------------------- |
2 files changed, 0 insertions(+), 423 deletions(-)
diff --git a/working/HMC.hs b/working/HMC.hs
@@ -1,224 +0,0 @@
--- | See Hoffman, Gelman (2011) The No U-Turn Sampler: Adaptively Setting Path
--- Lengths in Hamiltonian Monte Carlo.
-
-{-# OPTIONS_GHC -fno-warn-type-defaults #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-import Control.Monad
-import Control.Monad.Loops
-import Control.Monad.Primitive
-import System.Random.MWC
-import System.Random.MWC.Distributions
-
--- TODO what am i
-dMax :: Num t => t
-dMax = 1000
-
-hmc :: (Enum a, Eq a, Ord a, Num a, PrimMonad m )
- => ([Double] -> Double) -- ^ Log target function
- -> ([Double] -> [Double]) -- ^ Gradient of log target
- -> [Double] -- ^ Parameters
- -> a -- ^ Epochs to run the chain
- -> a -- ^ Number of discretizing steps
- -> Double -- ^ Step size
- -> Gen (PrimState m) -- ^ PRNG
- -> m [[Double]] -- ^ Chain
-hmc lTarget glTarget t n ndisc e g = unfoldrM kernel (n, (t, []))
- where
- kernel (m, (p, _)) = do
- (p1, r1) <- hmcKernel lTarget glTarget p ndisc e g
- return $ if m <= 0
- then Nothing
- else Just (p1, (pred m, (p1, r1)))
-
-hmcKernel :: (Enum a, Eq a, Ord a, Num a, PrimMonad m)
- => ([Double] -> Double) -- ^ Log target function
- -> ([Double] -> [Double]) -- ^ Gradient of log target
- -> [Double] -- ^ Parameters
- -> a -- ^ Number of discretizing steps
- -> Double -- ^ Step size
- -> Gen (PrimState m) -- ^ PRNG
- -> m ([Double], [Double]) -- ^ m (End params, end momenta)
-hmcKernel lTarget glTarget t0 ndisc e g = do
- r0 <- replicateM (length t0) (normal 0 1 g)
- z <- uniform g
- let (t1, r1) = leapfrog glTarget t0 r0 ndisc e
- a = min 1 $ hmcAcceptanceRatio lTarget t0 t1 r0 r1
- final | a > z = (t1, map negate r1)
- | otherwise = (t0, r0)
- return final
-
-leapfrog :: (Enum a, Eq a, Ord a, Fractional c, Num a)
- => ([c] -> [c]) -- ^ Gradient of log target function
- -> [c] -- ^ List of parameters to target
- -> [c] -- ^ Momentum variables
- -> a -- ^ Number of discretizing steps
- -> c -- ^ Step size
- -> ([c], [c]) -- ^ (End parameters, end momenta)
-leapfrog glTarget t0 r0 ndisc e | ndisc < 0 = (t0, r0)
- | otherwise = go t0 r0 ndisc
- where go t r 0 = (t, r)
- go t r n = let rm = zipWith (+) r (map (* (0.5 * e)) (glTarget t))
- tt = zipWith (+) t (map (* e) rm)
- rt = zipWith (+) rm (map (* (0.5 * e)) (glTarget t))
- in go tt rt (pred n)
-
--- | Acceptance ratio for a proposed move. t0/r0 denote the present state of
--- the parameters and auxilliary variables, and t1/r1 denote the proposed
--- state.
-hmcAcceptanceRatio :: Floating a => (t -> a) -> t -> t -> [a] -> [a] -> a
-hmcAcceptanceRatio lTarget t0 t1 r0 r1 = auxilliaryTarget lTarget t1 r1
- / auxilliaryTarget lTarget t0 r0
-
--- | Augment a log target with some auxilliary variables.
-auxilliaryTarget :: Floating a => (t -> a) -> t -> [a] -> a
-auxilliaryTarget lTarget t r = exp (lTarget t - 0.5 * innerProduct r r)
-
-findReasonableEpsilon :: PrimMonad m
- => ([Double] -> Double)
- -> ([Double] -> [Double])
- -> [Double]
- -> Gen (PrimState m)
- -> m Double
-findReasonableEpsilon lTarget glTarget t0 g = do
- r0 <- replicateM (length t0) (normal 0 1 g)
- let (t1, r1) = leapfrog glTarget t0 r0 1 1.0
-
- a = 2 * indicate (hmcAcceptanceRatio lTarget t0 t1 r0 r1 > 0.5) - 1
-
- go e t r | (hmcAcceptanceRatio lTarget t0 t r0 r) ^ a > 2 ^ (-a) =
- let en = 2 ^ a * e
- (tn, rn) = leapfrog glTarget t r 1 e
- in go en tn rn
- | otherwise = e
-
- return $ go 1.0 t1 r1
-
--- problem
-buildTree :: (Enum a, Eq a, Floating t, Fractional c, Integral c, Integral d
- , Num a, Num e, RealFrac d, RealFrac t, PrimMonad m , Variate c)
- => ([t] -> t)
- -> ([t] -> [t])
- -> Gen (PrimState m)
- -> [t]
- -> [t]
- -> t
- -> t
- -> a
- -> t
- -> t1
- -> [t]
- -> m ([t], [t], [t], [t], [t], c, d, t, e)
-buildTree lTarget glTarget g = go
- where
- go t r u v 0 e _ r0 = return $
- let (t1, r1) = leapfrog glTarget t r 1 (v * e)
- n = indicate (u <= auxilliaryTarget lTarget t1 r1)
- s = indicate (u < exp dMax * auxilliaryTarget lTarget t1 r1)
- m = min 1 (hmcAcceptanceRatio lTarget t1 r1 r0 r0)
- in (t1, r1, t1, r1, t1, n, s, m, 1)
-
- go t r u v j e t0 r0 = do
- z <- uniform g
- (tn, rn, tp, rp, t1, n1, s1, a1, na1) <- go t r u v (pred j) e t0 r0
-
- if s1 == 1
- then do
- (tnn, rnn, tpp, rpp, t2, n2, s2, a2, na2) <-
- if v == -1
- then go tn rn u v (pred j) e t0 r0
- else go tp rp u v (pred j) e t0 r0
-
- let p = n2 / (n1 + n2)
-
- t3 | p > z = t2
- | otherwise = t1
-
- a3 = a1 + a2
- na3 = na1 + na2
-
- s3 = s2 * indicate ((tpp .- tnn) `innerProduct` rnn >= 0)
- * indicate ((tpp .- tnn) `innerProduct` rpp >= 0)
-
- n3 = n1 + n2
- return (tnn, rnn, tpp, rpp, t3, n3, s3, a3, na3)
- else return (tn, rn, tp, rp, t1, n1, s1, a1, na1)
-
-innerNutsKernel :: (PrimMonad m, Variate b)
- => ([a] -> Double)
- -> t
- -> [a]
- -> c
- -> Gen (PrimState m)
- -> m b
-innerNutsKernel lTarget glTarget t e g = do
- r0 <- replicateM (length t) (normal 0 1 g)
- u <- uniformR (0, auxilliaryTarget lTarget t r0) g
-
- let go (tn, tp, rn, rp, j, tm, n, s) a b gen = do
- vj <- symmetricCategorical [-1, 1] gen
- z <- uniform gen
-
- return z
--- let go (tn, tp, rn, rp, j, tm, n, s) aOrig naOrig g
--- | s == 1 = do
--- vj <- symmetricCategorical [-1, 1] g
--- z <- uniform g
---
--- (tnn, rnn, tpp, rpp, t1, n1, s, a, na) <-
--- buildTree lTarget glTarget g tn rn u vj j e t r0 -- FIXME
---
--- return $ (t1, a, na)
-
- go (t, t, r0, r0, 0, t, 1, 1) 0 0 g
-
- -- let go (tn, tp, rn, rp, j, tm, n, s) aOrig naOrig g
- -- | s == 1 = do
- -- vj <- symmetricCategorical [-1, 1] g
- -- z <- uniform g
-
- -- (tnn, rnn, tpp, rpp, t1, n1, s1, a, na) <-
- -- if vj == -1
- -- then buildTree lTarget glTarget g tn rn u vj j e t r0
- -- else buildTree lTarget glTarget g tp rp u vj j e t r0
-
- -- let t2 | s1 == 1 && (min 1 (fromIntegral n1 / fromIntegral n :: Double) > z) = tnn
- -- | otherwise = t
-
- -- n2 = n + n1
- -- s2 = s1 * indicate ((tpp .- tnn) `innerProduct` rnn >= 0)
- -- * indicate ((tpp .- tnn) `innerProduct` rpp >= 0)
- -- j1 = succ j
-
- -- go (tnn, rnn, tpp, rpp, j1, t2, n2, s2) a na g
-
- -- | otherwise = return (tm, aOrig, naOrig)
-
- -- return $ go (t, t, r0, r0, 0, t, 1, 1) 0 0 g
-
-
-
-
-
--- Utilities ------------------------------------------------------------------
-
-innerProduct :: Num a => [a] -> [a] -> a
-innerProduct xs ys = sum $ zipWith (*) xs ys
-
-(.-) :: Num a => [a] -> [a] -> [a]
-xs .- ys = zipWith (-) xs ys
-
-indicate :: Integral a => Bool -> a
-indicate True = 1
-indicate False = 0
-
--- | Round to a specified number of digits.
-roundTo :: RealFrac a => Int -> a -> a
-roundTo n f = fromIntegral (round $ f * (10 ^ n) :: Int) / (10.0 ^^ n)
-
-symmetricCategorical :: PrimMonad m => [a] -> Gen (PrimState m) -> m a
-symmetricCategorical [] _ = error "symmetricCategorical: no candidates"
-symmetricCategorical zs g = do
- z <- uniform g
- return $ zs !! truncate (z * fromIntegral (length zs) :: Double)
-
diff --git a/working/daNUTS.hs b/working/daNUTS.hs
@@ -1,199 +0,0 @@
--- | See Hoffman, Gelman (2011) The No U-Turn Sampler: Adaptively Setting Path
--- Lengths in Hamiltonian Monte Carlo.
-
-import Control.Monad
-import Control.Monad.Primitive
-import System.Random.MWC
-import System.Random.MWC.Distributions
-import Statistics.Distribution.Normal
-
-type Parameters = [Double]
-type Density = Parameters -> Double
-type Gradient = Parameters -> Parameters
-type Particle = (Parameters, Parameters)
-
-leapfrogIntegrator :: Int -> Gradient -> Particle -> Double -> Particle
-leapfrogIntegrator n glTarget particle e = go particle n
- where go state ndisc
- | ndisc <= 0 = state
- | otherwise = go (leapfrog glTarget state e) (pred n)
-
-leapfrog :: Gradient -> Particle -> Double -> Particle
-leapfrog glTarget (t, r) e = (tf, rf)
- where rm = zipWith (+) r ((e / 2) .* glTarget t)
- tf = zipWith (+) t (e .* rm)
- rf = zipWith (+) rm ((e / 2) .* glTarget tf)
-
-findReasonableEpsilon :: PrimMonad m
- => Density
- -> Gradient
- -> Parameters
- -> Gen (PrimState m)
- -> m Double
-findReasonableEpsilon lTarget glTarget t0 g = do
- r0 <- replicateM (length t0) (normal 0 1 g)
- let (t1, r1) = leapfrog glTarget (t0, r0) 1.0
- a = 2 * indicate (acceptanceRatio lTarget t0 t1 r0 r1 > 0.5) - 1
-
- go e t r | (acceptanceRatio lTarget t0 t r0 r) ^ a > 2 ^ (-a) =
- let (tn, rn) = leapfrog glTarget (t, r) e
- in go (2 ^ a * e) tn rn
- | otherwise = e
-
- return $ go 1.0 t1 r1
-
--- this is the dual averaging buildTree
-buildTree
- :: PrimMonad m
- => Density
- -> Gradient
- -> Gen (PrimState m)
- -> Parameters
- -> Parameters
- -> Double
- -> Double
- -> Int
- -> Double
- -> Parameters
- -> Parameters
- -> m ([Double], [Double], [Double], [Double], [Double], Int, Int, Double, Int)
-buildTree lTarget glTarget g = go
- where
- go t r u v 0 e _ r0 = return $
- let (t1, r1) = leapfrog glTarget (t, r) (v * e)
- n = indicate (u <= auxilliaryTarget lTarget t1 r1)
- s = indicate (u < exp 1000 * auxilliaryTarget lTarget t1 r1)
- m = min 1 (acceptanceRatio lTarget t1 r1 r0 r0)
- in (t1, r1, t1, r1, t1, n, s, m, 1)
-
- go t r u v j e t0 r0 = do
- z <- uniform g
- (tn, rn, tp, rp, t1, n1, s1, a1, na1) <- go t r u v (pred j) e t0 r0
-
- if s1 == 1
- then do
- (tnn, rnn, tpp, rpp, t2, n2, s2, a2, na2) <-
- if v == -1
- then go tn rn u v (pred j) e t0 r0
- else go tp rp u v (pred j) e t0 r0
-
- let p = fromIntegral n2 / fromIntegral (n1 + n2)
- n3 = n1 + n2
- t3 | p > (z :: Double) = t2
- | otherwise = t1
- a3 = a1 + a2
- na3 = na1 + na2
- s3 = s2 * indicate ((tpp .- tnn) `innerProduct` rnn >= 0)
- * indicate ((tpp .- tnn) `innerProduct` rpp >= 0)
-
- return (tnn, rnn, tpp, rpp, t3, n3, s3, a3, na3)
- else return (tn, rn, tp, rp, t1, n1, s1, a1, na1)
-
-relaxingNuts = undefined
-
--- better idea: wrap this dual averaging scheme around the actual nuts
--- kernel itself. in fact you'd like to just be able to loosely
--- add dual-averaging to any procedure.
---
--- adaptingNutsKenel lTarget glTarget t m g = do
--- e0 <- findReasonableEpsilon lTarget glTarget t g
---
--- let mu = log (10 * e)
--- epsBar0 = 0
--- h0Bar = 0
--- gamma = 0.05
--- delta = 0.45 -- target mean acceptance probability
--- tau0 = 10
--- kappa = 0.75
---
--- go hBar eNext logEpsBar tToReturn n
--- | n <= 0 = return (tToReturn, logEpsBar,
---
--- | otherwise = do
--- (t0, a, na) <- innerNutsKernel lTarget glTarget t e g
--- let hBarNext = (1 - 1 / (m - n + tau0)) * hBar
--- + (1 / (m - n + tau0)) * (delta - a)
---
--- logEpsNext = mu - ((sqrt (m - n)) / gamma) * hmBar
---
--- logEpsBarNext = (m - n) ^ (-kappa) * logEpsNext
--- + (1 - (m - n) ^ (-kappa)) * logEpsBar
---
--- go hBarNext logEpsBarNext t0 (pred n)
-
-
-
-
-innerNutsKernel
- :: PrimMonad m
- => Density
- -> Gradient
- -> Parameters
- -> Double
- -> Gen (PrimState m)
- -> m (Parameters, Double, Int)
-innerNutsKernel lTarget glTarget t e g = do
- r0 <- replicateM (length t) (normal 0 1 g)
- u <- uniformR (0, auxilliaryTarget lTarget t r0) g
-
- let go (tn, tp, rn, rp, j, tm, n, s) aOrig naOrig g
- | s == 1 = do
- vj <- symmetricCategorical [-1, 1] g
- z <- uniform g
-
- (tnn, rnn, tpp, rpp, t1, n1, s1, a, na) <-
- if vj == -1
- then buildTree lTarget glTarget g tn rn u vj j e t r0
- else buildTree lTarget glTarget g tp rp u vj j e t r0
-
- let t2 | s1 == 1 && min 1 (fi n1 / fi n :: Double) > z = tnn
- | otherwise = t
-
- n2 = n + n1
- s2 = s1 * indicate ((tpp .- tnn) `innerProduct` rnn >= 0)
- * indicate ((tpp .- tnn) `innerProduct` rpp >= 0)
- j1 = succ j
-
- go (tnn, rnn, tpp, rpp, j1, t2, n2, s2) a na g
-
- | otherwise = return (tm, aOrig, naOrig)
-
- go (t, t, r0, r0, 0, t, 1, 1) 0 0 g
-
-auxilliaryTarget :: Floating a => (t -> a) -> t -> [a] -> a
-auxilliaryTarget lTarget t r = exp (lTarget t - 0.5 * innerProduct r r)
-
-acceptanceRatio :: Floating a => (t -> a) -> t -> t -> [a] -> [a] -> a
-acceptanceRatio lTarget t0 t1 r0 r1 = auxilliaryTarget lTarget t1 r1
- / auxilliaryTarget lTarget t0 r0
-
-innerProduct :: Num a => [a] -> [a] -> a
-innerProduct xs ys = sum $ zipWith (*) xs ys
-
-(.*) :: Num b => b -> [b] -> [b]
-z .* xs = map (* z) xs
-
-(.-) :: Num a => [a] -> [a] -> [a]
-xs .- ys = zipWith (-) xs ys
-
-indicate :: Integral a => Bool -> a
-indicate True = 1
-indicate False = 0
-
-symmetricCategorical :: PrimMonad m => [a] -> Gen (PrimState m) -> m a
-symmetricCategorical [] _ = error "symmetricCategorical: no candidates"
-symmetricCategorical zs g = do
- z <- uniform g
- return $ zs !! truncate (z * fromIntegral (length zs) :: Double)
-
-fi :: (Integral a, Num b) => a -> b
-fi = fromIntegral
-
--- Testing
-
-f :: Density
-f _ = log $ 1 / 10
-
-g :: Gradient
-g xs = replicate (length xs) 0
-