hmm-lapack-0.4.1: private/Math/HiddenMarkovModel/Example/SineWavePrivate.hs
module Math.HiddenMarkovModel.Example.SineWavePrivate where
import qualified Math.HiddenMarkovModel.Public as HMM
import qualified Math.HiddenMarkovModel.Public.Distribution as Distr
import Math.HiddenMarkovModel.Utility (normalizeProb, squareFromLists)
import qualified Numeric.LAPACK.Matrix.Hermitian as Hermitian
import qualified Numeric.LAPACK.Matrix.Layout as Layout
import qualified Numeric.LAPACK.Vector as Vector
import Numeric.LAPACK.Vector (Vector, singleton)
import qualified Data.Array.Comfort.Boxed as Array
import qualified Data.Array.Comfort.Shape as Shape
import qualified Data.NonEmpty.Class as NonEmptyC
import qualified Data.NonEmpty as NonEmpty
import Data.Function.HT (nest)
import Data.Tuple.HT (mapSnd)
{- $setup
>>> import qualified Data.NonEmpty as NonEmpty
-}
data State = Rising | High | Falling | Low
deriving (Eq, Ord, Enum, Bounded, Show)
type StateSet = Shape.Enumeration State
stateSet :: StateSet
stateSet = Shape.Enumeration
type HMM = HMM.Gaussian () StateSet Double
hmm :: HMM
hmm =
HMM.Cons {
HMM.initial = normalizeProb $ Vector.one stateSet,
HMM.transition =
squareFromLists stateSet $
stateVector 0.9 0.0 0.0 0.1 :
stateVector 0.1 0.9 0.0 0.0 :
stateVector 0.0 0.1 0.9 0.0 :
stateVector 0.0 0.0 0.1 0.9 :
[],
HMM.distribution =
Distr.gaussian $ Array.fromList stateSet $
(singleton 0 , Hermitian.identity Layout.RowMajor ()) :
(singleton 1 , Hermitian.identity Layout.RowMajor ()) :
(singleton 0 , Hermitian.identity Layout.RowMajor ()) :
(singleton (-1), Hermitian.identity Layout.RowMajor ()) :
[]
}
stateVector :: Double -> Double -> Double -> Double -> Vector StateSet Double
stateVector x0 x1 x2 x3 = Vector.fromList stateSet [x0,x1,x2,x3]
{- |
>>> take 20 $ map fst $ NonEmpty.flatten sineWaveLabeled
[Rising,Rising,High,High,High,Falling,Falling,Falling,Low,Low,Low,Rising,Rising,Rising,Rising,High,High,High,Falling,Falling]
-}
sineWaveLabeled :: NonEmpty.T [] (State, Double)
sineWaveLabeled =
NonEmpty.mapTail (take 200) $
fmap (\x -> (toEnum $ mod (floor (x*2/pi+0.5)) 4, sin x)) $
NonEmptyC.iterate (0.5+) 0
sineWave :: NonEmpty.T [] Double
sineWave = fmap snd sineWaveLabeled
{- |
>>> take 20 $ NonEmpty.flatten revealed
[Rising,Rising,High,High,High,Falling,Falling,Falling,Low,Low,Low,Low,Rising,Rising,Rising,High,High,High,Falling,Falling]
-}
revealed :: NonEmpty.T [] State
revealed = HMM.reveal hmmTrainedSupervised $ fmap singleton sineWave
hmmTrainedSupervised :: HMM
hmmTrainedSupervised =
HMM.finishTraining $ HMM.trainSupervised stateSet $
fmap (mapSnd singleton) sineWaveLabeled
hmmTrainedUnsupervised :: HMM
hmmTrainedUnsupervised =
HMM.finishTraining $ HMM.trainUnsupervised hmm $ fmap singleton sineWave
hmmIterativelyTrained :: HMM
hmmIterativelyTrained =
nest 100
(\model ->
HMM.finishTraining $ HMM.trainUnsupervised model $
fmap singleton sineWave)
hmm