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.
- {nltk-3.2 → nltk-3.3}/INSTALL.txt +6 -6
- {nltk-3.2 → nltk-3.3}/LICENSE.txt +13 -13
- {nltk-3.2 → nltk-3.3}/MANIFEST.in +6 -6
- {nltk-3.2/nltk.egg-info → nltk-3.3}/PKG-INFO +13 -5
- nltk-3.2/README.txt → nltk-3.3/README.md +49 -48
- nltk-3.3/nltk/VERSION +1 -0
- {nltk-3.2 → nltk-3.3}/nltk/__init__.py +185 -185
- {nltk-3.2 → nltk-3.3}/nltk/app/__init__.py +52 -53
- {nltk-3.2 → nltk-3.3}/nltk/app/chartparser_app.py +2276 -2276
- {nltk-3.2 → nltk-3.3}/nltk/app/chunkparser_app.py +1262 -1264
- {nltk-3.2 → nltk-3.3}/nltk/app/collocations_app.py +347 -350
- {nltk-3.2 → nltk-3.3}/nltk/app/concordance_app.py +568 -570
- {nltk-3.2 → nltk-3.3}/nltk/app/nemo_app.py +156 -155
- {nltk-3.2 → nltk-3.3}/nltk/app/rdparser_app.py +892 -894
- {nltk-3.2 → nltk-3.3}/nltk/app/srparser_app.py +809 -809
- {nltk-3.2 → nltk-3.3}/nltk/app/wordfreq_app.py +32 -32
- {nltk-3.2 → nltk-3.3}/nltk/app/wordnet_app.py +968 -968
- {nltk-3.2 → nltk-3.3}/nltk/book.py +91 -90
- {nltk-3.2 → nltk-3.3}/nltk/ccg/__init__.py +22 -22
- {nltk-3.2 → nltk-3.3}/nltk/ccg/api.py +359 -335
- {nltk-3.2 → nltk-3.3}/nltk/ccg/chart.py +394 -361
- {nltk-3.2 → nltk-3.3}/nltk/ccg/combinator.py +343 -312
- {nltk-3.2 → nltk-3.3}/nltk/ccg/lexicon.py +328 -290
- nltk-3.3/nltk/ccg/logic.py +46 -0
- {nltk-3.2 → nltk-3.3}/nltk/chat/__init__.py +49 -49
- {nltk-3.2 → nltk-3.3}/nltk/chat/eliza.py +244 -244
- {nltk-3.2 → nltk-3.3}/nltk/chat/iesha.py +140 -140
- {nltk-3.2 → nltk-3.3}/nltk/chat/rude.py +92 -92
- {nltk-3.2 → nltk-3.3}/nltk/chat/suntsu.py +117 -117
- {nltk-3.2 → nltk-3.3}/nltk/chat/util.py +122 -120
- {nltk-3.2 → nltk-3.3}/nltk/chat/zen.py +282 -282
- {nltk-3.2 → nltk-3.3}/nltk/chunk/__init__.py +190 -190
- {nltk-3.2 → nltk-3.3}/nltk/chunk/api.py +51 -51
- {nltk-3.2 → nltk-3.3}/nltk/chunk/named_entity.py +331 -331
- {nltk-3.2 → nltk-3.3}/nltk/chunk/regexp.py +1390 -1384
- {nltk-3.2 → nltk-3.3}/nltk/chunk/util.py +600 -600
- {nltk-3.2 → nltk-3.3}/nltk/classify/__init__.py +98 -98
- {nltk-3.2 → nltk-3.3}/nltk/classify/api.py +193 -193
- {nltk-3.2 → nltk-3.3}/nltk/classify/decisiontree.py +295 -295
- {nltk-3.2 → nltk-3.3}/nltk/classify/maxent.py +1510 -1492
- {nltk-3.2 → nltk-3.3}/nltk/classify/megam.py +179 -178
- {nltk-3.2 → nltk-3.3}/nltk/classify/naivebayes.py +245 -242
- {nltk-3.2 → nltk-3.3}/nltk/classify/positivenaivebayes.py +170 -170
- {nltk-3.2 → nltk-3.3}/nltk/classify/rte_classify.py +160 -191
- {nltk-3.2 → nltk-3.3}/nltk/classify/scikitlearn.py +153 -151
- {nltk-3.2 → nltk-3.3}/nltk/classify/senna.py +183 -181
- {nltk-3.2 → nltk-3.3}/nltk/classify/svm.py +15 -15
- {nltk-3.2 → nltk-3.3}/nltk/classify/tadm.py +113 -112
- {nltk-3.2 → nltk-3.3}/nltk/classify/textcat.py +193 -193
- {nltk-3.2 → nltk-3.3}/nltk/classify/util.py +324 -312
- {nltk-3.2 → nltk-3.3}/nltk/classify/weka.py +346 -345
- {nltk-3.2 → nltk-3.3}/nltk/cluster/__init__.py +86 -86
- {nltk-3.2 → nltk-3.3}/nltk/cluster/api.py +74 -70
- {nltk-3.2 → nltk-3.3}/nltk/cluster/em.py +247 -247
- {nltk-3.2 → nltk-3.3}/nltk/cluster/gaac.py +168 -168
- {nltk-3.2 → nltk-3.3}/nltk/cluster/kmeans.py +221 -221
- {nltk-3.2 → nltk-3.3}/nltk/cluster/util.py +304 -289
- nltk-3.3/nltk/collections.py +640 -0
- {nltk-3.2 → nltk-3.3}/nltk/collocations.py +388 -388
- nltk-3.3/nltk/compat.py +365 -0
- {nltk-3.2 → nltk-3.3}/nltk/corpus/__init__.py +341 -320
- {nltk-3.2 → nltk-3.3}/nltk/corpus/europarl_raw.py +44 -44
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/__init__.py +147 -145
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/aligned.py +115 -114
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/api.py +448 -446
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/bnc.py +252 -252
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/bracket_parse.py +227 -227
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/categorized_sents.py +179 -178
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/chasen.py +140 -139
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/childes.py +522 -494
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/chunked.py +212 -212
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/cmudict.py +97 -95
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/comparative_sents.py +280 -278
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/conll.py +528 -521
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/crubadan.py +116 -116
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/dependency.py +101 -101
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/framenet.py +3059 -2093
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ieer.py +112 -111
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/indian.py +85 -86
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ipipan.py +332 -331
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/knbc.py +187 -187
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/lin.py +156 -156
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/mte.py +311 -310
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nkjp.py +429 -428
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nombank.py +421 -421
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nps_chat.py +73 -73
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/opinion_lexicon.py +115 -115
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/panlex_lite.py +165 -165
- nltk-3.3/nltk/corpus/reader/pl196x.py +292 -0
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/plaintext.py +232 -233
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ppattach.py +96 -95
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/propbank.py +479 -481
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/pros_cons.py +128 -126
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/reviews.py +330 -328
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/rte.py +144 -146
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/semcor.py +256 -256
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/senseval.py +203 -201
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/sentiwordnet.py +137 -137
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/sinica_treebank.py +75 -75
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/string_category.py +60 -59
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/switchboard.py +119 -119
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/tagged.py +295 -294
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/timit.py +452 -450
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/toolbox.py +68 -68
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/twitter.py +155 -157
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/udhr.py +80 -80
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/util.py +804 -800
- nltk-3.3/nltk/corpus/reader/verbnet.py +595 -0
- nltk-3.3/nltk/corpus/reader/wordlist.py +134 -0
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/wordnet.py +2108 -2036
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/xmldocs.py +392 -387
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ycoe.py +243 -242
- {nltk-3.2 → nltk-3.3}/nltk/corpus/util.py +144 -127
- {nltk-3.2 → nltk-3.3}/nltk/data.py +1487 -1451
- {nltk-3.2 → nltk-3.3}/nltk/decorators.py +219 -215
- {nltk-3.2 → nltk-3.3}/nltk/downloader.py +2278 -2274
- {nltk-3.2 → nltk-3.3}/nltk/draw/__init__.py +27 -27
- {nltk-3.2 → nltk-3.3}/nltk/draw/cfg.py +774 -777
- {nltk-3.2 → nltk-3.3}/nltk/draw/dispersion.py +58 -58
- {nltk-3.2 → nltk-3.3}/nltk/draw/table.py +1098 -1098
- {nltk-3.2 → nltk-3.3}/nltk/draw/tree.py +963 -966
- {nltk-3.2 → nltk-3.3}/nltk/draw/util.py +2356 -2356
- {nltk-3.2 → nltk-3.3}/nltk/featstruct.py +2617 -2500
- {nltk-3.2 → nltk-3.3}/nltk/grammar.py +1559 -1516
- {nltk-3.2 → nltk-3.3}/nltk/help.py +56 -56
- {nltk-3.2 → nltk-3.3}/nltk/inference/__init__.py +20 -20
- {nltk-3.2 → nltk-3.3}/nltk/inference/api.py +597 -589
- {nltk-3.2 → nltk-3.3}/nltk/inference/discourse.py +612 -608
- {nltk-3.2 → nltk-3.3}/nltk/inference/mace.py +311 -311
- {nltk-3.2 → nltk-3.3}/nltk/inference/nonmonotonic.py +509 -509
- {nltk-3.2 → nltk-3.3}/nltk/inference/prover9.py +431 -431
- {nltk-3.2 → nltk-3.3}/nltk/inference/resolution.py +687 -687
- {nltk-3.2 → nltk-3.3}/nltk/inference/tableau.py +607 -607
- {nltk-3.2 → nltk-3.3}/nltk/internals.py +982 -982
- {nltk-3.2 → nltk-3.3}/nltk/jsontags.py +63 -63
- {nltk-3.2 → nltk-3.3}/nltk/lazyimport.py +142 -142
- {nltk-3.2 → nltk-3.3}/nltk/metrics/__init__.py +30 -29
- {nltk-3.2 → nltk-3.3}/nltk/metrics/agreement.py +421 -401
- nltk-3.3/nltk/metrics/aline.py +607 -0
- {nltk-3.2 → nltk-3.3}/nltk/metrics/association.py +414 -410
- {nltk-3.2 → nltk-3.3}/nltk/metrics/confusionmatrix.py +206 -206
- {nltk-3.2 → nltk-3.3}/nltk/metrics/distance.py +207 -202
- {nltk-3.2 → nltk-3.3}/nltk/metrics/paice.py +381 -381
- {nltk-3.2 → nltk-3.3}/nltk/metrics/scores.py +228 -228
- {nltk-3.2 → nltk-3.3}/nltk/metrics/segmentation.py +231 -232
- {nltk-3.2 → nltk-3.3}/nltk/metrics/spearman.py +69 -69
- {nltk-3.2 → nltk-3.3}/nltk/misc/__init__.py +11 -11
- {nltk-3.2 → nltk-3.3}/nltk/misc/babelfish.py +10 -10
- {nltk-3.2 → nltk-3.3}/nltk/misc/chomsky.py +135 -133
- {nltk-3.2 → nltk-3.3}/nltk/misc/minimalset.py +83 -83
- {nltk-3.2 → nltk-3.3}/nltk/misc/sort.py +157 -157
- {nltk-3.2 → nltk-3.3}/nltk/misc/wordfinder.py +129 -129
- {nltk-3.2 → nltk-3.3}/nltk/parse/__init__.py +81 -80
- {nltk-3.2 → nltk-3.3}/nltk/parse/api.py +66 -66
- {nltk-3.2 → nltk-3.3}/nltk/parse/bllip.py +282 -282
- {nltk-3.2 → nltk-3.3}/nltk/parse/chart.py +1682 -1681
- nltk-3.3/nltk/parse/corenlp.py +780 -0
- {nltk-3.2 → nltk-3.3}/nltk/parse/dependencygraph.py +760 -758
- {nltk-3.2 → nltk-3.3}/nltk/parse/earleychart.py +452 -451
- {nltk-3.2 → nltk-3.3}/nltk/parse/evaluate.py +129 -129
- {nltk-3.2 → nltk-3.3}/nltk/parse/featurechart.py +580 -578
- {nltk-3.2 → nltk-3.3}/nltk/parse/generate.py +87 -76
- {nltk-3.2 → nltk-3.3}/nltk/parse/malt.py +356 -356
- {nltk-3.2 → nltk-3.3}/nltk/parse/nonprojectivedependencyparser.py +783 -783
- {nltk-3.2 → nltk-3.3}/nltk/parse/pchart.py +522 -522
- {nltk-3.2 → nltk-3.3}/nltk/parse/projectivedependencyparser.py +579 -578
- {nltk-3.2 → nltk-3.3}/nltk/parse/recursivedescent.py +655 -656
- {nltk-3.2 → nltk-3.3}/nltk/parse/shiftreduce.py +458 -459
- {nltk-3.2 → nltk-3.3}/nltk/parse/stanford.py +431 -406
- {nltk-3.2 → nltk-3.3}/nltk/parse/transitionparser.py +774 -772
- {nltk-3.2 → nltk-3.3}/nltk/parse/util.py +231 -231
- {nltk-3.2 → nltk-3.3}/nltk/parse/viterbi.py +401 -401
- {nltk-3.2 → nltk-3.3}/nltk/probability.py +2410 -2355
- {nltk-3.2 → nltk-3.3}/nltk/sem/__init__.py +61 -61
- {nltk-3.2 → nltk-3.3}/nltk/sem/boxer.py +1261 -1261
- {nltk-3.2 → nltk-3.3}/nltk/sem/chat80.py +782 -782
- {nltk-3.2 → nltk-3.3}/nltk/sem/cooper_storage.py +118 -118
- {nltk-3.2 → nltk-3.3}/nltk/sem/drt.py +1258 -1257
- {nltk-3.2 → nltk-3.3}/nltk/sem/drt_glue_demo.py +485 -489
- {nltk-3.2 → nltk-3.3}/nltk/sem/evaluate.py +790 -784
- {nltk-3.2 → nltk-3.3}/nltk/sem/glue.py +696 -694
- {nltk-3.2 → nltk-3.3}/nltk/sem/hole.py +386 -384
- {nltk-3.2 → nltk-3.3}/nltk/sem/lfg.py +210 -208
- {nltk-3.2 → nltk-3.3}/nltk/sem/linearlogic.py +451 -449
- {nltk-3.2 → nltk-3.3}/nltk/sem/logic.py +1910 -1910
- {nltk-3.2 → nltk-3.3}/nltk/sem/relextract.py +476 -483
- {nltk-3.2 → nltk-3.3}/nltk/sem/skolemize.py +101 -101
- {nltk-3.2 → nltk-3.3}/nltk/sem/util.py +249 -249
- {nltk-3.2 → nltk-3.3}/nltk/sentiment/__init__.py +14 -14
- {nltk-3.2 → nltk-3.3}/nltk/sentiment/sentiment_analyzer.py +229 -229
- {nltk-3.2 → nltk-3.3}/nltk/sentiment/util.py +762 -752
- {nltk-3.2 → nltk-3.3}/nltk/sentiment/vader.py +443 -445
- {nltk-3.2 → nltk-3.3}/nltk/stem/__init__.py +31 -33
- {nltk-3.2 → nltk-3.3}/nltk/stem/api.py +28 -25
- nltk-3.3/nltk/stem/arlstem.py +369 -0
- {nltk-3.2 → nltk-3.3}/nltk/stem/isri.py +345 -345
- {nltk-3.2 → nltk-3.3}/nltk/stem/lancaster.py +337 -310
- nltk-3.3/nltk/stem/porter.py +710 -0
- {nltk-3.2 → nltk-3.3}/nltk/stem/regexp.py +61 -61
- {nltk-3.2 → nltk-3.3}/nltk/stem/rslp.py +142 -142
- {nltk-3.2 → nltk-3.3}/nltk/stem/snowball.py +4236 -3712
- {nltk-3.2 → nltk-3.3}/nltk/stem/util.py +22 -12
- {nltk-3.2 → nltk-3.3}/nltk/stem/wordnet.py +51 -51
- {nltk-3.2 → nltk-3.3}/nltk/tag/__init__.py +152 -127
- {nltk-3.2 → nltk-3.3}/nltk/tag/api.py +86 -81
- {nltk-3.2 → nltk-3.3}/nltk/tag/brill.py +424 -426
- {nltk-3.2 → nltk-3.3}/nltk/tag/brill_trainer.py +608 -608
- {nltk-3.2 → nltk-3.3}/nltk/tag/crf.py +204 -200
- {nltk-3.2 → nltk-3.3}/nltk/tag/hmm.py +1277 -1277
- {nltk-3.2 → nltk-3.3}/nltk/tag/hunpos.py +132 -132
- {nltk-3.2 → nltk-3.3}/nltk/tag/mapping.py +101 -101
- {nltk-3.2 → nltk-3.3}/nltk/tag/perceptron.py +329 -314
- {nltk-3.2 → nltk-3.3}/nltk/tag/senna.py +147 -145
- {nltk-3.2 → nltk-3.3}/nltk/tag/sequential.py +740 -736
- {nltk-3.2 → nltk-3.3}/nltk/tag/stanford.py +219 -196
- {nltk-3.2 → nltk-3.3}/nltk/tag/tnt.py +595 -604
- {nltk-3.2 → nltk-3.3}/nltk/tag/util.py +72 -72
- {nltk-3.2 → nltk-3.3}/nltk/tbl/__init__.py +28 -28
- {nltk-3.2 → nltk-3.3}/nltk/tbl/api.py +1 -1
- {nltk-3.2 → nltk-3.3}/nltk/tbl/demo.py +366 -366
- {nltk-3.2 → nltk-3.3}/nltk/tbl/erroranalysis.py +39 -39
- {nltk-3.2 → nltk-3.3}/nltk/tbl/feature.py +259 -261
- {nltk-3.2 → nltk-3.3}/nltk/tbl/rule.py +321 -321
- {nltk-3.2 → nltk-3.3}/nltk/tbl/template.py +303 -308
- {nltk-3.2 → nltk-3.3}/nltk/test/__init__.py +18 -18
- {nltk-3.2 → nltk-3.3}/nltk/test/all.py +24 -23
- {nltk-3.2 → nltk-3.3}/nltk/test/bleu.doctest +14 -14
- {nltk-3.2 → nltk-3.3}/nltk/test/bnc.doctest +60 -60
- {nltk-3.2 → nltk-3.3}/nltk/test/ccg.doctest +376 -395
- nltk-3.3/nltk/test/ccg_semantics.doctest +553 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/chat80.doctest +234 -234
- {nltk-3.2 → nltk-3.3}/nltk/test/childes.doctest +184 -184
- {nltk-3.2 → nltk-3.3}/nltk/test/childes_fixt.py +14 -13
- {nltk-3.2 → nltk-3.3}/nltk/test/chunk.doctest +373 -373
- {nltk-3.2 → nltk-3.3}/nltk/test/classify.doctest +185 -185
- {nltk-3.2 → nltk-3.3}/nltk/test/classify_fixt.py +11 -10
- nltk-3.3/nltk/test/collections.doctest +20 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/collocations.doctest +276 -276
- {nltk-3.2 → nltk-3.3}/nltk/test/compat.doctest +134 -138
- {nltk-3.2 → nltk-3.3}/nltk/test/compat_fixt.py +9 -8
- nltk-3.3/nltk/test/concordance.doctest +55 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/corpus.doctest +2200 -2212
- {nltk-3.2 → nltk-3.3}/nltk/test/corpus_fixt.py +3 -3
- {nltk-3.2 → nltk-3.3}/nltk/test/crubadan.doctest +65 -65
- {nltk-3.2 → nltk-3.3}/nltk/test/data.doctest +379 -379
- {nltk-3.2 → nltk-3.3}/nltk/test/dependency.doctest +241 -241
- {nltk-3.2 → nltk-3.3}/nltk/test/discourse.doctest +546 -546
- {nltk-3.2 → nltk-3.3}/nltk/test/discourse_fixt.py +14 -13
- {nltk-3.2 → nltk-3.3}/nltk/test/doctest_nose_plugin.py +159 -156
- {nltk-3.2 → nltk-3.3}/nltk/test/drt.doctest +517 -517
- {nltk-3.2 → nltk-3.3}/nltk/test/featgram.doctest +607 -607
- {nltk-3.2 → nltk-3.3}/nltk/test/featstruct.doctest +1229 -1230
- {nltk-3.2 → nltk-3.3}/nltk/test/framenet.doctest +288 -239
- {nltk-3.2 → nltk-3.3}/nltk/test/generate.doctest +67 -67
- {nltk-3.2 → nltk-3.3}/nltk/test/gensim.doctest +140 -141
- {nltk-3.2 → nltk-3.3}/nltk/test/gensim_fixt.py +10 -9
- {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics.doctest +384 -386
- {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics_malt.doctest +68 -68
- {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics_malt_fixt.py +12 -11
- {nltk-3.2 → nltk-3.3}/nltk/test/grammar.doctest +48 -48
- {nltk-3.2 → nltk-3.3}/nltk/test/grammartestsuites.doctest +109 -109
- {nltk-3.2 → nltk-3.3}/nltk/test/index.doctest +100 -100
- {nltk-3.2 → nltk-3.3}/nltk/test/inference.doctest +534 -534
- {nltk-3.2 → nltk-3.3}/nltk/test/inference_fixt.py +12 -11
- {nltk-3.2 → nltk-3.3}/nltk/test/internals.doctest +140 -140
- {nltk-3.2 → nltk-3.3}/nltk/test/japanese.doctest +48 -48
- {nltk-3.2 → nltk-3.3}/nltk/test/logic.doctest +1098 -1098
- {nltk-3.2 → nltk-3.3}/nltk/test/metrics.doctest +270 -270
- {nltk-3.2 → nltk-3.3}/nltk/test/misc.doctest +118 -118
- {nltk-3.2 → nltk-3.3}/nltk/test/nonmonotonic.doctest +286 -286
- {nltk-3.2 → nltk-3.3}/nltk/test/nonmonotonic_fixt.py +12 -11
- {nltk-3.2 → nltk-3.3}/nltk/test/paice.doctest +35 -35
- {nltk-3.2 → nltk-3.3}/nltk/test/parse.doctest +884 -884
- {nltk-3.2 → nltk-3.3}/nltk/test/portuguese_en.doctest +565 -565
- {nltk-3.2 → nltk-3.3}/nltk/test/portuguese_en_fixt.py +16 -16
- {nltk-3.2 → nltk-3.3}/nltk/test/probability.doctest +304 -304
- {nltk-3.2 → nltk-3.3}/nltk/test/probability_fixt.py +13 -12
- {nltk-3.2 → nltk-3.3}/nltk/test/propbank.doctest +176 -176
- {nltk-3.2 → nltk-3.3}/nltk/test/relextract.doctest +263 -263
- {nltk-3.2 → nltk-3.3}/nltk/test/resolution.doctest +221 -221
- {nltk-3.2 → nltk-3.3}/nltk/test/runtests.py +86 -64
- {nltk-3.2 → nltk-3.3}/nltk/test/segmentation_fixt.py +10 -10
- {nltk-3.2 → nltk-3.3}/nltk/test/semantics.doctest +665 -665
- {nltk-3.2 → nltk-3.3}/nltk/test/semantics_fixt.py +7 -7
- {nltk-3.2 → nltk-3.3}/nltk/test/sentiment.doctest +233 -233
- {nltk-3.2 → nltk-3.3}/nltk/test/sentiwordnet.doctest +41 -41
- {nltk-3.2 → nltk-3.3}/nltk/test/simple.doctest +85 -85
- {nltk-3.2 → nltk-3.3}/nltk/test/stem.doctest +78 -78
- {nltk-3.2 → nltk-3.3}/nltk/test/tag.doctest +33 -33
- {nltk-3.2 → nltk-3.3}/nltk/test/tokenize.doctest +273 -166
- {nltk-3.2 → nltk-3.3}/nltk/test/toolbox.doctest +307 -307
- {nltk-3.2 → nltk-3.3}/nltk/test/translate.doctest +242 -242
- {nltk-3.2 → nltk-3.3}/nltk/test/translate_fixt.py +3 -3
- {nltk-3.2 → nltk-3.3}/nltk/test/tree.doctest +1101 -1101
- {nltk-3.2 → nltk-3.3}/nltk/test/treeprettyprinter.doctest +127 -127
- {nltk-3.2 → nltk-3.3}/nltk/test/treetransforms.doctest +156 -156
- nltk-3.3/nltk/test/unit/test_2x_compat.py +63 -0
- nltk-3.3/nltk/test/unit/test_aline.py +52 -0
- nltk-3.3/nltk/test/unit/test_chunk.py +56 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_classify.py +55 -53
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_collocations.py +88 -79
- nltk-3.3/nltk/test/unit/test_concordance.py +98 -0
- nltk-3.3/nltk/test/unit/test_corenlp.py +1000 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_corpora.py +200 -183
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_corpus_views.py +45 -45
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_hmm.py +88 -88
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_json2csv_corpus.py +188 -187
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_naivebayes.py +26 -26
- nltk-3.3/nltk/test/unit/test_rte_classify.py +86 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_seekable_unicode_stream_reader.py +124 -124
- nltk-3.3/nltk/test/unit/test_senna.py +74 -0
- nltk-3.3/nltk/test/unit/test_stem.py +121 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_tag.py +20 -20
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_tgrep.py +628 -626
- nltk-3.3/nltk/test/unit/test_tokenize.py +168 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_twitter_auth.py +185 -185
- nltk-3.3/nltk/test/unit/test_wordnet.py +134 -0
- nltk-3.3/nltk/test/unit/translate/test_bleu.py +244 -0
- nltk-3.3/nltk/test/unit/translate/test_gdfa.py +57 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm1.py +75 -75
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm2.py +87 -87
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm3.py +105 -105
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm4.py +126 -126
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm5.py +166 -166
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm_model.py +270 -270
- nltk-3.3/nltk/test/unit/translate/test_nist.py +37 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_stack_decoder.py +300 -300
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/utils.py +41 -41
- {nltk-3.2 → nltk-3.3}/nltk/test/util.doctest +48 -48
- {nltk-3.2 → nltk-3.3}/nltk/test/wordnet.doctest +595 -581
- {nltk-3.2 → nltk-3.3}/nltk/test/wordnet_fixt.py +7 -6
- {nltk-3.2 → nltk-3.3}/nltk/test/wordnet_lch.doctest +53 -53
- {nltk-3.2 → nltk-3.3}/nltk/test/wsd.doctest +68 -68
- {nltk-3.2 → nltk-3.3}/nltk/text.py +663 -610
- {nltk-3.2 → nltk-3.3}/nltk/tgrep.py +938 -937
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/__init__.py +130 -107
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/api.py +77 -78
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/casual.py +343 -342
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/mwe.py +120 -120
- nltk-3.3/nltk/tokenize/nist.py +173 -0
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/punkt.py +1620 -1601
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/regexp.py +208 -202
- nltk-3.3/nltk/tokenize/repp.py +151 -0
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/sexpr.py +140 -142
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/simple.py +138 -136
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/stanford.py +117 -113
- nltk-3.3/nltk/tokenize/stanford_segmenter.py +246 -0
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/texttiling.py +458 -460
- nltk-3.3/nltk/tokenize/toktok.py +155 -0
- nltk-3.3/nltk/tokenize/treebank.py +363 -0
- nltk-3.3/nltk/tokenize/util.py +261 -0
- {nltk-3.2 → nltk-3.3}/nltk/toolbox.py +499 -497
- {nltk-3.2 → nltk-3.3}/nltk/translate/__init__.py +24 -24
- {nltk-3.2 → nltk-3.3}/nltk/translate/api.py +331 -321
- {nltk-3.2 → nltk-3.3}/nltk/translate/bleu_score.py +615 -556
- nltk-3.3/nltk/translate/chrf_score.py +137 -0
- {nltk-3.2 → nltk-3.3}/nltk/translate/gale_church.py +248 -235
- {nltk-3.2 → nltk-3.3}/nltk/translate/gdfa.py +135 -131
- nltk-3.3/nltk/translate/gleu_score.py +193 -0
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm1.py +250 -241
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm2.py +308 -308
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm3.py +337 -337
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm4.py +467 -467
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm5.py +639 -639
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm_model.py +536 -533
- {nltk-3.2 → nltk-3.3}/nltk/translate/metrics.py +40 -40
- nltk-3.3/nltk/translate/nist_score.py +178 -0
- {nltk-3.2 → nltk-3.3}/nltk/translate/phrase_based.py +175 -175
- {nltk-3.2 → nltk-3.3}/nltk/translate/ribes_score.py +325 -325
- {nltk-3.2 → nltk-3.3}/nltk/translate/stack_decoder.py +499 -495
- {nltk-3.2 → nltk-3.3}/nltk/tree.py +1605 -1603
- {nltk-3.2 → nltk-3.3}/nltk/treeprettyprinter.py +564 -564
- {nltk-3.2 → nltk-3.3}/nltk/treetransforms.py +309 -309
- {nltk-3.2 → nltk-3.3}/nltk/twitter/__init__.py +28 -28
- {nltk-3.2 → nltk-3.3}/nltk/twitter/api.py +141 -136
- {nltk-3.2 → nltk-3.3}/nltk/twitter/common.py +264 -258
- {nltk-3.2 → nltk-3.3}/nltk/twitter/twitter_demo.py +288 -288
- {nltk-3.2 → nltk-3.3}/nltk/twitter/twitterclient.py +530 -530
- {nltk-3.2 → nltk-3.3}/nltk/twitter/util.py +147 -146
- nltk-3.3/nltk/util.py +751 -0
- {nltk-3.2 → nltk-3.3}/nltk/wsd.py +53 -53
- {nltk-3.2 → nltk-3.3/nltk.egg-info}/PKG-INFO +13 -5
- {nltk-3.2 → nltk-3.3}/nltk.egg-info/SOURCES.txt +26 -3
- nltk-3.3/nltk.egg-info/requires.txt +31 -0
- {nltk-3.2 → nltk-3.3}/setup.cfg +0 -1
- {nltk-3.2 → nltk-3.3}/setup.py +102 -75
- nltk-3.2/nltk/VERSION +0 -1
- nltk-3.2/nltk/compat.py +0 -680
- nltk-3.2/nltk/corpus/reader/pl196x.py +0 -278
- nltk-3.2/nltk/corpus/reader/verbnet.py +0 -408
- nltk-3.2/nltk/corpus/reader/wordlist.py +0 -37
- nltk-3.2/nltk/sentiment/vader_lexicon.txt +0 -7517
- nltk-3.2/nltk/six.py +0 -868
- nltk-3.2/nltk/stem/porter.py +0 -692
- nltk-3.2/nltk/test/unit/test_2x_compat.py +0 -26
- nltk-3.2/nltk/test/unit/test_stem.py +0 -36
- nltk-3.2/nltk/test/unit/test_tokenize.py +0 -23
- nltk-3.2/nltk/test/unit/translate/test_bleu.py +0 -84
- nltk-3.2/nltk/tokenize/treebank.py +0 -124
- nltk-3.2/nltk/tokenize/util.py +0 -90
- nltk-3.2/nltk/util.py +0 -1364
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/__init__.py +0 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/__init__.py +0 -0
- {nltk-3.2 → nltk-3.3}/nltk.egg-info/dependency_links.txt +0 -0
- {nltk-3.2 → nltk-3.3}/nltk.egg-info/not-zip-safe +0 -0
- {nltk-3.2 → nltk-3.3}/nltk.egg-info/top_level.txt +0 -0
|
@@ -1,229 +1,229 @@
|
|
|
1
|
-
# coding: utf-8
|
|
2
|
-
#
|
|
3
|
-
# Natural Language Toolkit: Sentiment Analyzer
|
|
4
|
-
#
|
|
5
|
-
# Copyright (C) 2001-
|
|
6
|
-
# Author: Pierpaolo Pantone <24alsecondo@gmail.com>
|
|
7
|
-
# URL: <http://nltk.org/>
|
|
8
|
-
# For license information, see LICENSE.TXT
|
|
9
|
-
|
|
10
|
-
"""
|
|
11
|
-
A SentimentAnalyzer is a tool to implement and facilitate Sentiment Analysis tasks
|
|
12
|
-
using NLTK features and classifiers, especially for teaching and demonstrative
|
|
13
|
-
purposes.
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
from __future__ import print_function
|
|
17
|
-
from collections import defaultdict
|
|
18
|
-
|
|
19
|
-
from nltk.classify.util import apply_features, accuracy as eval_accuracy
|
|
20
|
-
from nltk.collocations import BigramCollocationFinder
|
|
21
|
-
from nltk.metrics import (BigramAssocMeasures, precision as eval_precision,
|
|
22
|
-
recall as eval_recall, f_measure as eval_f_measure)
|
|
23
|
-
|
|
24
|
-
from nltk.probability import FreqDist
|
|
25
|
-
|
|
26
|
-
from nltk.sentiment.util import save_file, timer
|
|
27
|
-
|
|
28
|
-
class SentimentAnalyzer(object):
|
|
29
|
-
"""
|
|
30
|
-
A Sentiment Analysis tool based on machine learning approaches.
|
|
31
|
-
"""
|
|
32
|
-
def __init__(self, classifier=None):
|
|
33
|
-
self.feat_extractors = defaultdict(list)
|
|
34
|
-
self.classifier = classifier
|
|
35
|
-
|
|
36
|
-
def all_words(self, documents, labeled=None):
|
|
37
|
-
"""
|
|
38
|
-
Return all words/tokens from the documents (with duplicates).
|
|
39
|
-
:param documents: a list of (words, label) tuples.
|
|
40
|
-
:param labeled: if `True`, assume that each document is represented by a
|
|
41
|
-
(words, label) tuple: (list(str), str). If `False`, each document is
|
|
42
|
-
considered as being a simple list of strings: list(str).
|
|
43
|
-
:rtype: list(str)
|
|
44
|
-
:return: A list of all words/tokens in `documents`.
|
|
45
|
-
"""
|
|
46
|
-
all_words = []
|
|
47
|
-
if labeled is None:
|
|
48
|
-
labeled = documents and isinstance(documents[0], tuple)
|
|
49
|
-
if labeled == True:
|
|
50
|
-
for words, sentiment in documents:
|
|
51
|
-
all_words.extend(words)
|
|
52
|
-
elif labeled == False:
|
|
53
|
-
for words in documents:
|
|
54
|
-
all_words.extend(words)
|
|
55
|
-
return all_words
|
|
56
|
-
|
|
57
|
-
def apply_features(self, documents, labeled=None):
|
|
58
|
-
"""
|
|
59
|
-
Apply all feature extractor functions to the documents. This is a wrapper
|
|
60
|
-
around `nltk.classify.util.apply_features`.
|
|
61
|
-
|
|
62
|
-
If `labeled=False`, return featuresets as:
|
|
63
|
-
[feature_func(doc) for doc in documents]
|
|
64
|
-
If `labeled=True`, return featuresets as:
|
|
65
|
-
[(feature_func(tok), label) for (tok, label) in toks]
|
|
66
|
-
|
|
67
|
-
:param documents: a list of documents. `If labeled=True`, the method expects
|
|
68
|
-
a list of (words, label) tuples.
|
|
69
|
-
:rtype: LazyMap
|
|
70
|
-
"""
|
|
71
|
-
return apply_features(self.extract_features, documents, labeled)
|
|
72
|
-
|
|
73
|
-
def unigram_word_feats(self, words, top_n=None, min_freq=0):
|
|
74
|
-
"""
|
|
75
|
-
Return most common top_n word features.
|
|
76
|
-
|
|
77
|
-
:param words: a list of words/tokens.
|
|
78
|
-
:param top_n: number of best words/tokens to use, sorted by frequency.
|
|
79
|
-
:rtype: list(str)
|
|
80
|
-
:return: A list of `top_n` words/tokens (with no duplicates) sorted by
|
|
81
|
-
frequency.
|
|
82
|
-
"""
|
|
83
|
-
# Stopwords are not removed
|
|
84
|
-
unigram_feats_freqs = FreqDist(word for word in words)
|
|
85
|
-
return [w for w, f in unigram_feats_freqs.most_common(top_n)
|
|
86
|
-
if unigram_feats_freqs[w] > min_freq]
|
|
87
|
-
|
|
88
|
-
def bigram_collocation_feats(self, documents, top_n=None, min_freq=3,
|
|
89
|
-
assoc_measure=BigramAssocMeasures.pmi):
|
|
90
|
-
"""
|
|
91
|
-
Return `top_n` bigram features (using `assoc_measure`).
|
|
92
|
-
Note that this method is based on bigram collocations measures, and not
|
|
93
|
-
on simple bigram frequency.
|
|
94
|
-
|
|
95
|
-
:param documents: a list (or iterable) of tokens.
|
|
96
|
-
:param top_n: number of best words/tokens to use, sorted by association
|
|
97
|
-
measure.
|
|
98
|
-
:param assoc_measure: bigram association measure to use as score function.
|
|
99
|
-
:param min_freq: the minimum number of occurrencies of bigrams to take
|
|
100
|
-
into consideration.
|
|
101
|
-
|
|
102
|
-
:return: `top_n` ngrams scored by the given association measure.
|
|
103
|
-
"""
|
|
104
|
-
finder = BigramCollocationFinder.from_documents(documents)
|
|
105
|
-
finder.apply_freq_filter(min_freq)
|
|
106
|
-
return finder.nbest(assoc_measure, top_n)
|
|
107
|
-
|
|
108
|
-
def classify(self, instance):
|
|
109
|
-
"""
|
|
110
|
-
Classify a single instance applying the features that have already been
|
|
111
|
-
stored in the SentimentAnalyzer.
|
|
112
|
-
|
|
113
|
-
:param instance: a list (or iterable) of tokens.
|
|
114
|
-
:return: the classification result given by applying the classifier.
|
|
115
|
-
"""
|
|
116
|
-
instance_feats = self.apply_features([instance], labeled=False)
|
|
117
|
-
return self.classifier.classify(instance_feats[0])
|
|
118
|
-
|
|
119
|
-
def add_feat_extractor(self, function, **kwargs):
|
|
120
|
-
"""
|
|
121
|
-
Add a new function to extract features from a document. This function will
|
|
122
|
-
be used in extract_features().
|
|
123
|
-
Important: in this step our kwargs are only representing additional parameters,
|
|
124
|
-
and NOT the document we have to parse. The document will always be the first
|
|
125
|
-
parameter in the parameter list, and it will be added in the extract_features()
|
|
126
|
-
function.
|
|
127
|
-
|
|
128
|
-
:param function: the extractor function to add to the list of feature extractors.
|
|
129
|
-
:param kwargs: additional parameters required by the `function` function.
|
|
130
|
-
"""
|
|
131
|
-
self.feat_extractors[function].append(kwargs)
|
|
132
|
-
|
|
133
|
-
def extract_features(self, document):
|
|
134
|
-
"""
|
|
135
|
-
Apply extractor functions (and their parameters) to the present document.
|
|
136
|
-
We pass `document` as the first parameter of the extractor functions.
|
|
137
|
-
If we want to use the same extractor function multiple times, we have to
|
|
138
|
-
add it to the extractors with `add_feat_extractor` using multiple sets of
|
|
139
|
-
parameters (one for each call of the extractor function).
|
|
140
|
-
|
|
141
|
-
:param document: the document that will be passed as argument to the
|
|
142
|
-
feature extractor functions.
|
|
143
|
-
:return: A dictionary of populated features extracted from the document.
|
|
144
|
-
:rtype: dict
|
|
145
|
-
"""
|
|
146
|
-
all_features = {}
|
|
147
|
-
for extractor in self.feat_extractors:
|
|
148
|
-
for param_set in self.feat_extractors[extractor]:
|
|
149
|
-
feats = extractor(document, **param_set)
|
|
150
|
-
all_features.update(feats)
|
|
151
|
-
return all_features
|
|
152
|
-
|
|
153
|
-
def train(self, trainer, training_set, save_classifier=None, **kwargs):
|
|
154
|
-
"""
|
|
155
|
-
Train classifier on the training set, optionally saving the output in the
|
|
156
|
-
file specified by `save_classifier`.
|
|
157
|
-
Additional arguments depend on the specific trainer used. For example,
|
|
158
|
-
a MaxentClassifier can use `max_iter` parameter to specify the number
|
|
159
|
-
of iterations, while a NaiveBayesClassifier cannot.
|
|
160
|
-
|
|
161
|
-
:param trainer: `train` method of a classifier.
|
|
162
|
-
E.g.: NaiveBayesClassifier.train
|
|
163
|
-
:param training_set: the training set to be passed as argument to the
|
|
164
|
-
classifier `train` method.
|
|
165
|
-
:param save_classifier: the filename of the file where the classifier
|
|
166
|
-
will be stored (optional).
|
|
167
|
-
:param kwargs: additional parameters that will be passed as arguments to
|
|
168
|
-
the classifier `train` function.
|
|
169
|
-
:return: A classifier instance trained on the training set.
|
|
170
|
-
:rtype:
|
|
171
|
-
"""
|
|
172
|
-
print("Training classifier")
|
|
173
|
-
self.classifier = trainer(training_set, **kwargs)
|
|
174
|
-
if save_classifier:
|
|
175
|
-
save_file(self.classifier, save_classifier)
|
|
176
|
-
|
|
177
|
-
return self.classifier
|
|
178
|
-
|
|
179
|
-
def evaluate(self, test_set, classifier=None, accuracy=True, f_measure=True,
|
|
180
|
-
precision=True, recall=True, verbose=False):
|
|
181
|
-
"""
|
|
182
|
-
Evaluate and print classifier performance on the test set.
|
|
183
|
-
|
|
184
|
-
:param test_set: A list of (tokens, label) tuples to use as gold set.
|
|
185
|
-
:param classifier: a classifier instance (previously trained).
|
|
186
|
-
:param accuracy: if `True`, evaluate classifier accuracy.
|
|
187
|
-
:param f_measure: if `True`, evaluate classifier f_measure.
|
|
188
|
-
:param precision: if `True`, evaluate classifier precision.
|
|
189
|
-
:param recall: if `True`, evaluate classifier recall.
|
|
190
|
-
:return: evaluation results.
|
|
191
|
-
:rtype: dict(str): float
|
|
192
|
-
"""
|
|
193
|
-
if classifier is None:
|
|
194
|
-
classifier = self.classifier
|
|
195
|
-
print("Evaluating {0} results...".format(type(classifier).__name__))
|
|
196
|
-
metrics_results = {}
|
|
197
|
-
if accuracy == True:
|
|
198
|
-
accuracy_score = eval_accuracy(classifier, test_set)
|
|
199
|
-
metrics_results['Accuracy'] = accuracy_score
|
|
200
|
-
|
|
201
|
-
gold_results = defaultdict(set)
|
|
202
|
-
test_results = defaultdict(set)
|
|
203
|
-
labels = set()
|
|
204
|
-
for i, (feats, label) in enumerate(test_set):
|
|
205
|
-
labels.add(label)
|
|
206
|
-
gold_results[label].add(i)
|
|
207
|
-
observed = classifier.classify(feats)
|
|
208
|
-
test_results[observed].add(i)
|
|
209
|
-
|
|
210
|
-
for label in labels:
|
|
211
|
-
if precision == True:
|
|
212
|
-
precision_score = eval_precision(gold_results[label],
|
|
213
|
-
test_results[label])
|
|
214
|
-
metrics_results['Precision [{0}]'.format(label)] = precision_score
|
|
215
|
-
if recall == True:
|
|
216
|
-
recall_score = eval_recall(gold_results[label],
|
|
217
|
-
test_results[label])
|
|
218
|
-
metrics_results['Recall [{0}]'.format(label)] = recall_score
|
|
219
|
-
if f_measure == True:
|
|
220
|
-
f_measure_score = eval_f_measure(gold_results[label],
|
|
221
|
-
test_results[label])
|
|
222
|
-
metrics_results['F-measure [{0}]'.format(label)] = f_measure_score
|
|
223
|
-
|
|
224
|
-
# Print evaluation results (in alphabetical order)
|
|
225
|
-
if verbose == True:
|
|
226
|
-
for result in sorted(metrics_results):
|
|
227
|
-
print('{0}: {1}'.format(result, metrics_results[result]))
|
|
228
|
-
|
|
229
|
-
return metrics_results
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# Natural Language Toolkit: Sentiment Analyzer
|
|
4
|
+
#
|
|
5
|
+
# Copyright (C) 2001-2018 NLTK Project
|
|
6
|
+
# Author: Pierpaolo Pantone <24alsecondo@gmail.com>
|
|
7
|
+
# URL: <http://nltk.org/>
|
|
8
|
+
# For license information, see LICENSE.TXT
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
A SentimentAnalyzer is a tool to implement and facilitate Sentiment Analysis tasks
|
|
12
|
+
using NLTK features and classifiers, especially for teaching and demonstrative
|
|
13
|
+
purposes.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import print_function
|
|
17
|
+
from collections import defaultdict
|
|
18
|
+
|
|
19
|
+
from nltk.classify.util import apply_features, accuracy as eval_accuracy
|
|
20
|
+
from nltk.collocations import BigramCollocationFinder
|
|
21
|
+
from nltk.metrics import (BigramAssocMeasures, precision as eval_precision,
|
|
22
|
+
recall as eval_recall, f_measure as eval_f_measure)
|
|
23
|
+
|
|
24
|
+
from nltk.probability import FreqDist
|
|
25
|
+
|
|
26
|
+
from nltk.sentiment.util import save_file, timer
|
|
27
|
+
|
|
28
|
+
class SentimentAnalyzer(object):
|
|
29
|
+
"""
|
|
30
|
+
A Sentiment Analysis tool based on machine learning approaches.
|
|
31
|
+
"""
|
|
32
|
+
def __init__(self, classifier=None):
|
|
33
|
+
self.feat_extractors = defaultdict(list)
|
|
34
|
+
self.classifier = classifier
|
|
35
|
+
|
|
36
|
+
def all_words(self, documents, labeled=None):
|
|
37
|
+
"""
|
|
38
|
+
Return all words/tokens from the documents (with duplicates).
|
|
39
|
+
:param documents: a list of (words, label) tuples.
|
|
40
|
+
:param labeled: if `True`, assume that each document is represented by a
|
|
41
|
+
(words, label) tuple: (list(str), str). If `False`, each document is
|
|
42
|
+
considered as being a simple list of strings: list(str).
|
|
43
|
+
:rtype: list(str)
|
|
44
|
+
:return: A list of all words/tokens in `documents`.
|
|
45
|
+
"""
|
|
46
|
+
all_words = []
|
|
47
|
+
if labeled is None:
|
|
48
|
+
labeled = documents and isinstance(documents[0], tuple)
|
|
49
|
+
if labeled == True:
|
|
50
|
+
for words, sentiment in documents:
|
|
51
|
+
all_words.extend(words)
|
|
52
|
+
elif labeled == False:
|
|
53
|
+
for words in documents:
|
|
54
|
+
all_words.extend(words)
|
|
55
|
+
return all_words
|
|
56
|
+
|
|
57
|
+
def apply_features(self, documents, labeled=None):
|
|
58
|
+
"""
|
|
59
|
+
Apply all feature extractor functions to the documents. This is a wrapper
|
|
60
|
+
around `nltk.classify.util.apply_features`.
|
|
61
|
+
|
|
62
|
+
If `labeled=False`, return featuresets as:
|
|
63
|
+
[feature_func(doc) for doc in documents]
|
|
64
|
+
If `labeled=True`, return featuresets as:
|
|
65
|
+
[(feature_func(tok), label) for (tok, label) in toks]
|
|
66
|
+
|
|
67
|
+
:param documents: a list of documents. `If labeled=True`, the method expects
|
|
68
|
+
a list of (words, label) tuples.
|
|
69
|
+
:rtype: LazyMap
|
|
70
|
+
"""
|
|
71
|
+
return apply_features(self.extract_features, documents, labeled)
|
|
72
|
+
|
|
73
|
+
def unigram_word_feats(self, words, top_n=None, min_freq=0):
|
|
74
|
+
"""
|
|
75
|
+
Return most common top_n word features.
|
|
76
|
+
|
|
77
|
+
:param words: a list of words/tokens.
|
|
78
|
+
:param top_n: number of best words/tokens to use, sorted by frequency.
|
|
79
|
+
:rtype: list(str)
|
|
80
|
+
:return: A list of `top_n` words/tokens (with no duplicates) sorted by
|
|
81
|
+
frequency.
|
|
82
|
+
"""
|
|
83
|
+
# Stopwords are not removed
|
|
84
|
+
unigram_feats_freqs = FreqDist(word for word in words)
|
|
85
|
+
return [w for w, f in unigram_feats_freqs.most_common(top_n)
|
|
86
|
+
if unigram_feats_freqs[w] > min_freq]
|
|
87
|
+
|
|
88
|
+
def bigram_collocation_feats(self, documents, top_n=None, min_freq=3,
|
|
89
|
+
assoc_measure=BigramAssocMeasures.pmi):
|
|
90
|
+
"""
|
|
91
|
+
Return `top_n` bigram features (using `assoc_measure`).
|
|
92
|
+
Note that this method is based on bigram collocations measures, and not
|
|
93
|
+
on simple bigram frequency.
|
|
94
|
+
|
|
95
|
+
:param documents: a list (or iterable) of tokens.
|
|
96
|
+
:param top_n: number of best words/tokens to use, sorted by association
|
|
97
|
+
measure.
|
|
98
|
+
:param assoc_measure: bigram association measure to use as score function.
|
|
99
|
+
:param min_freq: the minimum number of occurrencies of bigrams to take
|
|
100
|
+
into consideration.
|
|
101
|
+
|
|
102
|
+
:return: `top_n` ngrams scored by the given association measure.
|
|
103
|
+
"""
|
|
104
|
+
finder = BigramCollocationFinder.from_documents(documents)
|
|
105
|
+
finder.apply_freq_filter(min_freq)
|
|
106
|
+
return finder.nbest(assoc_measure, top_n)
|
|
107
|
+
|
|
108
|
+
def classify(self, instance):
|
|
109
|
+
"""
|
|
110
|
+
Classify a single instance applying the features that have already been
|
|
111
|
+
stored in the SentimentAnalyzer.
|
|
112
|
+
|
|
113
|
+
:param instance: a list (or iterable) of tokens.
|
|
114
|
+
:return: the classification result given by applying the classifier.
|
|
115
|
+
"""
|
|
116
|
+
instance_feats = self.apply_features([instance], labeled=False)
|
|
117
|
+
return self.classifier.classify(instance_feats[0])
|
|
118
|
+
|
|
119
|
+
def add_feat_extractor(self, function, **kwargs):
|
|
120
|
+
"""
|
|
121
|
+
Add a new function to extract features from a document. This function will
|
|
122
|
+
be used in extract_features().
|
|
123
|
+
Important: in this step our kwargs are only representing additional parameters,
|
|
124
|
+
and NOT the document we have to parse. The document will always be the first
|
|
125
|
+
parameter in the parameter list, and it will be added in the extract_features()
|
|
126
|
+
function.
|
|
127
|
+
|
|
128
|
+
:param function: the extractor function to add to the list of feature extractors.
|
|
129
|
+
:param kwargs: additional parameters required by the `function` function.
|
|
130
|
+
"""
|
|
131
|
+
self.feat_extractors[function].append(kwargs)
|
|
132
|
+
|
|
133
|
+
def extract_features(self, document):
|
|
134
|
+
"""
|
|
135
|
+
Apply extractor functions (and their parameters) to the present document.
|
|
136
|
+
We pass `document` as the first parameter of the extractor functions.
|
|
137
|
+
If we want to use the same extractor function multiple times, we have to
|
|
138
|
+
add it to the extractors with `add_feat_extractor` using multiple sets of
|
|
139
|
+
parameters (one for each call of the extractor function).
|
|
140
|
+
|
|
141
|
+
:param document: the document that will be passed as argument to the
|
|
142
|
+
feature extractor functions.
|
|
143
|
+
:return: A dictionary of populated features extracted from the document.
|
|
144
|
+
:rtype: dict
|
|
145
|
+
"""
|
|
146
|
+
all_features = {}
|
|
147
|
+
for extractor in self.feat_extractors:
|
|
148
|
+
for param_set in self.feat_extractors[extractor]:
|
|
149
|
+
feats = extractor(document, **param_set)
|
|
150
|
+
all_features.update(feats)
|
|
151
|
+
return all_features
|
|
152
|
+
|
|
153
|
+
def train(self, trainer, training_set, save_classifier=None, **kwargs):
|
|
154
|
+
"""
|
|
155
|
+
Train classifier on the training set, optionally saving the output in the
|
|
156
|
+
file specified by `save_classifier`.
|
|
157
|
+
Additional arguments depend on the specific trainer used. For example,
|
|
158
|
+
a MaxentClassifier can use `max_iter` parameter to specify the number
|
|
159
|
+
of iterations, while a NaiveBayesClassifier cannot.
|
|
160
|
+
|
|
161
|
+
:param trainer: `train` method of a classifier.
|
|
162
|
+
E.g.: NaiveBayesClassifier.train
|
|
163
|
+
:param training_set: the training set to be passed as argument to the
|
|
164
|
+
classifier `train` method.
|
|
165
|
+
:param save_classifier: the filename of the file where the classifier
|
|
166
|
+
will be stored (optional).
|
|
167
|
+
:param kwargs: additional parameters that will be passed as arguments to
|
|
168
|
+
the classifier `train` function.
|
|
169
|
+
:return: A classifier instance trained on the training set.
|
|
170
|
+
:rtype:
|
|
171
|
+
"""
|
|
172
|
+
print("Training classifier")
|
|
173
|
+
self.classifier = trainer(training_set, **kwargs)
|
|
174
|
+
if save_classifier:
|
|
175
|
+
save_file(self.classifier, save_classifier)
|
|
176
|
+
|
|
177
|
+
return self.classifier
|
|
178
|
+
|
|
179
|
+
def evaluate(self, test_set, classifier=None, accuracy=True, f_measure=True,
|
|
180
|
+
precision=True, recall=True, verbose=False):
|
|
181
|
+
"""
|
|
182
|
+
Evaluate and print classifier performance on the test set.
|
|
183
|
+
|
|
184
|
+
:param test_set: A list of (tokens, label) tuples to use as gold set.
|
|
185
|
+
:param classifier: a classifier instance (previously trained).
|
|
186
|
+
:param accuracy: if `True`, evaluate classifier accuracy.
|
|
187
|
+
:param f_measure: if `True`, evaluate classifier f_measure.
|
|
188
|
+
:param precision: if `True`, evaluate classifier precision.
|
|
189
|
+
:param recall: if `True`, evaluate classifier recall.
|
|
190
|
+
:return: evaluation results.
|
|
191
|
+
:rtype: dict(str): float
|
|
192
|
+
"""
|
|
193
|
+
if classifier is None:
|
|
194
|
+
classifier = self.classifier
|
|
195
|
+
print("Evaluating {0} results...".format(type(classifier).__name__))
|
|
196
|
+
metrics_results = {}
|
|
197
|
+
if accuracy == True:
|
|
198
|
+
accuracy_score = eval_accuracy(classifier, test_set)
|
|
199
|
+
metrics_results['Accuracy'] = accuracy_score
|
|
200
|
+
|
|
201
|
+
gold_results = defaultdict(set)
|
|
202
|
+
test_results = defaultdict(set)
|
|
203
|
+
labels = set()
|
|
204
|
+
for i, (feats, label) in enumerate(test_set):
|
|
205
|
+
labels.add(label)
|
|
206
|
+
gold_results[label].add(i)
|
|
207
|
+
observed = classifier.classify(feats)
|
|
208
|
+
test_results[observed].add(i)
|
|
209
|
+
|
|
210
|
+
for label in labels:
|
|
211
|
+
if precision == True:
|
|
212
|
+
precision_score = eval_precision(gold_results[label],
|
|
213
|
+
test_results[label])
|
|
214
|
+
metrics_results['Precision [{0}]'.format(label)] = precision_score
|
|
215
|
+
if recall == True:
|
|
216
|
+
recall_score = eval_recall(gold_results[label],
|
|
217
|
+
test_results[label])
|
|
218
|
+
metrics_results['Recall [{0}]'.format(label)] = recall_score
|
|
219
|
+
if f_measure == True:
|
|
220
|
+
f_measure_score = eval_f_measure(gold_results[label],
|
|
221
|
+
test_results[label])
|
|
222
|
+
metrics_results['F-measure [{0}]'.format(label)] = f_measure_score
|
|
223
|
+
|
|
224
|
+
# Print evaluation results (in alphabetical order)
|
|
225
|
+
if verbose == True:
|
|
226
|
+
for result in sorted(metrics_results):
|
|
227
|
+
print('{0}: {1}'.format(result, metrics_results[result]))
|
|
228
|
+
|
|
229
|
+
return metrics_results
|