packages feed

nlp-scores 0.3.0 → 0.4.0

raw patch · 2 files changed

+35/−30 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- NLP.Scores: accuracy :: (Eq a, Fractional n) => [a] -> [a] -> n
+ NLP.Scores: accuracy :: (Eq a, Fractional c, Foldable t) => t a -> t a -> c
- NLP.Scores: avgPrecision :: (Fractional n, Ord a) => Set a -> [a] -> n
+ NLP.Scores: avgPrecision :: (Fractional n, Ord a, Foldable t) => Set a -> t a -> n
- NLP.Scores: counts :: (Ord a, Ord b) => [(a, b)] -> Counts a b
+ NLP.Scores: counts :: (Ord a, Ord b, Foldable t) => t (a, b) -> Counts a b
- NLP.Scores: entropy :: [Count] -> Double
+ NLP.Scores: entropy :: (Floating c, Foldable t) => t c -> c
- NLP.Scores: mean :: (Fractional n, Real a) => [a] -> n
+ NLP.Scores: mean :: (Foldable t, Fractional n, Real a) => t a -> n
- NLP.Scores: recipRank :: (Eq a, Fractional n) => a -> [a] -> n
+ NLP.Scores: recipRank :: (Eq a, Fractional b, Foldable t) => a -> t a -> b
- NLP.Scores: sum :: Num a => [a] -> a
+ NLP.Scores: sum :: (Foldable t, Num a) => t a -> a

Files

