packages feed

chatter 0.2.0.0 → 0.2.0.1

raw patch · 10 files changed

+167/−20 lines, 10 filesPVP: minor bump suggested

API additions: PVP suggests at least a minor version bump

API changes (from Hackage documentation)

+ NLP.Extraction.Examples.ParsecExamples: chunk :: [(Text, Tag)] -> Tag -> (Text, Tag)
+ NLP.Extraction.Examples.ParsecExamples: clause :: Extractor (Text, Tag)
+ NLP.Extraction.Examples.ParsecExamples: nounPhrase :: Extractor (Text, Tag)
+ NLP.Extraction.Examples.ParsecExamples: prepPhrase :: Extractor (Text, Tag)
+ NLP.Extraction.Examples.ParsecExamples: verbPhrase :: Extractor (Text, Tag)

Files

chatter.cabal view
@@ -1,5 +1,5 @@ name:                chatter-version:             0.2.0.0+version:             0.2.0.1 synopsis:            A library of simple NLP algorithms. description:         chatter is a collection of simple Natural Language                      Processing algorithms.@@ -48,6 +48,7 @@                      NLP.Corpora.Email                      NLP.Similarity.VectorSim                      NLP.Extraction.Parsec+                     NLP.Extraction.Examples.ParsecExamples                      Data.DefaultMap     Build-depends:    base >= 4 && <= 6,@@ -160,6 +161,7 @@                      Data.DefaultMapTests                      Corpora                      TestUtils+                     IntegrationTests     Build-depends:    chatter,                      base       >= 4 && <= 6,
data/models/brown-train.model.gz view

file too large to diff

