packages feed

goal-probability-0.1: scripts/cross-entropy-descent.hs

{-# LANGUAGE TypeOperators, TypeFamilies, FlexibleContexts #-}

--- Imports ---


-- Goal --

import Goal.Core
import Goal.Geometry
import Goal.Probability


--- Globals ---

nsmps = 20

-- True Normal --

sp = chart Standard $ fromList Normal [1.5,2]

-- Gradient Ascent --

eps = 0.01
stps = 3000
sp0 = chart Standard $ fromList Normal [0,1]

-- Plot --

mnmu = 0
mxmu = 3
mnvr = 1
mxvr = 4

axprms = LinearAxisParams (show . round) 4 4

m1rng = (mnmu,mxmu,600)
m2rng = (mnvr,mxvr,600)
niso = 20
clrs = rgbaGradient (0,0,0,1) (1,0,0,1) niso

-- Functions --

logLikelihood p xs = sum $ log . density p <$> xs

naturalDerivatives :: [Double] -> Natural :#: Normal -> Differentials :#: Tangent Natural Normal
naturalDerivatives xs p = fromCoordinates (Tangent p) . coordinates
    $ meanPoint (sufficientStatistic Normal <$> xs) <-> potentialMapping p

standardDerivatives :: [Double] -> Standard :#: Normal -> Differentials :#: Tangent Standard Normal
standardDerivatives xs p =
    let [mu,vr] = listCoordinates p
     in meanPoint [ fromList (Tangent p) [ recip vr * (xi - mu), recip (2*vr) * (recip vr * (xi - mu)^2 - 1) ] | xi <- xs ]

-- Layout --

main = do

    smps <- runWithSystemRandom . replicateM nsmps $ generate sp

    let mp' = chart Mixture . meanPoint $ sufficientStatistic Normal <$> smps
        sp' = chart Standard $ transition mp'

    let vsps1 = take stps $ vanillaGradientAscent eps (standardDerivatives smps) sp0
        nsps1 = take stps $ gradientAscent eps (standardDerivatives smps) sp0

    let np0 = chart Natural $ transition sp0
        vnps2 = take stps $ vanillaGradientAscent eps (naturalDerivatives smps) np0
        --nnps2 = take stps $ gradientAscent eps (naturalDerivatives smps) np0
        vsps2 = chart Standard . transition <$> vnps2
        --nsps2 = chart Standard . transition <$> nnps2

    let rnbl = toRenderable . execEC $ do

            let f x y = logLikelihood (chart Standard $ fromList Normal [x,y]) smps
                cntrs = contours m1rng m2rng niso f

            layout_x_axis . laxis_generate .= scaledAxis axprms (mnmu,mxmu)
            layout_x_axis . laxis_override .= axisGridHide
            layout_x_axis . laxis_title .= "μ"
            layout_y_axis . laxis_generate .= scaledAxis axprms (mnvr,mxvr)
            layout_y_axis . laxis_override .= axisGridHide
            layout_y_axis . laxis_title .= "σ^2"

            sequence_ $ do

                ((_,cntr),clr) <- zip cntrs clrs

                return . plot . liftEC $ do

                    plot_lines_style .= solidLine 3 clr
                    plot_lines_values .= cntr

            plot . liftEC $ do
                plot_lines_style .= solidLine 3 (opaque blue)
                plot_lines_values .= [toPair <$> vsps2]

            plot . liftEC $ do
                plot_lines_style .= solidLine 3 (opaque green)
                plot_lines_values .= [toPair <$> vsps1]

            plot . liftEC $ do
                plot_lines_style .= solidLine 3 (opaque purple)
                plot_lines_values .= [toPair <$> nsps1]

            plot . liftEC $ do
                plot_points_style .= filledCircles 4 (opaque black)
                plot_points_values .= [toPair sp]

            plot . liftEC $ do
                plot_points_style .= filledCircles 4 (opaque red)
                plot_points_values .= [toPair sp']

    --renderableToAspectWindow False 800 600 . toRenderable $ lyt
    void $ renderableToFile (FileOptions (500,350) PDF) "cross-entropy-descent.pdf" rnbl