NLP/Scores.hs view
@@ -1,14 +1,18 @@ {-# LANGUAGE BangPatterns #-} -- | Scoring functions commonly used for evaluation of NLP--- systems. Most functions in this module work on lists, but some take--- a precomputed table of 'Counts'. This will give a speedup if you--- want to compute multiple scores on the same data. For example to--- compute the Mutual Information, Variation of Information and the--- Adujusted Rand Index on the same pair of clusterings:+-- systems. Most functions in this module work on sequences which are+-- instances of 'Data.Foldable', but some take a precomputed table of+-- 'Counts'. This will give a speedup if you want to compute multiple+-- scores on the same data. For example to compute the Mutual+-- Information, Variation of Information and the Adjusted Rand Index+-- on the same pair of clusterings: -- -- >>> let cs = counts $ zip "abcabc" "abaaba" -- >>> mapM_ (print . ($ cs)) [mi, ari, vi]---+-- >>> 0.9182958340544894+-- >>> 0.4444444444444445+-- >>> 0.6666666666666663+ module NLP.Scores      (        -- * Scores for classification and ranking@@ -29,30 +33,32 @@     , entropy     ) where+import qualified Data.Foldable as F+import Data.Monoid import Data.List hiding (sum) import qualified Data.Set as Set import qualified Data.Map as Map import Prelude hiding (sum) --- | Accuracy: the proportion of elements in the first list equal to --- elements at corresponding positions in second list. Lists should be--- of equal lengths.-accuracy :: (Eq a, Fractional n) => [a] -> [a] -> n-accuracy xs = mean . map fromEnum . zipWith (==) xs+-- | Accuracy: the proportion of elements in the first sequence equal+-- to elements at corresponding positions in second+-- sequence. Sequences should be of equal lengths.+accuracy :: (Eq a, Fractional c, F.Foldable t) =>  t a -> t a -> c+accuracy xs = mean . map fromEnum . zipWith (==) (F.toList xs) . F.toList {-# SPECIALIZE accuracy :: [Double] -> [Double] -> Double #-}  -- | Reciprocal rank: the reciprocal of the rank at which the first arguments--- occurs in the list given as the second argument.-recipRank :: (Eq a, Fractional n) => a -> [a] -> n+-- occurs in the sequence given as the second argument.+recipRank :: (Eq a, Fractional b, F.Foldable t) => a -> t a -> b recipRank y ys = -    case [ r | (r,y') <- zip [1::Int ..] ys , y' == y ] of+    case [ r | (r,y') <- zip [1::Int ..] . F.toList $ ys , y' == y ] of       []  -> 0       r:_ -> 1/fromIntegral r {-# SPECIALIZE recipRank :: Double -> [Double] -> Double #-}  -- | Average precision.  -- <http://en.wikipedia.org/wiki/Information_retrieval#Average_precision>-avgPrecision :: (Fractional n, Ord a) => Set.Set a -> [a] -> n+avgPrecision :: (Fractional n, Ord a, F.Foldable t) => Set.Set a -> t a -> n avgPrecision gold _ | Set.size gold == 0 = 0 avgPrecision gold xs =       (/fromIntegral (Set.size gold))@@ -63,7 +69,8 @@     . takeWhile (\(_,_,cum) -> cum <= Set.size gold)      . snd      . mapAccumL (\z (r,rel) -> (z+rel,(r,rel,z+rel))) 0-    $ [ (r,fromEnum $ x `Set.member` gold) | (x,r) <- zip xs [1::Int ..]]+    $ [ (r,fromEnum $ x `Set.member` gold) +      | (x,r) <- zip (F.toList xs) [1::Int ..]] {-# SPECIALIZE avgPrecision :: (Ord a) => Set.Set a -> [a] -> Double #-}  -- | Mutual information: MI(X,Y) = H(X) - H(X|Y) = H(Y) - H(Y|X). Also@@ -96,7 +103,7 @@ -- | Count table data Counts a b =    Counts -  { joint :: !(Map.Map (P a b) Count)   -- ^ Counts of both components+  { joint :: !(Map.Map (P a b) Count) -- ^ Counts of both components   , marginalFst :: !(Map.Map a Count) -- ^ Counts of the first component   , marginalSnd :: !(Map.Map b Count) -- ^ Counts of the second component   }@@ -106,18 +113,17 @@ empty :: (Ord a, Ord b) => Counts a b empty = Counts Map.empty Map.empty Map.empty --- | The sum of a list of numbers (without overflowing stack, --- unlike 'Prelude.sum').-sum :: (Num a) => [a] -> a-sum = foldl' (+) 0+-- | The sum of a sequence of numbers+sum :: (F.Foldable t, Num a) => t a -> a+sum = F.foldl' (+) 0 {-# SPECIALIZE sum :: [Double] -> Double #-} {-# SPECIALIZE sum :: [Int] -> Int #-} {-# INLINE sum #-} --- | The mean of a list of numbers.-mean :: (Fractional n, Real a) => [a] -> n+-- | The mean of a sequence of numbers.+mean :: (F.Foldable t, Fractional n, Real a) => t a -> n mean xs = -    let (P tot len) = foldl' (\(P s l) x -> (P (s+x) (l+1))) (P 0 0) xs+    let (P tot len) = F.foldl' (\(P s l) x -> (P (s+x) (l+1))) (P 0 0) xs     in realToFrac tot/len {-# SPECIALIZE mean :: [Double] -> Double #-} @@ -136,17 +142,16 @@ {-# SPECIALIZE jaccard :: (Ord a) => Set.Set a -> Set.Set a -> Double #-}    -- | Entropy: H(X) = -SUM_i P(X=i) log_2(P(X=i))-entropy :: [Count] -> Double-entropy cx = negate $ sum [ f nx | nx <- cx ]+entropy :: (Floating c, F.Foldable t) => t c -> c+entropy cx = negate . getSum . F.foldMap  (Sum . f)  $ cx     where n    = sum cx           logn = logBase 2 n           f nx = nx / n * (logBase 2 nx - logn)  -- | Creates count table 'Counts'-counts :: (Ord a, Ord b) => [(a,b)] -> Counts a b-counts xys = foldl' f empty xys+counts :: (Ord a, Ord b, F.Foldable t) => t (a, b) -> Counts a b+counts xys = F.foldl' f empty xys     where f cs@(Counts cxy cx cy) (!x,!y) =              cs { joint       = Map.insertWith' (+) (P x y) 1 cxy                , marginalFst = Map.insertWith' (+) x 1 cx                , marginalSnd = Map.insertWith' (+) y 1 cy }-            
nlp-scores.cabal view
@@ -7,7 +7,7 @@ -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented.-Version:             0.3.0+Version:             0.4.0  -- A short (one-line) description of the package. Synopsis:            Scoring functions commonly used for evaluation in NLP and IR