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,533 +1,536 @@
1
- # -*- coding: utf-8 -*-
2
- # Natural Language Toolkit: IBM Model Core
3
- #
4
- # Copyright (C) 2001-2015 NLTK Project
5
- # Author: Tah Wei Hoon <hoon.tw@gmail.com>
6
- # URL: <http://nltk.org/>
7
- # For license information, see LICENSE.TXT
8
-
9
- """
10
- Common methods and classes for all IBM models. See ``IBMModel1``,
11
- ``IBMModel2``, ``IBMModel3``, ``IBMModel4``, and ``IBMModel5``
12
- for specific implementations.
13
-
14
- The IBM models are a series of generative models that learn lexical
15
- translation probabilities, p(target language word|source language word),
16
- given a sentence-aligned parallel corpus.
17
-
18
- The models increase in sophistication from model 1 to 5. Typically, the
19
- output of lower models is used to seed the higher models. All models
20
- use the Expectation-Maximization (EM) algorithm to learn various
21
- probability tables.
22
-
23
- Words in a sentence are one-indexed. The first word of a sentence has
24
- position 1, not 0. Index 0 is reserved in the source sentence for the
25
- NULL token. The concept of position does not apply to NULL, but it is
26
- indexed at 0 by convention.
27
-
28
- Each target word is aligned to exactly one source word or the NULL
29
- token.
30
-
31
- References:
32
- Philipp Koehn. 2010. Statistical Machine Translation.
33
- Cambridge University Press, New York.
34
-
35
- Peter E Brown, Stephen A. Della Pietra, Vincent J. Della Pietra, and
36
- Robert L. Mercer. 1993. The Mathematics of Statistical Machine
37
- Translation: Parameter Estimation. Computational Linguistics, 19 (2),
38
- 263-311.
39
- """
40
- from __future__ import division
41
- from bisect import insort_left
42
- from collections import defaultdict
43
- from copy import deepcopy
44
- from math import ceil
45
-
46
-
47
- def longest_target_sentence_length(sentence_aligned_corpus):
48
- """
49
- :param sentence_aligned_corpus: Parallel corpus under consideration
50
- :type sentence_aligned_corpus: list(AlignedSent)
51
- :return: Number of words in the longest target language sentence
52
- of ``sentence_aligned_corpus``
53
- """
54
- max_m = 0
55
- for aligned_sentence in sentence_aligned_corpus:
56
- m = len(aligned_sentence.words)
57
- max_m = max(m, max_m)
58
- return max_m
59
-
60
-
61
- class IBMModel(object):
62
- """
63
- Abstract base class for all IBM models
64
- """
65
- # Avoid division by zero and precision errors by imposing a minimum
66
- # value for probabilities. Note that this approach is theoretically
67
- # incorrect, since it may create probabilities that sum to more
68
- # than 1. In practice, the contribution of probabilities with MIN_PROB
69
- # is tiny enough that the value of MIN_PROB can be treated as zero.
70
- MIN_PROB = 1.0e-12 # GIZA++ is more liberal and uses 1.0e-7
71
-
72
- def __init__(self, sentence_aligned_corpus):
73
- self.init_vocab(sentence_aligned_corpus)
74
- self.reset_probabilities()
75
-
76
- def reset_probabilities(self):
77
- self.translation_table = defaultdict(
78
- lambda: defaultdict(lambda: IBMModel.MIN_PROB))
79
- """
80
- dict[str][str]: float. Probability(target word | source word).
81
- Values accessed as ``translation_table[target_word][source_word]``.
82
- """
83
-
84
- self.alignment_table = defaultdict(
85
- lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(
86
- lambda: IBMModel.MIN_PROB))))
87
- """
88
- dict[int][int][int][int]: float. Probability(i | j,l,m).
89
- Values accessed as ``alignment_table[i][j][l][m]``.
90
- Used in model 2 and hill climbing in models 3 and above
91
- """
92
-
93
- self.fertility_table = defaultdict(
94
- lambda: defaultdict(lambda: self.MIN_PROB))
95
- """
96
- dict[int][str]: float. Probability(fertility | source word).
97
- Values accessed as ``fertility_table[fertility][source_word]``.
98
- Used in model 3 and higher.
99
- """
100
-
101
- self.p1 = 0.5
102
- """
103
- Probability that a generated word requires another target word
104
- that is aligned to NULL.
105
- Used in model 3 and higher.
106
- """
107
-
108
- def set_uniform_probabilities(self, sentence_aligned_corpus):
109
- """
110
- Initialize probability tables to a uniform distribution
111
-
112
- Derived classes should implement this accordingly.
113
- """
114
- pass
115
-
116
- def init_vocab(self, sentence_aligned_corpus):
117
- src_vocab = set()
118
- trg_vocab = set()
119
- for aligned_sentence in sentence_aligned_corpus:
120
- trg_vocab.update(aligned_sentence.words)
121
- src_vocab.update(aligned_sentence.mots)
122
- # Add the NULL token
123
- src_vocab.add(None)
124
-
125
- self.src_vocab = src_vocab
126
- """
127
- set(str): All source language words used in training
128
- """
129
-
130
- self.trg_vocab = trg_vocab
131
- """
132
- set(str): All target language words used in training
133
- """
134
-
135
- def sample(self, sentence_pair):
136
- """
137
- Sample the most probable alignments from the entire alignment
138
- space
139
-
140
- First, determine the best alignment according to IBM Model 2.
141
- With this initial alignment, use hill climbing to determine the
142
- best alignment according to a higher IBM Model. Add this
143
- alignment and its neighbors to the sample set. Repeat this
144
- process with other initial alignments obtained by pegging an
145
- alignment point.
146
-
147
- Hill climbing may be stuck in a local maxima, hence the pegging
148
- and trying out of different alignments.
149
-
150
- :param sentence_pair: Source and target language sentence pair
151
- to generate a sample of alignments from
152
- :type sentence_pair: AlignedSent
153
-
154
- :return: A set of best alignments represented by their ``AlignmentInfo``
155
- and the best alignment of the set for convenience
156
- :rtype: set(AlignmentInfo), AlignmentInfo
157
- """
158
- sampled_alignments = set()
159
- l = len(sentence_pair.mots)
160
- m = len(sentence_pair.words)
161
-
162
- # Start from the best model 2 alignment
163
- initial_alignment = self.best_model2_alignment(sentence_pair)
164
- potential_alignment = self.hillclimb(initial_alignment)
165
- sampled_alignments.update(self.neighboring(potential_alignment))
166
- best_alignment = potential_alignment
167
-
168
- # Start from other model 2 alignments,
169
- # with the constraint that j is aligned (pegged) to i
170
- for j in range(1, m + 1):
171
- for i in range(0, l + 1):
172
- initial_alignment = self.best_model2_alignment(
173
- sentence_pair, j, i)
174
- potential_alignment = self.hillclimb(initial_alignment, j)
175
- neighbors = self.neighboring(potential_alignment, j)
176
- sampled_alignments.update(neighbors)
177
- if potential_alignment.score > best_alignment.score:
178
- best_alignment = potential_alignment
179
-
180
- return sampled_alignments, best_alignment
181
-
182
- def best_model2_alignment(self, sentence_pair, j_pegged=None, i_pegged=0):
183
- """
184
- Finds the best alignment according to IBM Model 2
185
-
186
- Used as a starting point for hill climbing in Models 3 and
187
- above, because it is easier to compute than the best alignments
188
- in higher models
189
-
190
- :param sentence_pair: Source and target language sentence pair
191
- to be word-aligned
192
- :type sentence_pair: AlignedSent
193
-
194
- :param j_pegged: If specified, the alignment point of j_pegged
195
- will be fixed to i_pegged
196
- :type j_pegged: int
197
-
198
- :param i_pegged: Alignment point to j_pegged
199
- :type i_pegged: int
200
- """
201
- src_sentence = [None] + sentence_pair.mots
202
- trg_sentence = ['UNUSED'] + sentence_pair.words # 1-indexed
203
-
204
- l = len(src_sentence) - 1 # exclude NULL
205
- m = len(trg_sentence) - 1
206
-
207
- alignment = [0] * (m + 1) # init all alignments to NULL
208
- cepts = [[] for i in range((l + 1))] # init all cepts to empty list
209
-
210
- for j in range(1, m + 1):
211
- if j == j_pegged:
212
- # use the pegged alignment instead of searching for best one
213
- best_i = i_pegged
214
- else:
215
- best_i = 0
216
- max_alignment_prob = IBMModel.MIN_PROB
217
- t = trg_sentence[j]
218
-
219
- for i in range(0, l + 1):
220
- s = src_sentence[i]
221
- alignment_prob = (self.translation_table[t][s] *
222
- self.alignment_table[i][j][l][m])
223
-
224
- if alignment_prob >= max_alignment_prob:
225
- max_alignment_prob = alignment_prob
226
- best_i = i
227
-
228
- alignment[j] = best_i
229
- cepts[best_i].append(j)
230
-
231
- return AlignmentInfo(tuple(alignment), tuple(src_sentence),
232
- tuple(trg_sentence), cepts)
233
-
234
- def hillclimb(self, alignment_info, j_pegged=None):
235
- """
236
- Starting from the alignment in ``alignment_info``, look at
237
- neighboring alignments iteratively for the best one
238
-
239
- There is no guarantee that the best alignment in the alignment
240
- space will be found, because the algorithm might be stuck in a
241
- local maximum.
242
-
243
- :param j_pegged: If specified, the search will be constrained to
244
- alignments where ``j_pegged`` remains unchanged
245
- :type j_pegged: int
246
-
247
- :return: The best alignment found from hill climbing
248
- :rtype: AlignmentInfo
249
- """
250
- alignment = alignment_info # alias with shorter name
251
- max_probability = self.prob_t_a_given_s(alignment)
252
-
253
- while True:
254
- old_alignment = alignment
255
- for neighbor_alignment in self.neighboring(alignment, j_pegged):
256
- neighbor_probability = self.prob_t_a_given_s(neighbor_alignment)
257
-
258
- if neighbor_probability > max_probability:
259
- alignment = neighbor_alignment
260
- max_probability = neighbor_probability
261
-
262
- if alignment == old_alignment:
263
- # Until there are no better alignments
264
- break
265
-
266
- alignment.score = max_probability
267
- return alignment
268
-
269
- def neighboring(self, alignment_info, j_pegged=None):
270
- """
271
- Determine the neighbors of ``alignment_info``, obtained by
272
- moving or swapping one alignment point
273
-
274
- :param j_pegged: If specified, neighbors that have a different
275
- alignment point from j_pegged will not be considered
276
- :type j_pegged: int
277
-
278
- :return: A set neighboring alignments represented by their
279
- ``AlignmentInfo``
280
- :rtype: set(AlignmentInfo)
281
- """
282
- neighbors = set()
283
-
284
- l = len(alignment_info.src_sentence) - 1 # exclude NULL
285
- m = len(alignment_info.trg_sentence) - 1
286
- original_alignment = alignment_info.alignment
287
- original_cepts = alignment_info.cepts
288
-
289
- for j in range(1, m + 1):
290
- if j != j_pegged:
291
- # Add alignments that differ by one alignment point
292
- for i in range(0, l + 1):
293
- new_alignment = list(original_alignment)
294
- new_cepts = deepcopy(original_cepts)
295
- old_i = original_alignment[j]
296
-
297
- # update alignment
298
- new_alignment[j] = i
299
-
300
- # update cepts
301
- insort_left(new_cepts[i], j)
302
- new_cepts[old_i].remove(j)
303
-
304
- new_alignment_info = AlignmentInfo(
305
- tuple(new_alignment), alignment_info.src_sentence,
306
- alignment_info.trg_sentence, new_cepts)
307
- neighbors.add(new_alignment_info)
308
-
309
- for j in range(1, m + 1):
310
- if j != j_pegged:
311
- # Add alignments that have two alignment points swapped
312
- for other_j in range(1, m + 1):
313
- if other_j != j_pegged and other_j != j:
314
- new_alignment = list(original_alignment)
315
- new_cepts = deepcopy(original_cepts)
316
- other_i = original_alignment[other_j]
317
- i = original_alignment[j]
318
-
319
- # update alignments
320
- new_alignment[j] = other_i
321
- new_alignment[other_j] = i
322
-
323
- # update cepts
324
- new_cepts[other_i].remove(other_j)
325
- insort_left(new_cepts[other_i], j)
326
- new_cepts[i].remove(j)
327
- insort_left(new_cepts[i], other_j)
328
-
329
- new_alignment_info = AlignmentInfo(
330
- tuple(new_alignment), alignment_info.src_sentence,
331
- alignment_info.trg_sentence, new_cepts)
332
- neighbors.add(new_alignment_info)
333
-
334
- return neighbors
335
-
336
- def maximize_lexical_translation_probabilities(self, counts):
337
- for t, src_words in counts.t_given_s.items():
338
- for s in src_words:
339
- estimate = counts.t_given_s[t][s] / counts.any_t_given_s[s]
340
- self.translation_table[t][s] = max(estimate, IBMModel.MIN_PROB)
341
-
342
- def maximize_fertility_probabilities(self, counts):
343
- for phi, src_words in counts.fertility.items():
344
- for s in src_words:
345
- estimate = (counts.fertility[phi][s] /
346
- counts.fertility_for_any_phi[s])
347
- self.fertility_table[phi][s] = max(estimate, IBMModel.MIN_PROB)
348
-
349
- def maximize_null_generation_probabilities(self, counts):
350
- p1_estimate = counts.p1 / (counts.p1 + counts.p0)
351
- p1_estimate = max(p1_estimate, IBMModel.MIN_PROB)
352
- # Clip p1 if it is too large, because p0 = 1 - p1 should not be
353
- # smaller than MIN_PROB
354
- self.p1 = min(p1_estimate, 1 - IBMModel.MIN_PROB)
355
-
356
- def prob_of_alignments(self, alignments):
357
- probability = 0
358
- for alignment_info in alignments:
359
- probability += self.prob_t_a_given_s(alignment_info)
360
- return probability
361
-
362
- def prob_t_a_given_s(self, alignment_info):
363
- """
364
- Probability of target sentence and an alignment given the
365
- source sentence
366
-
367
- All required information is assumed to be in ``alignment_info``
368
- and self.
369
-
370
- Derived classes should override this method
371
- """
372
- return 0.0
373
-
374
-
375
- class AlignmentInfo(object):
376
- """
377
- Helper data object for training IBM Models 3 and up
378
-
379
- Read-only. For a source sentence and its counterpart in the target
380
- language, this class holds information about the sentence pair's
381
- alignment, cepts, and fertility.
382
-
383
- Warning: Alignments are one-indexed here, in contrast to
384
- nltk.translate.Alignment and AlignedSent, which are zero-indexed
385
- This class is not meant to be used outside of IBM models.
386
- """
387
-
388
- def __init__(self, alignment, src_sentence, trg_sentence, cepts):
389
- if not isinstance(alignment, tuple):
390
- raise TypeError("The alignment must be a tuple because it is used "
391
- "to uniquely identify AlignmentInfo objects.")
392
-
393
- self.alignment = alignment
394
- """
395
- tuple(int): Alignment function. ``alignment[j]`` is the position
396
- in the source sentence that is aligned to the position j in the
397
- target sentence.
398
- """
399
-
400
- self.src_sentence = src_sentence
401
- """
402
- tuple(str): Source sentence referred to by this object.
403
- Should include NULL token (None) in index 0.
404
- """
405
-
406
- self.trg_sentence = trg_sentence
407
- """
408
- tuple(str): Target sentence referred to by this object.
409
- Should have a dummy element in index 0 so that the first word
410
- starts from index 1.
411
- """
412
-
413
- self.cepts = cepts
414
- """
415
- list(list(int)): The positions of the target words, in
416
- ascending order, aligned to a source word position. For example,
417
- cepts[4] = (2, 3, 7) means that words in positions 2, 3 and 7
418
- of the target sentence are aligned to the word in position 4 of
419
- the source sentence
420
- """
421
-
422
- self.score = None
423
- """
424
- float: Optional. Probability of alignment, as defined by the
425
- IBM model that assesses this alignment
426
- """
427
-
428
- def fertility_of_i(self, i):
429
- """
430
- Fertility of word in position ``i`` of the source sentence
431
- """
432
- return len(self.cepts[i])
433
-
434
- def is_head_word(self, j):
435
- """
436
- :return: Whether the word in position ``j`` of the target
437
- sentence is a head word
438
- """
439
- i = self.alignment[j]
440
- return self.cepts[i][0] == j
441
-
442
- def center_of_cept(self, i):
443
- """
444
- :return: The ceiling of the average positions of the words in
445
- the tablet of cept ``i``, or 0 if ``i`` is None
446
- """
447
- if i is None:
448
- return 0
449
-
450
- average_position = sum(self.cepts[i]) / len(self.cepts[i])
451
- return int(ceil(average_position))
452
-
453
- def previous_cept(self, j):
454
- """
455
- :return: The previous cept of ``j``, or None if ``j`` belongs to
456
- the first cept
457
- """
458
- i = self.alignment[j]
459
- if i == 0:
460
- raise ValueError("Words aligned to NULL cannot have a previous "
461
- "cept because NULL has no position")
462
- previous_cept = i - 1
463
- while previous_cept > 0 and self.fertility_of_i(previous_cept) == 0:
464
- previous_cept -= 1
465
-
466
- if previous_cept <= 0:
467
- previous_cept = None
468
- return previous_cept
469
-
470
- def previous_in_tablet(self, j):
471
- """
472
- :return: The position of the previous word that is in the same
473
- tablet as ``j``, or None if ``j`` is the first word of the
474
- tablet
475
- """
476
- i = self.alignment[j]
477
- tablet_position = self.cepts[i].index(j)
478
- if tablet_position == 0:
479
- return None
480
- return self.cepts[i][tablet_position - 1]
481
-
482
- def zero_indexed_alignment(self):
483
- """
484
- :return: Zero-indexed alignment, suitable for use in external
485
- ``nltk.translate`` modules like ``nltk.translate.Alignment``
486
- :rtype: list(tuple)
487
- """
488
- zero_indexed_alignment = []
489
- for j in range(1, len(self.trg_sentence)):
490
- i = self.alignment[j] - 1
491
- if i < 0:
492
- i = None # alignment to NULL token
493
- zero_indexed_alignment.append((j - 1, i))
494
- return zero_indexed_alignment
495
-
496
- def __eq__(self, other):
497
- return self.alignment == other.alignment
498
-
499
- def __hash__(self):
500
- return hash(self.alignment)
501
-
502
-
503
- class Counts(object):
504
- """
505
- Data object to store counts of various parameters during training
506
- """
507
- def __init__(self):
508
- self.t_given_s = defaultdict(lambda: defaultdict(lambda: 0.0))
509
- self.any_t_given_s = defaultdict(lambda: 0.0)
510
- self.p0 = 0.0
511
- self.p1 = 0.0
512
- self.fertility = defaultdict(lambda: defaultdict(lambda: 0.0))
513
- self.fertility_for_any_phi = defaultdict(lambda: 0.0)
514
-
515
- def update_lexical_translation(self, count, alignment_info, j):
516
- i = alignment_info.alignment[j]
517
- t = alignment_info.trg_sentence[j]
518
- s = alignment_info.src_sentence[i]
519
- self.t_given_s[t][s] += count
520
- self.any_t_given_s[s] += count
521
-
522
- def update_null_generation(self, count, alignment_info):
523
- m = len(alignment_info.trg_sentence) - 1
524
- fertility_of_null = alignment_info.fertility_of_i(0)
525
- self.p1 += fertility_of_null * count
526
- self.p0 += (m - 2 * fertility_of_null) * count
527
-
528
- def update_fertility(self, count, alignment_info):
529
- for i in range(0, len(alignment_info.src_sentence)):
530
- s = alignment_info.src_sentence[i]
531
- phi = alignment_info.fertility_of_i(i)
532
- self.fertility[phi][s] += count
533
- self.fertility_for_any_phi[s] += count
1
+ # -*- coding: utf-8 -*-
2
+ # Natural Language Toolkit: IBM Model Core
3
+ #
4
+ # Copyright (C) 2001-2018 NLTK Project
5
+ # Author: Tah Wei Hoon <hoon.tw@gmail.com>
6
+ # URL: <http://nltk.org/>
7
+ # For license information, see LICENSE.TXT
8
+
9
+ """
10
+ Common methods and classes for all IBM models. See ``IBMModel1``,
11
+ ``IBMModel2``, ``IBMModel3``, ``IBMModel4``, and ``IBMModel5``
12
+ for specific implementations.
13
+
14
+ The IBM models are a series of generative models that learn lexical
15
+ translation probabilities, p(target language word|source language word),
16
+ given a sentence-aligned parallel corpus.
17
+
18
+ The models increase in sophistication from model 1 to 5. Typically, the
19
+ output of lower models is used to seed the higher models. All models
20
+ use the Expectation-Maximization (EM) algorithm to learn various
21
+ probability tables.
22
+
23
+ Words in a sentence are one-indexed. The first word of a sentence has
24
+ position 1, not 0. Index 0 is reserved in the source sentence for the
25
+ NULL token. The concept of position does not apply to NULL, but it is
26
+ indexed at 0 by convention.
27
+
28
+ Each target word is aligned to exactly one source word or the NULL
29
+ token.
30
+
31
+ References:
32
+ Philipp Koehn. 2010. Statistical Machine Translation.
33
+ Cambridge University Press, New York.
34
+
35
+ Peter E Brown, Stephen A. Della Pietra, Vincent J. Della Pietra, and
36
+ Robert L. Mercer. 1993. The Mathematics of Statistical Machine
37
+ Translation: Parameter Estimation. Computational Linguistics, 19 (2),
38
+ 263-311.
39
+ """
40
+ from __future__ import division
41
+ from bisect import insort_left
42
+ from collections import defaultdict
43
+ from copy import deepcopy
44
+ from math import ceil
45
+
46
+
47
+ def longest_target_sentence_length(sentence_aligned_corpus):
48
+ """
49
+ :param sentence_aligned_corpus: Parallel corpus under consideration
50
+ :type sentence_aligned_corpus: list(AlignedSent)
51
+ :return: Number of words in the longest target language sentence
52
+ of ``sentence_aligned_corpus``
53
+ """
54
+ max_m = 0
55
+ for aligned_sentence in sentence_aligned_corpus:
56
+ m = len(aligned_sentence.words)
57
+ max_m = max(m, max_m)
58
+ return max_m
59
+
60
+
61
+ class IBMModel(object):
62
+ """
63
+ Abstract base class for all IBM models
64
+ """
65
+ # Avoid division by zero and precision errors by imposing a minimum
66
+ # value for probabilities. Note that this approach is theoretically
67
+ # incorrect, since it may create probabilities that sum to more
68
+ # than 1. In practice, the contribution of probabilities with MIN_PROB
69
+ # is tiny enough that the value of MIN_PROB can be treated as zero.
70
+ MIN_PROB = 1.0e-12 # GIZA++ is more liberal and uses 1.0e-7
71
+
72
+ def __init__(self, sentence_aligned_corpus):
73
+ self.init_vocab(sentence_aligned_corpus)
74
+ self.reset_probabilities()
75
+
76
+ def reset_probabilities(self):
77
+ self.translation_table = defaultdict(
78
+ lambda: defaultdict(lambda: IBMModel.MIN_PROB))
79
+ """
80
+ dict[str][str]: float. Probability(target word | source word).
81
+ Values accessed as ``translation_table[target_word][source_word]``.
82
+ """
83
+
84
+ self.alignment_table = defaultdict(
85
+ lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(
86
+ lambda: IBMModel.MIN_PROB))))
87
+ """
88
+ dict[int][int][int][int]: float. Probability(i | j,l,m).
89
+ Values accessed as ``alignment_table[i][j][l][m]``.
90
+ Used in model 2 and hill climbing in models 3 and above
91
+ """
92
+
93
+ self.fertility_table = defaultdict(
94
+ lambda: defaultdict(lambda: self.MIN_PROB))
95
+ """
96
+ dict[int][str]: float. Probability(fertility | source word).
97
+ Values accessed as ``fertility_table[fertility][source_word]``.
98
+ Used in model 3 and higher.
99
+ """
100
+
101
+ self.p1 = 0.5
102
+ """
103
+ Probability that a generated word requires another target word
104
+ that is aligned to NULL.
105
+ Used in model 3 and higher.
106
+ """
107
+
108
+ def set_uniform_probabilities(self, sentence_aligned_corpus):
109
+ """
110
+ Initialize probability tables to a uniform distribution
111
+
112
+ Derived classes should implement this accordingly.
113
+ """
114
+ pass
115
+
116
+ def init_vocab(self, sentence_aligned_corpus):
117
+ src_vocab = set()
118
+ trg_vocab = set()
119
+ for aligned_sentence in sentence_aligned_corpus:
120
+ trg_vocab.update(aligned_sentence.words)
121
+ src_vocab.update(aligned_sentence.mots)
122
+ # Add the NULL token
123
+ src_vocab.add(None)
124
+
125
+ self.src_vocab = src_vocab
126
+ """
127
+ set(str): All source language words used in training
128
+ """
129
+
130
+ self.trg_vocab = trg_vocab
131
+ """
132
+ set(str): All target language words used in training
133
+ """
134
+
135
+ def sample(self, sentence_pair):
136
+ """
137
+ Sample the most probable alignments from the entire alignment
138
+ space
139
+
140
+ First, determine the best alignment according to IBM Model 2.
141
+ With this initial alignment, use hill climbing to determine the
142
+ best alignment according to a higher IBM Model. Add this
143
+ alignment and its neighbors to the sample set. Repeat this
144
+ process with other initial alignments obtained by pegging an
145
+ alignment point.
146
+
147
+ Hill climbing may be stuck in a local maxima, hence the pegging
148
+ and trying out of different alignments.
149
+
150
+ :param sentence_pair: Source and target language sentence pair
151
+ to generate a sample of alignments from
152
+ :type sentence_pair: AlignedSent
153
+
154
+ :return: A set of best alignments represented by their ``AlignmentInfo``
155
+ and the best alignment of the set for convenience
156
+ :rtype: set(AlignmentInfo), AlignmentInfo
157
+ """
158
+ sampled_alignments = set()
159
+ l = len(sentence_pair.mots)
160
+ m = len(sentence_pair.words)
161
+
162
+ # Start from the best model 2 alignment
163
+ initial_alignment = self.best_model2_alignment(sentence_pair)
164
+ potential_alignment = self.hillclimb(initial_alignment)
165
+ sampled_alignments.update(self.neighboring(potential_alignment))
166
+ best_alignment = potential_alignment
167
+
168
+ # Start from other model 2 alignments,
169
+ # with the constraint that j is aligned (pegged) to i
170
+ for j in range(1, m + 1):
171
+ for i in range(0, l + 1):
172
+ initial_alignment = self.best_model2_alignment(
173
+ sentence_pair, j, i)
174
+ potential_alignment = self.hillclimb(initial_alignment, j)
175
+ neighbors = self.neighboring(potential_alignment, j)
176
+ sampled_alignments.update(neighbors)
177
+ if potential_alignment.score > best_alignment.score:
178
+ best_alignment = potential_alignment
179
+
180
+ return sampled_alignments, best_alignment
181
+
182
+ def best_model2_alignment(self, sentence_pair, j_pegged=None, i_pegged=0):
183
+ """
184
+ Finds the best alignment according to IBM Model 2
185
+
186
+ Used as a starting point for hill climbing in Models 3 and
187
+ above, because it is easier to compute than the best alignments
188
+ in higher models
189
+
190
+ :param sentence_pair: Source and target language sentence pair
191
+ to be word-aligned
192
+ :type sentence_pair: AlignedSent
193
+
194
+ :param j_pegged: If specified, the alignment point of j_pegged
195
+ will be fixed to i_pegged
196
+ :type j_pegged: int
197
+
198
+ :param i_pegged: Alignment point to j_pegged
199
+ :type i_pegged: int
200
+ """
201
+ src_sentence = [None] + sentence_pair.mots
202
+ trg_sentence = ['UNUSED'] + sentence_pair.words # 1-indexed
203
+
204
+ l = len(src_sentence) - 1 # exclude NULL
205
+ m = len(trg_sentence) - 1
206
+
207
+ alignment = [0] * (m + 1) # init all alignments to NULL
208
+ cepts = [[] for i in range((l + 1))] # init all cepts to empty list
209
+
210
+ for j in range(1, m + 1):
211
+ if j == j_pegged:
212
+ # use the pegged alignment instead of searching for best one
213
+ best_i = i_pegged
214
+ else:
215
+ best_i = 0
216
+ max_alignment_prob = IBMModel.MIN_PROB
217
+ t = trg_sentence[j]
218
+
219
+ for i in range(0, l + 1):
220
+ s = src_sentence[i]
221
+ alignment_prob = (self.translation_table[t][s] *
222
+ self.alignment_table[i][j][l][m])
223
+
224
+ if alignment_prob >= max_alignment_prob:
225
+ max_alignment_prob = alignment_prob
226
+ best_i = i
227
+
228
+ alignment[j] = best_i
229
+ cepts[best_i].append(j)
230
+
231
+ return AlignmentInfo(tuple(alignment), tuple(src_sentence),
232
+ tuple(trg_sentence), cepts)
233
+
234
+ def hillclimb(self, alignment_info, j_pegged=None):
235
+ """
236
+ Starting from the alignment in ``alignment_info``, look at
237
+ neighboring alignments iteratively for the best one
238
+
239
+ There is no guarantee that the best alignment in the alignment
240
+ space will be found, because the algorithm might be stuck in a
241
+ local maximum.
242
+
243
+ :param j_pegged: If specified, the search will be constrained to
244
+ alignments where ``j_pegged`` remains unchanged
245
+ :type j_pegged: int
246
+
247
+ :return: The best alignment found from hill climbing
248
+ :rtype: AlignmentInfo
249
+ """
250
+ alignment = alignment_info # alias with shorter name
251
+ max_probability = self.prob_t_a_given_s(alignment)
252
+
253
+ while True:
254
+ old_alignment = alignment
255
+ for neighbor_alignment in self.neighboring(alignment, j_pegged):
256
+ neighbor_probability = self.prob_t_a_given_s(neighbor_alignment)
257
+
258
+ if neighbor_probability > max_probability:
259
+ alignment = neighbor_alignment
260
+ max_probability = neighbor_probability
261
+
262
+ if alignment == old_alignment:
263
+ # Until there are no better alignments
264
+ break
265
+
266
+ alignment.score = max_probability
267
+ return alignment
268
+
269
+ def neighboring(self, alignment_info, j_pegged=None):
270
+ """
271
+ Determine the neighbors of ``alignment_info``, obtained by
272
+ moving or swapping one alignment point
273
+
274
+ :param j_pegged: If specified, neighbors that have a different
275
+ alignment point from j_pegged will not be considered
276
+ :type j_pegged: int
277
+
278
+ :return: A set neighboring alignments represented by their
279
+ ``AlignmentInfo``
280
+ :rtype: set(AlignmentInfo)
281
+ """
282
+ neighbors = set()
283
+
284
+ l = len(alignment_info.src_sentence) - 1 # exclude NULL
285
+ m = len(alignment_info.trg_sentence) - 1
286
+ original_alignment = alignment_info.alignment
287
+ original_cepts = alignment_info.cepts
288
+
289
+ for j in range(1, m + 1):
290
+ if j != j_pegged:
291
+ # Add alignments that differ by one alignment point
292
+ for i in range(0, l + 1):
293
+ new_alignment = list(original_alignment)
294
+ new_cepts = deepcopy(original_cepts)
295
+ old_i = original_alignment[j]
296
+
297
+ # update alignment
298
+ new_alignment[j] = i
299
+
300
+ # update cepts
301
+ insort_left(new_cepts[i], j)
302
+ new_cepts[old_i].remove(j)
303
+
304
+ new_alignment_info = AlignmentInfo(
305
+ tuple(new_alignment), alignment_info.src_sentence,
306
+ alignment_info.trg_sentence, new_cepts)
307
+ neighbors.add(new_alignment_info)
308
+
309
+ for j in range(1, m + 1):
310
+ if j != j_pegged:
311
+ # Add alignments that have two alignment points swapped
312
+ for other_j in range(1, m + 1):
313
+ if other_j != j_pegged and other_j != j:
314
+ new_alignment = list(original_alignment)
315
+ new_cepts = deepcopy(original_cepts)
316
+ other_i = original_alignment[other_j]
317
+ i = original_alignment[j]
318
+
319
+ # update alignments
320
+ new_alignment[j] = other_i
321
+ new_alignment[other_j] = i
322
+
323
+ # update cepts
324
+ new_cepts[other_i].remove(other_j)
325
+ insort_left(new_cepts[other_i], j)
326
+ new_cepts[i].remove(j)
327
+ insort_left(new_cepts[i], other_j)
328
+
329
+ new_alignment_info = AlignmentInfo(
330
+ tuple(new_alignment), alignment_info.src_sentence,
331
+ alignment_info.trg_sentence, new_cepts)
332
+ neighbors.add(new_alignment_info)
333
+
334
+ return neighbors
335
+
336
+ def maximize_lexical_translation_probabilities(self, counts):
337
+ for t, src_words in counts.t_given_s.items():
338
+ for s in src_words:
339
+ estimate = counts.t_given_s[t][s] / counts.any_t_given_s[s]
340
+ self.translation_table[t][s] = max(estimate, IBMModel.MIN_PROB)
341
+
342
+ def maximize_fertility_probabilities(self, counts):
343
+ for phi, src_words in counts.fertility.items():
344
+ for s in src_words:
345
+ estimate = (counts.fertility[phi][s] /
346
+ counts.fertility_for_any_phi[s])
347
+ self.fertility_table[phi][s] = max(estimate, IBMModel.MIN_PROB)
348
+
349
+ def maximize_null_generation_probabilities(self, counts):
350
+ p1_estimate = counts.p1 / (counts.p1 + counts.p0)
351
+ p1_estimate = max(p1_estimate, IBMModel.MIN_PROB)
352
+ # Clip p1 if it is too large, because p0 = 1 - p1 should not be
353
+ # smaller than MIN_PROB
354
+ self.p1 = min(p1_estimate, 1 - IBMModel.MIN_PROB)
355
+
356
+ def prob_of_alignments(self, alignments):
357
+ probability = 0
358
+ for alignment_info in alignments:
359
+ probability += self.prob_t_a_given_s(alignment_info)
360
+ return probability
361
+
362
+ def prob_t_a_given_s(self, alignment_info):
363
+ """
364
+ Probability of target sentence and an alignment given the
365
+ source sentence
366
+
367
+ All required information is assumed to be in ``alignment_info``
368
+ and self.
369
+
370
+ Derived classes should override this method
371
+ """
372
+ return 0.0
373
+
374
+
375
+ class AlignmentInfo(object):
376
+ """
377
+ Helper data object for training IBM Models 3 and up
378
+
379
+ Read-only. For a source sentence and its counterpart in the target
380
+ language, this class holds information about the sentence pair's
381
+ alignment, cepts, and fertility.
382
+
383
+ Warning: Alignments are one-indexed here, in contrast to
384
+ nltk.translate.Alignment and AlignedSent, which are zero-indexed
385
+ This class is not meant to be used outside of IBM models.
386
+ """
387
+
388
+ def __init__(self, alignment, src_sentence, trg_sentence, cepts):
389
+ if not isinstance(alignment, tuple):
390
+ raise TypeError("The alignment must be a tuple because it is used "
391
+ "to uniquely identify AlignmentInfo objects.")
392
+
393
+ self.alignment = alignment
394
+ """
395
+ tuple(int): Alignment function. ``alignment[j]`` is the position
396
+ in the source sentence that is aligned to the position j in the
397
+ target sentence.
398
+ """
399
+
400
+ self.src_sentence = src_sentence
401
+ """
402
+ tuple(str): Source sentence referred to by this object.
403
+ Should include NULL token (None) in index 0.
404
+ """
405
+
406
+ self.trg_sentence = trg_sentence
407
+ """
408
+ tuple(str): Target sentence referred to by this object.
409
+ Should have a dummy element in index 0 so that the first word
410
+ starts from index 1.
411
+ """
412
+
413
+ self.cepts = cepts
414
+ """
415
+ list(list(int)): The positions of the target words, in
416
+ ascending order, aligned to a source word position. For example,
417
+ cepts[4] = (2, 3, 7) means that words in positions 2, 3 and 7
418
+ of the target sentence are aligned to the word in position 4 of
419
+ the source sentence
420
+ """
421
+
422
+ self.score = None
423
+ """
424
+ float: Optional. Probability of alignment, as defined by the
425
+ IBM model that assesses this alignment
426
+ """
427
+
428
+ def fertility_of_i(self, i):
429
+ """
430
+ Fertility of word in position ``i`` of the source sentence
431
+ """
432
+ return len(self.cepts[i])
433
+
434
+ def is_head_word(self, j):
435
+ """
436
+ :return: Whether the word in position ``j`` of the target
437
+ sentence is a head word
438
+ """
439
+ i = self.alignment[j]
440
+ return self.cepts[i][0] == j
441
+
442
+ def center_of_cept(self, i):
443
+ """
444
+ :return: The ceiling of the average positions of the words in
445
+ the tablet of cept ``i``, or 0 if ``i`` is None
446
+ """
447
+ if i is None:
448
+ return 0
449
+
450
+ average_position = sum(self.cepts[i]) / len(self.cepts[i])
451
+ return int(ceil(average_position))
452
+
453
+ def previous_cept(self, j):
454
+ """
455
+ :return: The previous cept of ``j``, or None if ``j`` belongs to
456
+ the first cept
457
+ """
458
+ i = self.alignment[j]
459
+ if i == 0:
460
+ raise ValueError("Words aligned to NULL cannot have a previous "
461
+ "cept because NULL has no position")
462
+ previous_cept = i - 1
463
+ while previous_cept > 0 and self.fertility_of_i(previous_cept) == 0:
464
+ previous_cept -= 1
465
+
466
+ if previous_cept <= 0:
467
+ previous_cept = None
468
+ return previous_cept
469
+
470
+ def previous_in_tablet(self, j):
471
+ """
472
+ :return: The position of the previous word that is in the same
473
+ tablet as ``j``, or None if ``j`` is the first word of the
474
+ tablet
475
+ """
476
+ i = self.alignment[j]
477
+ tablet_position = self.cepts[i].index(j)
478
+ if tablet_position == 0:
479
+ return None
480
+ return self.cepts[i][tablet_position - 1]
481
+
482
+ def zero_indexed_alignment(self):
483
+ """
484
+ :return: Zero-indexed alignment, suitable for use in external
485
+ ``nltk.translate`` modules like ``nltk.translate.Alignment``
486
+ :rtype: list(tuple)
487
+ """
488
+ zero_indexed_alignment = []
489
+ for j in range(1, len(self.trg_sentence)):
490
+ i = self.alignment[j] - 1
491
+ if i < 0:
492
+ i = None # alignment to NULL token
493
+ zero_indexed_alignment.append((j - 1, i))
494
+ return zero_indexed_alignment
495
+
496
+ def __eq__(self, other):
497
+ return self.alignment == other.alignment
498
+
499
+ def __ne__(self, other):
500
+ return not self == other
501
+
502
+ def __hash__(self):
503
+ return hash(self.alignment)
504
+
505
+
506
+ class Counts(object):
507
+ """
508
+ Data object to store counts of various parameters during training
509
+ """
510
+ def __init__(self):
511
+ self.t_given_s = defaultdict(lambda: defaultdict(lambda: 0.0))
512
+ self.any_t_given_s = defaultdict(lambda: 0.0)
513
+ self.p0 = 0.0
514
+ self.p1 = 0.0
515
+ self.fertility = defaultdict(lambda: defaultdict(lambda: 0.0))
516
+ self.fertility_for_any_phi = defaultdict(lambda: 0.0)
517
+
518
+ def update_lexical_translation(self, count, alignment_info, j):
519
+ i = alignment_info.alignment[j]
520
+ t = alignment_info.trg_sentence[j]
521
+ s = alignment_info.src_sentence[i]
522
+ self.t_given_s[t][s] += count
523
+ self.any_t_given_s[s] += count
524
+
525
+ def update_null_generation(self, count, alignment_info):
526
+ m = len(alignment_info.trg_sentence) - 1
527
+ fertility_of_null = alignment_info.fertility_of_i(0)
528
+ self.p1 += fertility_of_null * count
529
+ self.p0 += (m - 2 * fertility_of_null) * count
530
+
531
+ def update_fertility(self, count, alignment_info):
532
+ for i in range(0, len(alignment_info.src_sentence)):
533
+ s = alignment_info.src_sentence[i]
534
+ phi = alignment_info.fertility_of_i(i)
535
+ self.fertility[phi][s] += count
536
+ self.fertility_for_any_phi[s] += count