packages feed

crf-chain2-tiers 0.3.0 → 0.4.0

raw patch · 9 files changed

+118/−53 lines, 9 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.CRF.Chain2.Tiers.DAG: tag :: (Ord a, Ord b) => CRF a b -> Sent a b -> DAG () (Maybe [b])
+ Data.CRF.Chain2.Tiers.DAG.Inference: fastTag :: Model -> DAG a X -> DAG a (Maybe CbIx)
+ Data.CRF.Chain2.Tiers.DAG.Inference: fastTag' :: Model -> DAG a X -> DAG a (Maybe Cb)

Files

crf-chain2-tiers.cabal view
@@ -1,5 +1,5 @@ name:               crf-chain2-tiers-version:            0.3.0+version:            0.4.0 synopsis:           Second-order, tiered, constrained, linear conditional random fields description:     The library provides implementation of the second-order, linear
src/Data/CRF/Chain2/Tiers/Core.hs view
@@ -54,12 +54,12 @@ import           Data.Ix (Ix) import           Data.Int (Int16, Int32) import           Data.List (zip4)-import qualified Data.Array.Unboxed as A+-- import qualified Data.Array.Unboxed as A import qualified Data.Vector as V import qualified Data.Vector.Unboxed as U import           Data.Vector.Unboxed.Deriving-import qualified Data.Vector.Generic.Base as G-import qualified Data.Vector.Generic.Mutable as G+-- import qualified Data.Vector.Generic.Base as G+-- import qualified Data.Vector.Generic.Mutable as G import qualified Data.Number.LogFloat as L -- import qualified Data.Primitive.ByteArray as BA 
src/Data/CRF/Chain2/Tiers/DAG.hs view
@@ -15,7 +15,7 @@ -- , reTrain  -- * Tagging--- , tag+, tag , marginals , I.ProbType (..) , probs@@ -30,6 +30,7 @@ ) where  +import           Prelude hiding (Word) import           Control.Applicative ((<$>), (<*>)) import           Control.Monad (when) @@ -57,7 +58,7 @@ import qualified Data.CRF.Chain2.Tiers.DAG.Dataset.Codec as Codec import           Data.CRF.Chain2.Tiers.DAG.Dataset.Codec (Codec) import qualified Data.CRF.Chain2.Tiers.DAG.Feature as Feat-import           Data.CRF.Chain2.Tiers.DAG.Feature (Feat, FeatSel)+import           Data.CRF.Chain2.Tiers.DAG.Feature (Feat) import qualified Data.CRF.Chain2.Tiers.DAG.Inference as I import qualified Data.CRF.Chain2.Tiers.DAG.Probs as P @@ -204,8 +205,8 @@ --       report $ U.map (*0.1) para   where -    report para = do-      let crf = model {Model.values = para}+    report _para = do+      let crf = model {Model.values = _para}       llh <- show         . LogFloat.logFromLogFloat         . P.parLikelihood crf@@ -215,8 +216,8 @@         then show . I.accuracy crf <$> SGD.loadData evalData         else return "#"       putStrLn $ "[" ++ show (doneTotal k) ++ "] stats:"-      putStrLn $ "min(params) = " ++ show (U.minimum para)-      putStrLn $ "max(params) = " ++ show (U.maximum para)+      putStrLn $ "min(params) = " ++ show (U.minimum _para)+      putStrLn $ "max(params) = " ++ show (U.maximum _para)       putStrLn $ "log(likelihood(train)) = " ++ llh       putStrLn $ "acc(eval) = " ++ acc @@ -281,16 +282,17 @@ ----------------------------------------------------  --- -- | Find the most probable label sequence.--- tag :: (Ord a, Ord b) => CRF a b -> Sent a b -> [[b]]--- tag CRF{..} sent---     = onWords . decodeLabels codec---     . I.tag model . encodeSent codec---     $ sent---   where---     onWords xs =---         [ unJust codec word x---         | (word, x) <- zip sent xs ]+-- | Find the most probable labeled path.+tag :: (Ord a, Ord b) => CRF a b -> Sent a b -> DAG () (Maybe [b])+tag CRF{..} sent+  = fmap decodeChosen+  . DAG.zipE sent+  . I.fastTag' model+  . Codec.encodeSent codec+  $ sent+  where+    decodeChosen (word, chosen) = decode word <$> chosen+    decode word = Codec.unJust codec word . Codec.decodeLabel codec   -- | Tag labels with marginal probabilities.
src/Data/CRF/Chain2/Tiers/DAG/Dataset/External.hs view
@@ -6,7 +6,7 @@   import Prelude hiding (Word)-import qualified Data.DAG as DAG+-- import qualified Data.DAG as DAG import           Data.DAG (DAG)  import           Data.CRF.Chain2.Tiers.Dataset.External hiding (Sent, SentL)
src/Data/CRF/Chain2/Tiers/DAG/Inference.hs view
@@ -6,6 +6,8 @@ ( tag , tag' , tagK+, fastTag+, fastTag' , marginals , marginals' , ProbType (..)@@ -35,9 +37,10 @@ import qualified Control.Parallel.Strategies as Par  import qualified Data.Number.LogFloat as L-import qualified Data.Vector as V-import qualified Data.Array as A+-- import qualified Data.Vector as V+-- import qualified Data.Array as A import qualified Data.Set as S+import qualified Data.Map.Strict as M import           Data.Maybe (fromJust) import qualified Data.MemoCombinators as Memo import qualified Data.List as List@@ -106,9 +109,9 @@   table (f Beg) (memo (f . Mid)) (f End)   where     memo = memoEdgeIx dag-    table b m e Beg = b-    table b m e (Mid x) = m x-    table b m e End = e+    table b _ _ Beg = b+    table _ m _ (Mid x) = m x+    table _ _ e End = e   memoEdgeIx :: DAG a b -> Memo.Memo EdgeIx@@ -153,6 +156,66 @@   ---------------------------------------------+-- NEW STUFF+---------------------------------------------+++-- | A version of `tag` which should be, roughly, twice as efficient, since it+-- only performs one `forward` and no `backward` computation.  The downside is+-- that probabilities cannot be retrieved.+fastTag :: Md.Model -> DAG a X -> DAG a (Maybe CbIx)+fastTag crf dag =+  DAG.mapE label dag+  where+    label edgeID _ = M.lookup edgeID selSet+    alpha = forward maximum crf dag+    selSet = rewind dag alpha+++-- | Similar to `fastTag` but directly returns complex labels and not just+-- their `CbIx` indexes.+fastTag' :: Md.Model -> DAG a X -> DAG a (Maybe Cb)+fastTag' crf dag+  = fmap (\(x, mayIx) -> C.lbAt x <$> mayIx)+  $ DAG.zipE dag (fastTag crf dag)+++rewind+  :: DAG a X   -- ^ The input DAG+  -> ProbArray -- ^ The forward probability table (pre-calculated with `max`)+  -> M.Map EdgeID CbIx -- ^ The optimal `EdgeIx`s+rewind dag alpha =++  best M.empty End++  where++    best m u = pick m $ argmax Beg [(w, alpha u w) | w <- prev u]++    prev End = Mid <$> Ft.finalEdgeIxs dag+    prev (Mid u) = complicate Beg <$> Ft.prevEdgeIxs dag (Just $ edgeID u)+    prev _ = error "DAG.Inference.rewind: impossible 1 happened"++    pick m (Mid u) = best (M.insert (edgeID u) (lbIx u) m) (Mid u)+    pick m Beg = m+    pick _ _ = error "DAG.Inference.rewind: impossible 2 happened"+++-- | Return the key with the highest corresponding value, with a default value+-- for the empty list.+argmax :: Ord v => k -> [(k, v)] -> k+argmax _def (x:xs) =+  go (fst x) (snd x) xs+  where+    go k v ((k', v') : rest)+      | v >= v' = go k v rest+      | otherwise = go k' v' rest+    go k _ [] = k+argmax def [] = def+{-# INLINE argmax #-}+++--------------------------------------------- -- A bit more complex stuff --------------------------------------------- @@ -513,7 +576,7 @@ accuracy :: Md.Model -> [DAG a (X, Y)] -> Double accuracy crf dataset =     let k = numCapabilities-    	parts = partition k dataset+        parts = partition k dataset         xs = Par.parMap Par.rseq (goodAndBad' crf) parts         (good, bad) = F.foldl' add (0, 0) xs         add (g, b) (g', b') = (g + g', b + b')
src/Data/CRF/Chain2/Tiers/DAG/Probs.hs view
@@ -13,19 +13,19 @@  import           Control.Applicative ((<$>)) import qualified Control.Arrow as Arr-import qualified Control.Parallel as Par+-- import qualified Control.Parallel as Par import qualified Control.Parallel.Strategies as Par  import qualified Data.Number.LogFloat as L import qualified Data.Vector as V-import qualified Data.Vector.Unboxed as U-import qualified Data.Array as A-import qualified Data.Set as S-import           Data.Maybe (fromJust, maybeToList)-import qualified Data.MemoCombinators as Memo-import qualified Data.List as List-import           Data.Function (on)-import qualified Data.Foldable as F+-- import qualified Data.Vector.Unboxed as U+-- import qualified Data.Array as A+-- import qualified Data.Set as S+import           Data.Maybe (maybeToList)+-- import qualified Data.MemoCombinators as Memo+-- import qualified Data.List as List+-- import           Data.Function (on)+-- import qualified Data.Foldable as F  import           Data.DAG (EdgeID, DAG) import qualified Data.DAG as DAG@@ -35,13 +35,13 @@ import qualified Data.CRF.Chain2.Tiers.Model as Md import           Data.CRF.Chain2.Tiers.Util (partition) import           Data.CRF.Chain2.Tiers.DAG.Feature (EdgeIx(..))-import qualified Data.CRF.Chain2.Tiers.DAG.Feature as Ft+-- import qualified Data.CRF.Chain2.Tiers.DAG.Feature as Ft  import           Data.CRF.Chain2.Tiers.DAG.Inference                  (AccF, Pos(..), simplify, complicate, ProbArray) import qualified Data.CRF.Chain2.Tiers.DAG.Inference as I -import Debug.Trace (trace)+-- import Debug.Trace (trace)   --------------------------------------------
src/Data/CRF/Chain2/Tiers/Dataset/Codec.hs view
@@ -155,8 +155,8 @@     r' <- mapM encodeLbU (S.toList (lbs word))     let x = mkX x' r'     y  <- mkY <$> sequence-    	[ (,) <$> encodeLbU lb <*> pure pr-	| (lb, pr) <- (M.toList . unProb) choice ]+        [ (,) <$> encodeLbU lb <*> pure pr+        | (lb, pr) <- (M.toList . unProb) choice ]     return (x, y)  -- | Encodec the labeled word and do *not* update the codec.@@ -166,8 +166,8 @@     r' <- mapM encodeLbN (S.toList (lbs word))     let x = mkX x' r'     y  <- mkY <$> sequence-    	[ (,) <$> encodeLbN lb <*> pure pr-	| (lb, pr) <- (M.toList . unProb) choice ]+        [ (,) <$> encodeLbN lb <*> pure pr+        | (lb, pr) <- (M.toList . unProb) choice ]     return (x, y)  -- | Encode the word and update the codec.
src/Data/CRF/Chain2/Tiers/Feature.hs view
@@ -22,9 +22,9 @@ ) where  -import           Control.Applicative ((<*>), (<$>))+-- import           Control.Applicative ((<*>), (<$>)) import           Data.Maybe (maybeToList)-import           Data.Binary (Binary, put, get)+-- import           Data.Binary (Binary, put, get) import qualified Data.Vector as V import qualified Data.Number.LogFloat as L 
src/Data/CRF/Chain2/Tiers/Inference.hs view
@@ -72,10 +72,10 @@                 (\i   -> (0, lbNum sent i - 1))                 (\i _ -> (0, lbNum sent (i - 1) - 1))                 (\t i -> withMem (computePsi crf sent i) t i)-    withMem psi alpha i j k+    withMem psi _alpha i j k         | i == -1 = 1.0         | otherwise = acc-            [ alpha (i - 1) k h * psi j+            [ _alpha (i - 1) k h * psi j             * onTransition crf sent i j k h             | h <- lbIxs sent (i - 2) ] @@ -85,10 +85,10 @@                (\i   -> (0, lbNum sent (i - 1) - 1))                (\i _ -> (0, lbNum sent (i - 2) - 1))                (\t i -> withMem (computePsi crf sent i) t i)-    withMem psi beta i j k+    withMem psi _beta i j k         | i == V.length sent = 1.0         | otherwise = acc-            [ beta (i + 1) h j * psi h+            [ _beta (i + 1) h j * psi h             * onTransition crf sent i h j k             | h <- lbIxs sent i ] @@ -124,17 +124,17 @@                        (\i   -> (0, lbNum sent (i - 1) - 1))                        (\i _ -> (0, lbNum sent (i - 2) - 1))                        (\t i -> withMem (computePsi crf sent i) t i)-    withMem psiMem mem i j k+    withMem psiMem _mem i j k         | i == V.length sent = (-1, 1)         | otherwise = argmax eval $ lbIxs sent i         where eval h =-                  (snd $ mem (i + 1) h j) * psiMem h+                  (snd $ _mem (i + 1) h j) * psiMem h                   * onTransition crf sent i h j k-    collectMaxArg (i, j, k) acc mem =-        collect $ mem i j k+    collectMaxArg (i, j, k) acc _mem =+        collect $ _mem i j k         where collect (h, _)                   | h == -1 = reverse acc-                  | otherwise = collectMaxArg (i + 1, h, j) (h:acc) mem+                  | otherwise = collectMaxArg (i + 1, h, j) (h:acc) _mem  -- | Find the most probable label sequence satisfying the constraints -- imposed over label values.