nltk 3.2__zip → 3.3__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (406) hide show
  1. {nltk-3.2 → nltk-3.3}/INSTALL.txt +6 -6
  2. {nltk-3.2 → nltk-3.3}/LICENSE.txt +13 -13
  3. {nltk-3.2 → nltk-3.3}/MANIFEST.in +6 -6
  4. {nltk-3.2/nltk.egg-info → nltk-3.3}/PKG-INFO +13 -5
  5. nltk-3.2/README.txt → nltk-3.3/README.md +49 -48
  6. nltk-3.3/nltk/VERSION +1 -0
  7. {nltk-3.2 → nltk-3.3}/nltk/__init__.py +185 -185
  8. {nltk-3.2 → nltk-3.3}/nltk/app/__init__.py +52 -53
  9. {nltk-3.2 → nltk-3.3}/nltk/app/chartparser_app.py +2276 -2276
  10. {nltk-3.2 → nltk-3.3}/nltk/app/chunkparser_app.py +1262 -1264
  11. {nltk-3.2 → nltk-3.3}/nltk/app/collocations_app.py +347 -350
  12. {nltk-3.2 → nltk-3.3}/nltk/app/concordance_app.py +568 -570
  13. {nltk-3.2 → nltk-3.3}/nltk/app/nemo_app.py +156 -155
  14. {nltk-3.2 → nltk-3.3}/nltk/app/rdparser_app.py +892 -894
  15. {nltk-3.2 → nltk-3.3}/nltk/app/srparser_app.py +809 -809
  16. {nltk-3.2 → nltk-3.3}/nltk/app/wordfreq_app.py +32 -32
  17. {nltk-3.2 → nltk-3.3}/nltk/app/wordnet_app.py +968 -968
  18. {nltk-3.2 → nltk-3.3}/nltk/book.py +91 -90
  19. {nltk-3.2 → nltk-3.3}/nltk/ccg/__init__.py +22 -22
  20. {nltk-3.2 → nltk-3.3}/nltk/ccg/api.py +359 -335
  21. {nltk-3.2 → nltk-3.3}/nltk/ccg/chart.py +394 -361
  22. {nltk-3.2 → nltk-3.3}/nltk/ccg/combinator.py +343 -312
  23. {nltk-3.2 → nltk-3.3}/nltk/ccg/lexicon.py +328 -290
  24. nltk-3.3/nltk/ccg/logic.py +46 -0
  25. {nltk-3.2 → nltk-3.3}/nltk/chat/__init__.py +49 -49
  26. {nltk-3.2 → nltk-3.3}/nltk/chat/eliza.py +244 -244
  27. {nltk-3.2 → nltk-3.3}/nltk/chat/iesha.py +140 -140
  28. {nltk-3.2 → nltk-3.3}/nltk/chat/rude.py +92 -92
  29. {nltk-3.2 → nltk-3.3}/nltk/chat/suntsu.py +117 -117
  30. {nltk-3.2 → nltk-3.3}/nltk/chat/util.py +122 -120
  31. {nltk-3.2 → nltk-3.3}/nltk/chat/zen.py +282 -282
  32. {nltk-3.2 → nltk-3.3}/nltk/chunk/__init__.py +190 -190
  33. {nltk-3.2 → nltk-3.3}/nltk/chunk/api.py +51 -51
  34. {nltk-3.2 → nltk-3.3}/nltk/chunk/named_entity.py +331 -331
  35. {nltk-3.2 → nltk-3.3}/nltk/chunk/regexp.py +1390 -1384
  36. {nltk-3.2 → nltk-3.3}/nltk/chunk/util.py +600 -600
  37. {nltk-3.2 → nltk-3.3}/nltk/classify/__init__.py +98 -98
  38. {nltk-3.2 → nltk-3.3}/nltk/classify/api.py +193 -193
  39. {nltk-3.2 → nltk-3.3}/nltk/classify/decisiontree.py +295 -295
  40. {nltk-3.2 → nltk-3.3}/nltk/classify/maxent.py +1510 -1492
  41. {nltk-3.2 → nltk-3.3}/nltk/classify/megam.py +179 -178
  42. {nltk-3.2 → nltk-3.3}/nltk/classify/naivebayes.py +245 -242
  43. {nltk-3.2 → nltk-3.3}/nltk/classify/positivenaivebayes.py +170 -170
  44. {nltk-3.2 → nltk-3.3}/nltk/classify/rte_classify.py +160 -191
  45. {nltk-3.2 → nltk-3.3}/nltk/classify/scikitlearn.py +153 -151
  46. {nltk-3.2 → nltk-3.3}/nltk/classify/senna.py +183 -181
  47. {nltk-3.2 → nltk-3.3}/nltk/classify/svm.py +15 -15
  48. {nltk-3.2 → nltk-3.3}/nltk/classify/tadm.py +113 -112
  49. {nltk-3.2 → nltk-3.3}/nltk/classify/textcat.py +193 -193
  50. {nltk-3.2 → nltk-3.3}/nltk/classify/util.py +324 -312
  51. {nltk-3.2 → nltk-3.3}/nltk/classify/weka.py +346 -345
  52. {nltk-3.2 → nltk-3.3}/nltk/cluster/__init__.py +86 -86
  53. {nltk-3.2 → nltk-3.3}/nltk/cluster/api.py +74 -70
  54. {nltk-3.2 → nltk-3.3}/nltk/cluster/em.py +247 -247
  55. {nltk-3.2 → nltk-3.3}/nltk/cluster/gaac.py +168 -168
  56. {nltk-3.2 → nltk-3.3}/nltk/cluster/kmeans.py +221 -221
  57. {nltk-3.2 → nltk-3.3}/nltk/cluster/util.py +304 -289
  58. nltk-3.3/nltk/collections.py +640 -0
  59. {nltk-3.2 → nltk-3.3}/nltk/collocations.py +388 -388
  60. nltk-3.3/nltk/compat.py +365 -0
  61. {nltk-3.2 → nltk-3.3}/nltk/corpus/__init__.py +341 -320
  62. {nltk-3.2 → nltk-3.3}/nltk/corpus/europarl_raw.py +44 -44
  63. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/__init__.py +147 -145
  64. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/aligned.py +115 -114
  65. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/api.py +448 -446
  66. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/bnc.py +252 -252
  67. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/bracket_parse.py +227 -227
  68. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/categorized_sents.py +179 -178
  69. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/chasen.py +140 -139
  70. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/childes.py +522 -494
  71. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/chunked.py +212 -212
  72. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/cmudict.py +97 -95
  73. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/comparative_sents.py +280 -278
  74. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/conll.py +528 -521
  75. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/crubadan.py +116 -116
  76. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/dependency.py +101 -101
  77. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/framenet.py +3059 -2093
  78. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ieer.py +112 -111
  79. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/indian.py +85 -86
  80. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ipipan.py +332 -331
  81. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/knbc.py +187 -187
  82. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/lin.py +156 -156
  83. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/mte.py +311 -310
  84. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nkjp.py +429 -428
  85. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nombank.py +421 -421
  86. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nps_chat.py +73 -73
  87. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/opinion_lexicon.py +115 -115
  88. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/panlex_lite.py +165 -165
  89. nltk-3.3/nltk/corpus/reader/pl196x.py +292 -0
  90. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/plaintext.py +232 -233
  91. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ppattach.py +96 -95
  92. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/propbank.py +479 -481
  93. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/pros_cons.py +128 -126
  94. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/reviews.py +330 -328
  95. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/rte.py +144 -146
  96. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/semcor.py +256 -256
  97. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/senseval.py +203 -201
  98. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/sentiwordnet.py +137 -137
  99. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/sinica_treebank.py +75 -75
  100. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/string_category.py +60 -59
  101. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/switchboard.py +119 -119
  102. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/tagged.py +295 -294
  103. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/timit.py +452 -450
  104. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/toolbox.py +68 -68
  105. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/twitter.py +155 -157
  106. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/udhr.py +80 -80
  107. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/util.py +804 -800
  108. nltk-3.3/nltk/corpus/reader/verbnet.py +595 -0
  109. nltk-3.3/nltk/corpus/reader/wordlist.py +134 -0
  110. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/wordnet.py +2108 -2036
  111. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/xmldocs.py +392 -387
  112. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ycoe.py +243 -242
  113. {nltk-3.2 → nltk-3.3}/nltk/corpus/util.py +144 -127
  114. {nltk-3.2 → nltk-3.3}/nltk/data.py +1487 -1451
  115. {nltk-3.2 → nltk-3.3}/nltk/decorators.py +219 -215
  116. {nltk-3.2 → nltk-3.3}/nltk/downloader.py +2278 -2274
  117. {nltk-3.2 → nltk-3.3}/nltk/draw/__init__.py +27 -27
  118. {nltk-3.2 → nltk-3.3}/nltk/draw/cfg.py +774 -777
  119. {nltk-3.2 → nltk-3.3}/nltk/draw/dispersion.py +58 -58
  120. {nltk-3.2 → nltk-3.3}/nltk/draw/table.py +1098 -1098
  121. {nltk-3.2 → nltk-3.3}/nltk/draw/tree.py +963 -966
  122. {nltk-3.2 → nltk-3.3}/nltk/draw/util.py +2356 -2356
  123. {nltk-3.2 → nltk-3.3}/nltk/featstruct.py +2617 -2500
  124. {nltk-3.2 → nltk-3.3}/nltk/grammar.py +1559 -1516
  125. {nltk-3.2 → nltk-3.3}/nltk/help.py +56 -56
  126. {nltk-3.2 → nltk-3.3}/nltk/inference/__init__.py +20 -20
  127. {nltk-3.2 → nltk-3.3}/nltk/inference/api.py +597 -589
  128. {nltk-3.2 → nltk-3.3}/nltk/inference/discourse.py +612 -608
  129. {nltk-3.2 → nltk-3.3}/nltk/inference/mace.py +311 -311
  130. {nltk-3.2 → nltk-3.3}/nltk/inference/nonmonotonic.py +509 -509
  131. {nltk-3.2 → nltk-3.3}/nltk/inference/prover9.py +431 -431
  132. {nltk-3.2 → nltk-3.3}/nltk/inference/resolution.py +687 -687
  133. {nltk-3.2 → nltk-3.3}/nltk/inference/tableau.py +607 -607
  134. {nltk-3.2 → nltk-3.3}/nltk/internals.py +982 -982
  135. {nltk-3.2 → nltk-3.3}/nltk/jsontags.py +63 -63
  136. {nltk-3.2 → nltk-3.3}/nltk/lazyimport.py +142 -142
  137. {nltk-3.2 → nltk-3.3}/nltk/metrics/__init__.py +30 -29
  138. {nltk-3.2 → nltk-3.3}/nltk/metrics/agreement.py +421 -401
  139. nltk-3.3/nltk/metrics/aline.py +607 -0
  140. {nltk-3.2 → nltk-3.3}/nltk/metrics/association.py +414 -410
  141. {nltk-3.2 → nltk-3.3}/nltk/metrics/confusionmatrix.py +206 -206
  142. {nltk-3.2 → nltk-3.3}/nltk/metrics/distance.py +207 -202
  143. {nltk-3.2 → nltk-3.3}/nltk/metrics/paice.py +381 -381
  144. {nltk-3.2 → nltk-3.3}/nltk/metrics/scores.py +228 -228
  145. {nltk-3.2 → nltk-3.3}/nltk/metrics/segmentation.py +231 -232
  146. {nltk-3.2 → nltk-3.3}/nltk/metrics/spearman.py +69 -69
  147. {nltk-3.2 → nltk-3.3}/nltk/misc/__init__.py +11 -11
  148. {nltk-3.2 → nltk-3.3}/nltk/misc/babelfish.py +10 -10
  149. {nltk-3.2 → nltk-3.3}/nltk/misc/chomsky.py +135 -133
  150. {nltk-3.2 → nltk-3.3}/nltk/misc/minimalset.py +83 -83
  151. {nltk-3.2 → nltk-3.3}/nltk/misc/sort.py +157 -157
  152. {nltk-3.2 → nltk-3.3}/nltk/misc/wordfinder.py +129 -129
  153. {nltk-3.2 → nltk-3.3}/nltk/parse/__init__.py +81 -80
  154. {nltk-3.2 → nltk-3.3}/nltk/parse/api.py +66 -66
  155. {nltk-3.2 → nltk-3.3}/nltk/parse/bllip.py +282 -282
  156. {nltk-3.2 → nltk-3.3}/nltk/parse/chart.py +1682 -1681
  157. nltk-3.3/nltk/parse/corenlp.py +780 -0
  158. {nltk-3.2 → nltk-3.3}/nltk/parse/dependencygraph.py +760 -758
  159. {nltk-3.2 → nltk-3.3}/nltk/parse/earleychart.py +452 -451
  160. {nltk-3.2 → nltk-3.3}/nltk/parse/evaluate.py +129 -129
  161. {nltk-3.2 → nltk-3.3}/nltk/parse/featurechart.py +580 -578
  162. {nltk-3.2 → nltk-3.3}/nltk/parse/generate.py +87 -76
  163. {nltk-3.2 → nltk-3.3}/nltk/parse/malt.py +356 -356
  164. {nltk-3.2 → nltk-3.3}/nltk/parse/nonprojectivedependencyparser.py +783 -783
  165. {nltk-3.2 → nltk-3.3}/nltk/parse/pchart.py +522 -522
  166. {nltk-3.2 → nltk-3.3}/nltk/parse/projectivedependencyparser.py +579 -578
  167. {nltk-3.2 → nltk-3.3}/nltk/parse/recursivedescent.py +655 -656
  168. {nltk-3.2 → nltk-3.3}/nltk/parse/shiftreduce.py +458 -459
  169. {nltk-3.2 → nltk-3.3}/nltk/parse/stanford.py +431 -406
  170. {nltk-3.2 → nltk-3.3}/nltk/parse/transitionparser.py +774 -772
  171. {nltk-3.2 → nltk-3.3}/nltk/parse/util.py +231 -231
  172. {nltk-3.2 → nltk-3.3}/nltk/parse/viterbi.py +401 -401
  173. {nltk-3.2 → nltk-3.3}/nltk/probability.py +2410 -2355
  174. {nltk-3.2 → nltk-3.3}/nltk/sem/__init__.py +61 -61
  175. {nltk-3.2 → nltk-3.3}/nltk/sem/boxer.py +1261 -1261
  176. {nltk-3.2 → nltk-3.3}/nltk/sem/chat80.py +782 -782
  177. {nltk-3.2 → nltk-3.3}/nltk/sem/cooper_storage.py +118 -118
  178. {nltk-3.2 → nltk-3.3}/nltk/sem/drt.py +1258 -1257
  179. {nltk-3.2 → nltk-3.3}/nltk/sem/drt_glue_demo.py +485 -489
  180. {nltk-3.2 → nltk-3.3}/nltk/sem/evaluate.py +790 -784
  181. {nltk-3.2 → nltk-3.3}/nltk/sem/glue.py +696 -694
  182. {nltk-3.2 → nltk-3.3}/nltk/sem/hole.py +386 -384
  183. {nltk-3.2 → nltk-3.3}/nltk/sem/lfg.py +210 -208
  184. {nltk-3.2 → nltk-3.3}/nltk/sem/linearlogic.py +451 -449
  185. {nltk-3.2 → nltk-3.3}/nltk/sem/logic.py +1910 -1910
  186. {nltk-3.2 → nltk-3.3}/nltk/sem/relextract.py +476 -483
  187. {nltk-3.2 → nltk-3.3}/nltk/sem/skolemize.py +101 -101
  188. {nltk-3.2 → nltk-3.3}/nltk/sem/util.py +249 -249
  189. {nltk-3.2 → nltk-3.3}/nltk/sentiment/__init__.py +14 -14
  190. {nltk-3.2 → nltk-3.3}/nltk/sentiment/sentiment_analyzer.py +229 -229
  191. {nltk-3.2 → nltk-3.3}/nltk/sentiment/util.py +762 -752
  192. {nltk-3.2 → nltk-3.3}/nltk/sentiment/vader.py +443 -445
  193. {nltk-3.2 → nltk-3.3}/nltk/stem/__init__.py +31 -33
  194. {nltk-3.2 → nltk-3.3}/nltk/stem/api.py +28 -25
  195. nltk-3.3/nltk/stem/arlstem.py +369 -0
  196. {nltk-3.2 → nltk-3.3}/nltk/stem/isri.py +345 -345
  197. {nltk-3.2 → nltk-3.3}/nltk/stem/lancaster.py +337 -310
  198. nltk-3.3/nltk/stem/porter.py +710 -0
  199. {nltk-3.2 → nltk-3.3}/nltk/stem/regexp.py +61 -61
  200. {nltk-3.2 → nltk-3.3}/nltk/stem/rslp.py +142 -142
  201. {nltk-3.2 → nltk-3.3}/nltk/stem/snowball.py +4236 -3712
  202. {nltk-3.2 → nltk-3.3}/nltk/stem/util.py +22 -12
  203. {nltk-3.2 → nltk-3.3}/nltk/stem/wordnet.py +51 -51
  204. {nltk-3.2 → nltk-3.3}/nltk/tag/__init__.py +152 -127
  205. {nltk-3.2 → nltk-3.3}/nltk/tag/api.py +86 -81
  206. {nltk-3.2 → nltk-3.3}/nltk/tag/brill.py +424 -426
  207. {nltk-3.2 → nltk-3.3}/nltk/tag/brill_trainer.py +608 -608
  208. {nltk-3.2 → nltk-3.3}/nltk/tag/crf.py +204 -200
  209. {nltk-3.2 → nltk-3.3}/nltk/tag/hmm.py +1277 -1277
  210. {nltk-3.2 → nltk-3.3}/nltk/tag/hunpos.py +132 -132
  211. {nltk-3.2 → nltk-3.3}/nltk/tag/mapping.py +101 -101
  212. {nltk-3.2 → nltk-3.3}/nltk/tag/perceptron.py +329 -314
  213. {nltk-3.2 → nltk-3.3}/nltk/tag/senna.py +147 -145
  214. {nltk-3.2 → nltk-3.3}/nltk/tag/sequential.py +740 -736
  215. {nltk-3.2 → nltk-3.3}/nltk/tag/stanford.py +219 -196
  216. {nltk-3.2 → nltk-3.3}/nltk/tag/tnt.py +595 -604
  217. {nltk-3.2 → nltk-3.3}/nltk/tag/util.py +72 -72
  218. {nltk-3.2 → nltk-3.3}/nltk/tbl/__init__.py +28 -28
  219. {nltk-3.2 → nltk-3.3}/nltk/tbl/api.py +1 -1
  220. {nltk-3.2 → nltk-3.3}/nltk/tbl/demo.py +366 -366
  221. {nltk-3.2 → nltk-3.3}/nltk/tbl/erroranalysis.py +39 -39
  222. {nltk-3.2 → nltk-3.3}/nltk/tbl/feature.py +259 -261
  223. {nltk-3.2 → nltk-3.3}/nltk/tbl/rule.py +321 -321
  224. {nltk-3.2 → nltk-3.3}/nltk/tbl/template.py +303 -308
  225. {nltk-3.2 → nltk-3.3}/nltk/test/__init__.py +18 -18
  226. {nltk-3.2 → nltk-3.3}/nltk/test/all.py +24 -23
  227. {nltk-3.2 → nltk-3.3}/nltk/test/bleu.doctest +14 -14
  228. {nltk-3.2 → nltk-3.3}/nltk/test/bnc.doctest +60 -60
  229. {nltk-3.2 → nltk-3.3}/nltk/test/ccg.doctest +376 -395
  230. nltk-3.3/nltk/test/ccg_semantics.doctest +553 -0
  231. {nltk-3.2 → nltk-3.3}/nltk/test/chat80.doctest +234 -234
  232. {nltk-3.2 → nltk-3.3}/nltk/test/childes.doctest +184 -184
  233. {nltk-3.2 → nltk-3.3}/nltk/test/childes_fixt.py +14 -13
  234. {nltk-3.2 → nltk-3.3}/nltk/test/chunk.doctest +373 -373
  235. {nltk-3.2 → nltk-3.3}/nltk/test/classify.doctest +185 -185
  236. {nltk-3.2 → nltk-3.3}/nltk/test/classify_fixt.py +11 -10
  237. nltk-3.3/nltk/test/collections.doctest +20 -0
  238. {nltk-3.2 → nltk-3.3}/nltk/test/collocations.doctest +276 -276
  239. {nltk-3.2 → nltk-3.3}/nltk/test/compat.doctest +134 -138
  240. {nltk-3.2 → nltk-3.3}/nltk/test/compat_fixt.py +9 -8
  241. nltk-3.3/nltk/test/concordance.doctest +55 -0
  242. {nltk-3.2 → nltk-3.3}/nltk/test/corpus.doctest +2200 -2212
  243. {nltk-3.2 → nltk-3.3}/nltk/test/corpus_fixt.py +3 -3
  244. {nltk-3.2 → nltk-3.3}/nltk/test/crubadan.doctest +65 -65
  245. {nltk-3.2 → nltk-3.3}/nltk/test/data.doctest +379 -379
  246. {nltk-3.2 → nltk-3.3}/nltk/test/dependency.doctest +241 -241
  247. {nltk-3.2 → nltk-3.3}/nltk/test/discourse.doctest +546 -546
  248. {nltk-3.2 → nltk-3.3}/nltk/test/discourse_fixt.py +14 -13
  249. {nltk-3.2 → nltk-3.3}/nltk/test/doctest_nose_plugin.py +159 -156
  250. {nltk-3.2 → nltk-3.3}/nltk/test/drt.doctest +517 -517
  251. {nltk-3.2 → nltk-3.3}/nltk/test/featgram.doctest +607 -607
  252. {nltk-3.2 → nltk-3.3}/nltk/test/featstruct.doctest +1229 -1230
  253. {nltk-3.2 → nltk-3.3}/nltk/test/framenet.doctest +288 -239
  254. {nltk-3.2 → nltk-3.3}/nltk/test/generate.doctest +67 -67
  255. {nltk-3.2 → nltk-3.3}/nltk/test/gensim.doctest +140 -141
  256. {nltk-3.2 → nltk-3.3}/nltk/test/gensim_fixt.py +10 -9
  257. {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics.doctest +384 -386
  258. {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics_malt.doctest +68 -68
  259. {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics_malt_fixt.py +12 -11
  260. {nltk-3.2 → nltk-3.3}/nltk/test/grammar.doctest +48 -48
  261. {nltk-3.2 → nltk-3.3}/nltk/test/grammartestsuites.doctest +109 -109
  262. {nltk-3.2 → nltk-3.3}/nltk/test/index.doctest +100 -100
  263. {nltk-3.2 → nltk-3.3}/nltk/test/inference.doctest +534 -534
  264. {nltk-3.2 → nltk-3.3}/nltk/test/inference_fixt.py +12 -11
  265. {nltk-3.2 → nltk-3.3}/nltk/test/internals.doctest +140 -140
  266. {nltk-3.2 → nltk-3.3}/nltk/test/japanese.doctest +48 -48
  267. {nltk-3.2 → nltk-3.3}/nltk/test/logic.doctest +1098 -1098
  268. {nltk-3.2 → nltk-3.3}/nltk/test/metrics.doctest +270 -270
  269. {nltk-3.2 → nltk-3.3}/nltk/test/misc.doctest +118 -118
  270. {nltk-3.2 → nltk-3.3}/nltk/test/nonmonotonic.doctest +286 -286
  271. {nltk-3.2 → nltk-3.3}/nltk/test/nonmonotonic_fixt.py +12 -11
  272. {nltk-3.2 → nltk-3.3}/nltk/test/paice.doctest +35 -35
  273. {nltk-3.2 → nltk-3.3}/nltk/test/parse.doctest +884 -884
  274. {nltk-3.2 → nltk-3.3}/nltk/test/portuguese_en.doctest +565 -565
  275. {nltk-3.2 → nltk-3.3}/nltk/test/portuguese_en_fixt.py +16 -16
  276. {nltk-3.2 → nltk-3.3}/nltk/test/probability.doctest +304 -304
  277. {nltk-3.2 → nltk-3.3}/nltk/test/probability_fixt.py +13 -12
  278. {nltk-3.2 → nltk-3.3}/nltk/test/propbank.doctest +176 -176
  279. {nltk-3.2 → nltk-3.3}/nltk/test/relextract.doctest +263 -263
  280. {nltk-3.2 → nltk-3.3}/nltk/test/resolution.doctest +221 -221
  281. {nltk-3.2 → nltk-3.3}/nltk/test/runtests.py +86 -64
  282. {nltk-3.2 → nltk-3.3}/nltk/test/segmentation_fixt.py +10 -10
  283. {nltk-3.2 → nltk-3.3}/nltk/test/semantics.doctest +665 -665
  284. {nltk-3.2 → nltk-3.3}/nltk/test/semantics_fixt.py +7 -7
  285. {nltk-3.2 → nltk-3.3}/nltk/test/sentiment.doctest +233 -233
  286. {nltk-3.2 → nltk-3.3}/nltk/test/sentiwordnet.doctest +41 -41
  287. {nltk-3.2 → nltk-3.3}/nltk/test/simple.doctest +85 -85
  288. {nltk-3.2 → nltk-3.3}/nltk/test/stem.doctest +78 -78
  289. {nltk-3.2 → nltk-3.3}/nltk/test/tag.doctest +33 -33
  290. {nltk-3.2 → nltk-3.3}/nltk/test/tokenize.doctest +273 -166
  291. {nltk-3.2 → nltk-3.3}/nltk/test/toolbox.doctest +307 -307
  292. {nltk-3.2 → nltk-3.3}/nltk/test/translate.doctest +242 -242
  293. {nltk-3.2 → nltk-3.3}/nltk/test/translate_fixt.py +3 -3
  294. {nltk-3.2 → nltk-3.3}/nltk/test/tree.doctest +1101 -1101
  295. {nltk-3.2 → nltk-3.3}/nltk/test/treeprettyprinter.doctest +127 -127
  296. {nltk-3.2 → nltk-3.3}/nltk/test/treetransforms.doctest +156 -156
  297. nltk-3.3/nltk/test/unit/test_2x_compat.py +63 -0
  298. nltk-3.3/nltk/test/unit/test_aline.py +52 -0
  299. nltk-3.3/nltk/test/unit/test_chunk.py +56 -0
  300. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_classify.py +55 -53
  301. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_collocations.py +88 -79
  302. nltk-3.3/nltk/test/unit/test_concordance.py +98 -0
  303. nltk-3.3/nltk/test/unit/test_corenlp.py +1000 -0
  304. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_corpora.py +200 -183
  305. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_corpus_views.py +45 -45
  306. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_hmm.py +88 -88
  307. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_json2csv_corpus.py +188 -187
  308. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_naivebayes.py +26 -26
  309. nltk-3.3/nltk/test/unit/test_rte_classify.py +86 -0
  310. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_seekable_unicode_stream_reader.py +124 -124
  311. nltk-3.3/nltk/test/unit/test_senna.py +74 -0
  312. nltk-3.3/nltk/test/unit/test_stem.py +121 -0
  313. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_tag.py +20 -20
  314. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_tgrep.py +628 -626
  315. nltk-3.3/nltk/test/unit/test_tokenize.py +168 -0
  316. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_twitter_auth.py +185 -185
  317. nltk-3.3/nltk/test/unit/test_wordnet.py +134 -0
  318. nltk-3.3/nltk/test/unit/translate/test_bleu.py +244 -0
  319. nltk-3.3/nltk/test/unit/translate/test_gdfa.py +57 -0
  320. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm1.py +75 -75
  321. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm2.py +87 -87
  322. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm3.py +105 -105
  323. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm4.py +126 -126
  324. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm5.py +166 -166
  325. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm_model.py +270 -270
  326. nltk-3.3/nltk/test/unit/translate/test_nist.py +37 -0
  327. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_stack_decoder.py +300 -300
  328. {nltk-3.2 → nltk-3.3}/nltk/test/unit/utils.py +41 -41
  329. {nltk-3.2 → nltk-3.3}/nltk/test/util.doctest +48 -48
  330. {nltk-3.2 → nltk-3.3}/nltk/test/wordnet.doctest +595 -581
  331. {nltk-3.2 → nltk-3.3}/nltk/test/wordnet_fixt.py +7 -6
  332. {nltk-3.2 → nltk-3.3}/nltk/test/wordnet_lch.doctest +53 -53
  333. {nltk-3.2 → nltk-3.3}/nltk/test/wsd.doctest +68 -68
  334. {nltk-3.2 → nltk-3.3}/nltk/text.py +663 -610
  335. {nltk-3.2 → nltk-3.3}/nltk/tgrep.py +938 -937
  336. {nltk-3.2 → nltk-3.3}/nltk/tokenize/__init__.py +130 -107
  337. {nltk-3.2 → nltk-3.3}/nltk/tokenize/api.py +77 -78
  338. {nltk-3.2 → nltk-3.3}/nltk/tokenize/casual.py +343 -342
  339. {nltk-3.2 → nltk-3.3}/nltk/tokenize/mwe.py +120 -120
  340. nltk-3.3/nltk/tokenize/nist.py +173 -0
  341. {nltk-3.2 → nltk-3.3}/nltk/tokenize/punkt.py +1620 -1601
  342. {nltk-3.2 → nltk-3.3}/nltk/tokenize/regexp.py +208 -202
  343. nltk-3.3/nltk/tokenize/repp.py +151 -0
  344. {nltk-3.2 → nltk-3.3}/nltk/tokenize/sexpr.py +140 -142
  345. {nltk-3.2 → nltk-3.3}/nltk/tokenize/simple.py +138 -136
  346. {nltk-3.2 → nltk-3.3}/nltk/tokenize/stanford.py +117 -113
  347. nltk-3.3/nltk/tokenize/stanford_segmenter.py +246 -0
  348. {nltk-3.2 → nltk-3.3}/nltk/tokenize/texttiling.py +458 -460
  349. nltk-3.3/nltk/tokenize/toktok.py +155 -0
  350. nltk-3.3/nltk/tokenize/treebank.py +363 -0
  351. nltk-3.3/nltk/tokenize/util.py +261 -0
  352. {nltk-3.2 → nltk-3.3}/nltk/toolbox.py +499 -497
  353. {nltk-3.2 → nltk-3.3}/nltk/translate/__init__.py +24 -24
  354. {nltk-3.2 → nltk-3.3}/nltk/translate/api.py +331 -321
  355. {nltk-3.2 → nltk-3.3}/nltk/translate/bleu_score.py +615 -556
  356. nltk-3.3/nltk/translate/chrf_score.py +137 -0
  357. {nltk-3.2 → nltk-3.3}/nltk/translate/gale_church.py +248 -235
  358. {nltk-3.2 → nltk-3.3}/nltk/translate/gdfa.py +135 -131
  359. nltk-3.3/nltk/translate/gleu_score.py +193 -0
  360. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm1.py +250 -241
  361. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm2.py +308 -308
  362. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm3.py +337 -337
  363. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm4.py +467 -467
  364. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm5.py +639 -639
  365. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm_model.py +536 -533
  366. {nltk-3.2 → nltk-3.3}/nltk/translate/metrics.py +40 -40
  367. nltk-3.3/nltk/translate/nist_score.py +178 -0
  368. {nltk-3.2 → nltk-3.3}/nltk/translate/phrase_based.py +175 -175
  369. {nltk-3.2 → nltk-3.3}/nltk/translate/ribes_score.py +325 -325
  370. {nltk-3.2 → nltk-3.3}/nltk/translate/stack_decoder.py +499 -495
  371. {nltk-3.2 → nltk-3.3}/nltk/tree.py +1605 -1603
  372. {nltk-3.2 → nltk-3.3}/nltk/treeprettyprinter.py +564 -564
  373. {nltk-3.2 → nltk-3.3}/nltk/treetransforms.py +309 -309
  374. {nltk-3.2 → nltk-3.3}/nltk/twitter/__init__.py +28 -28
  375. {nltk-3.2 → nltk-3.3}/nltk/twitter/api.py +141 -136
  376. {nltk-3.2 → nltk-3.3}/nltk/twitter/common.py +264 -258
  377. {nltk-3.2 → nltk-3.3}/nltk/twitter/twitter_demo.py +288 -288
  378. {nltk-3.2 → nltk-3.3}/nltk/twitter/twitterclient.py +530 -530
  379. {nltk-3.2 → nltk-3.3}/nltk/twitter/util.py +147 -146
  380. nltk-3.3/nltk/util.py +751 -0
  381. {nltk-3.2 → nltk-3.3}/nltk/wsd.py +53 -53
  382. {nltk-3.2 → nltk-3.3/nltk.egg-info}/PKG-INFO +13 -5
  383. {nltk-3.2 → nltk-3.3}/nltk.egg-info/SOURCES.txt +26 -3
  384. nltk-3.3/nltk.egg-info/requires.txt +31 -0
  385. {nltk-3.2 → nltk-3.3}/setup.cfg +0 -1
  386. {nltk-3.2 → nltk-3.3}/setup.py +102 -75
  387. nltk-3.2/nltk/VERSION +0 -1
  388. nltk-3.2/nltk/compat.py +0 -680
  389. nltk-3.2/nltk/corpus/reader/pl196x.py +0 -278
  390. nltk-3.2/nltk/corpus/reader/verbnet.py +0 -408
  391. nltk-3.2/nltk/corpus/reader/wordlist.py +0 -37
  392. nltk-3.2/nltk/sentiment/vader_lexicon.txt +0 -7517
  393. nltk-3.2/nltk/six.py +0 -868
  394. nltk-3.2/nltk/stem/porter.py +0 -692
  395. nltk-3.2/nltk/test/unit/test_2x_compat.py +0 -26
  396. nltk-3.2/nltk/test/unit/test_stem.py +0 -36
  397. nltk-3.2/nltk/test/unit/test_tokenize.py +0 -23
  398. nltk-3.2/nltk/test/unit/translate/test_bleu.py +0 -84
  399. nltk-3.2/nltk/tokenize/treebank.py +0 -124
  400. nltk-3.2/nltk/tokenize/util.py +0 -90
  401. nltk-3.2/nltk/util.py +0 -1364
  402. {nltk-3.2 → nltk-3.3}/nltk/test/unit/__init__.py +0 -0
  403. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/__init__.py +0 -0
  404. {nltk-3.2 → nltk-3.3}/nltk.egg-info/dependency_links.txt +0 -0
  405. {nltk-3.2 → nltk-3.3}/nltk.egg-info/not-zip-safe +0 -0
  406. {nltk-3.2 → nltk-3.3}/nltk.egg-info/top_level.txt +0 -0
@@ -1,578 +1,579 @@
1
- # Natural Language Toolkit: Dependency Grammars
2
- #
3
- # Copyright (C) 2001-2015 NLTK Project
4
- # Author: Jason Narad <jason.narad@gmail.com>
5
- #
6
- # URL: <http://nltk.org/>
7
- # For license information, see LICENSE.TXT
8
- #
9
- from __future__ import print_function, unicode_literals
10
-
11
- from collections import defaultdict
12
-
13
- from nltk.grammar import (DependencyProduction, DependencyGrammar,
14
- ProbabilisticDependencyGrammar)
15
- from nltk.parse.dependencygraph import DependencyGraph
16
- from nltk.internals import raise_unorderable_types
17
- from nltk.compat import total_ordering, python_2_unicode_compatible
18
-
19
- #################################################################
20
- # Dependency Span
21
- #################################################################
22
-
23
- @total_ordering
24
- @python_2_unicode_compatible
25
- class DependencySpan(object):
26
- """
27
- A contiguous span over some part of the input string representing
28
- dependency (head -> modifier) relationships amongst words. An atomic
29
- span corresponds to only one word so it isn't a 'span' in the conventional
30
- sense, as its _start_index = _end_index = _head_index for concatenation
31
- purposes. All other spans are assumed to have arcs between all nodes
32
- within the start and end indexes of the span, and one head index corresponding
33
- to the head word for the entire span. This is the same as the root node if
34
- the dependency structure were depicted as a graph.
35
- """
36
- def __init__(self, start_index, end_index, head_index, arcs, tags):
37
- self._start_index = start_index
38
- self._end_index = end_index
39
- self._head_index = head_index
40
- self._arcs = arcs
41
- self._tags = tags
42
- self._comparison_key = (start_index, end_index, head_index, tuple(arcs))
43
- self._hash = hash(self._comparison_key)
44
-
45
- def head_index(self):
46
- """
47
- :return: An value indexing the head of the entire ``DependencySpan``.
48
- :rtype: int
49
- """
50
- return self._head_index
51
-
52
- def __repr__(self):
53
- """
54
- :return: A concise string representatino of the ``DependencySpan``.
55
- :rtype: str.
56
- """
57
- return 'Span %d-%d; Head Index: %d' % (self._start_index, self._end_index, self._head_index)
58
-
59
- def __str__(self):
60
- """
61
- :return: A verbose string representation of the ``DependencySpan``.
62
- :rtype: str
63
- """
64
- str = 'Span %d-%d; Head Index: %d' % (self._start_index, self._end_index, self._head_index)
65
- for i in range(len(self._arcs)):
66
- str += '\n%d <- %d, %s' % (i, self._arcs[i], self._tags[i])
67
- return str
68
-
69
- def __eq__(self, other):
70
- return (type(self) == type(other) and
71
- self._comparison_key == other._comparison_key)
72
-
73
- def __ne__(self, other):
74
- return not self == other
75
-
76
- def __lt__(self, other):
77
- if not isinstance(other, DependencySpan):
78
- raise_unorderable_types("<", self, other)
79
- return self._comparison_key < other._comparison_key
80
-
81
- def __hash__(self):
82
- """
83
- :return: The hash value of this ``DependencySpan``.
84
- """
85
- return self._hash
86
-
87
- #################################################################
88
- # Chart Cell
89
- #################################################################
90
-
91
- @python_2_unicode_compatible
92
- class ChartCell(object):
93
- """
94
- A cell from the parse chart formed when performing the CYK algorithm.
95
- Each cell keeps track of its x and y coordinates (though this will probably
96
- be discarded), and a list of spans serving as the cell's entries.
97
- """
98
- def __init__(self, x, y):
99
- """
100
- :param x: This cell's x coordinate.
101
- :type x: int.
102
- :param y: This cell's y coordinate.
103
- :type y: int.
104
- """
105
- self._x = x
106
- self._y = y
107
- self._entries = set([])
108
-
109
- def add(self, span):
110
- """
111
- Appends the given span to the list of spans
112
- representing the chart cell's entries.
113
-
114
- :param span: The span to add.
115
- :type span: DependencySpan
116
- """
117
- self._entries.add(span)
118
-
119
- def __str__(self):
120
- """
121
- :return: A verbose string representation of this ``ChartCell``.
122
- :rtype: str.
123
- """
124
- return 'CC[%d,%d]: %s' % (self._x, self._y, self._entries)
125
-
126
- def __repr__(self):
127
- """
128
- :return: A concise string representation of this ``ChartCell``.
129
- :rtype: str.
130
- """
131
- return '%s' % self
132
-
133
-
134
- #################################################################
135
- # Parsing with Dependency Grammars
136
- #################################################################
137
-
138
-
139
- class ProjectiveDependencyParser(object):
140
- """
141
- A projective, rule-based, dependency parser. A ProjectiveDependencyParser
142
- is created with a DependencyGrammar, a set of productions specifying
143
- word-to-word dependency relations. The parse() method will then
144
- return the set of all parses, in tree representation, for a given input
145
- sequence of tokens. Each parse must meet the requirements of the both
146
- the grammar and the projectivity constraint which specifies that the
147
- branches of the dependency tree are not allowed to cross. Alternatively,
148
- this can be understood as stating that each parent node and its children
149
- in the parse tree form a continuous substring of the input sequence.
150
- """
151
-
152
- def __init__(self, dependency_grammar):
153
- """
154
- Create a new ProjectiveDependencyParser, from a word-to-word
155
- dependency grammar ``DependencyGrammar``.
156
-
157
- :param dependency_grammar: A word-to-word relation dependencygrammar.
158
- :type dependency_grammar: DependencyGrammar
159
- """
160
- self._grammar = dependency_grammar
161
-
162
- def parse(self, tokens):
163
- """
164
- Performs a projective dependency parse on the list of tokens using
165
- a chart-based, span-concatenation algorithm similar to Eisner (1996).
166
-
167
- :param tokens: The list of input tokens.
168
- :type tokens: list(str)
169
- :return: An iterator over parse trees.
170
- :rtype: iter(Tree)
171
- """
172
- self._tokens = list(tokens)
173
- chart = []
174
- for i in range(0, len(self._tokens) + 1):
175
- chart.append([])
176
- for j in range(0, len(self._tokens) + 1):
177
- chart[i].append(ChartCell(i,j))
178
- if i==j+1:
179
- chart[i][j].add(DependencySpan(i-1,i,i-1,[-1], ['null']))
180
-
181
- for i in range(1,len(self._tokens)+1):
182
- for j in range(i-2,-1,-1):
183
- for k in range(i-1,j,-1):
184
- for span1 in chart[k][j]._entries:
185
- for span2 in chart[i][k]._entries:
186
- for newspan in self.concatenate(span1, span2):
187
- chart[i][j].add(newspan)
188
-
189
- for parse in chart[len(self._tokens)][0]._entries:
190
- conll_format = ""
191
- # malt_format = ""
192
- for i in range(len(tokens)):
193
- # malt_format += '%s\t%s\t%d\t%s\n' % (tokens[i], 'null', parse._arcs[i] + 1, 'null')
194
- #conll_format += '\t%d\t%s\t%s\t%s\t%s\t%s\t%d\t%s\t%s\t%s\n' % (i+1, tokens[i], tokens[i], 'null', 'null', 'null', parse._arcs[i] + 1, 'null', '-', '-')
195
- # Modify to comply with the new Dependency Graph requirement (at least must have an root elements)
196
- conll_format += '\t%d\t%s\t%s\t%s\t%s\t%s\t%d\t%s\t%s\t%s\n' % (i+1, tokens[i], tokens[i], 'null', 'null', 'null', parse._arcs[i] + 1, 'ROOT', '-', '-')
197
- dg = DependencyGraph(conll_format)
198
- # if self.meets_arity(dg):
199
- yield dg.tree()
200
-
201
-
202
- def concatenate(self, span1, span2):
203
- """
204
- Concatenates the two spans in whichever way possible. This
205
- includes rightward concatenation (from the leftmost word of the
206
- leftmost span to the rightmost word of the rightmost span) and
207
- leftward concatenation (vice-versa) between adjacent spans. Unlike
208
- Eisner's presentation of span concatenation, these spans do not
209
- share or pivot on a particular word/word-index.
210
-
211
- :return: A list of new spans formed through concatenation.
212
- :rtype: list(DependencySpan)
213
- """
214
- spans = []
215
- if span1._start_index == span2._start_index:
216
- print('Error: Mismatched spans - replace this with thrown error')
217
- if span1._start_index > span2._start_index:
218
- temp_span = span1
219
- span1 = span2
220
- span2 = temp_span
221
- # adjacent rightward covered concatenation
222
- new_arcs = span1._arcs + span2._arcs
223
- new_tags = span1._tags + span2._tags
224
- if self._grammar.contains(self._tokens[span1._head_index], self._tokens[span2._head_index]):
225
- # print 'Performing rightward cover %d to %d' % (span1._head_index, span2._head_index)
226
- new_arcs[span2._head_index - span1._start_index] = span1._head_index
227
- spans.append(DependencySpan(span1._start_index, span2._end_index, span1._head_index, new_arcs, new_tags))
228
- # adjacent leftward covered concatenation
229
- new_arcs = span1._arcs + span2._arcs
230
- if self._grammar.contains(self._tokens[span2._head_index], self._tokens[span1._head_index]):
231
- # print 'performing leftward cover %d to %d' % (span2._head_index, span1._head_index)
232
- new_arcs[span1._head_index - span1._start_index] = span2._head_index
233
- spans.append(DependencySpan(span1._start_index, span2._end_index, span2._head_index, new_arcs, new_tags))
234
- return spans
235
-
236
-
237
- #################################################################
238
- # Parsing with Probabilistic Dependency Grammars
239
- #################################################################
240
-
241
-
242
- class ProbabilisticProjectiveDependencyParser(object):
243
- """A probabilistic, projective dependency parser.
244
-
245
- This parser returns the most probable projective parse derived from the
246
- probabilistic dependency grammar derived from the train() method. The
247
- probabilistic model is an implementation of Eisner's (1996) Model C, which
248
- conditions on head-word, head-tag, child-word, and child-tag. The decoding
249
- uses a bottom-up chart-based span concatenation algorithm that's identical
250
- to the one utilized by the rule-based projective parser.
251
-
252
- Usage example
253
- -------------
254
- >>> from nltk.parse.dependencygraph import conll_data2
255
-
256
- >>> graphs = [
257
- ... DependencyGraph(entry) for entry in conll_data2.split('\\n\\n') if entry
258
- ... ]
259
-
260
- >>> ppdp = ProbabilisticProjectiveDependencyParser()
261
- >>> ppdp.train(graphs)
262
-
263
- >>> sent = ['Cathy', 'zag', 'hen', 'wild', 'zwaaien', '.']
264
- >>> list(ppdp.parse(sent))
265
- [Tree('zag', ['Cathy', 'hen', Tree('zwaaien', ['wild', '.'])])]
266
-
267
- """
268
-
269
- def __init__(self):
270
- """
271
- Create a new probabilistic dependency parser. No additional
272
- operations are necessary.
273
- """
274
-
275
- def parse(self, tokens):
276
- """
277
- Parses the list of tokens subject to the projectivity constraint
278
- and the productions in the parser's grammar. This uses a method
279
- similar to the span-concatenation algorithm defined in Eisner (1996).
280
- It returns the most probable parse derived from the parser's
281
- probabilistic dependency grammar.
282
- """
283
- self._tokens = list(tokens)
284
- chart = []
285
- for i in range(0, len(self._tokens) + 1):
286
- chart.append([])
287
- for j in range(0, len(self._tokens) + 1):
288
- chart[i].append(ChartCell(i,j))
289
- if i==j+1:
290
- if tokens[i-1] in self._grammar._tags:
291
- for tag in self._grammar._tags[tokens[i-1]]:
292
- chart[i][j].add(DependencySpan(i-1,i,i-1,[-1], [tag]))
293
- else:
294
- print('No tag found for input token \'%s\', parse is impossible.' % tokens[i-1])
295
- return []
296
- for i in range(1,len(self._tokens)+1):
297
- for j in range(i-2,-1,-1):
298
- for k in range(i-1,j,-1):
299
- for span1 in chart[k][j]._entries:
300
- for span2 in chart[i][k]._entries:
301
- for newspan in self.concatenate(span1, span2):
302
- chart[i][j].add(newspan)
303
- trees = []
304
- max_parse = None
305
- max_score = 0
306
- for parse in chart[len(self._tokens)][0]._entries:
307
- conll_format = ""
308
- malt_format = ""
309
- for i in range(len(tokens)):
310
- malt_format += '%s\t%s\t%d\t%s\n' % (tokens[i], 'null', parse._arcs[i] + 1, 'null')
311
- #conll_format += '\t%d\t%s\t%s\t%s\t%s\t%s\t%d\t%s\t%s\t%s\n' % (i+1, tokens[i], tokens[i], parse._tags[i], parse._tags[i], 'null', parse._arcs[i] + 1, 'null', '-', '-')
312
- # Modify to comply with recent change in dependency graph such that there must be a ROOT element.
313
- conll_format += '\t%d\t%s\t%s\t%s\t%s\t%s\t%d\t%s\t%s\t%s\n' % (i+1, tokens[i], tokens[i], parse._tags[i], parse._tags[i], 'null', parse._arcs[i] + 1, 'ROOT', '-', '-')
314
- dg = DependencyGraph(conll_format)
315
- score = self.compute_prob(dg)
316
- trees.append((score, dg.tree()))
317
- trees.sort()
318
- return (tree for (score, tree) in trees)
319
-
320
-
321
- def concatenate(self, span1, span2):
322
- """
323
- Concatenates the two spans in whichever way possible. This
324
- includes rightward concatenation (from the leftmost word of the
325
- leftmost span to the rightmost word of the rightmost span) and
326
- leftward concatenation (vice-versa) between adjacent spans. Unlike
327
- Eisner's presentation of span concatenation, these spans do not
328
- share or pivot on a particular word/word-index.
329
-
330
- :return: A list of new spans formed through concatenation.
331
- :rtype: list(DependencySpan)
332
- """
333
- spans = []
334
- if span1._start_index == span2._start_index:
335
- print('Error: Mismatched spans - replace this with thrown error')
336
- if span1._start_index > span2._start_index:
337
- temp_span = span1
338
- span1 = span2
339
- span2 = temp_span
340
- # adjacent rightward covered concatenation
341
- new_arcs = span1._arcs + span2._arcs
342
- new_tags = span1._tags + span2._tags
343
- if self._grammar.contains(self._tokens[span1._head_index], self._tokens[span2._head_index]):
344
- new_arcs[span2._head_index - span1._start_index] = span1._head_index
345
- spans.append(DependencySpan(span1._start_index, span2._end_index, span1._head_index, new_arcs, new_tags))
346
- # adjacent leftward covered concatenation
347
- new_arcs = span1._arcs + span2._arcs
348
- new_tags = span1._tags + span2._tags
349
- if self._grammar.contains(self._tokens[span2._head_index], self._tokens[span1._head_index]):
350
- new_arcs[span1._head_index - span1._start_index] = span2._head_index
351
- spans.append(DependencySpan(span1._start_index, span2._end_index, span2._head_index, new_arcs, new_tags))
352
- return spans
353
-
354
- def train(self, graphs):
355
- """
356
- Trains a ProbabilisticDependencyGrammar based on the list of input
357
- DependencyGraphs. This model is an implementation of Eisner's (1996)
358
- Model C, which derives its statistics from head-word, head-tag,
359
- child-word, and child-tag relationships.
360
-
361
- :param graphs: A list of dependency graphs to train from.
362
- :type: list(DependencyGraph)
363
- """
364
- productions = []
365
- events = defaultdict(int)
366
- tags = {}
367
- for dg in graphs:
368
- for node_index in range(1, len(dg.nodes)):
369
- #children = dg.nodes[node_index]['deps']
370
- # Put list so that in will work in python 3
371
- children = sum(list(dg.nodes[node_index]['deps'].values()), [])
372
-
373
- nr_left_children = dg.left_children(node_index)
374
- nr_right_children = dg.right_children(node_index)
375
- nr_children = nr_left_children + nr_right_children
376
- for child_index in range(0 - (nr_left_children + 1), nr_right_children + 2):
377
- head_word = dg.nodes[node_index]['word']
378
- head_tag = dg.nodes[node_index]['tag']
379
- if head_word in tags:
380
- tags[head_word].add(head_tag)
381
- else:
382
- tags[head_word] = set([head_tag])
383
- child = 'STOP'
384
- child_tag = 'STOP'
385
- prev_word = 'START'
386
- prev_tag = 'START'
387
- if child_index < 0:
388
- array_index = child_index + nr_left_children
389
- if array_index >= 0:
390
- child = dg.nodes[children[array_index]]['word']
391
- child_tag = dg.nodes[children[array_index]]['tag']
392
- if child_index != -1:
393
- prev_word = dg.nodes[children[array_index + 1]]['word']
394
- prev_tag = dg.nodes[children[array_index + 1]]['tag']
395
- if child != 'STOP':
396
- productions.append(DependencyProduction(head_word, [child]))
397
- head_event = '(head (%s %s) (mods (%s, %s, %s) left))' % (child, child_tag, prev_tag, head_word, head_tag)
398
- mod_event = '(mods (%s, %s, %s) left))' % (prev_tag, head_word, head_tag)
399
- events[head_event] += 1
400
- events[mod_event] += 1
401
- elif child_index > 0:
402
- array_index = child_index + nr_left_children - 1
403
- if array_index < nr_children:
404
- child = dg.nodes[children[array_index]]['word']
405
- child_tag = dg.nodes[children[array_index]]['tag']
406
- if child_index != 1:
407
- prev_word = dg.nodes[children[array_index - 1]]['word']
408
- prev_tag = dg.nodes[children[array_index - 1]]['tag']
409
- if child != 'STOP':
410
- productions.append(DependencyProduction(head_word, [child]))
411
- head_event = '(head (%s %s) (mods (%s, %s, %s) right))' % (child, child_tag, prev_tag, head_word, head_tag)
412
- mod_event = '(mods (%s, %s, %s) right))' % (prev_tag, head_word, head_tag)
413
- events[head_event] += 1
414
- events[mod_event] += 1
415
- self._grammar = ProbabilisticDependencyGrammar(productions, events, tags)
416
-
417
- def compute_prob(self, dg):
418
- """
419
- Computes the probability of a dependency graph based
420
- on the parser's probability model (defined by the parser's
421
- statistical dependency grammar).
422
-
423
- :param dg: A dependency graph to score.
424
- :type dg: DependencyGraph
425
- :return: The probability of the dependency graph.
426
- :rtype: int
427
- """
428
- prob = 1.0
429
- for node_index in range(1, len(dg.nodes)):
430
- #children = dg.nodes[node_index]['deps']
431
- children = sum(list(dg.nodes[node_index]['deps'].values()), [])
432
-
433
- nr_left_children = dg.left_children(node_index)
434
- nr_right_children = dg.right_children(node_index)
435
- nr_children = nr_left_children + nr_right_children
436
- for child_index in range(0 - (nr_left_children + 1), nr_right_children + 2):
437
- head_word = dg.nodes[node_index]['word']
438
- head_tag = dg.nodes[node_index]['tag']
439
- child = 'STOP'
440
- child_tag = 'STOP'
441
- prev_word = 'START'
442
- prev_tag = 'START'
443
- if child_index < 0:
444
- array_index = child_index + nr_left_children
445
- if array_index >= 0:
446
- child = dg.nodes[children[array_index]]['word']
447
- child_tag = dg.nodes[children[array_index]]['tag']
448
- if child_index != -1:
449
- prev_word = dg.nodes[children[array_index + 1]]['word']
450
- prev_tag = dg.nodes[children[array_index + 1]]['tag']
451
- head_event = '(head (%s %s) (mods (%s, %s, %s) left))' % (child, child_tag, prev_tag, head_word, head_tag)
452
- mod_event = '(mods (%s, %s, %s) left))' % (prev_tag, head_word, head_tag)
453
- h_count = self._grammar._events[head_event]
454
- m_count = self._grammar._events[mod_event]
455
-
456
- # If the grammar is not covered
457
- if m_count != 0:
458
- prob *= (h_count / m_count)
459
- else:
460
- prob = 0.00000001 # Very small number
461
-
462
- elif child_index > 0:
463
- array_index = child_index + nr_left_children - 1
464
- if array_index < nr_children:
465
- child = dg.nodes[children[array_index]]['word']
466
- child_tag = dg.nodes[children[array_index]]['tag']
467
- if child_index != 1:
468
- prev_word = dg.nodes[children[array_index - 1]]['word']
469
- prev_tag = dg.nodes[children[array_index - 1]]['tag']
470
- head_event = '(head (%s %s) (mods (%s, %s, %s) right))' % (child, child_tag, prev_tag, head_word, head_tag)
471
- mod_event = '(mods (%s, %s, %s) right))' % (prev_tag, head_word, head_tag)
472
- h_count = self._grammar._events[head_event]
473
- m_count = self._grammar._events[mod_event]
474
-
475
- if m_count != 0:
476
- prob *= (h_count / m_count)
477
- else:
478
- prob = 0.00000001 # Very small number
479
-
480
- return prob
481
-
482
-
483
- #################################################################
484
- # Demos
485
- #################################################################
486
-
487
- def demo():
488
- projective_rule_parse_demo()
489
- # arity_parse_demo()
490
- projective_prob_parse_demo()
491
-
492
-
493
- def projective_rule_parse_demo():
494
- """
495
- A demonstration showing the creation and use of a
496
- ``DependencyGrammar`` to perform a projective dependency
497
- parse.
498
- """
499
- grammar = DependencyGrammar.fromstring("""
500
- 'scratch' -> 'cats' | 'walls'
501
- 'walls' -> 'the'
502
- 'cats' -> 'the'
503
- """)
504
- print(grammar)
505
- pdp = ProjectiveDependencyParser(grammar)
506
- trees = pdp.parse(['the', 'cats', 'scratch', 'the', 'walls'])
507
- for tree in trees:
508
- print(tree)
509
-
510
- def arity_parse_demo():
511
- """
512
- A demonstration showing the creation of a ``DependencyGrammar``
513
- in which a specific number of modifiers is listed for a given
514
- head. This can further constrain the number of possible parses
515
- created by a ``ProjectiveDependencyParser``.
516
- """
517
- print()
518
- print('A grammar with no arity constraints. Each DependencyProduction')
519
- print('specifies a relationship between one head word and only one')
520
- print('modifier word.')
521
- grammar = DependencyGrammar.fromstring("""
522
- 'fell' -> 'price' | 'stock'
523
- 'price' -> 'of' | 'the'
524
- 'of' -> 'stock'
525
- 'stock' -> 'the'
526
- """)
527
- print(grammar)
528
-
529
- print()
530
- print('For the sentence \'The price of the stock fell\', this grammar')
531
- print('will produce the following three parses:')
532
- pdp = ProjectiveDependencyParser(grammar)
533
- trees = pdp.parse(['the', 'price', 'of', 'the', 'stock', 'fell'])
534
- for tree in trees:
535
- print(tree)
536
-
537
- print()
538
- print('By contrast, the following grammar contains a ')
539
- print('DependencyProduction that specifies a relationship')
540
- print('between a single head word, \'price\', and two modifier')
541
- print('words, \'of\' and \'the\'.')
542
- grammar = DependencyGrammar.fromstring("""
543
- 'fell' -> 'price' | 'stock'
544
- 'price' -> 'of' 'the'
545
- 'of' -> 'stock'
546
- 'stock' -> 'the'
547
- """)
548
- print(grammar)
549
-
550
- print()
551
- print('This constrains the number of possible parses to just one:') # unimplemented, soon to replace
552
- pdp = ProjectiveDependencyParser(grammar)
553
- trees = pdp.parse(['the', 'price', 'of', 'the', 'stock', 'fell'])
554
- for tree in trees:
555
- print(tree)
556
-
557
-
558
- def projective_prob_parse_demo():
559
- """
560
- A demo showing the training and use of a projective
561
- dependency parser.
562
- """
563
- from nltk.parse.dependencygraph import conll_data2
564
-
565
- graphs = [DependencyGraph(entry)
566
- for entry in conll_data2.split('\n\n') if entry]
567
- ppdp = ProbabilisticProjectiveDependencyParser()
568
- print('Training Probabilistic Projective Dependency Parser...')
569
- ppdp.train(graphs)
570
-
571
- sent = ['Cathy', 'zag', 'hen', 'wild', 'zwaaien', '.']
572
- print('Parsing \'', " ".join(sent), '\'...')
573
- print('Parse:')
574
- for tree in ppdp.parse(sent):
575
- print(tree)
576
-
577
- if __name__ == '__main__':
578
- demo()
1
+ # Natural Language Toolkit: Dependency Grammars
2
+ #
3
+ # Copyright (C) 2001-2018 NLTK Project
4
+ # Author: Jason Narad <jason.narad@gmail.com>
5
+ #
6
+ # URL: <http://nltk.org/>
7
+ # For license information, see LICENSE.TXT
8
+ #
9
+ from __future__ import print_function, unicode_literals
10
+
11
+ from collections import defaultdict
12
+ from itertools import chain
13
+ from functools import total_ordering
14
+
15
+ from nltk.grammar import (DependencyProduction, DependencyGrammar,
16
+ ProbabilisticDependencyGrammar)
17
+ from nltk.parse.dependencygraph import DependencyGraph
18
+ from nltk.internals import raise_unorderable_types
19
+ from nltk.compat import python_2_unicode_compatible
20
+
21
+ #################################################################
22
+ # Dependency Span
23
+ #################################################################
24
+
25
+ @total_ordering
26
+ @python_2_unicode_compatible
27
+ class DependencySpan(object):
28
+ """
29
+ A contiguous span over some part of the input string representing
30
+ dependency (head -> modifier) relationships amongst words. An atomic
31
+ span corresponds to only one word so it isn't a 'span' in the conventional
32
+ sense, as its _start_index = _end_index = _head_index for concatenation
33
+ purposes. All other spans are assumed to have arcs between all nodes
34
+ within the start and end indexes of the span, and one head index corresponding
35
+ to the head word for the entire span. This is the same as the root node if
36
+ the dependency structure were depicted as a graph.
37
+ """
38
+ def __init__(self, start_index, end_index, head_index, arcs, tags):
39
+ self._start_index = start_index
40
+ self._end_index = end_index
41
+ self._head_index = head_index
42
+ self._arcs = arcs
43
+ self._tags = tags
44
+ self._comparison_key = (start_index, end_index, head_index, tuple(arcs))
45
+ self._hash = hash(self._comparison_key)
46
+
47
+ def head_index(self):
48
+ """
49
+ :return: An value indexing the head of the entire ``DependencySpan``.
50
+ :rtype: int
51
+ """
52
+ return self._head_index
53
+
54
+ def __repr__(self):
55
+ """
56
+ :return: A concise string representatino of the ``DependencySpan``.
57
+ :rtype: str.
58
+ """
59
+ return 'Span %d-%d; Head Index: %d' % (self._start_index, self._end_index, self._head_index)
60
+
61
+ def __str__(self):
62
+ """
63
+ :return: A verbose string representation of the ``DependencySpan``.
64
+ :rtype: str
65
+ """
66
+ str = 'Span %d-%d; Head Index: %d' % (self._start_index, self._end_index, self._head_index)
67
+ for i in range(len(self._arcs)):
68
+ str += '\n%d <- %d, %s' % (i, self._arcs[i], self._tags[i])
69
+ return str
70
+
71
+ def __eq__(self, other):
72
+ return (type(self) == type(other) and
73
+ self._comparison_key == other._comparison_key)
74
+
75
+ def __ne__(self, other):
76
+ return not self == other
77
+
78
+ def __lt__(self, other):
79
+ if not isinstance(other, DependencySpan):
80
+ raise_unorderable_types("<", self, other)
81
+ return self._comparison_key < other._comparison_key
82
+
83
+ def __hash__(self):
84
+ """
85
+ :return: The hash value of this ``DependencySpan``.
86
+ """
87
+ return self._hash
88
+
89
+ #################################################################
90
+ # Chart Cell
91
+ #################################################################
92
+
93
+ @python_2_unicode_compatible
94
+ class ChartCell(object):
95
+ """
96
+ A cell from the parse chart formed when performing the CYK algorithm.
97
+ Each cell keeps track of its x and y coordinates (though this will probably
98
+ be discarded), and a list of spans serving as the cell's entries.
99
+ """
100
+ def __init__(self, x, y):
101
+ """
102
+ :param x: This cell's x coordinate.
103
+ :type x: int.
104
+ :param y: This cell's y coordinate.
105
+ :type y: int.
106
+ """
107
+ self._x = x
108
+ self._y = y
109
+ self._entries = set([])
110
+
111
+ def add(self, span):
112
+ """
113
+ Appends the given span to the list of spans
114
+ representing the chart cell's entries.
115
+
116
+ :param span: The span to add.
117
+ :type span: DependencySpan
118
+ """
119
+ self._entries.add(span)
120
+
121
+ def __str__(self):
122
+ """
123
+ :return: A verbose string representation of this ``ChartCell``.
124
+ :rtype: str.
125
+ """
126
+ return 'CC[%d,%d]: %s' % (self._x, self._y, self._entries)
127
+
128
+ def __repr__(self):
129
+ """
130
+ :return: A concise string representation of this ``ChartCell``.
131
+ :rtype: str.
132
+ """
133
+ return '%s' % self
134
+
135
+
136
+ #################################################################
137
+ # Parsing with Dependency Grammars
138
+ #################################################################
139
+
140
+
141
+ class ProjectiveDependencyParser(object):
142
+ """
143
+ A projective, rule-based, dependency parser. A ProjectiveDependencyParser
144
+ is created with a DependencyGrammar, a set of productions specifying
145
+ word-to-word dependency relations. The parse() method will then
146
+ return the set of all parses, in tree representation, for a given input
147
+ sequence of tokens. Each parse must meet the requirements of the both
148
+ the grammar and the projectivity constraint which specifies that the
149
+ branches of the dependency tree are not allowed to cross. Alternatively,
150
+ this can be understood as stating that each parent node and its children
151
+ in the parse tree form a continuous substring of the input sequence.
152
+ """
153
+
154
+ def __init__(self, dependency_grammar):
155
+ """
156
+ Create a new ProjectiveDependencyParser, from a word-to-word
157
+ dependency grammar ``DependencyGrammar``.
158
+
159
+ :param dependency_grammar: A word-to-word relation dependencygrammar.
160
+ :type dependency_grammar: DependencyGrammar
161
+ """
162
+ self._grammar = dependency_grammar
163
+
164
+ def parse(self, tokens):
165
+ """
166
+ Performs a projective dependency parse on the list of tokens using
167
+ a chart-based, span-concatenation algorithm similar to Eisner (1996).
168
+
169
+ :param tokens: The list of input tokens.
170
+ :type tokens: list(str)
171
+ :return: An iterator over parse trees.
172
+ :rtype: iter(Tree)
173
+ """
174
+ self._tokens = list(tokens)
175
+ chart = []
176
+ for i in range(0, len(self._tokens) + 1):
177
+ chart.append([])
178
+ for j in range(0, len(self._tokens) + 1):
179
+ chart[i].append(ChartCell(i,j))
180
+ if i==j+1:
181
+ chart[i][j].add(DependencySpan(i-1,i,i-1,[-1], ['null']))
182
+
183
+ for i in range(1,len(self._tokens)+1):
184
+ for j in range(i-2,-1,-1):
185
+ for k in range(i-1,j,-1):
186
+ for span1 in chart[k][j]._entries:
187
+ for span2 in chart[i][k]._entries:
188
+ for newspan in self.concatenate(span1, span2):
189
+ chart[i][j].add(newspan)
190
+
191
+ for parse in chart[len(self._tokens)][0]._entries:
192
+ conll_format = ""
193
+ # malt_format = ""
194
+ for i in range(len(tokens)):
195
+ # malt_format += '%s\t%s\t%d\t%s\n' % (tokens[i], 'null', parse._arcs[i] + 1, 'null')
196
+ #conll_format += '\t%d\t%s\t%s\t%s\t%s\t%s\t%d\t%s\t%s\t%s\n' % (i+1, tokens[i], tokens[i], 'null', 'null', 'null', parse._arcs[i] + 1, 'null', '-', '-')
197
+ # Modify to comply with the new Dependency Graph requirement (at least must have an root elements)
198
+ conll_format += '\t%d\t%s\t%s\t%s\t%s\t%s\t%d\t%s\t%s\t%s\n' % (i+1, tokens[i], tokens[i], 'null', 'null', 'null', parse._arcs[i] + 1, 'ROOT', '-', '-')
199
+ dg = DependencyGraph(conll_format)
200
+ # if self.meets_arity(dg):
201
+ yield dg.tree()
202
+
203
+
204
+ def concatenate(self, span1, span2):
205
+ """
206
+ Concatenates the two spans in whichever way possible. This
207
+ includes rightward concatenation (from the leftmost word of the
208
+ leftmost span to the rightmost word of the rightmost span) and
209
+ leftward concatenation (vice-versa) between adjacent spans. Unlike
210
+ Eisner's presentation of span concatenation, these spans do not
211
+ share or pivot on a particular word/word-index.
212
+
213
+ :return: A list of new spans formed through concatenation.
214
+ :rtype: list(DependencySpan)
215
+ """
216
+ spans = []
217
+ if span1._start_index == span2._start_index:
218
+ print('Error: Mismatched spans - replace this with thrown error')
219
+ if span1._start_index > span2._start_index:
220
+ temp_span = span1
221
+ span1 = span2
222
+ span2 = temp_span
223
+ # adjacent rightward covered concatenation
224
+ new_arcs = span1._arcs + span2._arcs
225
+ new_tags = span1._tags + span2._tags
226
+ if self._grammar.contains(self._tokens[span1._head_index], self._tokens[span2._head_index]):
227
+ # print 'Performing rightward cover %d to %d' % (span1._head_index, span2._head_index)
228
+ new_arcs[span2._head_index - span1._start_index] = span1._head_index
229
+ spans.append(DependencySpan(span1._start_index, span2._end_index, span1._head_index, new_arcs, new_tags))
230
+ # adjacent leftward covered concatenation
231
+ new_arcs = span1._arcs + span2._arcs
232
+ if self._grammar.contains(self._tokens[span2._head_index], self._tokens[span1._head_index]):
233
+ # print 'performing leftward cover %d to %d' % (span2._head_index, span1._head_index)
234
+ new_arcs[span1._head_index - span1._start_index] = span2._head_index
235
+ spans.append(DependencySpan(span1._start_index, span2._end_index, span2._head_index, new_arcs, new_tags))
236
+ return spans
237
+
238
+
239
+ #################################################################
240
+ # Parsing with Probabilistic Dependency Grammars
241
+ #################################################################
242
+
243
+
244
+ class ProbabilisticProjectiveDependencyParser(object):
245
+ """A probabilistic, projective dependency parser.
246
+
247
+ This parser returns the most probable projective parse derived from the
248
+ probabilistic dependency grammar derived from the train() method. The
249
+ probabilistic model is an implementation of Eisner's (1996) Model C, which
250
+ conditions on head-word, head-tag, child-word, and child-tag. The decoding
251
+ uses a bottom-up chart-based span concatenation algorithm that's identical
252
+ to the one utilized by the rule-based projective parser.
253
+
254
+ Usage example
255
+ -------------
256
+ >>> from nltk.parse.dependencygraph import conll_data2
257
+
258
+ >>> graphs = [
259
+ ... DependencyGraph(entry) for entry in conll_data2.split('\\n\\n') if entry
260
+ ... ]
261
+
262
+ >>> ppdp = ProbabilisticProjectiveDependencyParser()
263
+ >>> ppdp.train(graphs)
264
+
265
+ >>> sent = ['Cathy', 'zag', 'hen', 'wild', 'zwaaien', '.']
266
+ >>> list(ppdp.parse(sent))
267
+ [Tree('zag', ['Cathy', 'hen', Tree('zwaaien', ['wild', '.'])])]
268
+
269
+ """
270
+
271
+ def __init__(self):
272
+ """
273
+ Create a new probabilistic dependency parser. No additional
274
+ operations are necessary.
275
+ """
276
+
277
+ def parse(self, tokens):
278
+ """
279
+ Parses the list of tokens subject to the projectivity constraint
280
+ and the productions in the parser's grammar. This uses a method
281
+ similar to the span-concatenation algorithm defined in Eisner (1996).
282
+ It returns the most probable parse derived from the parser's
283
+ probabilistic dependency grammar.
284
+ """
285
+ self._tokens = list(tokens)
286
+ chart = []
287
+ for i in range(0, len(self._tokens) + 1):
288
+ chart.append([])
289
+ for j in range(0, len(self._tokens) + 1):
290
+ chart[i].append(ChartCell(i,j))
291
+ if i==j+1:
292
+ if tokens[i-1] in self._grammar._tags:
293
+ for tag in self._grammar._tags[tokens[i-1]]:
294
+ chart[i][j].add(DependencySpan(i-1,i,i-1,[-1], [tag]))
295
+ else:
296
+ print('No tag found for input token \'%s\', parse is impossible.' % tokens[i-1])
297
+ return []
298
+ for i in range(1,len(self._tokens)+1):
299
+ for j in range(i-2,-1,-1):
300
+ for k in range(i-1,j,-1):
301
+ for span1 in chart[k][j]._entries:
302
+ for span2 in chart[i][k]._entries:
303
+ for newspan in self.concatenate(span1, span2):
304
+ chart[i][j].add(newspan)
305
+ trees = []
306
+ max_parse = None
307
+ max_score = 0
308
+ for parse in chart[len(self._tokens)][0]._entries:
309
+ conll_format = ""
310
+ malt_format = ""
311
+ for i in range(len(tokens)):
312
+ malt_format += '%s\t%s\t%d\t%s\n' % (tokens[i], 'null', parse._arcs[i] + 1, 'null')
313
+ #conll_format += '\t%d\t%s\t%s\t%s\t%s\t%s\t%d\t%s\t%s\t%s\n' % (i+1, tokens[i], tokens[i], parse._tags[i], parse._tags[i], 'null', parse._arcs[i] + 1, 'null', '-', '-')
314
+ # Modify to comply with recent change in dependency graph such that there must be a ROOT element.
315
+ conll_format += '\t%d\t%s\t%s\t%s\t%s\t%s\t%d\t%s\t%s\t%s\n' % (i+1, tokens[i], tokens[i], parse._tags[i], parse._tags[i], 'null', parse._arcs[i] + 1, 'ROOT', '-', '-')
316
+ dg = DependencyGraph(conll_format)
317
+ score = self.compute_prob(dg)
318
+ trees.append((score, dg.tree()))
319
+ trees.sort()
320
+ return (tree for (score, tree) in trees)
321
+
322
+
323
+ def concatenate(self, span1, span2):
324
+ """
325
+ Concatenates the two spans in whichever way possible. This
326
+ includes rightward concatenation (from the leftmost word of the
327
+ leftmost span to the rightmost word of the rightmost span) and
328
+ leftward concatenation (vice-versa) between adjacent spans. Unlike
329
+ Eisner's presentation of span concatenation, these spans do not
330
+ share or pivot on a particular word/word-index.
331
+
332
+ :return: A list of new spans formed through concatenation.
333
+ :rtype: list(DependencySpan)
334
+ """
335
+ spans = []
336
+ if span1._start_index == span2._start_index:
337
+ print('Error: Mismatched spans - replace this with thrown error')
338
+ if span1._start_index > span2._start_index:
339
+ temp_span = span1
340
+ span1 = span2
341
+ span2 = temp_span
342
+ # adjacent rightward covered concatenation
343
+ new_arcs = span1._arcs + span2._arcs
344
+ new_tags = span1._tags + span2._tags
345
+ if self._grammar.contains(self._tokens[span1._head_index], self._tokens[span2._head_index]):
346
+ new_arcs[span2._head_index - span1._start_index] = span1._head_index
347
+ spans.append(DependencySpan(span1._start_index, span2._end_index, span1._head_index, new_arcs, new_tags))
348
+ # adjacent leftward covered concatenation
349
+ new_arcs = span1._arcs + span2._arcs
350
+ new_tags = span1._tags + span2._tags
351
+ if self._grammar.contains(self._tokens[span2._head_index], self._tokens[span1._head_index]):
352
+ new_arcs[span1._head_index - span1._start_index] = span2._head_index
353
+ spans.append(DependencySpan(span1._start_index, span2._end_index, span2._head_index, new_arcs, new_tags))
354
+ return spans
355
+
356
+ def train(self, graphs):
357
+ """
358
+ Trains a ProbabilisticDependencyGrammar based on the list of input
359
+ DependencyGraphs. This model is an implementation of Eisner's (1996)
360
+ Model C, which derives its statistics from head-word, head-tag,
361
+ child-word, and child-tag relationships.
362
+
363
+ :param graphs: A list of dependency graphs to train from.
364
+ :type: list(DependencyGraph)
365
+ """
366
+ productions = []
367
+ events = defaultdict(int)
368
+ tags = {}
369
+ for dg in graphs:
370
+ for node_index in range(1, len(dg.nodes)):
371
+ #children = dg.nodes[node_index]['deps']
372
+ children = list(chain(*dg.nodes[node_index]['deps'].values()))
373
+
374
+ nr_left_children = dg.left_children(node_index)
375
+ nr_right_children = dg.right_children(node_index)
376
+ nr_children = nr_left_children + nr_right_children
377
+ for child_index in range(0 - (nr_left_children + 1), nr_right_children + 2):
378
+ head_word = dg.nodes[node_index]['word']
379
+ head_tag = dg.nodes[node_index]['tag']
380
+ if head_word in tags:
381
+ tags[head_word].add(head_tag)
382
+ else:
383
+ tags[head_word] = set([head_tag])
384
+ child = 'STOP'
385
+ child_tag = 'STOP'
386
+ prev_word = 'START'
387
+ prev_tag = 'START'
388
+ if child_index < 0:
389
+ array_index = child_index + nr_left_children
390
+ if array_index >= 0:
391
+ child = dg.nodes[children[array_index]]['word']
392
+ child_tag = dg.nodes[children[array_index]]['tag']
393
+ if child_index != -1:
394
+ prev_word = dg.nodes[children[array_index + 1]]['word']
395
+ prev_tag = dg.nodes[children[array_index + 1]]['tag']
396
+ if child != 'STOP':
397
+ productions.append(DependencyProduction(head_word, [child]))
398
+ head_event = '(head (%s %s) (mods (%s, %s, %s) left))' % (child, child_tag, prev_tag, head_word, head_tag)
399
+ mod_event = '(mods (%s, %s, %s) left))' % (prev_tag, head_word, head_tag)
400
+ events[head_event] += 1
401
+ events[mod_event] += 1
402
+ elif child_index > 0:
403
+ array_index = child_index + nr_left_children - 1
404
+ if array_index < nr_children:
405
+ child = dg.nodes[children[array_index]]['word']
406
+ child_tag = dg.nodes[children[array_index]]['tag']
407
+ if child_index != 1:
408
+ prev_word = dg.nodes[children[array_index - 1]]['word']
409
+ prev_tag = dg.nodes[children[array_index - 1]]['tag']
410
+ if child != 'STOP':
411
+ productions.append(DependencyProduction(head_word, [child]))
412
+ head_event = '(head (%s %s) (mods (%s, %s, %s) right))' % (child, child_tag, prev_tag, head_word, head_tag)
413
+ mod_event = '(mods (%s, %s, %s) right))' % (prev_tag, head_word, head_tag)
414
+ events[head_event] += 1
415
+ events[mod_event] += 1
416
+ self._grammar = ProbabilisticDependencyGrammar(productions, events, tags)
417
+
418
+ def compute_prob(self, dg):
419
+ """
420
+ Computes the probability of a dependency graph based
421
+ on the parser's probability model (defined by the parser's
422
+ statistical dependency grammar).
423
+
424
+ :param dg: A dependency graph to score.
425
+ :type dg: DependencyGraph
426
+ :return: The probability of the dependency graph.
427
+ :rtype: int
428
+ """
429
+ prob = 1.0
430
+ for node_index in range(1, len(dg.nodes)):
431
+ #children = dg.nodes[node_index]['deps']
432
+ children = list(chain(*dg.nodes[node_index]['deps'].values()))
433
+
434
+ nr_left_children = dg.left_children(node_index)
435
+ nr_right_children = dg.right_children(node_index)
436
+ nr_children = nr_left_children + nr_right_children
437
+ for child_index in range(0 - (nr_left_children + 1), nr_right_children + 2):
438
+ head_word = dg.nodes[node_index]['word']
439
+ head_tag = dg.nodes[node_index]['tag']
440
+ child = 'STOP'
441
+ child_tag = 'STOP'
442
+ prev_word = 'START'
443
+ prev_tag = 'START'
444
+ if child_index < 0:
445
+ array_index = child_index + nr_left_children
446
+ if array_index >= 0:
447
+ child = dg.nodes[children[array_index]]['word']
448
+ child_tag = dg.nodes[children[array_index]]['tag']
449
+ if child_index != -1:
450
+ prev_word = dg.nodes[children[array_index + 1]]['word']
451
+ prev_tag = dg.nodes[children[array_index + 1]]['tag']
452
+ head_event = '(head (%s %s) (mods (%s, %s, %s) left))' % (child, child_tag, prev_tag, head_word, head_tag)
453
+ mod_event = '(mods (%s, %s, %s) left))' % (prev_tag, head_word, head_tag)
454
+ h_count = self._grammar._events[head_event]
455
+ m_count = self._grammar._events[mod_event]
456
+
457
+ # If the grammar is not covered
458
+ if m_count != 0:
459
+ prob *= (h_count / m_count)
460
+ else:
461
+ prob = 0.00000001 # Very small number
462
+
463
+ elif child_index > 0:
464
+ array_index = child_index + nr_left_children - 1
465
+ if array_index < nr_children:
466
+ child = dg.nodes[children[array_index]]['word']
467
+ child_tag = dg.nodes[children[array_index]]['tag']
468
+ if child_index != 1:
469
+ prev_word = dg.nodes[children[array_index - 1]]['word']
470
+ prev_tag = dg.nodes[children[array_index - 1]]['tag']
471
+ head_event = '(head (%s %s) (mods (%s, %s, %s) right))' % (child, child_tag, prev_tag, head_word, head_tag)
472
+ mod_event = '(mods (%s, %s, %s) right))' % (prev_tag, head_word, head_tag)
473
+ h_count = self._grammar._events[head_event]
474
+ m_count = self._grammar._events[mod_event]
475
+
476
+ if m_count != 0:
477
+ prob *= (h_count / m_count)
478
+ else:
479
+ prob = 0.00000001 # Very small number
480
+
481
+ return prob
482
+
483
+
484
+ #################################################################
485
+ # Demos
486
+ #################################################################
487
+
488
+ def demo():
489
+ projective_rule_parse_demo()
490
+ # arity_parse_demo()
491
+ projective_prob_parse_demo()
492
+
493
+
494
+ def projective_rule_parse_demo():
495
+ """
496
+ A demonstration showing the creation and use of a
497
+ ``DependencyGrammar`` to perform a projective dependency
498
+ parse.
499
+ """
500
+ grammar = DependencyGrammar.fromstring("""
501
+ 'scratch' -> 'cats' | 'walls'
502
+ 'walls' -> 'the'
503
+ 'cats' -> 'the'
504
+ """)
505
+ print(grammar)
506
+ pdp = ProjectiveDependencyParser(grammar)
507
+ trees = pdp.parse(['the', 'cats', 'scratch', 'the', 'walls'])
508
+ for tree in trees:
509
+ print(tree)
510
+
511
+ def arity_parse_demo():
512
+ """
513
+ A demonstration showing the creation of a ``DependencyGrammar``
514
+ in which a specific number of modifiers is listed for a given
515
+ head. This can further constrain the number of possible parses
516
+ created by a ``ProjectiveDependencyParser``.
517
+ """
518
+ print()
519
+ print('A grammar with no arity constraints. Each DependencyProduction')
520
+ print('specifies a relationship between one head word and only one')
521
+ print('modifier word.')
522
+ grammar = DependencyGrammar.fromstring("""
523
+ 'fell' -> 'price' | 'stock'
524
+ 'price' -> 'of' | 'the'
525
+ 'of' -> 'stock'
526
+ 'stock' -> 'the'
527
+ """)
528
+ print(grammar)
529
+
530
+ print()
531
+ print('For the sentence \'The price of the stock fell\', this grammar')
532
+ print('will produce the following three parses:')
533
+ pdp = ProjectiveDependencyParser(grammar)
534
+ trees = pdp.parse(['the', 'price', 'of', 'the', 'stock', 'fell'])
535
+ for tree in trees:
536
+ print(tree)
537
+
538
+ print()
539
+ print('By contrast, the following grammar contains a ')
540
+ print('DependencyProduction that specifies a relationship')
541
+ print('between a single head word, \'price\', and two modifier')
542
+ print('words, \'of\' and \'the\'.')
543
+ grammar = DependencyGrammar.fromstring("""
544
+ 'fell' -> 'price' | 'stock'
545
+ 'price' -> 'of' 'the'
546
+ 'of' -> 'stock'
547
+ 'stock' -> 'the'
548
+ """)
549
+ print(grammar)
550
+
551
+ print()
552
+ print('This constrains the number of possible parses to just one:') # unimplemented, soon to replace
553
+ pdp = ProjectiveDependencyParser(grammar)
554
+ trees = pdp.parse(['the', 'price', 'of', 'the', 'stock', 'fell'])
555
+ for tree in trees:
556
+ print(tree)
557
+
558
+
559
+ def projective_prob_parse_demo():
560
+ """
561
+ A demo showing the training and use of a projective
562
+ dependency parser.
563
+ """
564
+ from nltk.parse.dependencygraph import conll_data2
565
+
566
+ graphs = [DependencyGraph(entry)
567
+ for entry in conll_data2.split('\n\n') if entry]
568
+ ppdp = ProbabilisticProjectiveDependencyParser()
569
+ print('Training Probabilistic Projective Dependency Parser...')
570
+ ppdp.train(graphs)
571
+
572
+ sent = ['Cathy', 'zag', 'hen', 'wild', 'zwaaien', '.']
573
+ print('Parsing \'', " ".join(sent), '\'...')
574
+ print('Parse:')
575
+ for tree in ppdp.parse(sent):
576
+ print(tree)
577
+
578
+ if __name__ == '__main__':
579
+ demo()