packages feed

hmm 0.1 → 0.1.1

raw patch · 3 files changed

+26/−97 lines, 3 filesdep +logfloatPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: logfloat

API changes (from Hackage documentation)

+ Data.HMM: instance (Show state, Show observation) => Show (HMM state observation)
- Data.HMM: bestSequence :: (Ord observation) => HMM state observation -> [observation] -> [state]
+ Data.HMM: bestSequence :: Ord observation => HMM state observation -> [observation] -> [state]
- Data.HMM: sequenceProb :: (Ord observation) => HMM state observation -> [observation] -> Prob
+ Data.HMM: sequenceProb :: Ord observation => HMM state observation -> [observation] -> Prob
- Data.HMM: type Prob = Lognum Double
+ Data.HMM: type Prob = LogFloat

Files

Data/HMM.hs view
@@ -1,33 +1,37 @@+{-# LANGUAGE ParallelListComp #-}+ module Data.HMM     (Prob, HMM, train, bestSequence, sequenceProb)     where  import qualified Data.Map as M-import Data.List (sort, groupBy, maximumBy)+import Data.List (sort, groupBy, maximumBy, foldl') import Data.Maybe (fromMaybe, fromJust)-import System.IO.Unsafe (unsafeInterleaveIO)-import System.Environment (getArgs)+import Data.Ord (comparing)+import Data.Function (on) import Control.Monad-import qualified Data.Foldable-import Debug.Trace-import Data.Lognum+import Data.Number.LogFloat -type Prob = Lognum Double+type Prob = LogFloat  -- | The type of Hidden Markov Models. data HMM state observation = HMM [state] [Prob] [[Prob]] (observation -> [Prob]) +instance (Show state, Show observation) => Show (HMM state observation) where+    show (HMM states probs tpm _) = "HMM " ++ show states ++ " "+                                           ++ show probs ++ " " ++ show tpm ++ " <func>"+ -- | Perform a single step in the Viterbi algorithm. --   --   Takes a list of path probabilities, and an observation, and returns the updated --   list of (surviving) paths with probabilities.-viterbi :: Ord observation =>-               HMM state observation+viterbi ::     HMM state observation             -> [(Prob, [state])]             -> observation             -> [(Prob, [state])]-viterbi (HMM states _ state_transitions observations) prev x = -    [maximumBy (compare `on` fst)+viterbi (HMM states _ state_transitions observations) prev x =+    deepSeq prev `seq`+    [maximumBy (comparing fst)             [(transition_prob * prev_prob * observation_prob,                new_state:path)                     | transition_prob <- transition_probs@@ -37,6 +41,9 @@         | new_state <- states]     where         observation_probs = observations x+        deepSeq ((x, y:ys):xs) = x `seq` y `seq` (deepSeq xs)+        deepSeq ((x, _):xs) = x `seq` (deepSeq xs)+        deepSeq [] = []  -- | The initial value for the Viterbi algorithm viterbi_init :: HMM state observation -> [(Prob, [state])]@@ -46,12 +53,12 @@ --  --   Each item in the input and output list is the probability that the system --   ended in the respective state.-forward :: Ord observation =>-               HMM state observation+forward ::     HMM state observation             -> [Prob]             -> observation             -> [Prob] forward (HMM _ _ state_transitions observations) prev x =+    last prev `seq`     [sum [transition_prob * prev_prob * observation_prob                 | transition_prob <- transition_probs                 | prev_prob <- prev@@ -79,17 +86,9 @@                             . histogram  histogram :: (Ord a, Fractional prob) => [a] -> M.Map a prob-histogram xs = let hist = foldr (flip (M.insertWith (+)) 1) M.empty xs in+histogram xs = let hist = foldl' (flip $ flip (M.insertWith (+)) 1) M.empty xs in                 M.map (/ M.fold (+) 0 hist) hist -readBrownFile :: FilePath -> IO [(String, String)]-readBrownFile = (liftM (map split . words)) . readFile-    where-        split [] = ([], [])-        split ('/':xs) = ([], xs)-        split (x:xs) = let (first, snd) = split xs in-                        (x:first, snd)- -- | Calculate the parameters of an HMM from a list of observations --   and the corresponding states. train :: (Ord observation, Ord state) =>@@ -124,29 +123,12 @@                                            else                                             p : fill states xs' --- | Test Viterbi's algorithm on an HMM by comparing the predicted states---   against known states for the observations.-testViterbi :: (Ord observation, Ord state) =>-                   HMM state observation-                -> [(observation, state)]-                -> Rational-testViterbi hmm testData = (fromIntegral $ length $ filter id $ zipWith (==) (bestSequence hmm observations) states) -                            / (fromIntegral $ length testData)-    where-        observations = map fst testData-        states = map snd testData--train2 :: FilePath -> IO (HMM String String)-train2 = (liftM train) . readBrownFile- -- | Calculate the most likely sequence of states for a given sequence of observations --   using Viterbi's algorithm bestSequence :: (Ord observation) => HMM state observation -> [observation] -> [state]-bestSequence hmm = (reverse . tail . snd . (maximumBy (compare `on` fst))) . (foldl (viterbi hmm) (viterbi_init hmm))+bestSequence hmm = (reverse . tail . snd . (maximumBy (comparing fst))) . (foldl' (viterbi hmm) (viterbi_init hmm))  -- | Calculate the probability of a given sequence of observations --    using the forward algorithm. sequenceProb :: (Ord observation) => HMM state observation -> [observation] -> Prob-sequenceProb hmm = sum . (foldl (forward hmm) (forward_init hmm))--on f g a b = f (g a) (g b)+sequenceProb hmm = sum . (foldl' (forward hmm) (forward_init hmm))
− Data/Lognum.hs
@@ -1,50 +0,0 @@-module Data.Lognum (Lognum)-    where--import Data.Ratio--data Lognum t = L !Int !t deriving (Eq, Ord)--fromFloating :: (Floating t, Ord t) => t -> Lognum t-fromFloating a = case a `compare` 0 of-                LT -> L (-1) (log $ -a)-                EQ -> L 0 0-                GT -> L 1 (log a)--toFloating :: (Floating t, Ord t) => Lognum t -> t-toFloating (L s m) = case s of-                        -1 -> negate $ exp m-                        0  -> 0-                        1  -> exp m--logify2 :: (Floating t, Ord t) => (t -> t -> t) -> (Lognum t -> Lognum t -> Lognum t)-logify2 (*) a b = fromFloating $ toFloating a * toFloating b--instance (Floating t, Ord t) => Show (Lognum t) where-    show = show . toFloating--instance (Floating t, Ord t) => Num (Lognum t) where-    (+) = logify2 (+)--    (L s m) * (L s' m') =   if s == 0 || s' == 0 then-                                L 0 0-                            else-                                L (s*s') (m+m')--    (-) = logify2 (-)--    negate (L s m) = L (negate s) m--    abs (L s m) = L (abs s) m--    signum (L s m) = (L s 0)--    fromInteger = fromFloating . fromInteger--instance (Floating t, Ord t) => Fractional (Lognum t) where-    _ / (L 0 _) = error "division by zero"-    (L s m) / (L s' m') = L (s*s') (m-m')-    -    recip (L s m) = L s (-m)-    -    fromRational x = (fromInteger $ numerator x) / (fromInteger $ denominator x)
hmm.cabal view
@@ -1,5 +1,5 @@ Name:               hmm-Version:            0.1+Version:            0.1.1 Description:     A simple library for working with Hidden Markov Models.     Should be usable even by people who are not familiar with@@ -20,15 +20,12 @@  Library     if flag(small_base)-        Build-Depends:  base >= 3, containers+        Build-Depends:  base >= 3, containers, logfloat     else-        Build-Depends:  base < 3+        Build-Depends:  base < 3, logfloat              Exposed-Modules:         Data.HMM--    Other-Modules:-        Data.Lognum      Extensions:         ParallelListComp