+ src/NLP/Extraction/Examples/ParsecExamples.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE OverloadedStrings    #-}+module NLP.Extraction.Examples.ParsecExamples where++import qualified Data.Text as T+import Data.Text (Text)++import Text.Parsec.Prim (parse, (<|>), try)+import Text.Parsec.Pos+import qualified Text.Parsec.Combinator as PC++import NLP.Types+import NLP.Extraction.Parsec++-- grammar = r"""+--   NP: {<DT|JJ|NN.*>+}          # Chunk sequences of DT, JJ, NN+--   PP: {<IN><NP>}               # Chunk prepositions followed by NP+--   VP: {<VB.*><NP|PP|CLAUSE>+$} # Chunk verbs and their arguments+--   CLAUSE: {<NP><VP>}           # Chunk NP, VP+--   """+-- cp = nltk.RegexpParser(grammar)+-- sentence = [("Mary", "NN"), ("saw", "VBD"), ("the", "DT"), ("cat", "NN"),+--     ("sit", "VB"), ("on", "IN"), ("the", "DT"), ("mat", "NN")]+++-- | Create a chunked tag from a set of incomming tagged tokens.+chunk :: [(Text, Tag)] -- ^ The incomming tokens to create a chunk from.+      -> Tag           -- ^ The tag for the chunk.+      -> (Text, Tag)+chunk tss tg = (T.unwords (map fst tss), tg)++prepPhrase :: Extractor (Text, Tag)+prepPhrase = do+  prep <- posTok $ Tag "IN"+  np <- nounPhrase+  return $ chunk [prep, np] (Tag "p-phr")++nounPhrase :: Extractor (Text, Tag)+nounPhrase = do+  nlist <- PC.many1 (try (posTok $ Tag "NN")+              <|> try (posTok $ Tag "DT")+                  <|> (posTok $ Tag "JJ"))+  let term = T.intercalate " " (map fst nlist)+  return (term, Tag "n-phr")++clause :: Extractor (Text, Tag)+clause = do+  np <- nounPhrase+  vp <- verbPhrase+  return $ chunk [np, vp] $ Tag "clause"++--  VP: {<VB.*><NP|PP|CLAUSE>+$} # Chunk verbs and their arguments+--  CLAUSE: {<NP><VP>}+verbPhrase :: Extractor (Text, Tag)+verbPhrase = do+  vp <- posPrefix "V"+  obj <- PC.many1 $ ((try nounPhrase)+                  <|> (try prepPhrase)+                  <|> clause)+  return $ chunk (vp:obj) $ Tag "v-phr"
src/NLP/Extraction/Parsec.hs view
@@ -11,9 +11,9 @@ -- @ --   nounPhrase :: Extractor (Text, Tag) --   nounPhrase = do---     nlist <- many1 (try (posTok $ Tag "NN")---                 <|> try (posTok $ Tag "DT")---                     <|> (posTok $ Tag "JJ"))+--     nlist <- many1 (try (posTok $ Tag \"NN\")+--                 \<|\> try (posTok $ Tag \"DT\")+--                     \<|\> (posTok $ Tag \"JJ\")) --     let term = T.intercalate " " (map fst nlist) --     return (term, Tag "n-phr") -- @@@ -36,10 +36,12 @@ -- | A Parsec parser. -- -- Example usage:+--+-- @ -- > set -XOverloadedStrings -- > import Text.Parsec.Prim -- > parse myExtractor "interactive repl" someTaggedSentence---+-- @ type Extractor = Parsec TaggedSentence ()  -- | Consume a token with the given POS Tag@@ -52,9 +54,10 @@  -- | Consume a token with the specified POS prefix. --+-- @ -- > parse (posPrefix "n") "ghci" [("Bob", Tag "np")] -- Right [("Bob", Tag "np")]---+-- @ posPrefix :: Text -> Extractor (Text, Tag) posPrefix str = token showTok posFromTok testTok   where
src/NLP/POS.hs view
@@ -208,7 +208,6 @@                      Just b  -> do tgr <- train b exs                                    return $ Just tgr     trainer = posTrainer p-  putStrLn ("train - exs: "++show exs)   newTgr <- trainer exs   newBackoff <- trainBackoff   return (newTgr { posBackoff = newBackoff })
src/NLP/POS/LiteralTagger.hs view
@@ -60,12 +60,25 @@             Sensitive   -> id             Insensitive -> Map.mapKeys T.toLower +escapeRegexChars :: Text -> Text+escapeRegexChars input = helper [ "\\", ".", "+", "*", "?", "[", "^", "]", "$"+                                , "(", ")", "{", "}", "=", "!", "<", ">", "|"+                                , ":", "-"+                                ] input +  where+    helper :: [Text] -> Text -> Text+    helper []     term = term+    helper (x:xs) term = helper xs $ escapeChar x term++    escapeChar :: Text -> Text -> Text+    escapeChar char term = T.replace char (T.append "\\" char) term+ -- | Create a tokenizer that protects the provided terms (to tokenize -- multi-word terms) protectTerms :: [Text] -> CaseSensitive -> Tokenizer protectTerms terms sensitive =-  let sorted = sortBy (compare `on` T.length) terms+  let sorted = sortBy (compare `on` T.length) $ map escapeRegexChars terms        sensitivity = case sensitive of                       Insensitive -> False@@ -81,7 +94,8 @@        execOption = ExecOption { captureGroups = False } -      eRegex = compile compOption execOption (T.concat ["\\<", (T.intercalate "\\>|\\<" sorted), "\\>"])+      eRegex = compile compOption execOption+                 (T.concat ["\\<", (T.intercalate "\\>|\\<" sorted), "\\>"])        toEithers :: [(Int, Int)] -> Text -> [Either Text Text]       toEithers []                str = [Right str]
src/NLP/POS/UnambiguousTagger.hs view
@@ -17,6 +17,7 @@ import Data.Serialize (encode, decode) import Data.Text (Text) +import NLP.Tokenize.Text (defaultTokenizer, run) import NLP.Types  import qualified NLP.POS.LiteralTagger as LT@@ -38,14 +39,12 @@   trainer :: [TaggedSentence] -> IO POSTagger   trainer exs = do     let newTable = train table exs-    putStrLn ("exs: "++show exs)-    putStrLn ("table: "++show table)-    putStrLn ("new table: "++show newTable)     return $ mkTagger newTable mTgr    in litTagger { posTrainer = trainer                , posSerialize = encode table                , posID = taggerID+               , posTokenizer = run defaultTokenizer                }  -- | Trainer method for unambiguous taggers.
+ tests/src/IntegrationTests.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE OverloadedStrings    #-}+module IntegrationTests++where++----------------------------------------------------------------------+import Test.QuickCheck ( Arbitrary, arbitrary, (==>), Property+                       , NonEmptyList(..), listOf)+import Test.QuickCheck.Instances ()+import Test.Framework.Providers.QuickCheck2 (testProperty)+import Test.Framework.Providers.HUnit (testCase)+import Test.Framework ( testGroup, Test, buildTest )+import Test.HUnit      ( (@=?), Assertion, assertFailure, assertEqual )+----------------------------------------------------------------------+import qualified Data.Text as T+import Data.Text (Text)+import qualified Data.Map as Map+import Text.Parsec.Prim (parse, (<|>), try)+import Text.Parsec.Pos+import qualified Text.Parsec.Combinator as PC+----------------------------------------------------------------------+import NLP.Types+import NLP.POS+import NLP.Corpora.Parsing+import NLP.Extraction.Parsec+import NLP.Extraction.Examples.ParsecExamples++import qualified NLP.POS.AvgPerceptronTagger as Avg+import qualified NLP.POS.LiteralTagger       as LT+import qualified NLP.POS.UnambiguousTagger   as UT++import TestUtils++tests :: Test+tests = buildTest $ do+  tagger <- defaultTagger+  return $ testGroup "Integration Tests"+        [ testGroup "Default Tagger" $+            map (genTest $ tagText tagger)+              [ ("Simple 1", "The dog jumped.", "The/at dog/nn jumped/vbd ./.")+              ]+        , testGroup "POS Serialization" $+            map (testSerialization examples)+              [ ("Average Perceptron", Avg.mkTagger Avg.emptyPerceptron Nothing)+              , ("Unambiguous",  UT.mkTagger Map.empty Nothing)+              , ("Literal",  LT.mkTagger Map.empty Sensitive Nothing)+              , ("Unambiguous -> Avg"+                , UT.mkTagger Map.empty+                    (Just $ Avg.mkTagger Avg.emptyPerceptron Nothing))+              ]+        ]+++examples :: [Text]+examples = [ "This/dt is/bez a/at test/nn ./."+           , "The/at dog/nn jumped/vbd over/in the/at cat/nn ./."+           , "Where/wrb is/bez the/at conference/nn ?/."+           ]++testSerialization :: [Text]  -- ^ A training corpus.  One sentence per entry.+                  -> ( String    -- ^ The name of the POS tagger.+                     , POSTagger) -- ^ An empty (untrained) POS tagger.+                  -> Test+testSerialization training (name, newTagger) = testCase name doTest+  where+    doTest :: Assertion+    doTest = do+      preTagger <- train newTagger $ map readPOS training++      let ePostTagger = deserialize taggerTable (serialize preTagger)+      case ePostTagger of+        Left err -> assertFailure ("Tagger did not deserialize: "++err)+        Right postTagger -> do+          let pre = map (tagText preTagger) training+              post = map (tagText postTagger) training+          assertEqual "Taggers tagged differently" pre post
tests/src/Main.hs view
@@ -27,6 +27,7 @@ import qualified NLP.TypesTests as TypeTests import qualified Data.DefaultMapTests as DefMap import qualified NLP.Extraction.ParsecTests as Parsec+import qualified IntegrationTests as IT  import Corpora @@ -65,6 +66,7 @@         , TypeTests.tests         , DefMap.tests         , Parsec.tests+        , IT.tests         ]  
tests/src/NLP/Extraction/ParsecTests.hs view
@@ -19,6 +19,7 @@ ---------------------------------------------------------------------- import NLP.Types import NLP.Extraction.Parsec+import NLP.Extraction.Examples.ParsecExamples  import TestUtils @@ -73,14 +74,6 @@                              (taggedSent ++ [(theToken, theTag)])   in (theToken, theTag) == actual --nounPhrase :: Extractor (Text, Tag)-nounPhrase = do-  nlist <- PC.many1 (try (posTok $ Tag "NN")-              <|> try (posTok $ Tag "DT")-                  <|> (posTok $ Tag "JJ"))-  let term = T.intercalate " " (map fst nlist)-  return (term, Tag "n-phr")  parseNounPhrase :: TaggedSentence -> Maybe (Text, Tag) parseNounPhrase sent =