From 1b1aec4e2359ddba9ca42fea031ebb78635464af Mon Sep 17 00:00:00 2001 From: Michael Penkov Date: Sat, 17 Oct 2020 18:51:54 +0900 Subject: [PATCH 01/20] update changelog for 4.0.0 release --- CHANGELOG.md | 32 +++++++++++++++++++++++------ release/generate_changelog.py | 38 +++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 release/generate_changelog.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 52bf5a989f..1af1cdab58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,23 +7,43 @@ This release contains a major refactoring. ### :+1: Improvements -* Refactor ldamulticore to serialize less data (PR [#2300](https://github.com/RaRe-Technologies/gensim/pull/2300), __[@horpto](https://github.com/horpto)__) -* KeyedVectors & X2Vec API streamlining, consistency (PR [#2698](https://github.com/RaRe-Technologies/gensim/pull/2698), __[@gojomo](https://github.com/gojomo)__) * No more wheels for x32 platforms (if you need x32 binaries, please build them yourself). (__[menshikh-iv](https://github.com/menshikh-iv)__, [#6](https://github.com/RaRe-Technologies/gensim-wheels/pull/6)) +* Refactor ldamulticore to serialize less data (PR [#2300](https://github.com/RaRe-Technologies/gensim/pull/2300), __[@horpto](https://github.com/horpto)__) +* KeyedVectors & X2Vec API streamlining, consistency (PR [#2698](https://github.com/RaRe-Technologies/gensim/pull/2698), __[@gojomo](https://github.com/gojomo)__) +* Fix for Python 3.9/3.10: remove xml.etree.cElementTree [#2846](https://github.com/RaRe-Technologies/gensim/pull/2846), __[@hugovk](https://github.com/hugovk)__ * Speed up random number generation in word2vec model (PR [#2864](https://github.com/RaRe-Technologies/gensim/pull/2864), __[@zygm0nt](https://github.com/zygm0nt)__) -* Fix deprecations in SoftCosineSimilarity (PR [#2940](https://github.com/RaRe-Technologies/gensim/pull/2940), __[@Witiko](https://github.com/Witiko)__) +* Expose max_final_vocab parameter in FastText constructor [#2867](https://github.com/RaRe-Technologies/gensim/pull/2867), __[@mpenkov](https://github.com/mpenkov)__ +* Fix similarity bug in NMSLIB indexer + documentation fixes [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ +* Fix FastText word-vectors w/ ngrams/buckets off [#2891](https://github.com/RaRe-Technologies/gensim/pull/2891), __[@gojomo](https://github.com/gojomo)__ +* Fix AttributeError in WikiCorpus [#2901](https://github.com/RaRe-Technologies/gensim/pull/2901), __[@jenishah](https://github.com/jenishah)__ +* Fix doc2vec crash for large sets of doc-vectors [#2907](https://github.com/RaRe-Technologies/gensim/pull/2907), __[@gojomo](https://github.com/gojomo)__ +* Change num_words to topn in dtm_coherence [#2926](https://github.com/RaRe-Technologies/gensim/pull/2926), __[@MeganStodel](https://github.com/MeganStodel)__ +* Clear up job queue parameters in word2vec [#2931](https://github.com/RaRe-Technologies/gensim/pull/2931), __[@lunastera](https://github.com/lunastera)__ * Remove Keras dependency (PR [#2937](https://github.com/RaRe-Technologies/gensim/pull/2937), __[@piskvorky](https://github.com/piskvorky)__) +* X2Vec SaveLoad improvements [#2939](https://github.com/RaRe-Technologies/gensim/pull/2939), __[@piskvorky](https://github.com/piskvorky)__ +* Fix deprecations in SoftCosineSimilarity (PR [#2940](https://github.com/RaRe-Technologies/gensim/pull/2940), __[@Witiko](https://github.com/Witiko)__) * Bump minimum Python version to 3.6 (PR [#2947](https://github.com/RaRe-Technologies/gensim/pull/2947), __[@gojomo](https://github.com/gojomo)__) +* Fix deprecations in SoftCosineSimilarity [#2940](https://github.com/RaRe-Technologies/gensim/pull/2940), __[@Witiko](https://github.com/Witiko)__ +* Fix save_facebook_model failure after update-vocab & other initialization streamlining [#2944](https://github.com/RaRe-Technologies/gensim/pull/2944), __[@gojomo](https://github.com/gojomo)__ +* Refactor phrases submodule [#2976](https://github.com/RaRe-Technologies/gensim/pull/2976), __[@piskvorky](https://github.com/piskvorky)__ +* Skip common English words during phrase construction [#2979](https://github.com/RaRe-Technologies/gensim/pull/2979), __[@piskvorky](https://github.com/piskvorky)__ ### :books: Tutorial and doc improvements - * Clear up LdaModel documentation - remove claim that it accepts CSC matrix as input (PR [#2832](https://github.com/RaRe-Technologies/gensim/pull/2832), [@FyzHsn](https://github.com/FyzHsn)) - * Fix "generator" language in word2vec docs (PR [#2935](https://github.com/RaRe-Technologies/gensim/pull/2935), __[@polm](https://github.com/polm)__) +* Clear up LdaModel documentation - remove claim that it accepts CSC matrix as input (PR [#2832](https://github.com/RaRe-Technologies/gensim/pull/2832), [@FyzHsn](https://github.com/FyzHsn)) +* Clarify that license is LGPL-2.1 [#2871](https://github.com/RaRe-Technologies/gensim/pull/2871), __[@pombredanne](https://github.com/pombredanne)__ +* Make docs clearer on `alpha` parameter in LDA model [#2896](https://github.com/RaRe-Technologies/gensim/pull/2896), __[@xh2](https://github.com/xh2)__ +* Update Hoffman paper link for Online LDA [#2897](https://github.com/RaRe-Technologies/gensim/pull/2897), __[@xh2](https://github.com/xh2)__ +* Refresh docs for run_annoy tutorial [#2910](https://github.com/RaRe-Technologies/gensim/pull/2910), __[@piskvorky](https://github.com/piskvorky)__ +* Fix "generator" language in word2vec docs (PR [#2935](https://github.com/RaRe-Technologies/gensim/pull/2935), __[@polm](https://github.com/polm)__) +* Migrate tutorials & how-tos to 4.0.0 [#2968](https://github.com/RaRe-Technologies/gensim/pull/2968), __[@piskvorky](https://github.com/piskvorky)__ +* New docs theme [#2954](https://github.com/RaRe-Technologies/gensim/pull/2954), __[@dvorakvaclav](https://github.com/dvorakvaclav)__ ### :warning: Removed functionality - * Remove gensim.summarization subpackage, docs and test data (PR [#2958](https://github.com/RaRe-Technologies/gensim/pull/2958), __[@mpenkov](https://github.com/mpenkov)__) +* Remove gensim.summarization subpackage, docs and test data (PR [#2958](https://github.com/RaRe-Technologies/gensim/pull/2958), __[@mpenkov](https://github.com/mpenkov)__) +* Bump minimum Python version to 3.6 [#2947](https://github.com/RaRe-Technologies/gensim/pull/2947), __[@gojomo](https://github.com/gojomo)__ ## :warning: 3.8.x will be the last gensim version to support Py2.7. Starting with 4.0.0, gensim will only support Py3.5 and above diff --git a/release/generate_changelog.py b/release/generate_changelog.py new file mode 100644 index 0000000000..2884928d9b --- /dev/null +++ b/release/generate_changelog.py @@ -0,0 +1,38 @@ +"""Generate changelog entries for all PRs merged since the last release.""" +import requests + +get = requests.get('https://api.github.com/repos/RaRe-Technologies/gensim/releases') +get.raise_for_status() + +last_release_date = get.json()[0]['published_at'][:10] + + +def g(): + page = 1 + done = False + + while not done: + get = requests.get( + 'https://api.github.com/repos/RaRe-Technologies/gensim/pulls', + params={'state': 'closed', 'page': page}, + ) + get.raise_for_status() + pulls = get.json() + if not pulls: + break + + for i, pr in enumerate(pulls): + if pr['created_at'] < last_release_date: + done = True + break + + if pr['merged_at'] and pr['merged_at'] > last_release_date: + yield pr + + page += 1 + + +for pr in g(): + pr['user_login'] = pr['user']['login'] + pr['user_html_url'] = pr['user']['html_url'] + print('* %(title)s [#%(number)d](%(html_url)s), __[@%(user_login)s](%(user_html_url)s)__' % pr) From 6e21ee17d5e1d7fddbdc8aa7447d7d16c23a4b96 Mon Sep 17 00:00:00 2001 From: Michael Penkov Date: Sat, 17 Oct 2020 18:57:33 +0900 Subject: [PATCH 02/20] fixup --- CHANGELOG.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1af1cdab58..19ed0d6804 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,23 +8,22 @@ This release contains a major refactoring. ### :+1: Improvements * No more wheels for x32 platforms (if you need x32 binaries, please build them yourself). - (__[menshikh-iv](https://github.com/menshikh-iv)__, [#6](https://github.com/RaRe-Technologies/gensim-wheels/pull/6)) -* Refactor ldamulticore to serialize less data (PR [#2300](https://github.com/RaRe-Technologies/gensim/pull/2300), __[@horpto](https://github.com/horpto)__) -* KeyedVectors & X2Vec API streamlining, consistency (PR [#2698](https://github.com/RaRe-Technologies/gensim/pull/2698), __[@gojomo](https://github.com/gojomo)__) + __[menshikh-iv](https://github.com/menshikh-iv)__, [#6](https://github.com/RaRe-Technologies/gensim-wheels/pull/6) +* Refactor ldamulticore to serialize less data [#2300](https://github.com/RaRe-Technologies/gensim/pull/2300), __[@horpto](https://github.com/horpto)__ +* KeyedVectors & X2Vec API streamlining, consistency [#2698](https://github.com/RaRe-Technologies/gensim/pull/2698), __[@gojomo](https://github.com/gojomo)__ * Fix for Python 3.9/3.10: remove xml.etree.cElementTree [#2846](https://github.com/RaRe-Technologies/gensim/pull/2846), __[@hugovk](https://github.com/hugovk)__ -* Speed up random number generation in word2vec model (PR [#2864](https://github.com/RaRe-Technologies/gensim/pull/2864), __[@zygm0nt](https://github.com/zygm0nt)__) +* Speed up random number generation in word2vec model [#2864](https://github.com/RaRe-Technologies/gensim/pull/2864), __[@zygm0nt](https://github.com/zygm0nt)__ * Expose max_final_vocab parameter in FastText constructor [#2867](https://github.com/RaRe-Technologies/gensim/pull/2867), __[@mpenkov](https://github.com/mpenkov)__ -* Fix similarity bug in NMSLIB indexer + documentation fixes [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ * Fix FastText word-vectors w/ ngrams/buckets off [#2891](https://github.com/RaRe-Technologies/gensim/pull/2891), __[@gojomo](https://github.com/gojomo)__ +* Fix similarity bug in NMSLIB indexer + documentation fixes [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ * Fix AttributeError in WikiCorpus [#2901](https://github.com/RaRe-Technologies/gensim/pull/2901), __[@jenishah](https://github.com/jenishah)__ * Fix doc2vec crash for large sets of doc-vectors [#2907](https://github.com/RaRe-Technologies/gensim/pull/2907), __[@gojomo](https://github.com/gojomo)__ * Change num_words to topn in dtm_coherence [#2926](https://github.com/RaRe-Technologies/gensim/pull/2926), __[@MeganStodel](https://github.com/MeganStodel)__ * Clear up job queue parameters in word2vec [#2931](https://github.com/RaRe-Technologies/gensim/pull/2931), __[@lunastera](https://github.com/lunastera)__ -* Remove Keras dependency (PR [#2937](https://github.com/RaRe-Technologies/gensim/pull/2937), __[@piskvorky](https://github.com/piskvorky)__) +* Remove Keras dependency [#2937](https://github.com/RaRe-Technologies/gensim/pull/2937), __[@piskvorky](https://github.com/piskvorky)__ * X2Vec SaveLoad improvements [#2939](https://github.com/RaRe-Technologies/gensim/pull/2939), __[@piskvorky](https://github.com/piskvorky)__ -* Fix deprecations in SoftCosineSimilarity (PR [#2940](https://github.com/RaRe-Technologies/gensim/pull/2940), __[@Witiko](https://github.com/Witiko)__) -* Bump minimum Python version to 3.6 (PR [#2947](https://github.com/RaRe-Technologies/gensim/pull/2947), __[@gojomo](https://github.com/gojomo)__) * Fix deprecations in SoftCosineSimilarity [#2940](https://github.com/RaRe-Technologies/gensim/pull/2940), __[@Witiko](https://github.com/Witiko)__ +* Bump minimum Python version to 3.6 [#2947](https://github.com/RaRe-Technologies/gensim/pull/2947), __[@gojomo](https://github.com/gojomo)__ * Fix save_facebook_model failure after update-vocab & other initialization streamlining [#2944](https://github.com/RaRe-Technologies/gensim/pull/2944), __[@gojomo](https://github.com/gojomo)__ * Refactor phrases submodule [#2976](https://github.com/RaRe-Technologies/gensim/pull/2976), __[@piskvorky](https://github.com/piskvorky)__ * Skip common English words during phrase construction [#2979](https://github.com/RaRe-Technologies/gensim/pull/2979), __[@piskvorky](https://github.com/piskvorky)__ From f09d8a723fa0ba96659adf95c0e7d9b41f5d582d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Mon, 19 Oct 2020 01:17:42 +0200 Subject: [PATCH 03/20] wip: cleaning up changelog --- CHANGELOG.md | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19ed0d6804..57bc89d9d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,33 +3,35 @@ Changes ## Unreleased -This release contains a major refactoring. ### :+1: Improvements -* No more wheels for x32 platforms (if you need x32 binaries, please build them yourself). - __[menshikh-iv](https://github.com/menshikh-iv)__, [#6](https://github.com/RaRe-Technologies/gensim-wheels/pull/6) -* Refactor ldamulticore to serialize less data [#2300](https://github.com/RaRe-Technologies/gensim/pull/2300), __[@horpto](https://github.com/horpto)__ -* KeyedVectors & X2Vec API streamlining, consistency [#2698](https://github.com/RaRe-Technologies/gensim/pull/2698), __[@gojomo](https://github.com/gojomo)__ +* Use less RAM in LdaMulticore [#2300](https://github.com/RaRe-Technologies/gensim/pull/2300), __[@horpto](https://github.com/horpto)__ +* Streamline KeyedVectors & X2Vec API, consistency [#2698](https://github.com/RaRe-Technologies/gensim/pull/2698), __[@gojomo](https://github.com/gojomo)__ * Fix for Python 3.9/3.10: remove xml.etree.cElementTree [#2846](https://github.com/RaRe-Technologies/gensim/pull/2846), __[@hugovk](https://github.com/hugovk)__ -* Speed up random number generation in word2vec model [#2864](https://github.com/RaRe-Technologies/gensim/pull/2864), __[@zygm0nt](https://github.com/zygm0nt)__ -* Expose max_final_vocab parameter in FastText constructor [#2867](https://github.com/RaRe-Technologies/gensim/pull/2867), __[@mpenkov](https://github.com/mpenkov)__ -* Fix FastText word-vectors w/ ngrams/buckets off [#2891](https://github.com/RaRe-Technologies/gensim/pull/2891), __[@gojomo](https://github.com/gojomo)__ -* Fix similarity bug in NMSLIB indexer + documentation fixes [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ -* Fix AttributeError in WikiCorpus [#2901](https://github.com/RaRe-Technologies/gensim/pull/2901), __[@jenishah](https://github.com/jenishah)__ +* Speed up random number generation in word2vec [#2864](https://github.com/RaRe-Technologies/gensim/pull/2864), __[@zygm0nt](https://github.com/zygm0nt)__ +* Expose max_final_vocab parameter in fastText constructor [#2867](https://github.com/RaRe-Technologies/gensim/pull/2867), __[@mpenkov](https://github.com/mpenkov)__ +* Fix fastText word-vectors with ngrams off [#2891](https://github.com/RaRe-Technologies/gensim/pull/2891), __[@gojomo](https://github.com/gojomo)__ +* Fix similarity bug in NMSLIB indexer [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ +* Renamed overly broad `similarities.index` to the more appropriate `similarities.annoy` [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ +* Fixed deprecation warnings in Annoy integration. [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ +* Fix inheritance of WikiCorpus from TextCorpus [#2901](https://github.com/RaRe-Technologies/gensim/pull/2901), __[@jenishah](https://github.com/jenishah)__ * Fix doc2vec crash for large sets of doc-vectors [#2907](https://github.com/RaRe-Technologies/gensim/pull/2907), __[@gojomo](https://github.com/gojomo)__ -* Change num_words to topn in dtm_coherence [#2926](https://github.com/RaRe-Technologies/gensim/pull/2926), __[@MeganStodel](https://github.com/MeganStodel)__ +* Change `num_words` to `topn` in dtm_coherence [#2926](https://github.com/RaRe-Technologies/gensim/pull/2926), __[@MeganStodel](https://github.com/MeganStodel)__ * Clear up job queue parameters in word2vec [#2931](https://github.com/RaRe-Technologies/gensim/pull/2931), __[@lunastera](https://github.com/lunastera)__ * Remove Keras dependency [#2937](https://github.com/RaRe-Technologies/gensim/pull/2937), __[@piskvorky](https://github.com/piskvorky)__ * X2Vec SaveLoad improvements [#2939](https://github.com/RaRe-Technologies/gensim/pull/2939), __[@piskvorky](https://github.com/piskvorky)__ +* Code style & py3 migration clean up [#2939](https://github.com/RaRe-Technologies/gensim/pull/2939), __[@piskvorky](https://github.com/piskvorky)__ * Fix deprecations in SoftCosineSimilarity [#2940](https://github.com/RaRe-Technologies/gensim/pull/2940), __[@Witiko](https://github.com/Witiko)__ * Bump minimum Python version to 3.6 [#2947](https://github.com/RaRe-Technologies/gensim/pull/2947), __[@gojomo](https://github.com/gojomo)__ * Fix save_facebook_model failure after update-vocab & other initialization streamlining [#2944](https://github.com/RaRe-Technologies/gensim/pull/2944), __[@gojomo](https://github.com/gojomo)__ * Refactor phrases submodule [#2976](https://github.com/RaRe-Technologies/gensim/pull/2976), __[@piskvorky](https://github.com/piskvorky)__ * Skip common English words during phrase construction [#2979](https://github.com/RaRe-Technologies/gensim/pull/2979), __[@piskvorky](https://github.com/piskvorky)__ -### :books: Tutorial and doc improvements +### :books: Tutorials and docs +* Clean up of API docs language and formatting [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ +* Added documentation for NMSLIB indexer [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ * Clear up LdaModel documentation - remove claim that it accepts CSC matrix as input (PR [#2832](https://github.com/RaRe-Technologies/gensim/pull/2832), [@FyzHsn](https://github.com/FyzHsn)) * Clarify that license is LGPL-2.1 [#2871](https://github.com/RaRe-Technologies/gensim/pull/2871), __[@pombredanne](https://github.com/pombredanne)__ * Make docs clearer on `alpha` parameter in LDA model [#2896](https://github.com/RaRe-Technologies/gensim/pull/2896), __[@xh2](https://github.com/xh2)__ @@ -43,6 +45,8 @@ This release contains a major refactoring. * Remove gensim.summarization subpackage, docs and test data (PR [#2958](https://github.com/RaRe-Technologies/gensim/pull/2958), __[@mpenkov](https://github.com/mpenkov)__) * Bump minimum Python version to 3.6 [#2947](https://github.com/RaRe-Technologies/gensim/pull/2947), __[@gojomo](https://github.com/gojomo)__ +* No more binary wheels for x32 platforms. + __[menshikh-iv](https://github.com/menshikh-iv)__, [#6](https://github.com/RaRe-Technologies/gensim-wheels/pull/6) ## :warning: 3.8.x will be the last gensim version to support Py2.7. Starting with 4.0.0, gensim will only support Py3.5 and above @@ -280,24 +284,24 @@ This is primarily a bugfix release to bring back Py2.7 compatibility to gensim 3 #### Out-of-vocab word handling To achieve consistency with the reference implementation from Facebook, -a `FastText` model will now always report any word, out-of-vocabulary or -not, as being in the model, and always return some vector for any word +a `FastText` model will now always report any word, out-of-vocabulary or +not, as being in the model, and always return some vector for any word looked-up. Specifically: -1. `'any_word' in ft_model` will always return `True`. Previously, it -returned `True` only if the full word was in the vocabulary. (To test if a -full word is in the known vocabulary, you can consult the `wv.vocab` -property: `'any_word' in ft_model.wv.vocab` will return `False` if the full +1. `'any_word' in ft_model` will always return `True`. Previously, it +returned `True` only if the full word was in the vocabulary. (To test if a +full word is in the known vocabulary, you can consult the `wv.vocab` +property: `'any_word' in ft_model.wv.vocab` will return `False` if the full word wasn't learned during model training.) -2. `ft_model['any_word']` will always return a vector. Previously, it -raised `KeyError` for OOV words when the model had no vectors +2. `ft_model['any_word']` will always return a vector. Previously, it +raised `KeyError` for OOV words when the model had no vectors for **any** ngrams of the word. 3. If no ngrams from the term are present in the model, or when no ngrams could be extracted from the term, a vector pointing to the origin will be returned. Previously, a vector of NaN (not a number) was returned as a consequence of a divide-by-zero problem. 4. Models may use more more memory, or take longer for word-vector -lookup, especially after training on smaller corpuses where the previous +lookup, especially after training on smaller corpuses where the previous non-compliant behavior discarded some ngrams from consideration. #### Loading models in Facebook .bin format @@ -310,7 +314,7 @@ Since this function is deprecated, consider using one of its alternatives (see b Furthermore, you must now pass the full path to the file to load, **including the file extension.** Previously, if you specified a model path that ends with anything other than .bin, the code automatically appended .bin to the path before loading the model. This behavior was [confusing](https://github.com/RaRe-Technologies/gensim/issues/2407), so we removed it. - + ### :warning: Deprecations (will be removed in the next major release) Remove: From 9e9c17517aff6aa4bcbd455c2740fed83cd86404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Mon, 19 Oct 2020 01:49:41 +0200 Subject: [PATCH 04/20] extend + clean up changelog --- CHANGELOG.md | 731 +++++++++++++++++----------------- release/generate_changelog.py | 2 +- 2 files changed, 372 insertions(+), 361 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57bc89d9d4..96b848265c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,52 +3,57 @@ Changes ## Unreleased - ### :+1: Improvements -* Use less RAM in LdaMulticore [#2300](https://github.com/RaRe-Technologies/gensim/pull/2300), __[@horpto](https://github.com/horpto)__ -* Streamline KeyedVectors & X2Vec API, consistency [#2698](https://github.com/RaRe-Technologies/gensim/pull/2698), __[@gojomo](https://github.com/gojomo)__ -* Fix for Python 3.9/3.10: remove xml.etree.cElementTree [#2846](https://github.com/RaRe-Technologies/gensim/pull/2846), __[@hugovk](https://github.com/hugovk)__ -* Speed up random number generation in word2vec [#2864](https://github.com/RaRe-Technologies/gensim/pull/2864), __[@zygm0nt](https://github.com/zygm0nt)__ -* Expose max_final_vocab parameter in fastText constructor [#2867](https://github.com/RaRe-Technologies/gensim/pull/2867), __[@mpenkov](https://github.com/mpenkov)__ -* Fix fastText word-vectors with ngrams off [#2891](https://github.com/RaRe-Technologies/gensim/pull/2891), __[@gojomo](https://github.com/gojomo)__ -* Fix similarity bug in NMSLIB indexer [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ -* Renamed overly broad `similarities.index` to the more appropriate `similarities.annoy` [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ -* Fixed deprecation warnings in Annoy integration. [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ -* Fix inheritance of WikiCorpus from TextCorpus [#2901](https://github.com/RaRe-Technologies/gensim/pull/2901), __[@jenishah](https://github.com/jenishah)__ -* Fix doc2vec crash for large sets of doc-vectors [#2907](https://github.com/RaRe-Technologies/gensim/pull/2907), __[@gojomo](https://github.com/gojomo)__ -* Change `num_words` to `topn` in dtm_coherence [#2926](https://github.com/RaRe-Technologies/gensim/pull/2926), __[@MeganStodel](https://github.com/MeganStodel)__ -* Clear up job queue parameters in word2vec [#2931](https://github.com/RaRe-Technologies/gensim/pull/2931), __[@lunastera](https://github.com/lunastera)__ -* Remove Keras dependency [#2937](https://github.com/RaRe-Technologies/gensim/pull/2937), __[@piskvorky](https://github.com/piskvorky)__ -* X2Vec SaveLoad improvements [#2939](https://github.com/RaRe-Technologies/gensim/pull/2939), __[@piskvorky](https://github.com/piskvorky)__ -* Code style & py3 migration clean up [#2939](https://github.com/RaRe-Technologies/gensim/pull/2939), __[@piskvorky](https://github.com/piskvorky)__ -* Fix deprecations in SoftCosineSimilarity [#2940](https://github.com/RaRe-Technologies/gensim/pull/2940), __[@Witiko](https://github.com/Witiko)__ -* Bump minimum Python version to 3.6 [#2947](https://github.com/RaRe-Technologies/gensim/pull/2947), __[@gojomo](https://github.com/gojomo)__ -* Fix save_facebook_model failure after update-vocab & other initialization streamlining [#2944](https://github.com/RaRe-Technologies/gensim/pull/2944), __[@gojomo](https://github.com/gojomo)__ -* Refactor phrases submodule [#2976](https://github.com/RaRe-Technologies/gensim/pull/2976), __[@piskvorky](https://github.com/piskvorky)__ -* Skip common English words during phrase construction [#2979](https://github.com/RaRe-Technologies/gensim/pull/2979), __[@piskvorky](https://github.com/piskvorky)__ +* [#2947](https://github.com/RaRe-Technologies/gensim/pull/2947): Bump minimum Python version to 3.6, by [@gojomo](https://github.com/gojomo) +* [#2939](https://github.com/RaRe-Technologies/gensim/pull/2939) + [#2984](https://github.com/RaRe-Technologies/gensim/pull/2984): Code style & py3 migration clean up, by [@piskvorky](https://github.com/piskvorky) +* [#2300](https://github.com/RaRe-Technologies/gensim/pull/2300): Use less RAM in LdaMulticore, by [@horpto](https://github.com/horpto) +* [#2698](https://github.com/RaRe-Technologies/gensim/pull/2698): Streamline KeyedVectors & X2Vec API, by [@gojomo](https://github.com/gojomo) +* [#2864](https://github.com/RaRe-Technologies/gensim/pull/2864): Speed up random number generation in word2vec, by [@zygm0nt](https://github.com/zygm0nt) +* [#2976](https://github.com/RaRe-Technologies/gensim/pull/2976): Speed up phrase (collocation) detection, by [@piskvorky](https://github.com/piskvorky) +* [#2979](https://github.com/RaRe-Technologies/gensim/pull/2979): Allow skipping common English words in multi-word phrases, by [@piskvorky](https://github.com/piskvorky) +* [#2867](https://github.com/RaRe-Technologies/gensim/pull/2867): Expose `max_final_vocab` parameter in fastText constructor, by [@mpenkov](https://github.com/mpenkov) +* [#2891](https://github.com/RaRe-Technologies/gensim/pull/2891): Fix fastText word-vectors with ngrams off, by [@gojomo](https://github.com/gojomo) +* [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Fix similarity bug in NMSLIB indexer, by [@piskvorky](https://github.com/piskvorky) +* [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Fixed deprecation warnings in Annoy integration, by [@piskvorky](https://github.com/piskvorky) +* [#2901](https://github.com/RaRe-Technologies/gensim/pull/2901): Fix inheritance of WikiCorpus from TextCorpus, by [@jenishah](https://github.com/jenishah) +* [#2907](https://github.com/RaRe-Technologies/gensim/pull/2907): Fix doc2vec crash for large sets of doc-vectors, by [@gojomo](https://github.com/gojomo) +* [#2931](https://github.com/RaRe-Technologies/gensim/pull/2931): Clear up job queue parameters in word2vec, by [@lunastera](https://github.com/lunastera) +* [#2939](https://github.com/RaRe-Technologies/gensim/pull/2939): X2Vec SaveLoad improvements, by [@piskvorky](https://github.com/piskvorky) +* [#2940](https://github.com/RaRe-Technologies/gensim/pull/2940); Fix deprecations in SoftCosineSimilarity, by [@Witiko](https://github.com/Witiko) +* [#2944](https://github.com/RaRe-Technologies/gensim/pull/2944): Fix `save_facebook_model` failure after update-vocab & other initialization streamlining, by [@gojomo](https://github.com/gojomo) +* [#2846](https://github.com/RaRe-Technologies/gensim/pull/2846): Fix for Python 3.9/3.10: remove xml.etree.cElementTree, by [@hugovk](https://github.com/hugovk) + ### :books: Tutorials and docs -* Clean up of API docs language and formatting [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ -* Added documentation for NMSLIB indexer [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899), __[@piskvorky](https://github.com/piskvorky)__ -* Clear up LdaModel documentation - remove claim that it accepts CSC matrix as input (PR [#2832](https://github.com/RaRe-Technologies/gensim/pull/2832), [@FyzHsn](https://github.com/FyzHsn)) -* Clarify that license is LGPL-2.1 [#2871](https://github.com/RaRe-Technologies/gensim/pull/2871), __[@pombredanne](https://github.com/pombredanne)__ -* Make docs clearer on `alpha` parameter in LDA model [#2896](https://github.com/RaRe-Technologies/gensim/pull/2896), __[@xh2](https://github.com/xh2)__ -* Update Hoffman paper link for Online LDA [#2897](https://github.com/RaRe-Technologies/gensim/pull/2897), __[@xh2](https://github.com/xh2)__ -* Refresh docs for run_annoy tutorial [#2910](https://github.com/RaRe-Technologies/gensim/pull/2910), __[@piskvorky](https://github.com/piskvorky)__ -* Fix "generator" language in word2vec docs (PR [#2935](https://github.com/RaRe-Technologies/gensim/pull/2935), __[@polm](https://github.com/polm)__) -* Migrate tutorials & how-tos to 4.0.0 [#2968](https://github.com/RaRe-Technologies/gensim/pull/2968), __[@piskvorky](https://github.com/piskvorky)__ -* New docs theme [#2954](https://github.com/RaRe-Technologies/gensim/pull/2954), __[@dvorakvaclav](https://github.com/dvorakvaclav)__ +* [#2954](https://github.com/RaRe-Technologies/gensim/pull/2954): New theme for the Gensin website, [@dvorakvaclav](https://github.com/dvorakvaclav) +* [#2960](https://github.com/RaRe-Technologies/gensim/issues/2960): Added [Gensim and Compatibility](https://github.com/RaRe-Technologies/gensim/wiki/Gensim-And-Compatibility) Wiki page, by [@piskvorky](https://github.com/piskvorky) +* [#2960](https://github.com/RaRe-Technologies/gensim/issues/2960): Reworked & simplified the [Developer Wiki page](https://github.com/RaRe-Technologies/gensim/wiki/Developer-page), by [@piskvorky](https://github.com/piskvorky) +* [#2968](https://github.com/RaRe-Technologies/gensim/pull/2968): Migrate tutorials & how-tos to 4.0.0, by [@piskvorky](https://github.com/piskvorky) +* [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Clean up of language and formatting of docstrings, by [@piskvorky](https://github.com/piskvorky) +* [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Added documentation for NMSLIB indexer, by [@piskvorky](https://github.com/piskvorky) +* [#2832](https://github.com/RaRe-Technologies/gensim/pull/2832): Clear up LdaModel documentation - remove claim that it accepts CSC matrix as input, by [@FyzHsn](https://github.com/FyzHsn) +* [#2871](https://github.com/RaRe-Technologies/gensim/pull/2871): Clarify that license is LGPL-2.1, by [@pombredanne](https://github.com/pombredanne) +* [#2896](https://github.com/RaRe-Technologies/gensim/pull/2896): Make docs clearer on `alpha` parameter in LDA model, by [@xh2](https://github.com/xh2) +* [#2897](https://github.com/RaRe-Technologies/gensim/pull/2897): Update Hoffman paper link for Online LDA, by [@xh2](https://github.com/xh2) +* [#2910](https://github.com/RaRe-Technologies/gensim/pull/2910): Refresh docs for run_annoy tutorial, by [@piskvorky](https://github.com/piskvorky) +* [#2935](https://github.com/RaRe-Technologies/gensim/pull/2935): Fix "generator" language in word2vec docs, by [@polm](https://github.com/polm)) ### :warning: Removed functionality -* Remove gensim.summarization subpackage, docs and test data (PR [#2958](https://github.com/RaRe-Technologies/gensim/pull/2958), __[@mpenkov](https://github.com/mpenkov)__) -* Bump minimum Python version to 3.6 [#2947](https://github.com/RaRe-Technologies/gensim/pull/2947), __[@gojomo](https://github.com/gojomo)__ -* No more binary wheels for x32 platforms. - __[menshikh-iv](https://github.com/menshikh-iv)__, [#6](https://github.com/RaRe-Technologies/gensim-wheels/pull/6) +* [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Renamed overly broad `similarities.index` to the more appropriate `similarities.annoy`, by [@piskvorky](https://github.com/piskvorky) +* [#2958](https://github.com/RaRe-Technologies/gensim/pull/2958): Remove gensim.summarization subpackage, docs and test data, by [@mpenkov](https://github.com/mpenkov) +* [#6](https://github.com/RaRe-Technologies/gensim-wheels/pull/6): No more binary wheels for x32 platforms, by [menshikh-iv](https://github.com/menshikh-iv) +* [#2926](https://github.com/RaRe-Technologies/gensim/pull/2926): Rename `num_words` to `topn` in dtm_coherence, by [@MeganStodel](https://github.com/MeganStodel) +* [#2937](https://github.com/RaRe-Technologies/gensim/pull/2937): Remove Keras dependency, by [@piskvorky](https://github.com/piskvorky) + + +--- + + +## :warning: 3.8.x will be the last Gensim version to support Py2.7. Starting with 4.0.0, Gensim will only support Py3.5 and above. -## :warning: 3.8.x will be the last gensim version to support Py2.7. Starting with 4.0.0, gensim will only support Py3.5 and above ## 3.8.3, 2020-05-03 @@ -56,18 +61,18 @@ This is primarily a bugfix release to bring back Py2.7 compatibility to gensim 3 ### :red_circle: Bug fixes -* Bring back Py27 support (PR [#2812](https://github.com/RaRe-Technologies/gensim/pull/2812), __[@mpenkov](https://github.com/mpenkov)__) +* Bring back Py27 support (PR [#2812](https://github.com/RaRe-Technologies/gensim/pull/2812), [@mpenkov](https://github.com/mpenkov)) * Fix wrong version reported by setup.py (Issue [#2796](https://github.com/RaRe-Technologies/gensim/issues/2796)) * Fix missing C extensions (Issues [#2794](https://github.com/RaRe-Technologies/gensim/issues/2794) and [#2802](https://github.com/RaRe-Technologies/gensim/issues/2802)) ### :+1: Improvements -* Wheels for Python 3.8 (__[@menshikh-iv](https://github.com/menshikh-iv)__) -* Prepare for removal of deprecated `lxml.etree.cElementTree` (PR [#2777](https://github.com/RaRe-Technologies/gensim/pull/2777), __[@tirkarthi](https://github.com/tirkarthi)__) +* Wheels for Python 3.8 ([@menshikh-iv](https://github.com/menshikh-iv)) +* Prepare for removal of deprecated `lxml.etree.cElementTree` (PR [#2777](https://github.com/RaRe-Technologies/gensim/pull/2777), [@tirkarthi](https://github.com/tirkarthi)) ### :books: Tutorial and doc improvements -* Update test instructions in README (PR [#2814](https://github.com/RaRe-Technologies/gensim/pull/2814), __[@piskvorky](https://github.com/piskvorky)__) +* Update test instructions in README (PR [#2814](https://github.com/RaRe-Technologies/gensim/pull/2814), [@piskvorky](https://github.com/piskvorky)) ### :warning: Deprecations (will be removed in the next major release) @@ -91,6 +96,8 @@ This is primarily a bugfix release to bring back Py2.7 compatibility to gensim 3 - `gensim.utils` ➡ `gensim.utils.utils` (old imports will continue to work) - `gensim.parsing.*` ➡ `gensim.utils.text_utils` +--- + ## 3.8.2, 2020-04-10 ### :red_circle: Bug fixes @@ -119,23 +126,25 @@ This is primarily a bugfix release to bring back Py2.7 compatibility to gensim 3 - `gensim.utils` ➡ `gensim.utils.utils` (old imports will continue to work) - `gensim.parsing.*` ➡ `gensim.utils.text_utils` +--- + ## 3.8.1, 2019-09-23 ### :red_circle: Bug fixes -* Fix usage of base_dir instead of BASE_DIR in _load_info in downloader. (__[movb](https://github.com/movb)__, [#2605](https://github.com/RaRe-Technologies/gensim/pull/2605)) -* Update the version of smart_open in the setup.py file (__[AMR-KELEG](https://github.com/AMR-KELEG)__, [#2582](https://github.com/RaRe-Technologies/gensim/pull/2582)) -* Properly handle unicode_errors arg parameter when loading a vocab file (__[wmtzk](https://github.com/wmtzk)__, [#2570](https://github.com/RaRe-Technologies/gensim/pull/2570)) -* Catch loading older TfidfModels without smartirs (__[bnomis](https://github.com/bnomis)__, [#2559](https://github.com/RaRe-Technologies/gensim/pull/2559)) -* Fix bug where a module import set up logging, pin doctools for Py2 (__[piskvorky](https://github.com/piskvorky)__, [#2552](https://github.com/RaRe-Technologies/gensim/pull/2552)) +* Fix usage of base_dir instead of BASE_DIR in _load_info in downloader. ([movb](https://github.com/movb), [#2605](https://github.com/RaRe-Technologies/gensim/pull/2605)) +* Update the version of smart_open in the setup.py file ([AMR-KELEG](https://github.com/AMR-KELEG), [#2582](https://github.com/RaRe-Technologies/gensim/pull/2582)) +* Properly handle unicode_errors arg parameter when loading a vocab file ([wmtzk](https://github.com/wmtzk), [#2570](https://github.com/RaRe-Technologies/gensim/pull/2570)) +* Catch loading older TfidfModels without smartirs ([bnomis](https://github.com/bnomis), [#2559](https://github.com/RaRe-Technologies/gensim/pull/2559)) +* Fix bug where a module import set up logging, pin doctools for Py2 ([piskvorky](https://github.com/piskvorky), [#2552](https://github.com/RaRe-Technologies/gensim/pull/2552)) ### :books: Tutorial and doc improvements -* Fix usage example in phrases.py (__[piskvorky](https://github.com/piskvorky)__, [#2575](https://github.com/RaRe-Technologies/gensim/pull/2575)) +* Fix usage example in phrases.py ([piskvorky](https://github.com/piskvorky), [#2575](https://github.com/RaRe-Technologies/gensim/pull/2575)) ### :+1: Improvements -* Optimize Poincare model training (__[koiizukag](https://github.com/koiizukag)__, [#2589](https://github.com/RaRe-Technologies/gensim/pull/2589)) +* Optimize Poincare model training ([koiizukag](https://github.com/koiizukag), [#2589](https://github.com/RaRe-Technologies/gensim/pull/2589)) ### :warning: Deprecations (will be removed in the next major release) @@ -159,34 +168,36 @@ This is primarily a bugfix release to bring back Py2.7 compatibility to gensim 3 - `gensim.utils` ➡ `gensim.utils.utils` (old imports will continue to work) - `gensim.parsing.*` ➡ `gensim.utils.text_utils` +--- + ## 3.8.0, 2019-07-08 ### :star2: New Features -* Enable online training of Poincare models (__[koiizukag](https://github.com/koiizukag)__, [#2505](https://github.com/RaRe-Technologies/gensim/pull/2505)) -* Make BM25 more scalable by adding support for generator inputs (__[saraswatmks](https://github.com/saraswatmks)__, [#2479](https://github.com/RaRe-Technologies/gensim/pull/2479)) -* Allow the Gensim dataset / pre-trained model downloader `gensim.downloader` to run offline, by introducing a local file cache (__[mpenkov](https://github.com/mpenkov)__, [#2545](https://github.com/RaRe-Technologies/gensim/pull/2545)) -* Make the `gensim.downloader` target directory configurable (__[mpenkov](https://github.com/mpenkov)__, [#2456](https://github.com/RaRe-Technologies/gensim/pull/2456)) -* Add `nmslib` indexer (__[masa3141](https://github.com/masa3141)__, [#2417](https://github.com/RaRe-Technologies/gensim/pull/2417)) +* Enable online training of Poincare models ([koiizukag](https://github.com/koiizukag), [#2505](https://github.com/RaRe-Technologies/gensim/pull/2505)) +* Make BM25 more scalable by adding support for generator inputs ([saraswatmks](https://github.com/saraswatmks), [#2479](https://github.com/RaRe-Technologies/gensim/pull/2479)) +* Allow the Gensim dataset / pre-trained model downloader `gensim.downloader` to run offline, by introducing a local file cache ([mpenkov](https://github.com/mpenkov), [#2545](https://github.com/RaRe-Technologies/gensim/pull/2545)) +* Make the `gensim.downloader` target directory configurable ([mpenkov](https://github.com/mpenkov), [#2456](https://github.com/RaRe-Technologies/gensim/pull/2456)) +* Add `nmslib` indexer ([masa3141](https://github.com/masa3141), [#2417](https://github.com/RaRe-Technologies/gensim/pull/2417)) ### :red_circle: Bug fixes -* Fix `smart_open` deprecation warning globally (__[itayB](https://github.com/itayB)__, [#2530](https://github.com/RaRe-Technologies/gensim/pull/2530)) -* Fix AppVeyor issues with Windows and Py2 (__[mpenkov](https://github.com/mpenkov)__, [#2546](https://github.com/RaRe-Technologies/gensim/pull/2546)) -* Fix `topn=0` versus `topn=None` bug in `most_similar`, accept `topn` of any integer type (__[Witiko](https://github.com/Witiko)__, [#2497](https://github.com/RaRe-Technologies/gensim/pull/2497)) -* Fix Python version check (__[charsyam](https://github.com/charsyam)__, [#2547](https://github.com/RaRe-Technologies/gensim/pull/2547)) -* Fix typo in FastText documentation (__[Guitaricet](https://github.com/Guitaricet)__, [#2518](https://github.com/RaRe-Technologies/gensim/pull/2518)) -* Fix "Market Matrix" to "Matrix Market" typo. (__[Shooter23](https://github.com/Shooter23)__, [#2513](https://github.com/RaRe-Technologies/gensim/pull/2513)) -* Fix auto-generated hyperlinks in `CHANGELOG.md` (__[mpenkov](https://github.com/mpenkov)__, [#2482](https://github.com/RaRe-Technologies/gensim/pull/2482)) +* Fix `smart_open` deprecation warning globally ([itayB](https://github.com/itayB), [#2530](https://github.com/RaRe-Technologies/gensim/pull/2530)) +* Fix AppVeyor issues with Windows and Py2 ([mpenkov](https://github.com/mpenkov), [#2546](https://github.com/RaRe-Technologies/gensim/pull/2546)) +* Fix `topn=0` versus `topn=None` bug in `most_similar`, accept `topn` of any integer type ([Witiko](https://github.com/Witiko), [#2497](https://github.com/RaRe-Technologies/gensim/pull/2497)) +* Fix Python version check ([charsyam](https://github.com/charsyam), [#2547](https://github.com/RaRe-Technologies/gensim/pull/2547)) +* Fix typo in FastText documentation ([Guitaricet](https://github.com/Guitaricet), [#2518](https://github.com/RaRe-Technologies/gensim/pull/2518)) +* Fix "Market Matrix" to "Matrix Market" typo. ([Shooter23](https://github.com/Shooter23), [#2513](https://github.com/RaRe-Technologies/gensim/pull/2513)) +* Fix auto-generated hyperlinks in `CHANGELOG.md` ([mpenkov](https://github.com/mpenkov), [#2482](https://github.com/RaRe-Technologies/gensim/pull/2482)) ### :books: Tutorial and doc improvements -* Generate documentation for the `gensim.similarities.termsim` module (__[Witiko](https://github.com/Witiko)__, [#2485](https://github.com/RaRe-Technologies/gensim/pull/2485)) -* Simplify the `Support` section in README (__[piskvorky](https://github.com/piskvorky)__, [#2542](https://github.com/RaRe-Technologies/gensim/pull/2542)) +* Generate documentation for the `gensim.similarities.termsim` module ([Witiko](https://github.com/Witiko), [#2485](https://github.com/RaRe-Technologies/gensim/pull/2485)) +* Simplify the `Support` section in README ([piskvorky](https://github.com/piskvorky), [#2542](https://github.com/RaRe-Technologies/gensim/pull/2542)) ### :+1: Improvements -* Pin sklearn version for Py2, because sklearn dropped py2 support (__[mpenkov](https://github.com/mpenkov)__, [#2510](https://github.com/RaRe-Technologies/gensim/pull/2510)) +* Pin sklearn version for Py2, because sklearn dropped py2 support ([mpenkov](https://github.com/mpenkov), [#2510](https://github.com/RaRe-Technologies/gensim/pull/2510)) ### :warning: Deprecations (will be removed in the next major release) @@ -215,24 +226,24 @@ This is primarily a bugfix release to bring back Py2.7 compatibility to gensim 3 ### :red_circle: Bug fixes -* Fix fasttext model loading from gzip files (__[mpenkov](https://github.com/mpenkov)__, [#2476](https://github.com/RaRe-Technologies/gensim/pull/2476)) -* Fix misleading `Doc2Vec.docvecs` comment (__[gojomo](https://github.com/gojomo)__, [#2472](https://github.com/RaRe-Technologies/gensim/pull/2472)) -* NMF bugfix (__[mpenkov](https://github.com/mpenkov)__, [#2466](https://github.com/RaRe-Technologies/gensim/pull/2466)) -* Fix `WordEmbeddingsKeyedVectors.most_similar` (__[Witiko](https://github.com/Witiko)__, [#2461](https://github.com/RaRe-Technologies/gensim/pull/2461)) -* Fix LdaSequence model by updating to num_documents (__[Bharat123rox](https://github.com/Bharat123rox)__, [#2410](https://github.com/RaRe-Technologies/gensim/pull/2410)) -* Make termsim matrix positive definite even with negative similarities (__[Witiko](https://github.com/Witiko)__, [#2397](https://github.com/RaRe-Technologies/gensim/pull/2397)) -* Fix the off-by-one bug in the TFIDF model. (__[AMR-KELEG](https://github.com/AMR-KELEG)__, [#2392](https://github.com/RaRe-Technologies/gensim/pull/2392)) -* Update legacy model loading (__[mpenkov](https://github.com/mpenkov)__, [#2454](https://github.com/RaRe-Technologies/gensim/pull/2454), [#2457](https://github.com/RaRe-Technologies/gensim/pull/2457)) -* Make `matutils.unitvec` always return float norm when requested (__[Witiko](https://github.com/Witiko)__, [#2419](https://github.com/RaRe-Technologies/gensim/pull/2419)) +* Fix fasttext model loading from gzip files ([mpenkov](https://github.com/mpenkov), [#2476](https://github.com/RaRe-Technologies/gensim/pull/2476)) +* Fix misleading `Doc2Vec.docvecs` comment ([gojomo](https://github.com/gojomo), [#2472](https://github.com/RaRe-Technologies/gensim/pull/2472)) +* NMF bugfix ([mpenkov](https://github.com/mpenkov), [#2466](https://github.com/RaRe-Technologies/gensim/pull/2466)) +* Fix `WordEmbeddingsKeyedVectors.most_similar` ([Witiko](https://github.com/Witiko), [#2461](https://github.com/RaRe-Technologies/gensim/pull/2461)) +* Fix LdaSequence model by updating to num_documents ([Bharat123rox](https://github.com/Bharat123rox), [#2410](https://github.com/RaRe-Technologies/gensim/pull/2410)) +* Make termsim matrix positive definite even with negative similarities ([Witiko](https://github.com/Witiko), [#2397](https://github.com/RaRe-Technologies/gensim/pull/2397)) +* Fix the off-by-one bug in the TFIDF model. ([AMR-KELEG](https://github.com/AMR-KELEG), [#2392](https://github.com/RaRe-Technologies/gensim/pull/2392)) +* Update legacy model loading ([mpenkov](https://github.com/mpenkov), [#2454](https://github.com/RaRe-Technologies/gensim/pull/2454), [#2457](https://github.com/RaRe-Technologies/gensim/pull/2457)) +* Make `matutils.unitvec` always return float norm when requested ([Witiko](https://github.com/Witiko), [#2419](https://github.com/RaRe-Technologies/gensim/pull/2419)) ### :books: Tutorial and doc improvements -* Update word2vec.ipynb (__[asyabo](https://github.com/asyabo)__, [#2423](https://github.com/RaRe-Technologies/gensim/pull/2423)) +* Update word2vec.ipynb ([asyabo](https://github.com/asyabo), [#2423](https://github.com/RaRe-Technologies/gensim/pull/2423)) ### :+1: Improvements -* Adding type check for corpus_file argument (__[saraswatmks](https://github.com/saraswatmks)__, [#2469](https://github.com/RaRe-Technologies/gensim/pull/2469)) -* Clean up FastText Cython code, fix division by zero (__[mpenkov](https://github.com/mpenkov)__, [#2382](https://github.com/RaRe-Technologies/gensim/pull/2382)) +* Adding type check for corpus_file argument ([saraswatmks](https://github.com/saraswatmks), [#2469](https://github.com/RaRe-Technologies/gensim/pull/2469)) +* Clean up FastText Cython code, fix division by zero ([mpenkov](https://github.com/mpenkov), [#2382](https://github.com/RaRe-Technologies/gensim/pull/2382)) ### :warning: Deprecations (will be removed in the next major release) @@ -265,19 +276,19 @@ This is primarily a bugfix release to bring back Py2.7 compatibility to gensim 3 ### :red_circle: Bug fixes -* Fix unicode error when loading FastText vocabulary (__[@mpenkov](https://github.com/mpenkov)__, [#2390](https://github.com/RaRe-Technologies/gensim/pull/2390)) -* Avoid division by zero in fasttext_inner.pyx (__[@mpenkov](https://github.com/mpenkov)__, [#2404](https://github.com/RaRe-Technologies/gensim/pull/2404)) -* Avoid incorrect filename inference when loading model (__[@mpenkov](https://github.com/mpenkov)__, [#2408](https://github.com/RaRe-Technologies/gensim/pull/2408)) -* Handle invalid unicode when loading native FastText models (__[@mpenkov](https://github.com/mpenkov)__, [#2411](https://github.com/RaRe-Technologies/gensim/pull/2411)) -* Avoid divide by zero when calculating vectors for terms with no ngrams (__[@mpenkov](https://github.com/mpenkov)__, [#2411](https://github.com/RaRe-Technologies/gensim/pull/2411)) +* Fix unicode error when loading FastText vocabulary ([@mpenkov](https://github.com/mpenkov), [#2390](https://github.com/RaRe-Technologies/gensim/pull/2390)) +* Avoid division by zero in fasttext_inner.pyx ([@mpenkov](https://github.com/mpenkov), [#2404](https://github.com/RaRe-Technologies/gensim/pull/2404)) +* Avoid incorrect filename inference when loading model ([@mpenkov](https://github.com/mpenkov), [#2408](https://github.com/RaRe-Technologies/gensim/pull/2408)) +* Handle invalid unicode when loading native FastText models ([@mpenkov](https://github.com/mpenkov), [#2411](https://github.com/RaRe-Technologies/gensim/pull/2411)) +* Avoid divide by zero when calculating vectors for terms with no ngrams ([@mpenkov](https://github.com/mpenkov), [#2411](https://github.com/RaRe-Technologies/gensim/pull/2411)) ### :books: Tutorial and doc improvements -* Add link to bindr (__[rogueleaderr](https://github.com/rogueleaderr)__, [#2387](https://github.com/RaRe-Technologies/gensim/pull/2387)) +* Add link to bindr ([rogueleaderr](https://github.com/rogueleaderr), [#2387](https://github.com/RaRe-Technologies/gensim/pull/2387)) ### :+1: Improvements -* Undo the hash2index optimization (__[mpenkov](https://github.com/mpenkov)__, [#2370](https://github.com/RaRe-Technologies/gensim/pull/2370)) +* Undo the hash2index optimization ([mpenkov](https://github.com/mpenkov), [#2370](https://github.com/RaRe-Technologies/gensim/pull/2370)) ### :warning: Changes in FastText behavior @@ -325,28 +336,28 @@ Remove: ### :+1: Improvements -* NMF optimization & documentation (__[@anotherbugmaster](https://github.com/anotherbugmaster)__, [#2361](https://github.com/RaRe-Technologies/gensim/pull/2361)) -* Optimize `FastText.load_fasttext_model` (__[@mpenkov](https://github.com/mpenkov)__, [#2340](https://github.com/RaRe-Technologies/gensim/pull/2340)) -* Add warning when string is used as argument to `Doc2Vec.infer_vector` (__[@tobycheese](https://github.com/tobycheese)__, [#2347](https://github.com/RaRe-Technologies/gensim/pull/2347)) -* Fix light linting issues in `LdaSeqModel` (__[@horpto](https://github.com/horpto)__, [#2360](https://github.com/RaRe-Technologies/gensim/pull/2360)) -* Move out `process_result_queue` from cycle in `LdaMulticore` (__[@horpto](https://github.com/horpto)__, [#2358](https://github.com/RaRe-Technologies/gensim/pull/2358)) +* NMF optimization & documentation ([@anotherbugmaster](https://github.com/anotherbugmaster), [#2361](https://github.com/RaRe-Technologies/gensim/pull/2361)) +* Optimize `FastText.load_fasttext_model` ([@mpenkov](https://github.com/mpenkov), [#2340](https://github.com/RaRe-Technologies/gensim/pull/2340)) +* Add warning when string is used as argument to `Doc2Vec.infer_vector` ([@tobycheese](https://github.com/tobycheese), [#2347](https://github.com/RaRe-Technologies/gensim/pull/2347)) +* Fix light linting issues in `LdaSeqModel` ([@horpto](https://github.com/horpto), [#2360](https://github.com/RaRe-Technologies/gensim/pull/2360)) +* Move out `process_result_queue` from cycle in `LdaMulticore` ([@horpto](https://github.com/horpto), [#2358](https://github.com/RaRe-Technologies/gensim/pull/2358)) ### :red_circle: Bug fixes -* Fix infinite diff in `LdaModel.do_mstep` (__[@horpto](https://github.com/horpto)__, [#2344](https://github.com/RaRe-Technologies/gensim/pull/2344)) -* Fix backward compatibility issue: loading `FastTextKeyedVectors` using `KeyedVectors` (missing attribute `compatible_hash`) (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#2349](https://github.com/RaRe-Technologies/gensim/pull/2349)) -* Fix logging issue (conda-forge related) (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#2339](https://github.com/RaRe-Technologies/gensim/pull/2339)) -* Fix `WordEmbeddingsKeyedVectors.most_similar` (__[@Witiko](https://github.com/Witiko)__, [#2356](https://github.com/RaRe-Technologies/gensim/pull/2356)) -* Fix issues of `flake8==3.7.1` (__[@horpto](https://github.com/horpto)__, [#2365](https://github.com/RaRe-Technologies/gensim/pull/2365)) +* Fix infinite diff in `LdaModel.do_mstep` ([@horpto](https://github.com/horpto), [#2344](https://github.com/RaRe-Technologies/gensim/pull/2344)) +* Fix backward compatibility issue: loading `FastTextKeyedVectors` using `KeyedVectors` (missing attribute `compatible_hash`) ([@menshikh-iv](https://github.com/menshikh-iv), [#2349](https://github.com/RaRe-Technologies/gensim/pull/2349)) +* Fix logging issue (conda-forge related) ([@menshikh-iv](https://github.com/menshikh-iv), [#2339](https://github.com/RaRe-Technologies/gensim/pull/2339)) +* Fix `WordEmbeddingsKeyedVectors.most_similar` ([@Witiko](https://github.com/Witiko), [#2356](https://github.com/RaRe-Technologies/gensim/pull/2356)) +* Fix issues of `flake8==3.7.1` ([@horpto](https://github.com/horpto), [#2365](https://github.com/RaRe-Technologies/gensim/pull/2365)) ### :books: Tutorial and doc improvements -* Improve `FastText` documentation (__[@mpenkov](https://github.com/mpenkov)__, [#2353](https://github.com/RaRe-Technologies/gensim/pull/2353)) -* Minor corrections and improvements in `Any*Vec` docstrings (__[@tobycheese](https://github.com/tobycheese)__, [#2345](https://github.com/RaRe-Technologies/gensim/pull/2345)) -* Fix the example code for SparseTermSimilarityMatrix (__[@Witiko](https://github.com/Witiko)__, [#2359](https://github.com/RaRe-Technologies/gensim/pull/2359)) -* Update `poincare` documentation to indicate the relation format (__[@AMR-KELEG](https://github.com/AMR-KELEG)__, [#2357](https://github.com/RaRe-Technologies/gensim/pull/2357)) +* Improve `FastText` documentation ([@mpenkov](https://github.com/mpenkov), [#2353](https://github.com/RaRe-Technologies/gensim/pull/2353)) +* Minor corrections and improvements in `Any*Vec` docstrings ([@tobycheese](https://github.com/tobycheese), [#2345](https://github.com/RaRe-Technologies/gensim/pull/2345)) +* Fix the example code for SparseTermSimilarityMatrix ([@Witiko](https://github.com/Witiko), [#2359](https://github.com/RaRe-Technologies/gensim/pull/2359)) +* Update `poincare` documentation to indicate the relation format ([@AMR-KELEG](https://github.com/AMR-KELEG), [#2357](https://github.com/RaRe-Technologies/gensim/pull/2357)) ### :warning: Deprecations (will be removed in the next major release) @@ -375,7 +386,7 @@ Remove: ### :star2: New features -* Fast Online NMF (__[@anotherbugmaster](https://github.com/anotherbugmaster)__, [#2007](https://github.com/RaRe-Technologies/gensim/pull/2007)) +* Fast Online NMF ([@anotherbugmaster](https://github.com/anotherbugmaster), [#2007](https://github.com/RaRe-Technologies/gensim/pull/2007)) - Benchmark `wiki-english-20171001` | Model | Perplexity | Coherence | L2 norm | Train time (minutes) | @@ -421,7 +432,7 @@ Remove: - [NMF tutorial](https://github.com/RaRe-Technologies/gensim/blob/develop/docs/notebooks/nmf_tutorial.ipynb) - [Full NMF Benchmark](https://github.com/RaRe-Technologies/gensim/blob/develop/docs/notebooks/nmf_wikipedia.ipynb) -* Massive improvement`FastText` compatibilities (__[@mpenkov](https://github.com/mpenkov)__, [#2313](https://github.com/RaRe-Technologies/gensim/pull/2313)) +* Massive improvement`FastText` compatibilities ([@mpenkov](https://github.com/mpenkov), [#2313](https://github.com/RaRe-Technologies/gensim/pull/2313)) ```python from gensim.models import FastText @@ -467,7 +478,7 @@ Remove: model.train(corpus, total_examples=len(corpus), epochs=5) ``` -* Similarity search improvements (__[@Witiko](https://github.com/Witiko)__, [#2016](https://github.com/RaRe-Technologies/gensim/pull/2016)) +* Similarity search improvements ([@Witiko](https://github.com/Witiko), [#2016](https://github.com/RaRe-Technologies/gensim/pull/2016)) - Add similarity search using the Levenshtein distance in `gensim.similarities.LevenshteinSimilarityIndex` - Performance optimizations to `gensim.similarities.SoftCosineSimilarity` ([full benchmark](https://github.com/RaRe-Technologies/gensim/blob/develop/docs/notebooks/soft_cosine_benchmark.ipynb)) @@ -482,83 +493,83 @@ Remove: - See [updated soft-cosine tutorial](https://github.com/RaRe-Technologies/gensim/blob/develop/docs/notebooks/soft_cosine_tutorial.ipynb) for more information and usage examples -* Add `python3.7` support (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#2211](https://github.com/RaRe-Technologies/gensim/pull/2211)) - - Wheels for Window, OSX and Linux platforms (__[@menshikh-iv](https://github.com/menshikh-iv)__, [MacPython/gensim-wheels/#12](https://github.com/MacPython/gensim-wheels/pull/12)) +* Add `python3.7` support ([@menshikh-iv](https://github.com/menshikh-iv), [#2211](https://github.com/RaRe-Technologies/gensim/pull/2211)) + - Wheels for Window, OSX and Linux platforms ([@menshikh-iv](https://github.com/menshikh-iv), [MacPython/gensim-wheels/#12](https://github.com/MacPython/gensim-wheels/pull/12)) - Faster installation ### :+1: Improvements ##### Optimizations -* Reduce `Phraser` memory usage (drop frequencies) (__[@jenishah](https://github.com/jenishah)__, [#2208](https://github.com/RaRe-Technologies/gensim/pull/2208)) -* Reduce memory consumption of summarizer (__[@horpto](https://github.com/horpto)__, [#2298](https://github.com/RaRe-Technologies/gensim/pull/2298)) -* Replace inline slow equivalent of mean_absolute_difference with fast (__[@horpto](https://github.com/horpto)__, [#2284](https://github.com/RaRe-Technologies/gensim/pull/2284)) -* Reuse precalculated updated prior in `ldamodel.update_dir_prior` (__[@horpto](https://github.com/horpto)__, [#2274](https://github.com/RaRe-Technologies/gensim/pull/2274)) -* Improve `KeyedVector.wmdistance` (__[@horpto](https://github.com/horpto)__, [#2326](https://github.com/RaRe-Technologies/gensim/pull/2326)) -* Optimize `remove_unreachable_nodes` in `gensim.summarization` (__[@horpto](https://github.com/horpto)__, [#2263](https://github.com/RaRe-Technologies/gensim/pull/2263)) -* Optimize `mz_entropy` from `gensim.summarization` (__[@horpto](https://github.com/horpto)__, [#2267](https://github.com/RaRe-Technologies/gensim/pull/2267)) -* Improve `filter_extremes` methods in `Dictionary` and `HashDictionary` (__[@horpto](https://github.com/horpto)__, [#2303](https://github.com/RaRe-Technologies/gensim/pull/2303)) +* Reduce `Phraser` memory usage (drop frequencies) ([@jenishah](https://github.com/jenishah), [#2208](https://github.com/RaRe-Technologies/gensim/pull/2208)) +* Reduce memory consumption of summarizer ([@horpto](https://github.com/horpto), [#2298](https://github.com/RaRe-Technologies/gensim/pull/2298)) +* Replace inline slow equivalent of mean_absolute_difference with fast ([@horpto](https://github.com/horpto), [#2284](https://github.com/RaRe-Technologies/gensim/pull/2284)) +* Reuse precalculated updated prior in `ldamodel.update_dir_prior` ([@horpto](https://github.com/horpto), [#2274](https://github.com/RaRe-Technologies/gensim/pull/2274)) +* Improve `KeyedVector.wmdistance` ([@horpto](https://github.com/horpto), [#2326](https://github.com/RaRe-Technologies/gensim/pull/2326)) +* Optimize `remove_unreachable_nodes` in `gensim.summarization` ([@horpto](https://github.com/horpto), [#2263](https://github.com/RaRe-Technologies/gensim/pull/2263)) +* Optimize `mz_entropy` from `gensim.summarization` ([@horpto](https://github.com/horpto), [#2267](https://github.com/RaRe-Technologies/gensim/pull/2267)) +* Improve `filter_extremes` methods in `Dictionary` and `HashDictionary` ([@horpto](https://github.com/horpto), [#2303](https://github.com/RaRe-Technologies/gensim/pull/2303)) ##### Additions -* Add `KeyedVectors.relative_cosine_similarity` (__[@rsdel2007](https://github.com/rsdel2007)__, [#2307](https://github.com/RaRe-Technologies/gensim/pull/2307)) -* Add `random_seed` to `LdaMallet` (__[@Zohaggie](https://github.com/Zohaggie)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#2153](https://github.com/RaRe-Technologies/gensim/pull/2153)) -* Add `common_terms` parameter to `sklearn_api.PhrasesTransformer` (__[@pmlk](https://github.com/pmlk)__, [#2074](https://github.com/RaRe-Technologies/gensim/pull/2074)) -* Add method for patch `corpora.Dictionary` based on special tokens (__[@Froskekongen](https://github.com/Froskekongen)__, [#2200](https://github.com/RaRe-Technologies/gensim/pull/2200)) +* Add `KeyedVectors.relative_cosine_similarity` ([@rsdel2007](https://github.com/rsdel2007), [#2307](https://github.com/RaRe-Technologies/gensim/pull/2307)) +* Add `random_seed` to `LdaMallet` ([@Zohaggie](https://github.com/Zohaggie) & [@menshikh-iv](https://github.com/menshikh-iv), [#2153](https://github.com/RaRe-Technologies/gensim/pull/2153)) +* Add `common_terms` parameter to `sklearn_api.PhrasesTransformer` ([@pmlk](https://github.com/pmlk), [#2074](https://github.com/RaRe-Technologies/gensim/pull/2074)) +* Add method for patch `corpora.Dictionary` based on special tokens ([@Froskekongen](https://github.com/Froskekongen), [#2200](https://github.com/RaRe-Technologies/gensim/pull/2200)) ##### Cleanup -* Improve `six` usage (`xrange`, `map`, `zip`) (__[@horpto](https://github.com/horpto)__, [#2264](https://github.com/RaRe-Technologies/gensim/pull/2264)) -* Refactor `line2doc` methods of `LowCorpus` and `MalletCorpus` (__[@horpto](https://github.com/horpto)__, [#2269](https://github.com/RaRe-Technologies/gensim/pull/2269)) -* Get rid most of warnings in testing (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#2191](https://github.com/RaRe-Technologies/gensim/pull/2191)) -* Fix non-deterministic test failures (pin `PYTHONHASHSEED`) (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#2196](https://github.com/RaRe-Technologies/gensim/pull/2196)) -* Fix "aliasing chunkize to chunkize_serial" warning on Windows (__[@aquatiko](https://github.com/aquatiko)__, [#2202](https://github.com/RaRe-Technologies/gensim/pull/2202)) -* Remove `__getitem__` code duplication in `gensim.models.phrases` (__[@jenishah](https://github.com/jenishah)__, [#2206](https://github.com/RaRe-Technologies/gensim/pull/2206)) -* Add `flake8-rst` for docstring code examples (__[@kataev](https://github.com/kataev)__, [#2192](https://github.com/RaRe-Technologies/gensim/pull/2192)) -* Get rid `py26` stuff (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#2214](https://github.com/RaRe-Technologies/gensim/pull/2214)) -* Use `itertools.chain` instead of `sum` to concatenate lists (__[@Stigjb](https://github.com/Stigjb)__, [#2212](https://github.com/RaRe-Technologies/gensim/pull/2212)) -* Fix flake8 warnings W605, W504 (__[@horpto](https://github.com/horpto)__, [#2256](https://github.com/RaRe-Technologies/gensim/pull/2256)) -* Remove unnecessary creations of lists at all (__[@horpto](https://github.com/horpto)__, [#2261](https://github.com/RaRe-Technologies/gensim/pull/2261)) -* Fix extra list creation in `utils.get_max_id` (__[@horpto](https://github.com/horpto)__, [#2254](https://github.com/RaRe-Technologies/gensim/pull/2254)) -* Fix deprecation warning `np.sum(generator)` (__[@rsdel2007](https://github.com/rsdel2007)__, [#2296](https://github.com/RaRe-Technologies/gensim/pull/2296)) -* Refactor `BM25` (__[@horpto](https://github.com/horpto)__, [#2275](https://github.com/RaRe-Technologies/gensim/pull/2275)) -* Fix pyemd import (__[@ramprakash-94](https://github.com/ramprakash-94)__, [#2240](https://github.com/RaRe-Technologies/gensim/pull/2240)) -* Set `metadata=True` for `make_wikicorpus` script by default (__[@Xinyi2016](https://github.com/Xinyi2016)__, [#2245](https://github.com/RaRe-Technologies/gensim/pull/2245)) -* Remove unimportant warning from `Phrases` (__[@rsdel2007](https://github.com/rsdel2007)__, [#2331](https://github.com/RaRe-Technologies/gensim/pull/2331)) -* Replace `open()` by `smart_open()` in `gensim.models.fasttext._load_fasttext_format` (__[@rsdel2007](https://github.com/rsdel2007)__, [#2335](https://github.com/RaRe-Technologies/gensim/pull/2335)) +* Improve `six` usage (`xrange`, `map`, `zip`) ([@horpto](https://github.com/horpto), [#2264](https://github.com/RaRe-Technologies/gensim/pull/2264)) +* Refactor `line2doc` methods of `LowCorpus` and `MalletCorpus` ([@horpto](https://github.com/horpto), [#2269](https://github.com/RaRe-Technologies/gensim/pull/2269)) +* Get rid most of warnings in testing ([@menshikh-iv](https://github.com/menshikh-iv), [#2191](https://github.com/RaRe-Technologies/gensim/pull/2191)) +* Fix non-deterministic test failures (pin `PYTHONHASHSEED`) ([@menshikh-iv](https://github.com/menshikh-iv), [#2196](https://github.com/RaRe-Technologies/gensim/pull/2196)) +* Fix "aliasing chunkize to chunkize_serial" warning on Windows ([@aquatiko](https://github.com/aquatiko), [#2202](https://github.com/RaRe-Technologies/gensim/pull/2202)) +* Remove `getitem` code duplication in `gensim.models.phrases` ([@jenishah](https://github.com/jenishah), [#2206](https://github.com/RaRe-Technologies/gensim/pull/2206)) +* Add `flake8-rst` for docstring code examples ([@kataev](https://github.com/kataev), [#2192](https://github.com/RaRe-Technologies/gensim/pull/2192)) +* Get rid `py26` stuff ([@menshikh-iv](https://github.com/menshikh-iv), [#2214](https://github.com/RaRe-Technologies/gensim/pull/2214)) +* Use `itertools.chain` instead of `sum` to concatenate lists ([@Stigjb](https://github.com/Stigjb), [#2212](https://github.com/RaRe-Technologies/gensim/pull/2212)) +* Fix flake8 warnings W605, W504 ([@horpto](https://github.com/horpto), [#2256](https://github.com/RaRe-Technologies/gensim/pull/2256)) +* Remove unnecessary creations of lists at all ([@horpto](https://github.com/horpto), [#2261](https://github.com/RaRe-Technologies/gensim/pull/2261)) +* Fix extra list creation in `utils.get_max_id` ([@horpto](https://github.com/horpto), [#2254](https://github.com/RaRe-Technologies/gensim/pull/2254)) +* Fix deprecation warning `np.sum(generator)` ([@rsdel2007](https://github.com/rsdel2007), [#2296](https://github.com/RaRe-Technologies/gensim/pull/2296)) +* Refactor `BM25` ([@horpto](https://github.com/horpto), [#2275](https://github.com/RaRe-Technologies/gensim/pull/2275)) +* Fix pyemd import ([@ramprakash-94](https://github.com/ramprakash-94), [#2240](https://github.com/RaRe-Technologies/gensim/pull/2240)) +* Set `metadata=True` for `make_wikicorpus` script by default ([@Xinyi2016](https://github.com/Xinyi2016), [#2245](https://github.com/RaRe-Technologies/gensim/pull/2245)) +* Remove unimportant warning from `Phrases` ([@rsdel2007](https://github.com/rsdel2007), [#2331](https://github.com/RaRe-Technologies/gensim/pull/2331)) +* Replace `open()` by `smart_open()` in `gensim.models.fasttext._load_fasttext_format` ([@rsdel2007](https://github.com/rsdel2007), [#2335](https://github.com/RaRe-Technologies/gensim/pull/2335)) ### :red_circle: Bug fixes -* Fix overflow error for `*Vec` corpusfile-based training (__[@bm371613](https://github.com/bm371613)__, [#2239](https://github.com/RaRe-Technologies/gensim/pull/2239)) -* Fix `malletmodel2ldamodel` conversion (__[@horpto](https://github.com/horpto)__, [#2288](https://github.com/RaRe-Technologies/gensim/pull/2288)) -* Replace custom epsilons with numpy equivalent in `LdaModel` (__[@horpto](https://github.com/horpto)__, [#2308](https://github.com/RaRe-Technologies/gensim/pull/2308)) -* Add missing content to tarball (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#2194](https://github.com/RaRe-Technologies/gensim/pull/2194)) -* Fixes divided by zero when w_star_count==0 (__[@allenyllee](https://github.com/allenyllee)__, [#2259](https://github.com/RaRe-Technologies/gensim/pull/2259)) -* Fix check for callbacks (__[@allenyllee](https://github.com/allenyllee)__, [#2251](https://github.com/RaRe-Technologies/gensim/pull/2251)) -* Fix `SvmLightCorpus.serialize` if `labels` instance of numpy.ndarray (__[@aquatiko](https://github.com/aquatiko)__, [#2243](https://github.com/RaRe-Technologies/gensim/pull/2243)) -* Fix poincate viz incompatibility with `plotly>=3.0.0` (__[@jenishah](https://github.com/jenishah)__, [#2226](https://github.com/RaRe-Technologies/gensim/pull/2226)) -* Fix `keep_n` behavior for `Dictionary.filter_extremes` (__[@johann-petrak](https://github.com/johann-petrak)__, [#2232](https://github.com/RaRe-Technologies/gensim/pull/2232)) -* Fix for `sphinx==1.8.1` (last r (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#None](https://github.com/RaRe-Technologies/gensim/pull/None)) -* Fix `np.issubdtype` warnings (__[@marioyc](https://github.com/marioyc)__, [#2210](https://github.com/RaRe-Technologies/gensim/pull/2210)) -* Drop wrong key `-c` from `gensim.downloader` description (__[@horpto](https://github.com/horpto)__, [#2262](https://github.com/RaRe-Technologies/gensim/pull/2262)) -* Fix gensim build (docs & pyemd issues) (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#2318](https://github.com/RaRe-Technologies/gensim/pull/2318)) -* Limit visdom version (avoid py2 issue from the latest visdom release) (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#2334](https://github.com/RaRe-Technologies/gensim/pull/2334)) -* Fix visdom integration (using `viz.line()` instead of `viz.updatetrace()`) (__[@allenyllee](https://github.com/allenyllee)__, [#2252](https://github.com/RaRe-Technologies/gensim/pull/2252)) +* Fix overflow error for `*Vec` corpusfile-based training ([@bm371613](https://github.com/bm371613), [#2239](https://github.com/RaRe-Technologies/gensim/pull/2239)) +* Fix `malletmodel2ldamodel` conversion ([@horpto](https://github.com/horpto), [#2288](https://github.com/RaRe-Technologies/gensim/pull/2288)) +* Replace custom epsilons with numpy equivalent in `LdaModel` ([@horpto](https://github.com/horpto), [#2308](https://github.com/RaRe-Technologies/gensim/pull/2308)) +* Add missing content to tarball ([@menshikh-iv](https://github.com/menshikh-iv), [#2194](https://github.com/RaRe-Technologies/gensim/pull/2194)) +* Fixes divided by zero when w_star_count==0 ([@allenyllee](https://github.com/allenyllee), [#2259](https://github.com/RaRe-Technologies/gensim/pull/2259)) +* Fix check for callbacks ([@allenyllee](https://github.com/allenyllee), [#2251](https://github.com/RaRe-Technologies/gensim/pull/2251)) +* Fix `SvmLightCorpus.serialize` if `labels` instance of numpy.ndarray ([@aquatiko](https://github.com/aquatiko), [#2243](https://github.com/RaRe-Technologies/gensim/pull/2243)) +* Fix poincate viz incompatibility with `plotly>=3.0.0` ([@jenishah](https://github.com/jenishah), [#2226](https://github.com/RaRe-Technologies/gensim/pull/2226)) +* Fix `keep_n` behavior for `Dictionary.filter_extremes` ([@johann-petrak](https://github.com/johann-petrak), [#2232](https://github.com/RaRe-Technologies/gensim/pull/2232)) +* Fix for `sphinx==1.8.1` (last r ([@menshikh-iv](https://github.com/menshikh-iv), [#None](https://github.com/RaRe-Technologies/gensim/pull/None)) +* Fix `np.issubdtype` warnings ([@marioyc](https://github.com/marioyc), [#2210](https://github.com/RaRe-Technologies/gensim/pull/2210)) +* Drop wrong key `-c` from `gensim.downloader` description ([@horpto](https://github.com/horpto), [#2262](https://github.com/RaRe-Technologies/gensim/pull/2262)) +* Fix gensim build (docs & pyemd issues) ([@menshikh-iv](https://github.com/menshikh-iv), [#2318](https://github.com/RaRe-Technologies/gensim/pull/2318)) +* Limit visdom version (avoid py2 issue from the latest visdom release) ([@menshikh-iv](https://github.com/menshikh-iv), [#2334](https://github.com/RaRe-Technologies/gensim/pull/2334)) +* Fix visdom integration (using `viz.line()` instead of `viz.updatetrace()`) ([@allenyllee](https://github.com/allenyllee), [#2252](https://github.com/RaRe-Technologies/gensim/pull/2252)) ### :books: Tutorial and doc improvements -* Add gensim-data repo to `gensim.downloader` & fix rendering of code examples (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#2327](https://github.com/RaRe-Technologies/gensim/pull/2327)) -* Fix typos in `gensim.models` (__[@rsdel2007](https://github.com/rsdel2007)__, [#2323](https://github.com/RaRe-Technologies/gensim/pull/2323)) -* Fixed typos in notebooks (__[@rsdel2007](https://github.com/rsdel2007)__, [#2322](https://github.com/RaRe-Technologies/gensim/pull/2322)) -* Update `Doc2Vec` documentation: how tags are assigned in `corpus_file` mode (__[@persiyanov](https://github.com/persiyanov)__, [#2320](https://github.com/RaRe-Technologies/gensim/pull/2320)) -* Fix typos in `gensim/models/keyedvectors.py` (__[@rsdel2007](https://github.com/rsdel2007)__, [#2290](https://github.com/RaRe-Technologies/gensim/pull/2290)) -* Add documentation about ranges to scoring functions for `Phrases` (__[@jenishah](https://github.com/jenishah)__, [#2242](https://github.com/RaRe-Technologies/gensim/pull/2242)) -* Update return sections for `KeyedVectors.evaluate_word_*` (__[@Stigjb](https://github.com/Stigjb)__, [#2205](https://github.com/RaRe-Technologies/gensim/pull/2205)) -* Fix return type in `KeyedVector.evaluate_word_analogies` (__[@Stigjb](https://github.com/Stigjb)__, [#2207](https://github.com/RaRe-Technologies/gensim/pull/2207)) -* Fix `WmdSimilarity` documentation (__[@jagmoreira](https://github.com/jagmoreira)__, [#2217](https://github.com/RaRe-Technologies/gensim/pull/2217)) -* Replace `fify -> fifty` in `gensim.parsing.preprocessing.STOPWORDS` (__[@coderwassananmol](https://github.com/coderwassananmol)__, [#2220](https://github.com/RaRe-Technologies/gensim/pull/2220)) -* Remove `alpha="auto"` from `LdaMulticore` (not supported yet) (__[@johann-petrak](https://github.com/johann-petrak)__, [#2225](https://github.com/RaRe-Technologies/gensim/pull/2225)) -* Update Adopters in README (__[@piskvorky](https://github.com/piskvorky)__, [#2234](https://github.com/RaRe-Technologies/gensim/pull/2234)) -* Fix broken link in `tutorials.md` (__[@rsdel2007](https://github.com/rsdel2007)__, [#2302](https://github.com/RaRe-Technologies/gensim/pull/2302)) +* Add gensim-data repo to `gensim.downloader` & fix rendering of code examples ([@menshikh-iv](https://github.com/menshikh-iv), [#2327](https://github.com/RaRe-Technologies/gensim/pull/2327)) +* Fix typos in `gensim.models` ([@rsdel2007](https://github.com/rsdel2007), [#2323](https://github.com/RaRe-Technologies/gensim/pull/2323)) +* Fixed typos in notebooks ([@rsdel2007](https://github.com/rsdel2007), [#2322](https://github.com/RaRe-Technologies/gensim/pull/2322)) +* Update `Doc2Vec` documentation: how tags are assigned in `corpus_file` mode ([@persiyanov](https://github.com/persiyanov), [#2320](https://github.com/RaRe-Technologies/gensim/pull/2320)) +* Fix typos in `gensim/models/keyedvectors.py` ([@rsdel2007](https://github.com/rsdel2007), [#2290](https://github.com/RaRe-Technologies/gensim/pull/2290)) +* Add documentation about ranges to scoring functions for `Phrases` ([@jenishah](https://github.com/jenishah), [#2242](https://github.com/RaRe-Technologies/gensim/pull/2242)) +* Update return sections for `KeyedVectors.evaluate_word_*` ([@Stigjb](https://github.com/Stigjb), [#2205](https://github.com/RaRe-Technologies/gensim/pull/2205)) +* Fix return type in `KeyedVector.evaluate_word_analogies` ([@Stigjb](https://github.com/Stigjb), [#2207](https://github.com/RaRe-Technologies/gensim/pull/2207)) +* Fix `WmdSimilarity` documentation ([@jagmoreira](https://github.com/jagmoreira), [#2217](https://github.com/RaRe-Technologies/gensim/pull/2217)) +* Replace `fify -> fifty` in `gensim.parsing.preprocessing.STOPWORDS` ([@coderwassananmol](https://github.com/coderwassananmol), [#2220](https://github.com/RaRe-Technologies/gensim/pull/2220)) +* Remove `alpha="auto"` from `LdaMulticore` (not supported yet) ([@johann-petrak](https://github.com/johann-petrak), [#2225](https://github.com/RaRe-Technologies/gensim/pull/2225)) +* Update Adopters in README ([@piskvorky](https://github.com/piskvorky), [#2234](https://github.com/RaRe-Technologies/gensim/pull/2234)) +* Fix broken link in `tutorials.md` ([@rsdel2007](https://github.com/rsdel2007), [#2302](https://github.com/RaRe-Technologies/gensim/pull/2302)) ### :warning: Deprecations (will be removed in the next major release) @@ -586,7 +597,7 @@ Remove: ## 3.6.0, 2018-09-20 ### :star2: New features -* File-based training for `*2Vec` models (__[@persiyanov](https://github.com/persiyanov)__, [#2127](https://github.com/RaRe-Technologies/gensim/pull/2127) & [#2078](https://github.com/RaRe-Technologies/gensim/pull/2078) & [#2048](https://github.com/RaRe-Technologies/gensim/pull/2048)) +* File-based training for `*2Vec` models ([@persiyanov](https://github.com/persiyanov), [#2127](https://github.com/RaRe-Technologies/gensim/pull/2127) & [#2078](https://github.com/RaRe-Technologies/gensim/pull/2078) & [#2048](https://github.com/RaRe-Technologies/gensim/pull/2048)) New training mode for `*2Vec` models (word2vec, doc2vec, fasttext) that allows model training to scale linearly with the number of cores (full GIL elimination). The result of our Google Summer of Code 2018 project by Dmitry Persiyanov. @@ -632,36 +643,36 @@ Remove: ### :+1: Improvements -* Add scikit-learn wrapper for `FastText` (__[@mcemilg](https://github.com/mcemilg)__, [#2178](https://github.com/RaRe-Technologies/gensim/pull/2178)) -* Add multiprocessing support for `BM25` (__[@Shiki-H](https://github.com/Shiki-H)__, [#2146](https://github.com/RaRe-Technologies/gensim/pull/2146)) -* Add `name_only` option for downloader api (__[@aneesh-joshi](https://github.com/aneesh-joshi)__, [#2143](https://github.com/RaRe-Technologies/gensim/pull/2143)) -* Make `word2vec2tensor` script compatible with `python3` (__[@vsocrates](https://github.com/vsocrates)__, [#2147](https://github.com/RaRe-Technologies/gensim/pull/2147)) -* Add custom filter for `Wikicorpus` (__[@mattilyra](https://github.com/mattilyra)__, [#2089](https://github.com/RaRe-Technologies/gensim/pull/2089)) -* Make `similarity_matrix` support non-contiguous dictionaries (__[@Witiko](https://github.com/Witiko)__, [#2047](https://github.com/RaRe-Technologies/gensim/pull/2047)) +* Add scikit-learn wrapper for `FastText` ([@mcemilg](https://github.com/mcemilg), [#2178](https://github.com/RaRe-Technologies/gensim/pull/2178)) +* Add multiprocessing support for `BM25` ([@Shiki-H](https://github.com/Shiki-H), [#2146](https://github.com/RaRe-Technologies/gensim/pull/2146)) +* Add `name_only` option for downloader api ([@aneesh-joshi](https://github.com/aneesh-joshi), [#2143](https://github.com/RaRe-Technologies/gensim/pull/2143)) +* Make `word2vec2tensor` script compatible with `python3` ([@vsocrates](https://github.com/vsocrates), [#2147](https://github.com/RaRe-Technologies/gensim/pull/2147)) +* Add custom filter for `Wikicorpus` ([@mattilyra](https://github.com/mattilyra), [#2089](https://github.com/RaRe-Technologies/gensim/pull/2089)) +* Make `similarity_matrix` support non-contiguous dictionaries ([@Witiko](https://github.com/Witiko), [#2047](https://github.com/RaRe-Technologies/gensim/pull/2047)) ### :red_circle: Bug fixes -* Fix memory consumption in `AuthorTopicModel` (__[@philipphager](https://github.com/philipphager)__, [#2122](https://github.com/RaRe-Technologies/gensim/pull/2122)) -* Correctly process empty documents in `AuthorTopicModel` (__[@probinso](https://github.com/probinso)__, [#2133](https://github.com/RaRe-Technologies/gensim/pull/2133)) -* Fix ZeroDivisionError `keywords` issue with short input (__[@LShostenko](https://github.com/LShostenko)__, [#2154](https://github.com/RaRe-Technologies/gensim/pull/2154)) -* Fix `min_count` handling in phrases detection using `npmi_scorer` (__[@lopusz](https://github.com/lopusz)__, [#2072](https://github.com/RaRe-Technologies/gensim/pull/2072)) -* Remove duplicate count from `Phraser` log message (__[@robguinness](https://github.com/robguinness)__, [#2151](https://github.com/RaRe-Technologies/gensim/pull/2151)) -* Replace `np.integer` -> `np.int` in `AuthorTopicModel` (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#2145](https://github.com/RaRe-Technologies/gensim/pull/2145)) +* Fix memory consumption in `AuthorTopicModel` ([@philipphager](https://github.com/philipphager), [#2122](https://github.com/RaRe-Technologies/gensim/pull/2122)) +* Correctly process empty documents in `AuthorTopicModel` ([@probinso](https://github.com/probinso), [#2133](https://github.com/RaRe-Technologies/gensim/pull/2133)) +* Fix ZeroDivisionError `keywords` issue with short input ([@LShostenko](https://github.com/LShostenko), [#2154](https://github.com/RaRe-Technologies/gensim/pull/2154)) +* Fix `min_count` handling in phrases detection using `npmi_scorer` ([@lopusz](https://github.com/lopusz), [#2072](https://github.com/RaRe-Technologies/gensim/pull/2072)) +* Remove duplicate count from `Phraser` log message ([@robguinness](https://github.com/robguinness), [#2151](https://github.com/RaRe-Technologies/gensim/pull/2151)) +* Replace `np.integer` -> `np.int` in `AuthorTopicModel` ([@menshikh-iv](https://github.com/menshikh-iv), [#2145](https://github.com/RaRe-Technologies/gensim/pull/2145)) ### :books: Tutorial and doc improvements -* Update docstring with new analogy evaluation method (__[@akutuzov](https://github.com/akutuzov)__, [#2130](https://github.com/RaRe-Technologies/gensim/pull/2130)) -* Improve `prune_at` parameter description for `gensim.corpora.Dictionary` (__[@yxonic](https://github.com/yxonic)__, [#2128](https://github.com/RaRe-Technologies/gensim/pull/2128)) -* Fix `default` -> `auto` prior parameter in documentation for lda-related models (__[@Laubeee](https://github.com/Laubeee)__, [#2156](https://github.com/RaRe-Technologies/gensim/pull/2156)) -* Use heading instead of bold style in `gensim.models.translation_matrix` (__[@nzw0301](https://github.com/nzw0301)__, [#2164](https://github.com/RaRe-Technologies/gensim/pull/2164)) -* Fix quote of vocabulary from `gensim.models.Word2Vec` (__[@nzw0301](https://github.com/nzw0301)__, [#2161](https://github.com/RaRe-Technologies/gensim/pull/2161)) -* Replace deprecated parameters with new in docstring of `gensim.models.Doc2Vec` (__[@xuhdev](https://github.com/xuhdev)__, [#2165](https://github.com/RaRe-Technologies/gensim/pull/2165)) -* Fix formula in Mallet documentation (__[@Laubeee](https://github.com/Laubeee)__, [#2186](https://github.com/RaRe-Technologies/gensim/pull/2186)) -* Fix minor semantic issue in docs for `Phrases` (__[@RunHorst](https://github.com/RunHorst)__, [#2148](https://github.com/RaRe-Technologies/gensim/pull/2148)) -* Fix typo in documentation (__[@KenjiOhtsuka](https://github.com/KenjiOhtsuka)__, [#2157](https://github.com/RaRe-Technologies/gensim/pull/2157)) -* Additional documentation fixes (__[@piskvorky](https://github.com/piskvorky)__, [#2121](https://github.com/RaRe-Technologies/gensim/pull/2121)) +* Update docstring with new analogy evaluation method ([@akutuzov](https://github.com/akutuzov), [#2130](https://github.com/RaRe-Technologies/gensim/pull/2130)) +* Improve `prune_at` parameter description for `gensim.corpora.Dictionary` ([@yxonic](https://github.com/yxonic), [#2128](https://github.com/RaRe-Technologies/gensim/pull/2128)) +* Fix `default` -> `auto` prior parameter in documentation for lda-related models ([@Laubeee](https://github.com/Laubeee), [#2156](https://github.com/RaRe-Technologies/gensim/pull/2156)) +* Use heading instead of bold style in `gensim.models.translation_matrix` ([@nzw0301](https://github.com/nzw0301), [#2164](https://github.com/RaRe-Technologies/gensim/pull/2164)) +* Fix quote of vocabulary from `gensim.models.Word2Vec` ([@nzw0301](https://github.com/nzw0301), [#2161](https://github.com/RaRe-Technologies/gensim/pull/2161)) +* Replace deprecated parameters with new in docstring of `gensim.models.Doc2Vec` ([@xuhdev](https://github.com/xuhdev), [#2165](https://github.com/RaRe-Technologies/gensim/pull/2165)) +* Fix formula in Mallet documentation ([@Laubeee](https://github.com/Laubeee), [#2186](https://github.com/RaRe-Technologies/gensim/pull/2186)) +* Fix minor semantic issue in docs for `Phrases` ([@RunHorst](https://github.com/RunHorst), [#2148](https://github.com/RaRe-Technologies/gensim/pull/2148)) +* Fix typo in documentation ([@KenjiOhtsuka](https://github.com/KenjiOhtsuka), [#2157](https://github.com/RaRe-Technologies/gensim/pull/2157)) +* Additional documentation fixes ([@piskvorky](https://github.com/piskvorky), [#2121](https://github.com/RaRe-Technologies/gensim/pull/2121)) ### :warning: Deprecations (will be removed in the next major release) @@ -696,60 +707,60 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst ### :books: Documentation improvements -* Overhaul documentation for `*2vec` models (__[@steremma](https://github.com/steremma)__ & __[@piskvorky](https://github.com/piskvorky)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1944](https://github.com/RaRe-Technologies/gensim/pull/1944), [#2087](https://github.com/RaRe-Technologies/gensim/pull/2087)) -* Fix documentation for LDA-related models (__[@steremma](https://github.com/steremma)__ & __[@piskvorky](https://github.com/piskvorky)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#2026](https://github.com/RaRe-Technologies/gensim/pull/2026)) -* Fix documentation for utils, corpora, inferfaces (__[@piskvorky](https://github.com/piskvorky)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#2096](https://github.com/RaRe-Technologies/gensim/pull/2096)) -* Update non-API docs (about, intro, license etc) (__[@piskvorky](https://github.com/piskvorky)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#2101](https://github.com/RaRe-Technologies/gensim/pull/2101)) -* Refactor documentation for `gensim.models.phrases` (__[@CLearERR](https://github.com/CLearERR)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1950](https://github.com/RaRe-Technologies/gensim/pull/1950)) -* Fix HashDictionary documentation (__[@piskvorky](https://github.com/piskvorky)__, [#2073](https://github.com/RaRe-Technologies/gensim/pull/2073)) -* Fix docstrings for `gensim.models.AuthorTopicModel` (__[@souravsingh](https://github.com/souravsingh)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1907](https://github.com/RaRe-Technologies/gensim/pull/1907)) -* Fix docstrings for HdpModel, lda_worker & lda_dispatcher (__[@gyanesh-m](https://github.com/gyanesh-m)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1912](https://github.com/RaRe-Technologies/gensim/pull/1912)) -* Fix format & links for `gensim.similarities.docsim` (__[@CLearERR](https://github.com/CLearERR)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#2030](https://github.com/RaRe-Technologies/gensim/pull/2030)) -* Remove duplication of class documentation for `IndexedCorpus` (__[@darindf](https://github.com/darindf)__, [#2033](https://github.com/RaRe-Technologies/gensim/pull/2033)) -* Refactor documentation for `gensim.models.coherencemodel` (__[@CLearERR](https://github.com/CLearERR)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1933](https://github.com/RaRe-Technologies/gensim/pull/1933)) -* Fix docstrings for `gensim.sklearn_api` (__[@steremma](https://github.com/steremma)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1895](https://github.com/RaRe-Technologies/gensim/pull/1895)) -* Disable google-style docstring support (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#2106](https://github.com/RaRe-Technologies/gensim/pull/2106)) -* Fix docstring of `gensim.models.KeyedVectors.similarity_matrix` (__[@Witiko](https://github.com/Witiko)__, [#1971](https://github.com/RaRe-Technologies/gensim/pull/1971)) -* Consistently use `smart_open()` instead of `open()` in notebooks (__[@sharanry](https://github.com/sharanry)__, [#1812](https://github.com/RaRe-Technologies/gensim/pull/1812)) +* Overhaul documentation for `*2vec` models ([@steremma](https://github.com/steremma) & [@piskvorky](https://github.com/piskvorky) & [@menshikh-iv](https://github.com/menshikh-iv), [#1944](https://github.com/RaRe-Technologies/gensim/pull/1944), [#2087](https://github.com/RaRe-Technologies/gensim/pull/2087)) +* Fix documentation for LDA-related models ([@steremma](https://github.com/steremma) & [@piskvorky](https://github.com/piskvorky) & [@menshikh-iv](https://github.com/menshikh-iv), [#2026](https://github.com/RaRe-Technologies/gensim/pull/2026)) +* Fix documentation for utils, corpora, inferfaces ([@piskvorky](https://github.com/piskvorky) & [@menshikh-iv](https://github.com/menshikh-iv), [#2096](https://github.com/RaRe-Technologies/gensim/pull/2096)) +* Update non-API docs (about, intro, license etc) ([@piskvorky](https://github.com/piskvorky) & [@menshikh-iv](https://github.com/menshikh-iv), [#2101](https://github.com/RaRe-Technologies/gensim/pull/2101)) +* Refactor documentation for `gensim.models.phrases` ([@CLearERR](https://github.com/CLearERR) & [@menshikh-iv](https://github.com/menshikh-iv), [#1950](https://github.com/RaRe-Technologies/gensim/pull/1950)) +* Fix HashDictionary documentation ([@piskvorky](https://github.com/piskvorky), [#2073](https://github.com/RaRe-Technologies/gensim/pull/2073)) +* Fix docstrings for `gensim.models.AuthorTopicModel` ([@souravsingh](https://github.com/souravsingh) & [@menshikh-iv](https://github.com/menshikh-iv), [#1907](https://github.com/RaRe-Technologies/gensim/pull/1907)) +* Fix docstrings for HdpModel, lda_worker & lda_dispatcher ([@gyanesh-m](https://github.com/gyanesh-m) & [@menshikh-iv](https://github.com/menshikh-iv), [#1912](https://github.com/RaRe-Technologies/gensim/pull/1912)) +* Fix format & links for `gensim.similarities.docsim` ([@CLearERR](https://github.com/CLearERR) & [@menshikh-iv](https://github.com/menshikh-iv), [#2030](https://github.com/RaRe-Technologies/gensim/pull/2030)) +* Remove duplication of class documentation for `IndexedCorpus` ([@darindf](https://github.com/darindf), [#2033](https://github.com/RaRe-Technologies/gensim/pull/2033)) +* Refactor documentation for `gensim.models.coherencemodel` ([@CLearERR](https://github.com/CLearERR) & [@menshikh-iv](https://github.com/menshikh-iv), [#1933](https://github.com/RaRe-Technologies/gensim/pull/1933)) +* Fix docstrings for `gensim.sklearn_api` ([@steremma](https://github.com/steremma) & [@menshikh-iv](https://github.com/menshikh-iv), [#1895](https://github.com/RaRe-Technologies/gensim/pull/1895)) +* Disable google-style docstring support ([@menshikh-iv](https://github.com/menshikh-iv), [#2106](https://github.com/RaRe-Technologies/gensim/pull/2106)) +* Fix docstring of `gensim.models.KeyedVectors.similarity_matrix` ([@Witiko](https://github.com/Witiko), [#1971](https://github.com/RaRe-Technologies/gensim/pull/1971)) +* Consistently use `smart_open()` instead of `open()` in notebooks ([@sharanry](https://github.com/sharanry), [#1812](https://github.com/RaRe-Technologies/gensim/pull/1812)) ### :star2: New features: -* Add `add_entity` method to `KeyedVectors` to allow adding word vectors manually (__[@persiyanov](https://github.com/persiyanov)__, [#1957](https://github.com/RaRe-Technologies/gensim/pull/1957)) -* Add inference for new unseen author to `AuthorTopicModel` (__[@Stamenov](https://github.com/Stamenov)__, [#1766](https://github.com/RaRe-Technologies/gensim/pull/1766)) -* Add `evaluate_word_analogies` (will replace `accuracy`) method to `KeyedVectors` (__[@akutuzov](https://github.com/akutuzov)__, [#1935](https://github.com/RaRe-Technologies/gensim/pull/1935)) -* Add Pivot Normalization to `TfidfModel` (__[@markroxor](https://github.com/markroxor)__, [#1780](https://github.com/RaRe-Technologies/gensim/pull/1780)) +* Add `add_entity` method to `KeyedVectors` to allow adding word vectors manually ([@persiyanov](https://github.com/persiyanov), [#1957](https://github.com/RaRe-Technologies/gensim/pull/1957)) +* Add inference for new unseen author to `AuthorTopicModel` ([@Stamenov](https://github.com/Stamenov), [#1766](https://github.com/RaRe-Technologies/gensim/pull/1766)) +* Add `evaluate_word_analogies` (will replace `accuracy`) method to `KeyedVectors` ([@akutuzov](https://github.com/akutuzov), [#1935](https://github.com/RaRe-Technologies/gensim/pull/1935)) +* Add Pivot Normalization to `TfidfModel` ([@markroxor](https://github.com/markroxor), [#1780](https://github.com/RaRe-Technologies/gensim/pull/1780)) ### :+1: Improvements -* Allow initialization with `max_final_vocab` in lieu of `min_count` in `Word2Vec`(__[@aneesh-joshi](https://github.com/aneesh-joshi)__, [#1915](https://github.com/RaRe-Technologies/gensim/pull/1915)) -* Add `dtype` argument for `chunkize_serial` in `LdaModel` (__[@darindf](https://github.com/darindf)__, [#2027](https://github.com/RaRe-Technologies/gensim/pull/2027)) -* Increase performance in `Phrases.analyze_sentence` (__[@JonathanHourany](https://github.com/JonathanHourany)__, [#2070](https://github.com/RaRe-Technologies/gensim/pull/2070)) -* Add `ns_exponent` parameter to control the negative sampling distribution for `*2vec` models (__[@fernandocamargoti](https://github.com/fernandocamargoti)__, [#2093](https://github.com/RaRe-Technologies/gensim/pull/2093)) +* Allow initialization with `max_final_vocab` in lieu of `min_count` in `Word2Vec`([@aneesh-joshi](https://github.com/aneesh-joshi), [#1915](https://github.com/RaRe-Technologies/gensim/pull/1915)) +* Add `dtype` argument for `chunkize_serial` in `LdaModel` ([@darindf](https://github.com/darindf), [#2027](https://github.com/RaRe-Technologies/gensim/pull/2027)) +* Increase performance in `Phrases.analyze_sentence` ([@JonathanHourany](https://github.com/JonathanHourany), [#2070](https://github.com/RaRe-Technologies/gensim/pull/2070)) +* Add `ns_exponent` parameter to control the negative sampling distribution for `*2vec` models ([@fernandocamargoti](https://github.com/fernandocamargoti), [#2093](https://github.com/RaRe-Technologies/gensim/pull/2093)) ### :red_circle: Bug fixes: -* Fix `Doc2Vec.infer_vector` + notebook cleanup (__[@gojomo](https://github.com/gojomo)__, [#2103](https://github.com/RaRe-Technologies/gensim/pull/2103)) -* Fix linear decay for learning rate in `Doc2Vec.infer_vector` (__[@umangv](https://github.com/umangv)__, [#2063](https://github.com/RaRe-Technologies/gensim/pull/2063)) -* Fix negative sampling floating-point error for `gensim.models.Poincare (__[@jayantj](https://github.com/jayantj)__, [#1959](https://github.com/RaRe-Technologies/gensim/pull/1959)) -* Fix loading `word2vec` and `doc2vec` models saved using old Gensim versions (__[@manneshiva](https://github.com/manneshiva)__, [#2012](https://github.com/RaRe-Technologies/gensim/pull/2012)) -* Fix `SoftCosineSimilarity.get_similarities` on corpora ssues/1955) (__[@Witiko](https://github.com/Witiko)__, [#1972](https://github.com/RaRe-Technologies/gensim/pull/1972)) -* Fix return dtype for `matutils.unitvec` according to input dtype (__[@o-P-o](https://github.com/o-P-o)__, [#1992](https://github.com/RaRe-Technologies/gensim/pull/1992)) -* Fix passing empty dictionary to `gensim.corpora.WikiCorpus` (__[@steremma](https://github.com/steremma)__, [#2042](https://github.com/RaRe-Technologies/gensim/pull/2042)) -* Fix bug in `Similarity.query_shards` in multiprocessing case (__[@bohea](https://github.com/bohea)__, [#2044](https://github.com/RaRe-Technologies/gensim/pull/2044)) -* Fix SMART from TfidfModel for case when `df == "n"` (__[@PeteBleackley](https://github.com/PeteBleackley)__, [#2021](https://github.com/RaRe-Technologies/gensim/pull/2021)) -* Fix OverflowError when loading a large term-document matrix in compiled MatrixMarket format (__[@arlenk](https://github.com/arlenk)__, [#2001](https://github.com/RaRe-Technologies/gensim/pull/2001)) -* Update rules for removing table markup from Wikipedia dumps (__[@chaitaliSaini](https://github.com/chaitaliSaini)__, [#1954](https://github.com/RaRe-Technologies/gensim/pull/1954)) -* Fix `_is_single` from `Phrases` for case when corpus is a NumPy array (__[@rmalouf](https://github.com/rmalouf)__, [#1987](https://github.com/RaRe-Technologies/gensim/pull/1987)) -* Fix tests for `EuclideanKeyedVectors.similarity_matrix` (__[@Witiko](https://github.com/Witiko)__, [#1984](https://github.com/RaRe-Technologies/gensim/pull/1984)) -* Fix deprecated parameters in `D2VTransformer` and `W2VTransformer`(__[@MritunjayMohitesh](https://github.com/MritunjayMohitesh)__, [#1945](https://github.com/RaRe-Technologies/gensim/pull/1945)) -* Fix `Doc2Vec.infer_vector` after loading old `Doc2Vec` (`gensim<=3.2`)(__[@manneshiva](https://github.com/manneshiva)__, [#1974](https://github.com/RaRe-Technologies/gensim/pull/1974)) -* Fix inheritance chain for `load_word2vec_format` (__[@DennisChen0307](https://github.com/DennisChen0307)__, [#1968](https://github.com/RaRe-Technologies/gensim/pull/1968)) -* Update Keras version (avoid bug from `keras==2.1.5`) (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1963](https://github.com/RaRe-Technologies/gensim/pull/1963)) +* Fix `Doc2Vec.infer_vector` + notebook cleanup ([@gojomo](https://github.com/gojomo), [#2103](https://github.com/RaRe-Technologies/gensim/pull/2103)) +* Fix linear decay for learning rate in `Doc2Vec.infer_vector` ([@umangv](https://github.com/umangv), [#2063](https://github.com/RaRe-Technologies/gensim/pull/2063)) +* Fix negative sampling floating-point error for `gensim.models.Poincare ([@jayantj](https://github.com/jayantj), [#1959](https://github.com/RaRe-Technologies/gensim/pull/1959)) +* Fix loading `word2vec` and `doc2vec` models saved using old Gensim versions ([@manneshiva](https://github.com/manneshiva), [#2012](https://github.com/RaRe-Technologies/gensim/pull/2012)) +* Fix `SoftCosineSimilarity.get_similarities` on corpora ssues/1955) ([@Witiko](https://github.com/Witiko), [#1972](https://github.com/RaRe-Technologies/gensim/pull/1972)) +* Fix return dtype for `matutils.unitvec` according to input dtype ([@o-P-o](https://github.com/o-P-o), [#1992](https://github.com/RaRe-Technologies/gensim/pull/1992)) +* Fix passing empty dictionary to `gensim.corpora.WikiCorpus` ([@steremma](https://github.com/steremma), [#2042](https://github.com/RaRe-Technologies/gensim/pull/2042)) +* Fix bug in `Similarity.query_shards` in multiprocessing case ([@bohea](https://github.com/bohea), [#2044](https://github.com/RaRe-Technologies/gensim/pull/2044)) +* Fix SMART from TfidfModel for case when `df == "n"` ([@PeteBleackley](https://github.com/PeteBleackley), [#2021](https://github.com/RaRe-Technologies/gensim/pull/2021)) +* Fix OverflowError when loading a large term-document matrix in compiled MatrixMarket format ([@arlenk](https://github.com/arlenk), [#2001](https://github.com/RaRe-Technologies/gensim/pull/2001)) +* Update rules for removing table markup from Wikipedia dumps ([@chaitaliSaini](https://github.com/chaitaliSaini), [#1954](https://github.com/RaRe-Technologies/gensim/pull/1954)) +* Fix `_is_single` from `Phrases` for case when corpus is a NumPy array ([@rmalouf](https://github.com/rmalouf), [#1987](https://github.com/RaRe-Technologies/gensim/pull/1987)) +* Fix tests for `EuclideanKeyedVectors.similarity_matrix` ([@Witiko](https://github.com/Witiko), [#1984](https://github.com/RaRe-Technologies/gensim/pull/1984)) +* Fix deprecated parameters in `D2VTransformer` and `W2VTransformer`([@MritunjayMohitesh](https://github.com/MritunjayMohitesh), [#1945](https://github.com/RaRe-Technologies/gensim/pull/1945)) +* Fix `Doc2Vec.infer_vector` after loading old `Doc2Vec` (`gensim<=3.2`)([@manneshiva](https://github.com/manneshiva), [#1974](https://github.com/RaRe-Technologies/gensim/pull/1974)) +* Fix inheritance chain for `load_word2vec_format` ([@DennisChen0307](https://github.com/DennisChen0307), [#1968](https://github.com/RaRe-Technologies/gensim/pull/1968)) +* Update Keras version (avoid bug from `keras==2.1.5`) ([@menshikh-iv](https://github.com/menshikh-iv), [#1963](https://github.com/RaRe-Technologies/gensim/pull/1963)) @@ -777,7 +788,7 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst ## 3.4.0, 2018-03-01 ### :star2: New features: -* Massive optimizations of `gensim.models.LdaModel`: much faster training, using Cython. (__[@arlenk](https://github.com/arlenk)__, [#1767](https://github.com/RaRe-Technologies/gensim/pull/1767)) +* Massive optimizations of `gensim.models.LdaModel`: much faster training, using Cython. ([@arlenk](https://github.com/arlenk), [#1767](https://github.com/RaRe-Technologies/gensim/pull/1767)) - Training benchmark :boom: | dataset | old LDA [sec] | optimized LDA [sec] | speed up | @@ -786,7 +797,7 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst | enron | 774 | **437** | **1.77x** | - This change **affects all models that depend on `LdaModel`**, such as `LdaMulticore`, `LdaSeqModel`, `AuthorTopicModel`. -* Huge speed-ups to corpus I/O with `MmCorpus` (Cython) (__[@arlenk](https://github.com/arlenk)__, [#1825](https://github.com/RaRe-Technologies/gensim/pull/1825)) +* Huge speed-ups to corpus I/O with `MmCorpus` (Cython) ([@arlenk](https://github.com/arlenk), [#1825](https://github.com/RaRe-Technologies/gensim/pull/1825)) - File reading benchmark | dataset | file compressed? | old MmReader [sec] | optimized MmReader [sec] | speed up | @@ -800,7 +811,7 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst - Overall, a **2.5x** speedup for compressed `.mm.gz` input and **8.5x** :fire::fire::fire: for uncompressed plaintext `.mm`. -* Performance and memory optimization to `gensim.models.FastText` :rocket: (__[@jbaiter](https://github.com/jbaiter)__, [#1916](https://github.com/RaRe-Technologies/gensim/pull/1916)) +* Performance and memory optimization to `gensim.models.FastText` :rocket: ([@jbaiter](https://github.com/jbaiter), [#1916](https://github.com/RaRe-Technologies/gensim/pull/1916)) - Benchmark (first 500,000 articles from English Wikipedia) | Metric | old FastText | optimized FastText | improvement | @@ -812,7 +823,7 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst - Overall, a **2.5x** speedup & memory usage reduced by **30%**. -* Implemented [Soft Cosine Measure](https://en.wikipedia.org/wiki/Cosine_similarity#Soft_cosine_measure) (__[@Witiko](https://github.com/Witiko)__, [#1827](https://github.com/RaRe-Technologies/gensim/pull/1827)) +* Implemented [Soft Cosine Measure](https://en.wikipedia.org/wiki/Cosine_similarity#Soft_cosine_measure) ([@Witiko](https://github.com/Witiko), [#1827](https://github.com/RaRe-Technologies/gensim/pull/1827)) - New method for assessing document similarity, a nice faster alternative to [WMD, Word Mover's Distance](http://proceedings.mlr.press/v37/kusnerb15.pdf) - Benchmark @@ -831,39 +842,39 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst ### :+1: Improvements: -* New method to show the Gensim installation parameters: `python -m gensim.scripts.package_info --info`. Use this when reporting problems, for easier debugging. Fix #1902 (__[@sharanry](https://github.com/sharanry)__, [#1903](https://github.com/RaRe-Technologies/gensim/pull/1903)) -* Added a flag to optionally skip network-related tests, to help maintainers avoid network issues with CI services (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1930](https://github.com/RaRe-Technologies/gensim/pull/1930)) -* Added `license` field to `setup.py`, allowing the use of tools like `pip-licenses` (__[@nils-werner](https://github.com/nils-werner)__, [#1909](https://github.com/RaRe-Technologies/gensim/pull/1909)) +* New method to show the Gensim installation parameters: `python -m gensim.scripts.package_info --info`. Use this when reporting problems, for easier debugging. Fix #1902 ([@sharanry](https://github.com/sharanry), [#1903](https://github.com/RaRe-Technologies/gensim/pull/1903)) +* Added a flag to optionally skip network-related tests, to help maintainers avoid network issues with CI services ([@menshikh-iv](https://github.com/menshikh-iv), [#1930](https://github.com/RaRe-Technologies/gensim/pull/1930)) +* Added `license` field to `setup.py`, allowing the use of tools like `pip-licenses` ([@nils-werner](https://github.com/nils-werner), [#1909](https://github.com/RaRe-Technologies/gensim/pull/1909)) ### :red_circle: Bug fixes: -* Fix Python 3 compatibility for `gensim.corpora.UciCorpus.save_corpus` (__[@darindf](https://github.com/darindf)__, [#1875](https://github.com/RaRe-Technologies/gensim/pull/1875)) -* Add `wv` property to KeyedVectors for backward compatibility. Fix #1882 (__[@manneshiva](https://github.com/manneshiva)__, [#1884](https://github.com/RaRe-Technologies/gensim/pull/1884)) -* Fix deprecation warning from `inspect.getargspec`. Fix #1878 (__[@aneesh-joshi](https://github.com/aneesh-joshi)__, [#1887](https://github.com/RaRe-Technologies/gensim/pull/1887)) -* Add `LabeledSentence` to `gensim.models.doc2vec` for backward compatibility. Fix #1886 (__[@manneshiva](https://github.com/manneshiva)__, [#1891](https://github.com/RaRe-Technologies/gensim/pull/1891)) -* Fix empty output bug in `Phrases` (when using `model[tokens]` twice). Fix #1401 (__[@sj29-innovate](https://github.com/sj29-innovate)__, [#1853](https://github.com/RaRe-Technologies/gensim/pull/1853)) -* Fix type problems for `D2VTransformer.fit_transform`. Fix #1834 (__[@Utkarsh-Mishra-CIC](https://github.com/Utkarsh-Mishra-CIC)__, [#1845](https://github.com/RaRe-Technologies/gensim/pull/1845)) -* Fix `datatype` parameter for `KeyedVectors.load_word2vec_format`. Fix #1682 (__[@pushpankar](https://github.com/pushpankar)__, [#1819](https://github.com/RaRe-Technologies/gensim/pull/1819)) -* Fix deprecated parameters in `doc2vec-lee` notebook (__[@TheFlash10](https://github.com/TheFlash10)__, [#1918](https://github.com/RaRe-Technologies/gensim/pull/1918)) -* Fix file-like closing bug in `gensim.corpora.MmCorpus`. Fix #1869 (__[@sj29-innovate](https://github.com/sj29-innovate)__, [#1911](https://github.com/RaRe-Technologies/gensim/pull/1911)) -* Fix precision problem in `test_similarities.py`, no more FP fails. (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1928](https://github.com/RaRe-Technologies/gensim/pull/1928)) -* Fix encoding in Lee corpus reader. (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1931](https://github.com/RaRe-Technologies/gensim/pull/1931)) -* Fix OOV pairs counter in `WordEmbeddingsKeyedVectors.evaluate_word_pairs`. (__[@akutuzov](https://github.com/akutuzov)__, [#1934](https://github.com/RaRe-Technologies/gensim/pull/1934)) +* Fix Python 3 compatibility for `gensim.corpora.UciCorpus.save_corpus` ([@darindf](https://github.com/darindf), [#1875](https://github.com/RaRe-Technologies/gensim/pull/1875)) +* Add `wv` property to KeyedVectors for backward compatibility. Fix #1882 ([@manneshiva](https://github.com/manneshiva), [#1884](https://github.com/RaRe-Technologies/gensim/pull/1884)) +* Fix deprecation warning from `inspect.getargspec`. Fix #1878 ([@aneesh-joshi](https://github.com/aneesh-joshi), [#1887](https://github.com/RaRe-Technologies/gensim/pull/1887)) +* Add `LabeledSentence` to `gensim.models.doc2vec` for backward compatibility. Fix #1886 ([@manneshiva](https://github.com/manneshiva), [#1891](https://github.com/RaRe-Technologies/gensim/pull/1891)) +* Fix empty output bug in `Phrases` (when using `model[tokens]` twice). Fix #1401 ([@sj29-innovate](https://github.com/sj29-innovate), [#1853](https://github.com/RaRe-Technologies/gensim/pull/1853)) +* Fix type problems for `D2VTransformer.fit_transform`. Fix #1834 ([@Utkarsh-Mishra-CIC](https://github.com/Utkarsh-Mishra-CIC), [#1845](https://github.com/RaRe-Technologies/gensim/pull/1845)) +* Fix `datatype` parameter for `KeyedVectors.load_word2vec_format`. Fix #1682 ([@pushpankar](https://github.com/pushpankar), [#1819](https://github.com/RaRe-Technologies/gensim/pull/1819)) +* Fix deprecated parameters in `doc2vec-lee` notebook ([@TheFlash10](https://github.com/TheFlash10), [#1918](https://github.com/RaRe-Technologies/gensim/pull/1918)) +* Fix file-like closing bug in `gensim.corpora.MmCorpus`. Fix #1869 ([@sj29-innovate](https://github.com/sj29-innovate), [#1911](https://github.com/RaRe-Technologies/gensim/pull/1911)) +* Fix precision problem in `test_similarities.py`, no more FP fails. ([@menshikh-iv](https://github.com/menshikh-iv), [#1928](https://github.com/RaRe-Technologies/gensim/pull/1928)) +* Fix encoding in Lee corpus reader. ([@menshikh-iv](https://github.com/menshikh-iv), [#1931](https://github.com/RaRe-Technologies/gensim/pull/1931)) +* Fix OOV pairs counter in `WordEmbeddingsKeyedVectors.evaluate_word_pairs`. ([@akutuzov](https://github.com/akutuzov), [#1934](https://github.com/RaRe-Technologies/gensim/pull/1934)) ### :books: Tutorial and doc improvements: -* Fix example block for `gensim.models.Word2Vec` (__[@nzw0301](https://github.com/nzw0301)__, [#1870](https://github.com/RaRe-Technologies/gensim/pull/1876)) -* Fix `doc2vec-lee` notebook (__[@numericlee](https://github.com/numericlee)__, [#1870](https://github.com/RaRe-Technologies/gensim/pull/1870)) -* Store images from `README.md` directly in repository. Fix #1849 (__[@ibrahimsharaf](https://github.com/ibrahimsharaf)__, [#1861](https://github.com/RaRe-Technologies/gensim/pull/1861)) -* Add windows venv activate command to `CONTRIBUTING.md` (__[@aneesh-joshi](https://github.com/aneesh-joshi)__, [#1880](https://github.com/RaRe-Technologies/gensim/pull/1880)) -* Add anaconda-cloud badge. Partial fix #1901 (__[@sharanry](https://github.com/sharanry)__, [#1905](https://github.com/RaRe-Technologies/gensim/pull/1905)) -* Fix docstrings for lsi-related code (__[@steremma](https://github.com/steremma)__, [#1892](https://github.com/RaRe-Technologies/gensim/pull/1892)) -* Fix parameter description of `sg` parameter for `gensim.models.word2vec` (__[@mdcclv](https://github.com/mdcclv)__, [#1919](https://github.com/RaRe-Technologies/gensim/pull/1919)) -* Refactor documentation for `gensim.similarities.docsim` and `MmCorpus-related`. (__[@CLearERR](https://github.com/CLearERR)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1910](https://github.com/RaRe-Technologies/gensim/pull/1910)) -* Fix docstrings for `gensim.test.utils` (__[@yurkai](https://github.com/yurkai)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1904](https://github.com/RaRe-Technologies/gensim/pull/1904)) -* Refactor docstrings for `gensim.scripts`. Partial fix #1665 (__[@yurkai](https://github.com/yurkai)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1792](https://github.com/RaRe-Technologies/gensim/pull/1792)) -* Refactor API reference `gensim.corpora`. Partial fix #1671 (__[@CLearERR](https://github.com/CLearERR)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1835](https://github.com/RaRe-Technologies/gensim/pull/1835)) -* Fix documentation for `gensim.models.wrappers` (__[@kakshay21](https://github.com/kakshay21)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1859](https://github.com/RaRe-Technologies/gensim/pull/1859)) -* Fix docstrings for `gensim.interfaces` (__[@yurkai](https://github.com/yurkai)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1913](https://github.com/RaRe-Technologies/gensim/pull/1913)) +* Fix example block for `gensim.models.Word2Vec` ([@nzw0301](https://github.com/nzw0301), [#1870](https://github.com/RaRe-Technologies/gensim/pull/1876)) +* Fix `doc2vec-lee` notebook ([@numericlee](https://github.com/numericlee), [#1870](https://github.com/RaRe-Technologies/gensim/pull/1870)) +* Store images from `README.md` directly in repository. Fix #1849 ([@ibrahimsharaf](https://github.com/ibrahimsharaf), [#1861](https://github.com/RaRe-Technologies/gensim/pull/1861)) +* Add windows venv activate command to `CONTRIBUTING.md` ([@aneesh-joshi](https://github.com/aneesh-joshi), [#1880](https://github.com/RaRe-Technologies/gensim/pull/1880)) +* Add anaconda-cloud badge. Partial fix #1901 ([@sharanry](https://github.com/sharanry), [#1905](https://github.com/RaRe-Technologies/gensim/pull/1905)) +* Fix docstrings for lsi-related code ([@steremma](https://github.com/steremma), [#1892](https://github.com/RaRe-Technologies/gensim/pull/1892)) +* Fix parameter description of `sg` parameter for `gensim.models.word2vec` ([@mdcclv](https://github.com/mdcclv), [#1919](https://github.com/RaRe-Technologies/gensim/pull/1919)) +* Refactor documentation for `gensim.similarities.docsim` and `MmCorpus-related`. ([@CLearERR](https://github.com/CLearERR) & [@menshikh-iv](https://github.com/menshikh-iv), [#1910](https://github.com/RaRe-Technologies/gensim/pull/1910)) +* Fix docstrings for `gensim.test.utils` ([@yurkai](https://github.com/yurkai) & [@menshikh-iv](https://github.com/menshikh-iv), [#1904](https://github.com/RaRe-Technologies/gensim/pull/1904)) +* Refactor docstrings for `gensim.scripts`. Partial fix #1665 ([@yurkai](https://github.com/yurkai) & [@menshikh-iv](https://github.com/menshikh-iv), [#1792](https://github.com/RaRe-Technologies/gensim/pull/1792)) +* Refactor API reference `gensim.corpora`. Partial fix #1671 ([@CLearERR](https://github.com/CLearERR) & [@menshikh-iv](https://github.com/menshikh-iv), [#1835](https://github.com/RaRe-Technologies/gensim/pull/1835)) +* Fix documentation for `gensim.models.wrappers` ([@kakshay21](https://github.com/kakshay21) & [@menshikh-iv](https://github.com/menshikh-iv), [#1859](https://github.com/RaRe-Technologies/gensim/pull/1859)) +* Fix docstrings for `gensim.interfaces` ([@yurkai](https://github.com/yurkai) & [@menshikh-iv](https://github.com/menshikh-iv), [#1913](https://github.com/RaRe-Technologies/gensim/pull/1913)) ### :warning: Deprecations (will be removed in the next major release) @@ -890,13 +901,13 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst ## 3.3.0, 2018-02-02 :star2: New features: -* Re-designed all "*2vec" implementations (__[@manneshiva](https://github.com/manneshiva)__, [#1777](https://github.com/RaRe-Technologies/gensim/pull/1777)) +* Re-designed all "*2vec" implementations ([@manneshiva](https://github.com/manneshiva), [#1777](https://github.com/RaRe-Technologies/gensim/pull/1777)) - Modular organization of `Word2Vec`, `Doc2Vec`, `FastText`, etc ..., making it easier to add new models in the future and re-use code - Fully backward compatible (even with loading models stored by a previous Gensim version) - [Detailed documentation for the *2vec refactoring project](https://github.com/manneshiva/gensim/wiki/Any2Vec-Refactoring-Summary) * Improve `gensim.scripts.segment_wiki` by retaining interwiki links. Fix #1712 - (__[@steremma](https://github.com/steremma)__, [PR #1839](https://github.com/RaRe-Technologies/gensim/pull/1839)) + ([@steremma](https://github.com/steremma), [PR #1839](https://github.com/RaRe-Technologies/gensim/pull/1839)) - Optionally extract interlinks from Wikipedia pages (use the `--include-interlinks` option). This will output one additional JSON dict for each article: ``` { @@ -937,7 +948,7 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst ``` -* Add support for [SMART notation](https://nlp.stanford.edu/IR-book/html/htmledition/document-and-query-weighting-schemes-1.html) for `TfidfModel`. Fix #1785 (__[@markroxor](https://github.com/markroxor)__, [#1791](https://github.com/RaRe-Technologies/gensim/pull/1791)) +* Add support for [SMART notation](https://nlp.stanford.edu/IR-book/html/htmledition/document-and-query-weighting-schemes-1.html) for `TfidfModel`. Fix #1785 ([@markroxor](https://github.com/markroxor), [#1791](https://github.com/RaRe-Technologies/gensim/pull/1791)) - Natural extension of `TfidfModel` to allow different weighting and normalization schemes ```python from gensim.corpora import Dictionary @@ -961,7 +972,7 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst ``` - [SMART Information Retrieval System (wiki)](https://en.wikipedia.org/wiki/SMART_Information_Retrieval_System) -* Add CircleCI for building Gensim documentation. Fix #1807 (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1822](https://github.com/RaRe-Technologies/gensim/pull/1822)) +* Add CircleCI for building Gensim documentation. Fix #1807 ([@menshikh-iv](https://github.com/menshikh-iv), [#1822](https://github.com/RaRe-Technologies/gensim/pull/1822)) - An easy way to preview the rendered documentation (especially, if don't use Linux) - Go to "Details" link of CircleCI in your PR, click on the "Artifacts" tab, choose the HTML file that you want to view; a new tab will open with the rendered HTML page - Integration with Github, to see the documentation directly from the pull request page @@ -971,47 +982,47 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst :red_circle: Bug fixes: -* Fix import in `get_my_ip`. Fix #1771 (__[@darindf](https://github.com/darindf)__, [#1772](https://github.com/RaRe-Technologies/gensim/pull/1772)) -* Fix tox.ini/setup.cfg configuration (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1815](https://github.com/RaRe-Technologies/gensim/pull/1815)) -* Fix formula in `gensim.summarization.bm25`. Fix #1828 (__[@sj29-innovate](https://github.com/sj29-innovate)__, [#1833](https://github.com/RaRe-Technologies/gensim/pull/1833)) -* Fix the train method of `TranslationMatrix` (__[@robotcator](https://github.com/robotcator)__, [#1838](https://github.com/RaRe-Technologies/gensim/pull/1838)) -* Fix positional params used for `gensim.models.CoherenceModel` in `gensim.models.callbacks` (__[@Alexjmsherman](https://github.com/Alexjmsherman)__, [#1823](https://github.com/RaRe-Technologies/gensim/pull/1823)) -* Fix parameter setting for `FastText.train`. Fix #1818 (__[@sj29-innovate](https://github.com/sj29-innovate)__, [#1837](https://github.com/RaRe-Technologies/gensim/pull/1837)) -* Pin python2 explicitly for building documentation (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1840](https://github.com/RaRe-Technologies/gensim/pull/1840)) -* Remove dispatcher deadlock for distributed LDA (__[@darindf](https://github.com/darindf)__, [#1817](https://github.com/RaRe-Technologies/gensim/pull/1817)) -* Fix `score_function` from `LexicalEntailmentEvaluation`. Fix #1858 (__[@hachibaka](https://github.com/hachibaka)__, [#1863](https://github.com/RaRe-Technologies/gensim/pull/1863)) -* Fix symmetrical case for hellinger distance. Fix #1854 (__[@caiyulun](https://github.com/caiyulun)__, [#1860](https://github.com/RaRe-Technologies/gensim/pull/1860)) -* Remove wrong logging at import. Fix #1706 (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1871](https://github.com/RaRe-Technologies/gensim/pull/1871)) +* Fix import in `get_my_ip`. Fix #1771 ([@darindf](https://github.com/darindf), [#1772](https://github.com/RaRe-Technologies/gensim/pull/1772)) +* Fix tox.ini/setup.cfg configuration ([@menshikh-iv](https://github.com/menshikh-iv), [#1815](https://github.com/RaRe-Technologies/gensim/pull/1815)) +* Fix formula in `gensim.summarization.bm25`. Fix #1828 ([@sj29-innovate](https://github.com/sj29-innovate), [#1833](https://github.com/RaRe-Technologies/gensim/pull/1833)) +* Fix the train method of `TranslationMatrix` ([@robotcator](https://github.com/robotcator), [#1838](https://github.com/RaRe-Technologies/gensim/pull/1838)) +* Fix positional params used for `gensim.models.CoherenceModel` in `gensim.models.callbacks` ([@Alexjmsherman](https://github.com/Alexjmsherman), [#1823](https://github.com/RaRe-Technologies/gensim/pull/1823)) +* Fix parameter setting for `FastText.train`. Fix #1818 ([@sj29-innovate](https://github.com/sj29-innovate), [#1837](https://github.com/RaRe-Technologies/gensim/pull/1837)) +* Pin python2 explicitly for building documentation ([@menshikh-iv](https://github.com/menshikh-iv), [#1840](https://github.com/RaRe-Technologies/gensim/pull/1840)) +* Remove dispatcher deadlock for distributed LDA ([@darindf](https://github.com/darindf), [#1817](https://github.com/RaRe-Technologies/gensim/pull/1817)) +* Fix `score_function` from `LexicalEntailmentEvaluation`. Fix #1858 ([@hachibaka](https://github.com/hachibaka), [#1863](https://github.com/RaRe-Technologies/gensim/pull/1863)) +* Fix symmetrical case for hellinger distance. Fix #1854 ([@caiyulun](https://github.com/caiyulun), [#1860](https://github.com/RaRe-Technologies/gensim/pull/1860)) +* Remove wrong logging at import. Fix #1706 ([@menshikh-iv](https://github.com/menshikh-iv), [#1871](https://github.com/RaRe-Technologies/gensim/pull/1871)) :books: Tutorial and doc improvements: -* Refactor documentation API Reference for `gensim.summarization` (__[@yurkai](https://github.com/yurkai)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1709](https://github.com/RaRe-Technologies/gensim/pull/1709)) -* Fix docstrings for `gensim.similarities.index`. Partial fix #1666 (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1681](https://github.com/RaRe-Technologies/gensim/pull/1681)) -* Fix docstrings for `gensim.models.translation_matrix` (__[@KokuKUSIAKU](https://github.com/KokuKUSIAKU)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1806](https://github.com/RaRe-Technologies/gensim/pull/1806)) -* Fix docstrings for `gensim.models.rpmodel` (__[@jazzmuesli](https://github.com/jazzmuesli)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1802](https://github.com/RaRe-Technologies/gensim/pull/1802)) -* Fix docstrings for `gensim.utils` (__[@kakshay21](https://github.com/kakshay21)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1797](https://github.com/RaRe-Technologies/gensim/pull/1797)) -* Fix docstrings for `gensim.matutils` (__[@Cheukting](https://github.com/Cheukting)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1804](https://github.com/RaRe-Technologies/gensim/pull/1804)) -* Fix docstrings for `gensim.models.logentropy_model` (__[@minggli](https://github.com/minggli)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1803](https://github.com/RaRe-Technologies/gensim/pull/1803)) -* Fix docstrings for `gensim.models.normmodel` (__[@AustenLamacraft](https://github.com/AustenLamacraft)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1805](https://github.com/RaRe-Technologies/gensim/pull/1805)) -* Refactor API reference `gensim.topic_coherence`. Fix #1669 (__[@CLearERR](https://github.com/CLearERR)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1714](https://github.com/RaRe-Technologies/gensim/pull/1714)) -* Fix documentation for `gensim.corpora.dictionary` and `gensim.corpora.hashdictionary`. Partial fix #1671 (__[@CLearERR](https://github.com/CLearERR)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1814](https://github.com/RaRe-Technologies/gensim/pull/1814)) -* Fix documentation for `gensim.corpora`. Partial fix #1671 (__[@anotherbugmaster](https://github.com/anotherbugmaster)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1729](https://github.com/RaRe-Technologies/gensim/pull/1729)) -* Update banner in doc pages (__[@piskvorky](https://github.com/piskvorky)__, [#1865](https://github.com/RaRe-Technologies/gensim/pull/1865)) -* Fix errors in the doc2vec-lee notebook (__[@PeterHamilton](https://github.com/PeterHamilton)__, [#1841](https://github.com/RaRe-Technologies/gensim/pull/1841)) -* Add wordnet mammal train file for Poincare notebook (__[@jayantj](https://github.com/jayantj)__, [#1781](https://github.com/RaRe-Technologies/gensim/pull/1781)) -* Update Poincare notebooks (#1774) (__[@jayantj](https://github.com/jayantj)__, [#1774](https://github.com/RaRe-Technologies/gensim/pull/1774)) -* Update contributing guide. Fix #1786 (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1793](https://github.com/RaRe-Technologies/gensim/pull/1793)) -* Add `model_to_dict` one-liner to word2vec notebook. Fix #1269 (__[@kakshay21](https://github.com/kakshay21)__, [#1776](https://github.com/RaRe-Technologies/gensim/pull/1776)) -* Add word embedding viz to word2vec notebook. Fix #1419 (__[@markroxor](https://github.com/markroxor)__, [#1800](https://github.com/RaRe-Technologies/gensim/pull/1800)) -* Fix description of `sg` parameter for `gensim.models.FastText` (__[@akutuzov](https://github.com/akutuzov)__, [#1801](https://github.com/RaRe-Technologies/gensim/pull/1801)) -* Fix typo in `doc2vec-IMDB`. Fix #1788 (__[@apoorvaeternity](https://github.com/apoorvaeternity)__, [#1796](https://github.com/RaRe-Technologies/gensim/pull/1796)) -* Remove outdated bz2 examples from tutorials[2] (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1868](https://github.com/RaRe-Technologies/gensim/pull/1868)) -* Remove outdated `bz2` + `MmCorpus` examples from tutorials (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1867](https://github.com/RaRe-Technologies/gensim/pull/1867)) +* Refactor documentation API Reference for `gensim.summarization` ([@yurkai](https://github.com/yurkai) & [@menshikh-iv](https://github.com/menshikh-iv), [#1709](https://github.com/RaRe-Technologies/gensim/pull/1709)) +* Fix docstrings for `gensim.similarities.index`. Partial fix #1666 ([@menshikh-iv](https://github.com/menshikh-iv), [#1681](https://github.com/RaRe-Technologies/gensim/pull/1681)) +* Fix docstrings for `gensim.models.translation_matrix` ([@KokuKUSIAKU](https://github.com/KokuKUSIAKU) & [@menshikh-iv](https://github.com/menshikh-iv), [#1806](https://github.com/RaRe-Technologies/gensim/pull/1806)) +* Fix docstrings for `gensim.models.rpmodel` ([@jazzmuesli](https://github.com/jazzmuesli) & [@menshikh-iv](https://github.com/menshikh-iv), [#1802](https://github.com/RaRe-Technologies/gensim/pull/1802)) +* Fix docstrings for `gensim.utils` ([@kakshay21](https://github.com/kakshay21) & [@menshikh-iv](https://github.com/menshikh-iv), [#1797](https://github.com/RaRe-Technologies/gensim/pull/1797)) +* Fix docstrings for `gensim.matutils` ([@Cheukting](https://github.com/Cheukting) & [@menshikh-iv](https://github.com/menshikh-iv), [#1804](https://github.com/RaRe-Technologies/gensim/pull/1804)) +* Fix docstrings for `gensim.models.logentropy_model` ([@minggli](https://github.com/minggli) & [@menshikh-iv](https://github.com/menshikh-iv), [#1803](https://github.com/RaRe-Technologies/gensim/pull/1803)) +* Fix docstrings for `gensim.models.normmodel` ([@AustenLamacraft](https://github.com/AustenLamacraft) & [@menshikh-iv](https://github.com/menshikh-iv), [#1805](https://github.com/RaRe-Technologies/gensim/pull/1805)) +* Refactor API reference `gensim.topic_coherence`. Fix #1669 ([@CLearERR](https://github.com/CLearERR) & [@menshikh-iv](https://github.com/menshikh-iv), [#1714](https://github.com/RaRe-Technologies/gensim/pull/1714)) +* Fix documentation for `gensim.corpora.dictionary` and `gensim.corpora.hashdictionary`. Partial fix #1671 ([@CLearERR](https://github.com/CLearERR) & [@menshikh-iv](https://github.com/menshikh-iv), [#1814](https://github.com/RaRe-Technologies/gensim/pull/1814)) +* Fix documentation for `gensim.corpora`. Partial fix #1671 ([@anotherbugmaster](https://github.com/anotherbugmaster) & [@menshikh-iv](https://github.com/menshikh-iv), [#1729](https://github.com/RaRe-Technologies/gensim/pull/1729)) +* Update banner in doc pages ([@piskvorky](https://github.com/piskvorky), [#1865](https://github.com/RaRe-Technologies/gensim/pull/1865)) +* Fix errors in the doc2vec-lee notebook ([@PeterHamilton](https://github.com/PeterHamilton), [#1841](https://github.com/RaRe-Technologies/gensim/pull/1841)) +* Add wordnet mammal train file for Poincare notebook ([@jayantj](https://github.com/jayantj), [#1781](https://github.com/RaRe-Technologies/gensim/pull/1781)) +* Update Poincare notebooks (#1774) ([@jayantj](https://github.com/jayantj), [#1774](https://github.com/RaRe-Technologies/gensim/pull/1774)) +* Update contributing guide. Fix #1786 ([@menshikh-iv](https://github.com/menshikh-iv), [#1793](https://github.com/RaRe-Technologies/gensim/pull/1793)) +* Add `model_to_dict` one-liner to word2vec notebook. Fix #1269 ([@kakshay21](https://github.com/kakshay21), [#1776](https://github.com/RaRe-Technologies/gensim/pull/1776)) +* Add word embedding viz to word2vec notebook. Fix #1419 ([@markroxor](https://github.com/markroxor), [#1800](https://github.com/RaRe-Technologies/gensim/pull/1800)) +* Fix description of `sg` parameter for `gensim.models.FastText` ([@akutuzov](https://github.com/akutuzov), [#1801](https://github.com/RaRe-Technologies/gensim/pull/1801)) +* Fix typo in `doc2vec-IMDB`. Fix #1788 ([@apoorvaeternity](https://github.com/apoorvaeternity), [#1796](https://github.com/RaRe-Technologies/gensim/pull/1796)) +* Remove outdated bz2 examples from tutorials[2] ([@menshikh-iv](https://github.com/menshikh-iv), [#1868](https://github.com/RaRe-Technologies/gensim/pull/1868)) +* Remove outdated `bz2` + `MmCorpus` examples from tutorials ([@menshikh-iv](https://github.com/menshikh-iv), [#1867](https://github.com/RaRe-Technologies/gensim/pull/1867)) :+1: Improvements: -* Refactor tests for `gensim.corpora.WikiCorpus` (__[@steremma](https://github.com/steremma)__, [#1821](https://github.com/RaRe-Technologies/gensim/pull/1821)) +* Refactor tests for `gensim.corpora.WikiCorpus` ([@steremma](https://github.com/steremma), [#1821](https://github.com/RaRe-Technologies/gensim/pull/1821)) :warning: Deprecations (will be removed in the next major release) @@ -1039,7 +1050,7 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst :star2: New features: -* New download API for corpora and pre-trained models (__[@chaitaliSaini](https://github.com/chaitaliSaini)__ & __[@menshikh-iv](https://github.com/menshikh-iv)__, [#1705](https://github.com/RaRe-Technologies/gensim/pull/1705) & [#1632](https://github.com/RaRe-Technologies/gensim/pull/1632) & [#1492](https://github.com/RaRe-Technologies/gensim/pull/1492)) +* New download API for corpora and pre-trained models ([@chaitaliSaini](https://github.com/chaitaliSaini) & [@menshikh-iv](https://github.com/menshikh-iv), [#1705](https://github.com/RaRe-Technologies/gensim/pull/1705) & [#1632](https://github.com/RaRe-Technologies/gensim/pull/1632) & [#1492](https://github.com/RaRe-Technologies/gensim/pull/1492)) - Download large NLP datasets in one line of Python, then use with memory-efficient data streaming: ```python import gensim.downloader as api @@ -1069,7 +1080,7 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst - [Blog post](https://rare-technologies.com/new-api-for-pretrained-nlp-models-and-datasets-in-gensim/) introducing the API and design decisions. - [Notebook with examples](https://github.com/RaRe-Technologies/gensim/blob/be4500e4f0616ec2864c2ce70cb5d4db4b46512d/docs/notebooks/downloader_api_tutorial.ipynb) -* New model: Poincaré embeddings (__[@jayantj](https://github.com/jayantj)__, [#1696](https://github.com/RaRe-Technologies/gensim/pull/1696) & [#1700](https://github.com/RaRe-Technologies/gensim/pull/1700) & [#1757](https://github.com/RaRe-Technologies/gensim/pull/1757) & [#1734](https://github.com/RaRe-Technologies/gensim/pull/1734)) +* New model: Poincaré embeddings ([@jayantj](https://github.com/jayantj), [#1696](https://github.com/RaRe-Technologies/gensim/pull/1696) & [#1700](https://github.com/RaRe-Technologies/gensim/pull/1700) & [#1757](https://github.com/RaRe-Technologies/gensim/pull/1757) & [#1734](https://github.com/RaRe-Technologies/gensim/pull/1734)) - Embed a graph (taxonomy) in the same way as word2vec embeds words: ```python from gensim.models.poincare import PoincareRelations, PoincareModel @@ -1090,7 +1101,7 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst - [Model introduction and the journey of its implementation](https://rare-technologies.com/implementing-poincare-embeddings/) - [Original paper](https://arxiv.org/abs/1705.08039) on arXiv -* Optimized FastText (__[@manneshiva](https://github.com/manneshiva)__, [#1742](https://github.com/RaRe-Technologies/gensim/pull/1742)) +* Optimized FastText ([@manneshiva](https://github.com/manneshiva), [#1742](https://github.com/RaRe-Technologies/gensim/pull/1742)) - New fast multithreaded implementation of FastText, natively in Python/Cython. Deprecates the existing wrapper for Facebook’s C++ implementation. ```python import gensim.downloader as api @@ -1113,54 +1124,54 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst ``` -* Binary pre-compiled wheels for Windows, OSX and Linux (__[@menshikh-iv](https://github.com/menshikh-iv)__, [MacPython/gensim-wheels/#7](https://github.com/MacPython/gensim-wheels/pull/7)) +* Binary pre-compiled wheels for Windows, OSX and Linux ([@menshikh-iv](https://github.com/menshikh-iv), [MacPython/gensim-wheels/#7](https://github.com/MacPython/gensim-wheels/pull/7)) - Users no longer need to have a C compiler for using the fast (Cythonized) version of word2vec, doc2vec, etc. - Faster Gensim pip installation * Added `DeprecationWarnings` to deprecated methods and parameters, with a clear schedule for removal. :+1: Improvements: -* Add Montemurro and Zanette's entropy based keyword extraction algorithm. Fix #665 (__[@PeteBleackley](https://github.com/PeteBleackley)__, [#1738](https://github.com/RaRe-Technologies/gensim/pull/1738)) -* Fix flake8 E731, E402, refactor tests & sklearn API code. Partial fix #1644 (__[@horpto](https://github.com/horpto)__, [#1689](https://github.com/RaRe-Technologies/gensim/pull/1689)) -* Reduce distribution size. Fix #1698 (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1699](https://github.com/RaRe-Technologies/gensim/pull/1699)) -* Improve `scan_vocab` speed, `build_vocab_from_freq` method (__[@jodevak](https://github.com/jodevak)__, [#1695](https://github.com/RaRe-Technologies/gensim/pull/1695)) -* Improve `segment_wiki` script (__[@piskvorky](https://github.com/piskvorky)__, [#1707](https://github.com/RaRe-Technologies/gensim/pull/1707)) -* Add custom `dtype` support for `LdaModel`. Partially fix #1576 (__[@xelez](https://github.com/xelez)__, [#1656](https://github.com/RaRe-Technologies/gensim/pull/1656)) -* Add `doc2idx` method for `gensim.corpora.Dictionary`. Fix #1634 (__[@roopalgarg](https://github.com/roopalgarg)__, [#1720](https://github.com/RaRe-Technologies/gensim/pull/1720)) -* Add tox and pytest to gensim, integration with Travis and Appveyor. Fix #1613, #1644 (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1721](https://github.com/RaRe-Technologies/gensim/pull/1721)) -* Add flag for hiding outdated data for `gensim.downloader.info` (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1736](https://github.com/RaRe-Technologies/gensim/pull/1736)) -* Add reproducible order between python versions for `gensim.corpora.Dictionary` (__[@formi23](https://github.com/formi23)__, [#1715](https://github.com/RaRe-Technologies/gensim/pull/1715)) -* Update `tox.ini`, `setup.cfg`, `README.md` (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1741](https://github.com/RaRe-Technologies/gensim/pull/1741)) -* Add custom `logsumexp` for `LdaModel` (__[@arlenk](https://github.com/arlenk)__, [#1745](https://github.com/RaRe-Technologies/gensim/pull/1745)) +* Add Montemurro and Zanette's entropy based keyword extraction algorithm. Fix #665 ([@PeteBleackley](https://github.com/PeteBleackley), [#1738](https://github.com/RaRe-Technologies/gensim/pull/1738)) +* Fix flake8 E731, E402, refactor tests & sklearn API code. Partial fix #1644 ([@horpto](https://github.com/horpto), [#1689](https://github.com/RaRe-Technologies/gensim/pull/1689)) +* Reduce distribution size. Fix #1698 ([@menshikh-iv](https://github.com/menshikh-iv), [#1699](https://github.com/RaRe-Technologies/gensim/pull/1699)) +* Improve `scan_vocab` speed, `build_vocab_from_freq` method ([@jodevak](https://github.com/jodevak), [#1695](https://github.com/RaRe-Technologies/gensim/pull/1695)) +* Improve `segment_wiki` script ([@piskvorky](https://github.com/piskvorky), [#1707](https://github.com/RaRe-Technologies/gensim/pull/1707)) +* Add custom `dtype` support for `LdaModel`. Partially fix #1576 ([@xelez](https://github.com/xelez), [#1656](https://github.com/RaRe-Technologies/gensim/pull/1656)) +* Add `doc2idx` method for `gensim.corpora.Dictionary`. Fix #1634 ([@roopalgarg](https://github.com/roopalgarg), [#1720](https://github.com/RaRe-Technologies/gensim/pull/1720)) +* Add tox and pytest to gensim, integration with Travis and Appveyor. Fix #1613, #1644 ([@menshikh-iv](https://github.com/menshikh-iv), [#1721](https://github.com/RaRe-Technologies/gensim/pull/1721)) +* Add flag for hiding outdated data for `gensim.downloader.info` ([@menshikh-iv](https://github.com/menshikh-iv), [#1736](https://github.com/RaRe-Technologies/gensim/pull/1736)) +* Add reproducible order between python versions for `gensim.corpora.Dictionary` ([@formi23](https://github.com/formi23), [#1715](https://github.com/RaRe-Technologies/gensim/pull/1715)) +* Update `tox.ini`, `setup.cfg`, `README.md` ([@menshikh-iv](https://github.com/menshikh-iv), [#1741](https://github.com/RaRe-Technologies/gensim/pull/1741)) +* Add custom `logsumexp` for `LdaModel` ([@arlenk](https://github.com/arlenk), [#1745](https://github.com/RaRe-Technologies/gensim/pull/1745)) :red_circle: Bug fixes: -* Fix ranking formula in `gensim.summarization.bm25`. Fix #1718 (__[@souravsingh](https://github.com/souravsingh)__, [#1726](https://github.com/RaRe-Technologies/gensim/pull/1726)) -* Fixed incompatibility in persistence for `FastText` wrapper. Fix #1642 (__[@chinmayapancholi13](https://github.com/chinmayapancholi13)__, [#1723](https://github.com/RaRe-Technologies/gensim/pull/1723)) -* Fix `gensim.sklearn_api` bug with `documents_columns` parameter. Fix #1676 (__[@chinmayapancholi13](https://github.com/chinmayapancholi13)__, [#1704](https://github.com/RaRe-Technologies/gensim/pull/1704)) -* Fix slowdown of CI, remove pytest-cov (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1728](https://github.com/RaRe-Technologies/gensim/pull/1728)) -* Replace outdated packages in Dockerfile (__[@rbahumi](https://github.com/rbahumi)__, [#1730](https://github.com/RaRe-Technologies/gensim/pull/1730)) -* Replace `num_words` to `topn` in `LdaMallet.show_topics`. Fix #1747 (__[@apoorvaeternity](https://github.com/apoorvaeternity)__, [#1749](https://github.com/RaRe-Technologies/gensim/pull/1749)) -* Fix `os.rename` from `gensim.downloader` when 'src' and 'dst' on different partitions (__[@anotherbugmaster](https://github.com/anotherbugmaster)__, [#1733](https://github.com/RaRe-Technologies/gensim/pull/1733)) -* Fix `DeprecationWarning` from `logsumexp` (__[@dreamgonfly](https://github.com/dreamgonfly)__, [#1703](https://github.com/RaRe-Technologies/gensim/pull/1703)) -* Fix backward compatibility problem in `Phrases.load`. Fix #1751 (__[@alexgarel](https://github.com/alexgarel)__, [#1758](https://github.com/RaRe-Technologies/gensim/pull/1758)) -* Fix `load_word2vec_format` from `FastText`. Fix #1743 (__[@manneshiva](https://github.com/manneshiva)__, [#1755](https://github.com/RaRe-Technologies/gensim/pull/1755)) -* Fix ipython kernel version in `Dockerfile`. Fix #1762 (__[@rbahumi](https://github.com/rbahumi)__, [#1764](https://github.com/RaRe-Technologies/gensim/pull/1764)) -* Fix writing in `segment_wiki` (__[@horpto](https://github.com/horpto)__, [#1763](https://github.com/RaRe-Technologies/gensim/pull/1763)) -* Fix write method of file requires byte-like object in `segment_wiki` (__[@horpto](https://github.com/horpto)__, [#1750](https://github.com/RaRe-Technologies/gensim/pull/1750)) -* Fix incorrect vectors learned during online training for `FastText`. Fix #1752 (__[@manneshiva](https://github.com/manneshiva)__, [#1756](https://github.com/RaRe-Technologies/gensim/pull/1756)) -* Fix `dtype` of `model.wv.syn0_vocab` on updating `vocab` for `FastText`. Fix #1759 (__[@manneshiva](https://github.com/manneshiva)__, [#1760](https://github.com/RaRe-Technologies/gensim/pull/1760)) -* Fix hashing-trick from `FastText.build_vocab`. Fix #1765 (__[@manneshiva](https://github.com/manneshiva)__, [#1768](https://github.com/RaRe-Technologies/gensim/pull/1768)) -* Add explicit `DeprecationWarning` for all outdated stuff. Fix #1753 (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1769](https://github.com/RaRe-Technologies/gensim/pull/1769)) -* Fix epsilon according to `dtype` in `LdaModel` (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1770](https://github.com/RaRe-Technologies/gensim/pull/1770)) +* Fix ranking formula in `gensim.summarization.bm25`. Fix #1718 ([@souravsingh](https://github.com/souravsingh), [#1726](https://github.com/RaRe-Technologies/gensim/pull/1726)) +* Fixed incompatibility in persistence for `FastText` wrapper. Fix #1642 ([@chinmayapancholi13](https://github.com/chinmayapancholi13), [#1723](https://github.com/RaRe-Technologies/gensim/pull/1723)) +* Fix `gensim.sklearn_api` bug with `documents_columns` parameter. Fix #1676 ([@chinmayapancholi13](https://github.com/chinmayapancholi13), [#1704](https://github.com/RaRe-Technologies/gensim/pull/1704)) +* Fix slowdown of CI, remove pytest-cov ([@menshikh-iv](https://github.com/menshikh-iv), [#1728](https://github.com/RaRe-Technologies/gensim/pull/1728)) +* Replace outdated packages in Dockerfile ([@rbahumi](https://github.com/rbahumi), [#1730](https://github.com/RaRe-Technologies/gensim/pull/1730)) +* Replace `num_words` to `topn` in `LdaMallet.show_topics`. Fix #1747 ([@apoorvaeternity](https://github.com/apoorvaeternity), [#1749](https://github.com/RaRe-Technologies/gensim/pull/1749)) +* Fix `os.rename` from `gensim.downloader` when 'src' and 'dst' on different partitions ([@anotherbugmaster](https://github.com/anotherbugmaster), [#1733](https://github.com/RaRe-Technologies/gensim/pull/1733)) +* Fix `DeprecationWarning` from `logsumexp` ([@dreamgonfly](https://github.com/dreamgonfly), [#1703](https://github.com/RaRe-Technologies/gensim/pull/1703)) +* Fix backward compatibility problem in `Phrases.load`. Fix #1751 ([@alexgarel](https://github.com/alexgarel), [#1758](https://github.com/RaRe-Technologies/gensim/pull/1758)) +* Fix `load_word2vec_format` from `FastText`. Fix #1743 ([@manneshiva](https://github.com/manneshiva), [#1755](https://github.com/RaRe-Technologies/gensim/pull/1755)) +* Fix ipython kernel version in `Dockerfile`. Fix #1762 ([@rbahumi](https://github.com/rbahumi), [#1764](https://github.com/RaRe-Technologies/gensim/pull/1764)) +* Fix writing in `segment_wiki` ([@horpto](https://github.com/horpto), [#1763](https://github.com/RaRe-Technologies/gensim/pull/1763)) +* Fix write method of file requires byte-like object in `segment_wiki` ([@horpto](https://github.com/horpto), [#1750](https://github.com/RaRe-Technologies/gensim/pull/1750)) +* Fix incorrect vectors learned during online training for `FastText`. Fix #1752 ([@manneshiva](https://github.com/manneshiva), [#1756](https://github.com/RaRe-Technologies/gensim/pull/1756)) +* Fix `dtype` of `model.wv.syn0_vocab` on updating `vocab` for `FastText`. Fix #1759 ([@manneshiva](https://github.com/manneshiva), [#1760](https://github.com/RaRe-Technologies/gensim/pull/1760)) +* Fix hashing-trick from `FastText.build_vocab`. Fix #1765 ([@manneshiva](https://github.com/manneshiva), [#1768](https://github.com/RaRe-Technologies/gensim/pull/1768)) +* Add explicit `DeprecationWarning` for all outdated stuff. Fix #1753 ([@menshikh-iv](https://github.com/menshikh-iv), [#1769](https://github.com/RaRe-Technologies/gensim/pull/1769)) +* Fix epsilon according to `dtype` in `LdaModel` ([@menshikh-iv](https://github.com/menshikh-iv), [#1770](https://github.com/RaRe-Technologies/gensim/pull/1770)) :books: Tutorial and doc improvements: -* Update perf numbers of `segment_wiki` (__[@piskvorky](https://github.com/piskvorky)__, [#1708](https://github.com/RaRe-Technologies/gensim/pull/1708)) -* Update docstring for `gensim.summarization.summarize`. Fix #1575 (__[@fbarrios](https://github.com/fbarrios)__, [#1702](https://github.com/RaRe-Technologies/gensim/pull/1702)) -* Refactor API Reference for `gensim.parsing`. Fix #1664 (__[@CLearERR](https://github.com/CLearERR)__, [#1684](https://github.com/RaRe-Technologies/gensim/pull/1684)) -* Fix typos in doc2vec-wikipedia notebook (__[@youqad](https://github.com/youqad)__, [#1727](https://github.com/RaRe-Technologies/gensim/pull/1727)) -* Fix PyPI long description rendering (__[@edigaryev](https://github.com/edigaryev)__, [#1739](https://github.com/RaRe-Technologies/gensim/pull/1739)) -* Fix twitter badge src (__[@menshikh-iv](https://github.com/menshikh-iv)__) -* Fix maillist badge color (__[@menshikh-iv](https://github.com/menshikh-iv)__) +* Update perf numbers of `segment_wiki` ([@piskvorky](https://github.com/piskvorky), [#1708](https://github.com/RaRe-Technologies/gensim/pull/1708)) +* Update docstring for `gensim.summarization.summarize`. Fix #1575 ([@fbarrios](https://github.com/fbarrios), [#1702](https://github.com/RaRe-Technologies/gensim/pull/1702)) +* Refactor API Reference for `gensim.parsing`. Fix #1664 ([@CLearERR](https://github.com/CLearERR), [#1684](https://github.com/RaRe-Technologies/gensim/pull/1684)) +* Fix typos in doc2vec-wikipedia notebook ([@youqad](https://github.com/youqad), [#1727](https://github.com/RaRe-Technologies/gensim/pull/1727)) +* Fix PyPI long description rendering ([@edigaryev](https://github.com/edigaryev), [#1739](https://github.com/RaRe-Technologies/gensim/pull/1739)) +* Fix twitter badge src ([@menshikh-iv](https://github.com/menshikh-iv)) +* Fix maillist badge color ([@menshikh-iv](https://github.com/menshikh-iv)) :warning: Deprecations (will be removed in the next major release) * Remove @@ -1185,7 +1196,7 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst :star2: New features: -* Massive optimizations to LSI model training (__[@isamaru](https://github.com/isamaru)__, [#1620](https://github.com/RaRe-Technologies/gensim/pull/1620) & [#1622](https://github.com/RaRe-Technologies/gensim/pull/1622)) +* Massive optimizations to LSI model training ([@isamaru](https://github.com/isamaru), [#1620](https://github.com/RaRe-Technologies/gensim/pull/1620) & [#1622](https://github.com/RaRe-Technologies/gensim/pull/1622)) - LSI model allows use of single precision (float32), to consume *40% less memory* while being *40% faster*. - LSI model can now also accept CSC matrix as input, for further memory and speed boost. - Overall, if your entire corpus fits in RAM: 3x faster LSI training (SVD) in 4x less memory! @@ -1203,7 +1214,7 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst ```python model = LsiModel(corpus=streaming_corpus, num_topics=500, dtype=np.float32) ``` -* Add common terms to Phrases. Fix #1258 (__[@alexgarel](https://github.com/alexgarel)__, [#1568](https://github.com/RaRe-Technologies/gensim/pull/1568)) +* Add common terms to Phrases. Fix #1258 ([@alexgarel](https://github.com/alexgarel), [#1568](https://github.com/RaRe-Technologies/gensim/pull/1568)) - Phrases allows to use common terms in bigrams. Before, if you are searching to reveal ngrams like `car_with_driver` and `car_without_driver`, you can either remove stop words before processing, but you will only find `car_driver`, or you won't find any of those forms (because they have three words, but also because high frequency of with will avoid them to be scored correctly), inspired by [ES common grams token filter](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-common-grams-tokenfilter.html). ```python phr_old = Phrases(corpus) @@ -1212,7 +1223,7 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst print(phr_old[["we", "provide", "car", "with", "driver"]]) # ["we", "provide", "car_with", "driver"] print(phr_new[["we", "provide", "car", "with", "driver"]]) # ["we", "provide", "car_with_driver"] ``` -* New [segment_wiki.py](https://github.com/RaRe-Technologies/gensim/blob/develop/gensim/scripts/segment_wiki.py) script (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1483](https://github.com/RaRe-Technologies/gensim/pull/1483) & [#1694](https://github.com/RaRe-Technologies/gensim/pull/1694)) +* New [segment_wiki.py](https://github.com/RaRe-Technologies/gensim/blob/develop/gensim/scripts/segment_wiki.py) script ([@menshikh-iv](https://github.com/menshikh-iv), [#1483](https://github.com/RaRe-Technologies/gensim/pull/1483) & [#1694](https://github.com/RaRe-Technologies/gensim/pull/1694)) - CLI script for processing a raw Wikipedia dump (the xml.bz2 format provided by WikiMedia) to extract its articles in a plain text format. It extracts each article's title, section names and section content and saves them as json-line: ```bash python -m gensim.scripts.segment_wiki -f enwiki-latest-pages-articles.xml.bz2 | gzip > enwiki-latest-pages-articles.json.gz @@ -1230,33 +1241,33 @@ Apart from the **massive overhaul of all Gensim documentation** (including docst ``` :+1: Improvements: -* Speedup FastText tests (__[@horpto](https://github.com/horpto)__, [#1686](https://github.com/RaRe-Technologies/gensim/pull/1686)) -* Add optimization for `SlicedCorpus.__len__` (__[@horpto](https://github.com/horpto)__, [#1679](https://github.com/RaRe-Technologies/gensim/pull/1679)) -* Make `word_vec` return immutable vector. Fix #1651 (__[@CLearERR](https://github.com/CLearERR)__, [#1662](https://github.com/RaRe-Technologies/gensim/pull/1662)) -* Drop Win x32 support & add rolling builds (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1652](https://github.com/RaRe-Technologies/gensim/pull/1652)) -* Fix scoring function in Phrases. Fix #1533, #1635 (__[@michaelwsherman](https://github.com/michaelwsherman)__, [#1573](https://github.com/RaRe-Technologies/gensim/pull/1573)) -* Add configuration for flake8 to setup.cfg (__[@mcobzarenco](https://github.com/mcobzarenco)__, [#1636](https://github.com/RaRe-Technologies/gensim/pull/1636)) -* Add `build_vocab_from_freq` to Word2Vec, speedup scan\_vocab (__[@jodevak](https://github.com/jodevak)__, [#1599](https://github.com/RaRe-Technologies/gensim/pull/1599)) -* Add `most_similar_to_given` method for KeyedVectors (__[@TheMathMajor](https://github.com/TheMathMajor)__, [#1582](https://github.com/RaRe-Technologies/gensim/pull/1582)) -* Add `__getitem__` method to Sparse2Corpus to allow direct queries (__[@isamaru](https://github.com/isamaru)__, [#1621](https://github.com/RaRe-Technologies/gensim/pull/1621)) +* Speedup FastText tests ([@horpto](https://github.com/horpto), [#1686](https://github.com/RaRe-Technologies/gensim/pull/1686)) +* Add optimization for `SlicedCorpus.len` ([@horpto](https://github.com/horpto), [#1679](https://github.com/RaRe-Technologies/gensim/pull/1679)) +* Make `word_vec` return immutable vector. Fix #1651 ([@CLearERR](https://github.com/CLearERR), [#1662](https://github.com/RaRe-Technologies/gensim/pull/1662)) +* Drop Win x32 support & add rolling builds ([@menshikh-iv](https://github.com/menshikh-iv), [#1652](https://github.com/RaRe-Technologies/gensim/pull/1652)) +* Fix scoring function in Phrases. Fix #1533, #1635 ([@michaelwsherman](https://github.com/michaelwsherman), [#1573](https://github.com/RaRe-Technologies/gensim/pull/1573)) +* Add configuration for flake8 to setup.cfg ([@mcobzarenco](https://github.com/mcobzarenco), [#1636](https://github.com/RaRe-Technologies/gensim/pull/1636)) +* Add `build_vocab_from_freq` to Word2Vec, speedup scan\_vocab ([@jodevak](https://github.com/jodevak), [#1599](https://github.com/RaRe-Technologies/gensim/pull/1599)) +* Add `most_similar_to_given` method for KeyedVectors ([@TheMathMajor](https://github.com/TheMathMajor), [#1582](https://github.com/RaRe-Technologies/gensim/pull/1582)) +* Add `getitem` method to Sparse2Corpus to allow direct queries ([@isamaru](https://github.com/isamaru), [#1621](https://github.com/RaRe-Technologies/gensim/pull/1621)) :red_circle: Bug fixes: -* Add single core mode to CoherenceModel. Fix #1683 (__[@horpto](https://github.com/horpto)__, [#1685](https://github.com/RaRe-Technologies/gensim/pull/1685)) -* Fix ResourceWarnings in tests. Partially fix #1519 (__[@horpto](https://github.com/horpto)__, [#1660](https://github.com/RaRe-Technologies/gensim/pull/1660)) -* Fix DeprecationWarnings generated by deprecated assertEquals. Partial fix #1519 (__[@poornagurram](https://github.com/poornagurram)__, [#1658](https://github.com/RaRe-Technologies/gensim/pull/1658)) -* Fix DeprecationWarnings for regex string literals. Fix #1646 (__[@franklsf95](https://github.com/franklsf95)__, [#1649](https://github.com/RaRe-Technologies/gensim/pull/1649)) -* Fix pagerank algorithm. Fix #805 (__[@xelez](https://github.com/xelez)__, [#1653](https://github.com/RaRe-Technologies/gensim/pull/1653)) -* Fix FastText inconsistent dtype. Fix #1637 (__[@mcobzarenco](https://github.com/mcobzarenco)__, [#1638](https://github.com/RaRe-Technologies/gensim/pull/1638)) -* Fix `test_filename_filtering` test (__[@nehaljwani](https://github.com/nehaljwani)__, [#1647](https://github.com/RaRe-Technologies/gensim/pull/1647)) +* Add single core mode to CoherenceModel. Fix #1683 ([@horpto](https://github.com/horpto), [#1685](https://github.com/RaRe-Technologies/gensim/pull/1685)) +* Fix ResourceWarnings in tests. Partially fix #1519 ([@horpto](https://github.com/horpto), [#1660](https://github.com/RaRe-Technologies/gensim/pull/1660)) +* Fix DeprecationWarnings generated by deprecated assertEquals. Partial fix #1519 ([@poornagurram](https://github.com/poornagurram), [#1658](https://github.com/RaRe-Technologies/gensim/pull/1658)) +* Fix DeprecationWarnings for regex string literals. Fix #1646 ([@franklsf95](https://github.com/franklsf95), [#1649](https://github.com/RaRe-Technologies/gensim/pull/1649)) +* Fix pagerank algorithm. Fix #805 ([@xelez](https://github.com/xelez), [#1653](https://github.com/RaRe-Technologies/gensim/pull/1653)) +* Fix FastText inconsistent dtype. Fix #1637 ([@mcobzarenco](https://github.com/mcobzarenco), [#1638](https://github.com/RaRe-Technologies/gensim/pull/1638)) +* Fix `test_filename_filtering` test ([@nehaljwani](https://github.com/nehaljwani), [#1647](https://github.com/RaRe-Technologies/gensim/pull/1647)) :books: Tutorial and doc improvements: -* Fix code/docstring style (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1650](https://github.com/RaRe-Technologies/gensim/pull/1650)) -* Update error message for supervised FastText. Fix #1498 (__[@ElSaico](https://github.com/ElSaico)__, [#1645](https://github.com/RaRe-Technologies/gensim/pull/1645)) -* Add "DOI badge" to README. Fix #1610 (__[@dphov](https://github.com/dphov)__, [#1639](https://github.com/RaRe-Technologies/gensim/pull/1639)) -* Remove duplicate annoy notebook. Fix #1415 (__[@Karamax](https://github.com/Karamax)__, [#1640](https://github.com/RaRe-Technologies/gensim/pull/1640)) -* Fix duplication and wrong markup in docs (__[@horpto](https://github.com/horpto)__, [#1633](https://github.com/RaRe-Technologies/gensim/pull/1633)) -* Refactor dendrogram & topic network notebooks (__[@parulsethi](https://github.com/parulsethi)__, [#1571](https://github.com/RaRe-Technologies/gensim/pull/1571)) -* Fix release badge (__[@menshikh-iv](https://github.com/menshikh-iv)__, [#1631](https://github.com/RaRe-Technologies/gensim/pull/1631)) +* Fix code/docstring style ([@menshikh-iv](https://github.com/menshikh-iv), [#1650](https://github.com/RaRe-Technologies/gensim/pull/1650)) +* Update error message for supervised FastText. Fix #1498 ([@ElSaico](https://github.com/ElSaico), [#1645](https://github.com/RaRe-Technologies/gensim/pull/1645)) +* Add "DOI badge" to README. Fix #1610 ([@dphov](https://github.com/dphov), [#1639](https://github.com/RaRe-Technologies/gensim/pull/1639)) +* Remove duplicate annoy notebook. Fix #1415 ([@Karamax](https://github.com/Karamax), [#1640](https://github.com/RaRe-Technologies/gensim/pull/1640)) +* Fix duplication and wrong markup in docs ([@horpto](https://github.com/horpto), [#1633](https://github.com/RaRe-Technologies/gensim/pull/1633)) +* Refactor dendrogram & topic network notebooks ([@parulsethi](https://github.com/parulsethi), [#1571](https://github.com/RaRe-Technologies/gensim/pull/1571)) +* Fix release badge ([@menshikh-iv](https://github.com/menshikh-iv), [#1631](https://github.com/RaRe-Technologies/gensim/pull/1631)) :warning: Deprecation part (will come into force in the next major release) * Remove @@ -1699,7 +1710,7 @@ Tutorial and doc improvements: * Tutorial: Reproducing Doc2vec paper result on wikipedia. (@isohyt, [#654](https://github.com/RaRe-Technologies/gensim/pull/654)) * Add Save/Load interface to AnnoyIndexer for index persistence (@fortiema, [#845](https://github.com/RaRe-Technologies/gensim/pull/845)) * Fixed issue [#938](https://github.com/RaRe-Technologies/gensim/issues/938),Creating a unified base class for all topic models. ([@markroxor](https://github.com/markroxor), [#946](https://github.com/RaRe-Technologies/gensim/pull/946)) - - _breaking change in HdpTopicFormatter.show_\__topics_ + - breaking change in `HdpTopicFormatter.show_topics` * Add Phraser for Phrases optimization. ( @gojomo & @anujkhare , [#837](https://github.com/RaRe-Technologies/gensim/pull/837)) * Fix issue #743, in word2vec's n_similarity method if at least one empty list is passed ZeroDivisionError is raised (@pranay360, [#883](https://github.com/RaRe-Technologies/gensim/pull/883)) * Change export_phrases in Phrases model. Fix issue #794 (@AadityaJ, [#879](https://github.com/RaRe-Technologies/gensim/pull/879)) diff --git a/release/generate_changelog.py b/release/generate_changelog.py index 2884928d9b..e47f7155e3 100644 --- a/release/generate_changelog.py +++ b/release/generate_changelog.py @@ -35,4 +35,4 @@ def g(): for pr in g(): pr['user_login'] = pr['user']['login'] pr['user_html_url'] = pr['user']['html_url'] - print('* %(title)s [#%(number)d](%(html_url)s), __[@%(user_login)s](%(user_html_url)s)__' % pr) + print('* [#%(number)d](%(html_url)s): %(title)s, by [@%(user_login)s](%(user_html_url)s)' % pr) From c3a6be68bd75f338c4e72992c70a0bf256af29eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Mon, 19 Oct 2020 02:28:52 +0200 Subject: [PATCH 05/20] note the removal of deprecations in CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96b848265c..4ad74b4b0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,7 +47,7 @@ Changes * [#6](https://github.com/RaRe-Technologies/gensim-wheels/pull/6): No more binary wheels for x32 platforms, by [menshikh-iv](https://github.com/menshikh-iv) * [#2926](https://github.com/RaRe-Technologies/gensim/pull/2926): Rename `num_words` to `topn` in dtm_coherence, by [@MeganStodel](https://github.com/MeganStodel) * [#2937](https://github.com/RaRe-Technologies/gensim/pull/2937): Remove Keras dependency, by [@piskvorky](https://github.com/piskvorky) - +* Removed all code, methods, attributes and functions marked as deprecated in 3.8.3. --- From 4afd863db536609573745328dc44ebefae77e6e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Mon, 19 Oct 2020 17:17:11 +0200 Subject: [PATCH 06/20] finish CHANGELOG - except removed modules, pending info from @mpenkov --- CHANGELOG.md | 73 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ad74b4b0b..01ae941972 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,56 @@ Changes ======= -## Unreleased +## 4.0.0beta, Unreleased FIXME 2020-10-?? + +**⚠️ Gensim 4.0 contains breaking API changes! See the [Migration guide](https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4) to update your existing Gensim 3.x code and models.** + +Gensim 4.0 is a major release with lots of performance & robustness improvements and a [new website](https://radimrehurek.com/gensim_4.0.0). + +### Main highlights (see also *👍 Improvements* below) + +* Massively optimized popular algorithms the community has grown to love: [fastText](https://radimrehurek.com/gensim/models/fasttext.html), [word2vec](https://radimrehurek.com/gensim/models/word2vec.html), [doc2vec](https://radimrehurek.com/gensim/models/doc2vec.html), [phrases](https://radimrehurek.com/gensim/models/phrases.html): + a. **Efficiency**. + + | model | 3.8.3: wall time / peak RAM / throughput | 4.0.0: wall time / peak RAM / throughput | + |----------|------------|--------| + | fastText | 2.9h / 4.11 GB / 822k words/s | 2.3h / **1.26 GB** / 914k words/s | + | word2vec | 1.7h / 0.36 GB / 1685k words/s | **1.2h** / 0.33 GB / 1762k words/s | + + In other words, **fastText now needs 3x less RAM** (and is faster); word2vec has 2x faster init (and needs less RAM, and is faster); detecting collocation phrases is 2x faster. ([4.0 benchmarks](https://github.com/RaRe-Technologies/gensim/issues/2887#issuecomment-711097334))) + b. **Robustness**. We fixed a bunch of long-standing bugs by refactoring the internal code structure (see 🔴 Bug fixes below) + c. **Simplified OOP model** for easier model exports and integration with TensorFlow, PyTorch &co. + + Most of these updates come to you transparently aka "for free", but see [Migration guide](https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4) for some changes that break the old Gensim 3.x API. **Update your code accordingly**. + +* Dropped a bunch of externally contributed modules: summarization, pivoted TFIDF normalization, FIXME. + - Code quality was not up to our standards. Also there was no one to maintain them, answer user questions, support these modules. + + So rather than let them rot, we took the hard decision of removing these contributed modules from Gensim. If anyone's interested in maintaining them please fork into your own repo, they can live happily outside of Gensim. + +* Dropped Python 2. Gensim 4.0 is Py3.6+. Read our [Python version support policy](https://github.com/RaRe-Technologies/gensim/wiki/Gensim-And-Compatibility). + - If you still need Python 2 for some reason, stay at [Gensim 3.8.3](https://github.com/RaRe-Technologies/gensim/releases/tag/3.8.3). + +* A new [Gensim website](https://radimrehurek.com/gensim_4.0.0) – finally! 🙃 + +So, a major clean-up release overall. We're happy with this **tighter, leaner and faster Gensim**. + +This is the direction we'll keep going forward: less kitchen-sink of "latest academic algorithms", more focus on robust engineering, targetting common concrete NLP & document similarity use-cases. + +### Why pre-release? + +This 4.0.0beta pre-release is for users who want the cutting edge models: extra performance, bug fixes. Plus users who want to help out, by testing and providing feedback: code, documentation, workflows… Please let us know on the [mailing list](https://groups.google.com/forum/#!forum/gensim)! + +Install the pre-release with: + +```bash +pip install --pre --upgrade gensim +``` + +### What will change between this pre-release and a "full" 4.0 release? + +Production stability is important to Gensim, so we're improving the process of **upgrading already-trained saved models**. There'll be an explicit model upgrade script between each `4.n` to `4.(n+1)` Gensim release. Check progress [here](https://github.com/RaRe-Technologies/gensim/milestone/3). + ### :+1: Improvements @@ -13,17 +62,8 @@ Changes * [#2976](https://github.com/RaRe-Technologies/gensim/pull/2976): Speed up phrase (collocation) detection, by [@piskvorky](https://github.com/piskvorky) * [#2979](https://github.com/RaRe-Technologies/gensim/pull/2979): Allow skipping common English words in multi-word phrases, by [@piskvorky](https://github.com/piskvorky) * [#2867](https://github.com/RaRe-Technologies/gensim/pull/2867): Expose `max_final_vocab` parameter in fastText constructor, by [@mpenkov](https://github.com/mpenkov) -* [#2891](https://github.com/RaRe-Technologies/gensim/pull/2891): Fix fastText word-vectors with ngrams off, by [@gojomo](https://github.com/gojomo) -* [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Fix similarity bug in NMSLIB indexer, by [@piskvorky](https://github.com/piskvorky) -* [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Fixed deprecation warnings in Annoy integration, by [@piskvorky](https://github.com/piskvorky) -* [#2901](https://github.com/RaRe-Technologies/gensim/pull/2901): Fix inheritance of WikiCorpus from TextCorpus, by [@jenishah](https://github.com/jenishah) -* [#2907](https://github.com/RaRe-Technologies/gensim/pull/2907): Fix doc2vec crash for large sets of doc-vectors, by [@gojomo](https://github.com/gojomo) * [#2931](https://github.com/RaRe-Technologies/gensim/pull/2931): Clear up job queue parameters in word2vec, by [@lunastera](https://github.com/lunastera) * [#2939](https://github.com/RaRe-Technologies/gensim/pull/2939): X2Vec SaveLoad improvements, by [@piskvorky](https://github.com/piskvorky) -* [#2940](https://github.com/RaRe-Technologies/gensim/pull/2940); Fix deprecations in SoftCosineSimilarity, by [@Witiko](https://github.com/Witiko) -* [#2944](https://github.com/RaRe-Technologies/gensim/pull/2944): Fix `save_facebook_model` failure after update-vocab & other initialization streamlining, by [@gojomo](https://github.com/gojomo) -* [#2846](https://github.com/RaRe-Technologies/gensim/pull/2846): Fix for Python 3.9/3.10: remove xml.etree.cElementTree, by [@hugovk](https://github.com/hugovk) - ### :books: Tutorials and docs @@ -40,7 +80,18 @@ Changes * [#2910](https://github.com/RaRe-Technologies/gensim/pull/2910): Refresh docs for run_annoy tutorial, by [@piskvorky](https://github.com/piskvorky) * [#2935](https://github.com/RaRe-Technologies/gensim/pull/2935): Fix "generator" language in word2vec docs, by [@polm](https://github.com/polm)) -### :warning: Removed functionality +### :red_circle: Bug fixes + +* [#2891](https://github.com/RaRe-Technologies/gensim/pull/2891): Fix fastText word-vectors with ngrams off, by [@gojomo](https://github.com/gojomo) +* [#2907](https://github.com/RaRe-Technologies/gensim/pull/2907): Fix doc2vec crash for large sets of doc-vectors, by [@gojomo](https://github.com/gojomo) +* [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Fix similarity bug in NMSLIB indexer, by [@piskvorky](https://github.com/piskvorky) +* [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Fix deprecation warnings in Annoy integration, by [@piskvorky](https://github.com/piskvorky) +* [#2901](https://github.com/RaRe-Technologies/gensim/pull/2901): Fix inheritance of WikiCorpus from TextCorpus, by [@jenishah](https://github.com/jenishah) +* [#2940](https://github.com/RaRe-Technologies/gensim/pull/2940); Fix deprecations in SoftCosineSimilarity, by [@Witiko](https://github.com/Witiko) +* [#2944](https://github.com/RaRe-Technologies/gensim/pull/2944): Fix `save_facebook_model` failure after update-vocab & other initialization streamlining, by [@gojomo](https://github.com/gojomo) +* [#2846](https://github.com/RaRe-Technologies/gensim/pull/2846): Fix for Python 3.9/3.10: remove `xml.etree.cElementTree`, by [@hugovk](https://github.com/hugovk) + +### :warning: Removed functionality & deprecations * [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Renamed overly broad `similarities.index` to the more appropriate `similarities.annoy`, by [@piskvorky](https://github.com/piskvorky) * [#2958](https://github.com/RaRe-Technologies/gensim/pull/2958): Remove gensim.summarization subpackage, docs and test data, by [@mpenkov](https://github.com/mpenkov) From a22ba2ed870ec2814000d47c284acd76a3b5d355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Mon, 19 Oct 2020 17:44:12 +0200 Subject: [PATCH 07/20] CHANGELOG formatting fixes --- CHANGELOG.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01ae941972..0945020a66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,27 +1,30 @@ Changes ======= -## 4.0.0beta, Unreleased FIXME 2020-10-?? +## 4.0.0beta, FIXME 2020-10-?? **⚠️ Gensim 4.0 contains breaking API changes! See the [Migration guide](https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4) to update your existing Gensim 3.x code and models.** -Gensim 4.0 is a major release with lots of performance & robustness improvements and a [new website](https://radimrehurek.com/gensim_4.0.0). +Gensim 4.0 is a major release with lots of performance & robustness improvements and a new website. ### Main highlights (see also *👍 Improvements* below) * Massively optimized popular algorithms the community has grown to love: [fastText](https://radimrehurek.com/gensim/models/fasttext.html), [word2vec](https://radimrehurek.com/gensim/models/word2vec.html), [doc2vec](https://radimrehurek.com/gensim/models/doc2vec.html), [phrases](https://radimrehurek.com/gensim/models/phrases.html): - a. **Efficiency**. + + a. **Efficiency** | model | 3.8.3: wall time / peak RAM / throughput | 4.0.0: wall time / peak RAM / throughput | |----------|------------|--------| | fastText | 2.9h / 4.11 GB / 822k words/s | 2.3h / **1.26 GB** / 914k words/s | | word2vec | 1.7h / 0.36 GB / 1685k words/s | **1.2h** / 0.33 GB / 1762k words/s | - In other words, **fastText now needs 3x less RAM** (and is faster); word2vec has 2x faster init (and needs less RAM, and is faster); detecting collocation phrases is 2x faster. ([4.0 benchmarks](https://github.com/RaRe-Technologies/gensim/issues/2887#issuecomment-711097334))) + In other words, fastText now needs 3x less RAM (and is faster); word2vec has 2x faster init (and needs less RAM, and is faster); detecting collocation phrases is 2x faster. ([4.0 benchmarks](https://github.com/RaRe-Technologies/gensim/issues/2887#issuecomment-711097334)) + b. **Robustness**. We fixed a bunch of long-standing bugs by refactoring the internal code structure (see 🔴 Bug fixes below) + c. **Simplified OOP model** for easier model exports and integration with TensorFlow, PyTorch &co. - Most of these updates come to you transparently aka "for free", but see [Migration guide](https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4) for some changes that break the old Gensim 3.x API. **Update your code accordingly**. + These improvements come to you transparently aka "for free", but see [Migration guide](https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4) for some changes that break the old Gensim 3.x API. **Update your code accordingly**. * Dropped a bunch of externally contributed modules: summarization, pivoted TFIDF normalization, FIXME. - Code quality was not up to our standards. Also there was no one to maintain them, answer user questions, support these modules. @@ -39,7 +42,7 @@ This is the direction we'll keep going forward: less kitchen-sink of "latest aca ### Why pre-release? -This 4.0.0beta pre-release is for users who want the cutting edge models: extra performance, bug fixes. Plus users who want to help out, by testing and providing feedback: code, documentation, workflows… Please let us know on the [mailing list](https://groups.google.com/forum/#!forum/gensim)! +This 4.0.0beta pre-release is for users who want the **cutting edge performance and bug fixes**. Plus users who want to help out, by **testing and providing feedback**: code, documentation, workflows… Please let us know on the [mailing list](https://groups.google.com/forum/#!forum/gensim)! Install the pre-release with: @@ -73,12 +76,12 @@ Production stability is important to Gensim, so we're improving the process of * * [#2968](https://github.com/RaRe-Technologies/gensim/pull/2968): Migrate tutorials & how-tos to 4.0.0, by [@piskvorky](https://github.com/piskvorky) * [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Clean up of language and formatting of docstrings, by [@piskvorky](https://github.com/piskvorky) * [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Added documentation for NMSLIB indexer, by [@piskvorky](https://github.com/piskvorky) -* [#2832](https://github.com/RaRe-Technologies/gensim/pull/2832): Clear up LdaModel documentation - remove claim that it accepts CSC matrix as input, by [@FyzHsn](https://github.com/FyzHsn) +* [#2832](https://github.com/RaRe-Technologies/gensim/pull/2832): Clear up LdaModel documentation by [@FyzHsn](https://github.com/FyzHsn) * [#2871](https://github.com/RaRe-Technologies/gensim/pull/2871): Clarify that license is LGPL-2.1, by [@pombredanne](https://github.com/pombredanne) * [#2896](https://github.com/RaRe-Technologies/gensim/pull/2896): Make docs clearer on `alpha` parameter in LDA model, by [@xh2](https://github.com/xh2) * [#2897](https://github.com/RaRe-Technologies/gensim/pull/2897): Update Hoffman paper link for Online LDA, by [@xh2](https://github.com/xh2) * [#2910](https://github.com/RaRe-Technologies/gensim/pull/2910): Refresh docs for run_annoy tutorial, by [@piskvorky](https://github.com/piskvorky) -* [#2935](https://github.com/RaRe-Technologies/gensim/pull/2935): Fix "generator" language in word2vec docs, by [@polm](https://github.com/polm)) +* [#2935](https://github.com/RaRe-Technologies/gensim/pull/2935): Fix "generator" language in word2vec docs, by [@polm](https://github.com/polm) ### :red_circle: Bug fixes @@ -93,21 +96,20 @@ Production stability is important to Gensim, so we're improving the process of * ### :warning: Removed functionality & deprecations +* [#6](https://github.com/RaRe-Technologies/gensim-wheels/pull/6): No more binary wheels for x32 platforms, by [menshikh-iv](https://github.com/menshikh-iv) * [#2899](https://github.com/RaRe-Technologies/gensim/pull/2899): Renamed overly broad `similarities.index` to the more appropriate `similarities.annoy`, by [@piskvorky](https://github.com/piskvorky) * [#2958](https://github.com/RaRe-Technologies/gensim/pull/2958): Remove gensim.summarization subpackage, docs and test data, by [@mpenkov](https://github.com/mpenkov) -* [#6](https://github.com/RaRe-Technologies/gensim-wheels/pull/6): No more binary wheels for x32 platforms, by [menshikh-iv](https://github.com/menshikh-iv) * [#2926](https://github.com/RaRe-Technologies/gensim/pull/2926): Rename `num_words` to `topn` in dtm_coherence, by [@MeganStodel](https://github.com/MeganStodel) * [#2937](https://github.com/RaRe-Technologies/gensim/pull/2937): Remove Keras dependency, by [@piskvorky](https://github.com/piskvorky) -* Removed all code, methods, attributes and functions marked as deprecated in 3.8.3. +* Removed all code, methods, attributes and functions marked as deprecated in [Gensim 3.8.3](https://github.com/RaRe-Technologies/gensim/releases/tag/3.8.3). --- -## :warning: 3.8.x will be the last Gensim version to support Py2.7. Starting with 4.0.0, Gensim will only support Py3.5 and above. - - ## 3.8.3, 2020-05-03 +**:warning: 3.8.x will be the last Gensim version to support Py2.7. Starting with 4.0.0, Gensim will only support Py3.5 and above.** + This is primarily a bugfix release to bring back Py2.7 compatibility to gensim 3.8. ### :red_circle: Bug fixes From 37689bff6519095b1fa4fdb7406cb980477baf0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Sun, 25 Oct 2020 22:34:11 +0100 Subject: [PATCH 08/20] fix outdated docs - found while updating the migration guide --- gensim/models/fasttext.py | 28 ++++++++++++++-------------- gensim/test/test_word2vec.py | 12 ++++++++---- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/gensim/models/fasttext.py b/gensim/models/fasttext.py index 460a1682f5..9876ea9332 100644 --- a/gensim/models/fasttext.py +++ b/gensim/models/fasttext.py @@ -139,7 +139,7 @@ >>> import numpy as np >>> - >>> 'computation' in model.wv.vocab # New word, currently out of vocab + >>> 'computation' in model.wv.key_to_index # New word, currently out of vocab False >>> old_vector = np.copy(model.wv['computation']) # Grab the existing vector >>> new_sentences = [ @@ -157,7 +157,7 @@ >>> new_vector = model.wv['computation'] >>> np.allclose(old_vector, new_vector, atol=1e-4) # Vector has changed, model has learnt something False - >>> 'computation' in model.wv.vocab # Word is still out of vocab + >>> 'computation' in model.wv.key_to_index # Word is still out of vocab False .. Important:: @@ -178,7 +178,7 @@ .. sourcecode:: pycon - >>> 'computer' in fb_model.wv.vocab # New word, currently out of vocab + >>> 'computer' in fb_model.wv.key_to_index # New word, currently out of vocab False >>> old_computer = np.copy(fb_model.wv['computer']) # Calculate current vectors >>> fb_model.build_vocab(new_sentences, update=True) @@ -186,7 +186,7 @@ >>> new_computer = fb_model.wv['computer'] >>> np.allclose(old_computer, new_computer, atol=1e-4) # Vector has changed, model has learnt something False - >>> 'computer' in fb_model.wv.vocab # New word is now in the vocabulary + >>> 'computer' in fb_model.wv.key_to_index # New word is now in the vocabulary True If you do not intend to continue training the model, consider using the @@ -200,25 +200,25 @@ >>> cap_path = datapath("crime-and-punishment.bin") >>> wv = load_facebook_vectors(cap_path) >>> - >>> 'landlord' in wv.vocab # Word is out of vocabulary + >>> 'landlord' in wv.key_to_index # Word is out of vocabulary False - >>> oov_vector = wv['landlord'] + >>> oov_vector = wv['landlord'] # Even OOV words have vectors in FastText >>> - >>> 'landlady' in wv.vocab # Word is in the vocabulary + >>> 'landlady' in wv.key_to_index # Word is in the vocabulary True >>> iv_vector = wv['landlady'] -Retrieve word-vector for vocab and out-of-vocab word: +Retrieve the word-vector for vocab and out-of-vocab word: .. sourcecode:: pycon >>> existent_word = "computer" - >>> existent_word in model.wv.vocab + >>> existent_word in model.wv.key_to_index True >>> computer_vec = model.wv[existent_word] # numpy vector of a word >>> >>> oov_word = "graph-out-of-vocab" - >>> oov_word in model.wv.vocab + >>> oov_word in model.wv.key_to_index False >>> oov_vec = model.wv[oov_word] # numpy vector for OOV word @@ -699,11 +699,11 @@ def load_facebook_model(path, encoding='utf-8'): >>> cap_path = datapath("crime-and-punishment.bin") >>> fb_model = load_facebook_model(cap_path) >>> - >>> 'landlord' in fb_model.wv.vocab # Word is out of vocabulary + >>> 'landlord' in fb_model.wv.key_to_index # Word is out of vocabulary False >>> oov_term = fb_model.wv['landlord'] >>> - >>> 'landlady' in fb_model.wv.vocab # Word is in the vocabulary + >>> 'landlady' in fb_model.wv.key_to_index # Word is in the vocabulary True >>> iv_term = fb_model.wv['landlady'] >>> @@ -764,11 +764,11 @@ def load_facebook_vectors(path, encoding='utf-8'): >>> cap_path = datapath("crime-and-punishment.bin") >>> fbkv = load_facebook_vectors(cap_path) >>> - >>> 'landlord' in fbkv.vocab # Word is out of vocabulary + >>> 'landlord' in fbkv.key_to_index # Word is out of vocabulary False >>> oov_vector = fbkv['landlord'] >>> - >>> 'landlady' in fbkv.vocab # Word is in the vocabulary + >>> 'landlady' in fbkv.key_to_index # Word is in the vocabulary True >>> iv_vector = fbkv['landlady'] diff --git a/gensim/test/test_word2vec.py b/gensim/test/test_word2vec.py index a9e57036f0..c8219cdddd 100644 --- a/gensim/test/test_word2vec.py +++ b/gensim/test/test_word2vec.py @@ -409,8 +409,10 @@ def testPersistenceWord2VecFormatWithVocab(self): testvocab = get_tmpfile('gensim_word2vec.vocab') model.wv.save_word2vec_format(tmpf, testvocab, binary=True) binary_model_with_vocab_kv = keyedvectors.KeyedVectors.load_word2vec_format(tmpf, testvocab, binary=True) - self.assertEqual(model.wv.get_vecattr('human', 'count'), - binary_model_with_vocab_kv.get_vecattr('human', 'count')) + self.assertEqual( + model.wv.get_vecattr('human', 'count'), + binary_model_with_vocab_kv.get_vecattr('human', 'count'), + ) def testPersistenceKeyedVectorsFormatWithVocab(self): """Test storing/loading the entire model and vocabulary in word2vec format.""" @@ -419,8 +421,10 @@ def testPersistenceKeyedVectorsFormatWithVocab(self): testvocab = get_tmpfile('gensim_word2vec.vocab') model.wv.save_word2vec_format(tmpf, testvocab, binary=True) kv_binary_model_with_vocab = keyedvectors.KeyedVectors.load_word2vec_format(tmpf, testvocab, binary=True) - self.assertEqual(model.wv.get_vecattr('human', 'count'), - kv_binary_model_with_vocab.get_vecattr('human', 'count')) + self.assertEqual( + model.wv.get_vecattr('human', 'count'), + kv_binary_model_with_vocab.get_vecattr('human', 'count'), + ) def testPersistenceWord2VecFormatCombinationWithStandardPersistence(self): """Test storing/loading the entire model and vocabulary in word2vec format chained with From 695b6d5782a24e760a3197adab062bb2aa3b2ade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Mon, 26 Oct 2020 10:14:08 +0100 Subject: [PATCH 09/20] update migration hyperlinks --- gensim/models/doc2vec.py | 2 +- gensim/models/fasttext.py | 2 +- gensim/models/keyedvectors.py | 10 +++++----- gensim/models/word2vec.py | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/gensim/models/doc2vec.py b/gensim/models/doc2vec.py index 9d8489657e..453f704401 100644 --- a/gensim/models/doc2vec.py +++ b/gensim/models/doc2vec.py @@ -751,7 +751,7 @@ def save_word2vec_format(self, fname, doctag_vec=False, word_vec=True, prefix='* @deprecated( "Gensim 4.0.0 implemented internal optimizations that make calls to init_sims() unnecessary. " "init_sims() is now obsoleted and will be completely removed in future versions. " - "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4#init_sims" + "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4" ) def init_sims(self, replace=False): """ diff --git a/gensim/models/fasttext.py b/gensim/models/fasttext.py index 9876ea9332..433df55fcd 100644 --- a/gensim/models/fasttext.py +++ b/gensim/models/fasttext.py @@ -541,7 +541,7 @@ def _do_train_job(self, sentences, alpha, inits): @deprecated( "Gensim 4.0.0 implemented internal optimizations that make calls to init_sims() unnecessary. " "init_sims() is now obsoleted and will be completely removed in future versions. " - "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4#init_sims" + "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4" ) def init_sims(self, replace=False): """ diff --git a/gensim/models/keyedvectors.py b/gensim/models/keyedvectors.py index 3a92c24f62..a27aea287b 100644 --- a/gensim/models/keyedvectors.py +++ b/gensim/models/keyedvectors.py @@ -587,7 +587,7 @@ def vectors_norm(self): raise AttributeError( "The `.vectors_norm` attribute is computed dynamically since Gensim 4.0.0. " "Use `.get_normed_vectors()` instead.\n" - "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4#init_sims" + "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4" ) @vectors_norm.setter @@ -625,7 +625,7 @@ def fill_norms(self, force=False): def index2entity(self): raise AttributeError( "The index2entity attribute has been replaced by index_to_key since Gensim 4.0.0.\n" - "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4#init_sims" + "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4" ) @index2entity.setter @@ -636,7 +636,7 @@ def index2entity(self, value): def index2word(self): raise AttributeError( "The index2word attribute has been replaced by index_to_key since Gensim 4.0.0.\n" - "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4#init_sims" + "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4" ) @index2word.setter @@ -649,7 +649,7 @@ def vocab(self): "The vocab attribute was removed from KeyedVector in Gensim 4.0.0.\n" "Use KeyedVector's .key_to_index dict, .index_to_key list, and methods " ".get_vecattr(key, attr) and .set_vecattr(key, attr, new_val) instead.\n" - "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4#init_sims" + "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4" ) @vocab.setter @@ -1435,7 +1435,7 @@ def evaluate_word_pairs( @deprecated( "Use fill_norms() instead. " - "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4#init_sims" + "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4" ) def init_sims(self, replace=False): """Precompute data helpful for bulk similarity calculations. diff --git a/gensim/models/word2vec.py b/gensim/models/word2vec.py index 05b7f43cd6..17efa68b14 100755 --- a/gensim/models/word2vec.py +++ b/gensim/models/word2vec.py @@ -861,7 +861,7 @@ def update_weights(self): @deprecated( "Gensim 4.0.0 implemented internal optimizations that make calls to init_sims() unnecessary. " "init_sims() is now obsoleted and will be completely removed in future versions. " - "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4#init_sims" + "See https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4" ) def init_sims(self, replace=False): """ From 52acca5f85a5779ada3bb641fb67eb0e5fbf0f69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Tue, 27 Oct 2020 18:58:03 +0100 Subject: [PATCH 10/20] fixing fixable FIXMEs, in preparation for 4.0.0beta --- gensim/models/fasttext.py | 10 ++++---- gensim/models/keyedvectors.py | 47 +++++++++++++++++++++-------------- gensim/test/test_fasttext.py | 11 ++++---- gensim/test/test_ldamodel.py | 2 +- gensim/utils.py | 6 ++--- 5 files changed, 43 insertions(+), 33 deletions(-) diff --git a/gensim/models/fasttext.py b/gensim/models/fasttext.py index 433df55fcd..5832330611 100644 --- a/gensim/models/fasttext.py +++ b/gensim/models/fasttext.py @@ -30,7 +30,7 @@ .. sourcecode:: pycon - >>> # from gensim.models import FastText # FIXME: why does Sphinx dislike this import? + >>> from gensim.models import FastText >>> from gensim.test.utils import common_texts # some example sentences >>> >>> print(common_texts[0]) @@ -488,9 +488,9 @@ def estimate_memory(self, vocab_size=None, report=None): hashes = ft_ngram_hashes(word, self.wv.min_n, self.wv.max_n, self.wv.bucket) num_ngrams += len(hashes) # A list (64 bytes) with one np.array (100 bytes) per key, with a total of - # num_ngrams uint32s (4 bytes) amongst them - # Only used during training, not stored with the model - report['buckets_word'] = 64 + (100 * len(self.wv)) + (4 * num_ngrams) # FIXME: caching & calc sensible? + # num_ngrams uint32s (4 bytes) amongst them. + # Only used during training, not stored with the model. + report['buckets_word'] = 64 + (100 * len(self.wv)) + (4 * num_ngrams) # TODO: caching & calc sensible? report['total'] = sum(report.values()) logger.info( "estimated required memory for %i words, %i buckets and %i dimensions: %i bytes", @@ -1193,7 +1193,7 @@ def recalc_char_ngram_buckets(self): Scan the vocabulary, calculate ngrams and their hashes, and cache the list of ngrams for each known word. """ - # FIXME: evaluate if precaching even necessary, compared to recalculating as needed + # TODO: evaluate if precaching even necessary, compared to recalculating as needed. if self.bucket == 0: self.buckets_word = [np.array([], dtype=np.uint32)] * len(self.index_to_key) return diff --git a/gensim/models/keyedvectors.py b/gensim/models/keyedvectors.py index a27aea287b..f39aa181b4 100644 --- a/gensim/models/keyedvectors.py +++ b/gensim/models/keyedvectors.py @@ -215,7 +215,7 @@ def __init__(self, vector_size, count=0, dtype=np.float32, mapfile_path=None): Vector dimensions will default to `np.float32` (AKA `REAL` in some Gensim code) unless another type is provided here. mapfile_path : string, optional - FIXME: UNDER CONSTRUCTION / WILL CHANGE PRE-4.0.0 PER #2955 / #2975 + FIXME: UNDER CONSTRUCTION / WILL CHANGE PRE-4.0.0 PER #2955 / #2975. """ self.vector_size = vector_size # pre-allocating `index_to_key` to full size helps avoid redundant re-allocations, esp for `expandos` @@ -974,7 +974,7 @@ def most_similar_cosmul(self, positive=None, negative=None, topn=10): one-dimensional numpy array with the size of the vocabulary. """ - # FIXME: Update to better match & share code with most_similar() + # TODO: Update to better match & share code with most_similar() if isinstance(topn, Integral) and topn < 1: return [] @@ -1520,45 +1520,52 @@ def save_word2vec_format( (in case word vectors are appended with document vectors afterwards). write_header : bool, optional If False, don't write the 1st line declaring the count of vectors and dimensions. - FIXME: doc prefix, append, sort_attr + prefix : str, optional + String to prepend in front of each stored word. Default = no prefix. + append : bool, optional + If set, open `fname` in `ab` mode instead of the default `wb` mode. + sort_attr : str, optional + Sort the output vectors in descending order of this attribute. Default: most frequent keys first. + """ if total_vec is None: total_vec = len(self.index_to_key) mode = 'wb' if not append else 'ab' - if 'count' in self.expandos: - # if frequency-info available, store in most-to-least-frequent order - store_order_vocab_keys = sorted(self.key_to_index.keys(), key=lambda k: -self.get_vecattr(k, sort_attr)) - else: - store_order_vocab_keys = self.index_to_key + if sort_attr not in self.expandos: + raise ValueError(f"attribute {sort_attr} not present in {self}") + store_order_vocab_keys = sorted(self.key_to_index.keys(), key=lambda k: -self.get_vecattr(k, sort_attr)) if fvocab is not None: logger.info("storing vocabulary in %s", fvocab) with utils.open(fvocab, mode) as vout: for word in store_order_vocab_keys: - vout.write(utils.to_utf8("%s%s %s\n" % (prefix, word, self.get_vecattr(word, sort_attr)))) + vout.write(f"{prefix}{word} {self.get_vecattr(word, sort_attr)}\n") logger.info("storing %sx%s projection weights into %s", total_vec, self.vector_size, fname) assert (len(self.index_to_key), self.vector_size) == self.vectors.shape - # after (possibly-empty) initial range of int-only keys, - # store in sorted order: most frequent keys at the top + # After (possibly-empty) initial range of int-only keys, + # store in sorted order: most frequent keys at the top. + # TODO: is this still relevant in 4.0? What is this about? + # Needs clear comments at the very least. index_id_count = 0 for i, val in enumerate(self.index_to_key): - if not (i == val): + if i != val: break index_id_count += 1 keys_to_write = itertools.chain(range(0, index_id_count), store_order_vocab_keys) + # Store the actual vectors to the output file, in the order defined by sort_attr. with utils.open(fname, mode) as fout: if write_header: - fout.write(utils.to_utf8("%s %s\n" % (total_vec, self.vector_size))) + fout.write(f"{total_vec} {self.vector_size}".encode('utf8')) for key in keys_to_write: - row = self[key] + key_vector = self[key] if binary: row = row.astype(REAL) - fout.write(utils.to_utf8(prefix + str(key)) + b" " + row.tobytes()) + fout.write(f"{prefix}{key} ".encode('utf8') + key_vector.tobytes()) else: - fout.write(utils.to_utf8("%s%s %s\n" % (prefix, str(key), ' '.join(repr(val) for val in row)))) + fout.write(f"{prefix}{key} {' '.join(repr(val) for val in key_vector)}\n".encode('utf8')) @classmethod def load_word2vec_format(cls, fname, fvocab=None, binary=False, encoding='utf8', unicode_errors='strict', @@ -1915,9 +1922,11 @@ def pseudorandom_weak_vector(size, seed_string=None, hashfxn=hash): def prep_vectors(target_shape, prior_vectors=None, seed=0, dtype=REAL): - """FIXME: NAME/DOCS CHANGES PRE-4.0.0 FOR #2955/#2975 MMAP & OTHER INITIALIZATION CLEANUP WORK - Return a numpy array of the given shape. Reuse prior_vectors object or values - to extent possible. Initialize new values randomly if requested.""" + """Return a numpy array of the given shape. Reuse prior_vectors object or values + to extent possible. Initialize new values randomly if requested. + + FIXME: NAME/DOCS CHANGES PRE-4.0.0 FOR #2955/#2975 MMAP & OTHER INITIALIZATION CLEANUP WORK. + """ if prior_vectors is None: prior_vectors = np.zeros((0, 0)) if prior_vectors.shape == target_shape: diff --git a/gensim/test/test_fasttext.py b/gensim/test/test_fasttext.py index 3d3537d03e..4864802b5c 100644 --- a/gensim/test/test_fasttext.py +++ b/gensim/test/test_fasttext.py @@ -18,8 +18,9 @@ from gensim.models.word2vec import LineSentence from gensim.models.fasttext import FastText as FT_gensim, FastTextKeyedVectors, _unpack from gensim.models.keyedvectors import KeyedVectors -from gensim.test.utils import datapath, get_tmpfile, temporary_file, common_texts as sentences, \ - lee_corpus_list as list_corpus +from gensim.test.utils import ( + datapath, get_tmpfile, temporary_file, common_texts as sentences, lee_corpus_list as list_corpus, +) from gensim.test.test_word2vec import TestWord2VecModel import gensim.models._fasttext_bin from gensim.models.fasttext_inner import compute_ngrams, compute_ngrams_bytes, ft_hash_bytes @@ -813,7 +814,7 @@ def test_estimate_memory(self): self.assertEqual(report['syn0_vocab'], 192) self.assertEqual(report['syn1'], 192) self.assertEqual(report['syn1neg'], 192) - # FIXME: these fixed numbers for particular implementation generations encumber changes without real QA + # TODO: these fixed numbers for particular implementation generations encumber changes without real QA # perhaps instead verify reports' total is within some close factor of a deep-audit of actual memory used? self.assertEqual(report['syn0_ngrams'], model.vector_size * np.dtype(np.float32).itemsize * BUCKET) self.assertEqual(report['buckets_word'], 688) @@ -996,10 +997,10 @@ def test_continuation_native(self): self.model_structural_sanity(native) # - # Pick a word that's is in both corpuses. + # Pick a word that is in both corpuses. # Its vectors should be different between training runs. # - word = 'human' # FIXME: this isn't actually in model, except via OOV ngrams + word = 'society' old_vector = native.wv.get_vector(word).tolist() native.train(list_corpus, total_examples=len(list_corpus), epochs=native.epochs) diff --git a/gensim/test/test_ldamodel.py b/gensim/test/test_ldamodel.py index f1c17ac0c9..2b92e3887b 100644 --- a/gensim/test/test_ldamodel.py +++ b/gensim/test/test_ldamodel.py @@ -292,7 +292,7 @@ def testGetDocumentTopics(self): self.assertTrue(isinstance(phi_values, list)) # word_topics looks like this: ({word_id => [topic_id_most_probable, topic_id_second_most_probable, ...]). - # we check one case in word_topics, i.e of the first word in the doc, and it's likely topics. + # we check one case in word_topics, i.e of the first word in the doc, and its likely topics. # FIXME: Fails on osx and win # expected_word = 0 diff --git a/gensim/utils.py b/gensim/utils.py index 49877249f1..ba6171f109 100644 --- a/gensim/utils.py +++ b/gensim/utils.py @@ -1679,9 +1679,9 @@ def lemmatize(content, allowed_tags=re.compile(r'(NN|VB|JJ|RB)'), light=False, import warnings warnings.warn("The light flag is no longer supported by pattern.") - # tokenization in `pattern` is weird; it gets thrown off by non-letters, - # producing '==relate/VBN' or '**/NN'... try to preprocess the text a little - # FIXME this throws away all fancy parsing cues, including sentence structure, + # Tokenization in `pattern` is weird; it gets thrown off by non-letters, + # producing '==relate/VBN' or '**/NN'... try to preprocess the text a little. + # XXX: this throws away all fancy parsing cues, including sentence structure, # abbreviations etc. content = ' '.join(tokenize(content, lower=True, errors='ignore')) From 5cc7359b255c404344198e81d3328dda1cbf7681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Tue, 27 Oct 2020 19:17:19 +0100 Subject: [PATCH 11/20] fixing iter + size in docstrings --- gensim/models/callbacks.py | 2 +- gensim/models/fasttext.py | 11 +---------- gensim/models/keyedvectors.py | 2 +- gensim/models/word2vec.py | 8 ++++---- gensim/models/wrappers/wordrank.py | 3 +-- gensim/scripts/word2vec_standalone.py | 4 ++-- gensim/similarities/annoy.py | 2 +- gensim/similarities/docsim.py | 4 ++-- gensim/similarities/nmslib.py | 4 ++-- gensim/similarities/termsim.py | 2 +- gensim/sklearn_api/d2vmodel.py | 2 +- gensim/test/test_big.py | 2 +- gensim/test/test_d2vmodel.py | 2 +- gensim/topic_coherence/probability_estimation.py | 6 +++--- 14 files changed, 22 insertions(+), 32 deletions(-) diff --git a/gensim/models/callbacks.py b/gensim/models/callbacks.py index cefdd33091..c07f981848 100644 --- a/gensim/models/callbacks.py +++ b/gensim/models/callbacks.py @@ -61,7 +61,7 @@ ... >>> >>> epoch_logger = EpochLogger() - >>> w2v_model = Word2Vec(common_texts, iter=5, size=10, min_count=0, seed=42, callbacks=[epoch_logger]) + >>> w2v_model = Word2Vec(common_texts, epochs=5, vector_size=10, min_count=0, seed=42, callbacks=[epoch_logger]) Epoch #0 start Epoch #0 end Epoch #1 start diff --git a/gensim/models/fasttext.py b/gensim/models/fasttext.py index 5832330611..e83e85ab59 100644 --- a/gensim/models/fasttext.py +++ b/gensim/models/fasttext.py @@ -50,16 +50,7 @@ .. sourcecode:: pycon - >>> model2 = FastText(vector_size=4, window=3, min_count=1, sentences=common_texts, iter=10) - -.. Important:: - This style of initialize-and-train in a single line is **deprecated**. We include it here - for backward compatibility only. - - Please use the initialize-`build_vocab`-`train` pattern above instead, including using `epochs` - instead of `iter`. - The motivation is to simplify the API and resolve naming inconsistencies, - e.g. the iter parameter to the constructor is called epochs in the train function. + >>> model2 = FastText(vector_size=4, window=3, min_count=1, sentences=common_texts, epochs=10) The two models above are instantiated differently, but behave identically. For example, we can compare the embeddings they've calculated for the word "computer": diff --git a/gensim/models/keyedvectors.py b/gensim/models/keyedvectors.py index f39aa181b4..245bc547d5 100644 --- a/gensim/models/keyedvectors.py +++ b/gensim/models/keyedvectors.py @@ -67,7 +67,7 @@ >>> from gensim.test.utils import lee_corpus_list >>> from gensim.models import Word2Vec >>> - >>> model = Word2Vec(lee_corpus_list, size=24, epochs=100) + >>> model = Word2Vec(lee_corpus_list, vector_size=24, epochs=100) >>> word_vectors = model.wv Persist the word vectors to disk with diff --git a/gensim/models/word2vec.py b/gensim/models/word2vec.py index 17efa68b14..1a0879f163 100755 --- a/gensim/models/word2vec.py +++ b/gensim/models/word2vec.py @@ -1856,8 +1856,8 @@ def __str__(self): and learning rate. """ - return "%s(vocab=%s, size=%s, alpha=%s)" % ( - self.__class__.__name__, len(self.wv.index_to_key), self.wv.vector_size, self.alpha + return "%s(vocab=%s, vector_size=%s, alpha=%s)" % ( + self.__class__.__name__, len(self.wv.index_to_key), self.wv.vector_size, self.alpha, ) def save(self, *args, **kwargs): @@ -2259,9 +2259,9 @@ def _assign_binary_codes(wv): corpus = LineSentence(args.train) model = Word2Vec( - corpus, size=args.size, min_count=args.min_count, workers=args.threads, + corpus, vector_size=args.size, min_count=args.min_count, workers=args.threads, window=args.window, sample=args.sample, sg=skipgram, hs=args.hs, - negative=args.negative, cbow_mean=1, iter=args.iter + negative=args.negative, cbow_mean=1, epochs=args.iter, ) if args.output: diff --git a/gensim/models/wrappers/wordrank.py b/gensim/models/wrappers/wordrank.py index ba49d73c14..6de3c256ad 100644 --- a/gensim/models/wrappers/wordrank.py +++ b/gensim/models/wrappers/wordrank.py @@ -49,13 +49,12 @@ import os import copy import multiprocessing +from shutil import copyfile, rmtree from gensim import utils from gensim.models.keyedvectors import KeyedVectors from gensim.scripts.glove2word2vec import glove2word2vec -from shutil import copyfile, rmtree - logger = logging.getLogger(__name__) diff --git a/gensim/scripts/word2vec_standalone.py b/gensim/scripts/word2vec_standalone.py index 57f4d907ba..22be887cd1 100644 --- a/gensim/scripts/word2vec_standalone.py +++ b/gensim/scripts/word2vec_standalone.py @@ -120,9 +120,9 @@ corpus = LineSentence(args.train) model = Word2Vec( - corpus, size=args.size, min_count=args.min_count, workers=args.threads, + corpus, vector_size=args.size, min_count=args.min_count, workers=args.threads, window=args.window, sample=args.sample, alpha=args.alpha, sg=skipgram, - hs=args.hs, negative=args.negative, cbow_mean=1, iter=args.iter + hs=args.hs, negative=args.negative, cbow_mean=1, epochs=args.iter, ) if args.output: diff --git a/gensim/similarities/annoy.py b/gensim/similarities/annoy.py index eaebaaa770..b237c11a99 100644 --- a/gensim/similarities/annoy.py +++ b/gensim/similarities/annoy.py @@ -123,7 +123,7 @@ def load(self, fname): >>> from tempfile import mkstemp >>> >>> sentences = [['cute', 'cat', 'say', 'meow'], ['cute', 'dog', 'say', 'woof']] - >>> model = Word2Vec(sentences, min_count=1, seed=1, iter=10) + >>> model = Word2Vec(sentences, min_count=1, seed=1, epochs=10) >>> >>> indexer = AnnoyIndexer(model, 2) >>> _, temp_fn = mkstemp() diff --git a/gensim/similarities/docsim.py b/gensim/similarities/docsim.py index 14ada07904..bce59620b7 100755 --- a/gensim/similarities/docsim.py +++ b/gensim/similarities/docsim.py @@ -890,7 +890,7 @@ class SoftCosineSimilarity(interfaces.SimilarityABC): >>> from gensim.models import Word2Vec, WordEmbeddingSimilarityIndex >>> from gensim.similarities import SoftCosineSimilarity, SparseTermSimilarityMatrix >>> - >>> model = Word2Vec(common_texts, size=20, min_count=1) # train word-vectors + >>> model = Word2Vec(common_texts, vector_size=20, min_count=1) # train word-vectors >>> termsim_index = WordEmbeddingSimilarityIndex(model.wv) >>> dictionary = Dictionary(common_texts) >>> bow_corpus = [dictionary.doc2bow(document) for document in common_texts] @@ -1006,7 +1006,7 @@ class WmdSimilarity(interfaces.SimilarityABC): >>> from gensim.models import Word2Vec >>> from gensim.similarities import WmdSimilarity >>> - >>> model = Word2Vec(common_texts, size=20, min_count=1) # train word-vectors + >>> model = Word2Vec(common_texts, vector_size=20, min_count=1) # train word-vectors >>> >>> index = WmdSimilarity(common_texts, model) >>> # Make query. diff --git a/gensim/similarities/nmslib.py b/gensim/similarities/nmslib.py index 7ff78539c1..620f32e519 100644 --- a/gensim/similarities/nmslib.py +++ b/gensim/similarities/nmslib.py @@ -26,7 +26,7 @@ >>> from gensim.models import Word2Vec >>> >>> sentences = [['cute', 'cat', 'say', 'meow'], ['cute', 'dog', 'say', 'woof']] - >>> model = Word2Vec(sentences, min_count=1, iter=10, seed=2) + >>> model = Word2Vec(sentences, min_count=1, epochs=10, seed=2) >>> >>> indexer = NmslibIndexer(model) >>> model.wv.most_similar("cat", topn=2, indexer=indexer) @@ -42,7 +42,7 @@ >>> from tempfile import mkstemp >>> >>> sentences = [['cute', 'cat', 'say', 'meow'], ['cute', 'dog', 'say', 'woof']] - >>> model = Word2Vec(sentences, min_count=1, seed=2, iter=10) + >>> model = Word2Vec(sentences, min_count=1, seed=2, epochs=10) >>> >>> indexer = NmslibIndexer(model) >>> _, temp_fn = mkstemp() diff --git a/gensim/similarities/termsim.py b/gensim/similarities/termsim.py index 3949d77960..c047587339 100644 --- a/gensim/similarities/termsim.py +++ b/gensim/similarities/termsim.py @@ -410,7 +410,7 @@ class SparseTermSimilarityMatrix(SaveLoad): >>> from gensim.similarities.index import AnnoyIndexer >>> from scikits.sparse.cholmod import cholesky >>> - >>> model = Word2Vec(common_texts, size=20, min_count=1) # train word-vectors + >>> model = Word2Vec(common_texts, vector_size=20, min_count=1) # train word-vectors >>> annoy = AnnoyIndexer(model, num_trees=2) # use annoy for faster word similarity lookups >>> termsim_index = WordEmbeddingSimilarityIndex(model.wv, kwargs={'indexer': annoy}) >>> dictionary = Dictionary(common_texts) diff --git a/gensim/sklearn_api/d2vmodel.py b/gensim/sklearn_api/d2vmodel.py index 9f01f9818b..660d101131 100644 --- a/gensim/sklearn_api/d2vmodel.py +++ b/gensim/sklearn_api/d2vmodel.py @@ -15,7 +15,7 @@ >>> from gensim.test.utils import common_texts >>> from gensim.sklearn_api import D2VTransformer >>> - >>> model = D2VTransformer(min_count=1, size=5) + >>> model = D2VTransformer(min_count=1, vector_size=5) >>> docvecs = model.fit_transform(common_texts) # represent `common_texts` as vectors """ diff --git a/gensim/test/test_big.py b/gensim/test/test_big.py index f422953d18..d6c5bd9d18 100644 --- a/gensim/test/test_big.py +++ b/gensim/test/test_big.py @@ -46,7 +46,7 @@ class TestLargeData(unittest.TestCase): def testWord2Vec(self): corpus = BigCorpus(words_only=True, num_docs=100000, num_terms=3000000, doc_len=200) tmpf = get_tmpfile('gensim_big.tst') - model = gensim.models.Word2Vec(corpus, size=300, workers=4) + model = gensim.models.Word2Vec(corpus, vector_size=300, workers=4) model.save(tmpf, ignore=['syn1']) del model gensim.models.Word2Vec.load(tmpf) diff --git a/gensim/test/test_d2vmodel.py b/gensim/test/test_d2vmodel.py index 44d3d1612c..aa24203277 100644 --- a/gensim/test/test_d2vmodel.py +++ b/gensim/test/test_d2vmodel.py @@ -48,7 +48,7 @@ def __iter__(self): class TestD2VTransformer(unittest.TestCase): def TestWorksWithIterableNotHavingElementWithZeroIndex(self): a = IterableWithoutZeroElement(common_texts) - transformer = D2VTransformer(min_count=1, size=5) + transformer = D2VTransformer(min_count=1, vector_size=5) transformer.fit(a) diff --git a/gensim/topic_coherence/probability_estimation.py b/gensim/topic_coherence/probability_estimation.py index 27aa95b80d..6296437a94 100644 --- a/gensim/topic_coherence/probability_estimation.py +++ b/gensim/topic_coherence/probability_estimation.py @@ -1,7 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# Copyright (C) 2013 Radim Rehurek # Licensed under the GNU LGPL v2.1 - http://www.gnu.org/licenses/lgpl.html """This module contains functions to perform segmentation on a list of topics.""" @@ -11,7 +10,8 @@ from gensim.topic_coherence.text_analysis import ( CorpusAccumulator, WordOccurrenceAccumulator, ParallelWordOccurrenceAccumulator, - WordVectorsAccumulator) + WordVectorsAccumulator, +) logger = logging.getLogger(__name__) @@ -218,7 +218,7 @@ def p_word2vec(texts, segmented_topics, dictionary, window_size=None, processes= ... ['human', 'interface', 'computer'], ... ['survey', 'user', 'computer', 'system', 'response', 'time'] ... ] - >>> model = word2vec.Word2Vec(sentences, size=100, min_count=1) + >>> model = word2vec.Word2Vec(sentences, vector_size=100, min_count=1) >>> accumulator = probability_estimation.p_word2vec(texts, segmented_topics, dictionary, 2, 1, model) """ From 20f5090b44177fbb2fe74b7d6c447aa87954ea45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Tue, 27 Oct 2020 19:22:22 +0100 Subject: [PATCH 12/20] fix typo --- gensim/models/keyedvectors.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gensim/models/keyedvectors.py b/gensim/models/keyedvectors.py index 245bc547d5..fb95583c07 100644 --- a/gensim/models/keyedvectors.py +++ b/gensim/models/keyedvectors.py @@ -1539,7 +1539,7 @@ def save_word2vec_format( logger.info("storing vocabulary in %s", fvocab) with utils.open(fvocab, mode) as vout: for word in store_order_vocab_keys: - vout.write(f"{prefix}{word} {self.get_vecattr(word, sort_attr)}\n") + vout.write(f"{prefix}{word} {self.get_vecattr(word, sort_attr)}\n".encode('utf8')) logger.info("storing %sx%s projection weights into %s", total_vec, self.vector_size, fname) assert (len(self.index_to_key), self.vector_size) == self.vectors.shape @@ -1558,12 +1558,11 @@ def save_word2vec_format( # Store the actual vectors to the output file, in the order defined by sort_attr. with utils.open(fname, mode) as fout: if write_header: - fout.write(f"{total_vec} {self.vector_size}".encode('utf8')) + fout.write(f"{total_vec} {self.vector_size}\n".encode('utf8')) for key in keys_to_write: key_vector = self[key] if binary: - row = row.astype(REAL) - fout.write(f"{prefix}{key} ".encode('utf8') + key_vector.tobytes()) + fout.write(f"{prefix}{key} ".encode('utf8') + key_vector.astype(REAL).tobytes()) else: fout.write(f"{prefix}{key} {' '.join(repr(val) for val in key_vector)}\n".encode('utf8')) From 65bc446e6a200b6b15a9fe35f5b8fd47f90bba45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Tue, 27 Oct 2020 21:13:54 +0100 Subject: [PATCH 13/20] clean up logic & docs for KeyedVectors.save_word2vec_format --- gensim/models/keyedvectors.py | 49 +++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/gensim/models/keyedvectors.py b/gensim/models/keyedvectors.py index fb95583c07..0e22fe9a46 100644 --- a/gensim/models/keyedvectors.py +++ b/gensim/models/keyedvectors.py @@ -1510,9 +1510,9 @@ def save_word2vec_format( Parameters ---------- fname : str - The file path used to save the vectors in. + File path to save the vectors to. fvocab : str, optional - File path used to save the vocabulary. + File path to save additional vocabulary information to. `None` to not store the vocabulary. binary : bool, optional If True, the data wil be saved in binary word2vec format, else it will be saved in plain text. total_vec : int, optional @@ -1520,6 +1520,7 @@ def save_word2vec_format( (in case word vectors are appended with document vectors afterwards). write_header : bool, optional If False, don't write the 1st line declaring the count of vectors and dimensions. + This is the format used by e.g. gloVe vectors. prefix : str, optional String to prepend in front of each stored word. Default = no prefix. append : bool, optional @@ -1531,9 +1532,20 @@ def save_word2vec_format( if total_vec is None: total_vec = len(self.index_to_key) mode = 'wb' if not append else 'ab' - if sort_attr not in self.expandos: - raise ValueError(f"attribute {sort_attr} not present in {self}") - store_order_vocab_keys = sorted(self.key_to_index.keys(), key=lambda k: -self.get_vecattr(k, sort_attr)) + + if sort_attr in self.expandos: + store_order_vocab_keys = sorted(self.key_to_index.keys(), key=lambda k: -self.get_vecattr(k, sort_attr)) + else: + # This can happen even for the default `count`: the "native C word2vec" format does not store counts, + # so models loaded via load_word2vec_format() do not have the "count" attribute set. They have + # no attributes at all, and fall under this code path. + if fvocab is not None: + raise ValueError(f"Cannot store vocabulary with '{sort_attr}' because that attribute does not exist") + logger.warning( + "attribute %s not present in %s; will store in internal index_to_key order", + sort_attr, self, + ) + store_order_vocab_keys = self.index_to_key if fvocab is not None: logger.info("storing vocabulary in %s", fvocab) @@ -1544,10 +1556,10 @@ def save_word2vec_format( logger.info("storing %sx%s projection weights into %s", total_vec, self.vector_size, fname) assert (len(self.index_to_key), self.vector_size) == self.vectors.shape - # After (possibly-empty) initial range of int-only keys, + # After (possibly-empty) initial range of int-only keys in Doc2Vec, # store in sorted order: most frequent keys at the top. - # TODO: is this still relevant in 4.0? What is this about? - # Needs clear comments at the very least. + # XXX: get rid of this: not used much, too complex and brittle. + # See https://github.com/RaRe-Technologies/gensim/pull/2981#discussion_r512969788 index_id_count = 0 for i, val in enumerate(self.index_to_key): if i != val: @@ -1567,8 +1579,10 @@ def save_word2vec_format( fout.write(f"{prefix}{key} {' '.join(repr(val) for val in key_vector)}\n".encode('utf8')) @classmethod - def load_word2vec_format(cls, fname, fvocab=None, binary=False, encoding='utf8', unicode_errors='strict', - limit=None, datatype=REAL, no_header=False): + def load_word2vec_format( + cls, fname, fvocab=None, binary=False, encoding='utf8', unicode_errors='strict', + limit=None, datatype=REAL, no_header=False, + ): """Load the input-hidden weight matrix from the original C word2vec-tool format. Warnings @@ -1613,7 +1627,8 @@ def load_word2vec_format(cls, fname, fvocab=None, binary=False, encoding='utf8', """ return _load_word2vec_format( cls, fname, fvocab=fvocab, binary=binary, encoding=encoding, unicode_errors=unicode_errors, - limit=limit, datatype=datatype, no_header=no_header) + limit=limit, datatype=datatype, no_header=no_header, + ) def intersect_word2vec_format(self, fname, lockf=0.0, binary=False, encoding='utf8', unicode_errors='strict'): """Merge in an input-hidden weight matrix loaded from the original C word2vec-tool format, @@ -1817,8 +1832,10 @@ def _word2vec_detect_sizes_text(fin, limit, datatype, unicode_errors, encoding): return vocab_size, vector_size -def _load_word2vec_format(cls, fname, fvocab=None, binary=False, encoding='utf8', unicode_errors='strict', - limit=sys.maxsize, datatype=REAL, no_header=False, binary_chunk_size=100 * 1024): +def _load_word2vec_format( + cls, fname, fvocab=None, binary=False, encoding='utf8', unicode_errors='strict', + limit=sys.maxsize, datatype=REAL, no_header=False, binary_chunk_size=100 * 1024, + ): """Load the input-hidden weight matrix from the original C word2vec-tool format. Note that the information stored in the file is incomplete (the binary tree is missing), @@ -1856,7 +1873,6 @@ def _load_word2vec_format(cls, fname, fvocab=None, binary=False, encoding='utf8' Returns the loaded model as an instance of :class:`cls`. """ - counts = None if fvocab is not None: logger.info("loading word counts from %s", fvocab) @@ -1878,15 +1894,14 @@ def _load_word2vec_format(cls, fname, fvocab=None, binary=False, encoding='utf8' fin = utils.open(fname, 'rb') else: header = utils.to_unicode(fin.readline(), encoding=encoding) - vocab_size, vector_size = (int(x) for x in header.split()) # throws for invalid file format + vocab_size, vector_size = [int(x) for x in header.split()] # throws for invalid file format if limit: vocab_size = min(vocab_size, limit) kv = cls(vector_size, vocab_size, dtype=datatype) if binary: _word2vec_read_binary( - fin, kv, counts, - vocab_size, vector_size, datatype, unicode_errors, binary_chunk_size, + fin, kv, counts, vocab_size, vector_size, datatype, unicode_errors, binary_chunk_size, ) else: _word2vec_read_text(fin, kv, counts, vocab_size, vector_size, datatype, unicode_errors, encoding) From 58d7db6d9eee16f90bfd451c7b7934758011d59c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Tue, 27 Oct 2020 23:03:19 +0100 Subject: [PATCH 14/20] flake8 fix --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 1d0c0b0e09..e076698942 100644 --- a/tox.ini +++ b/tox.ini @@ -13,7 +13,7 @@ show-source = True [flake8-rst] filename = *.rst *.py max-line-length = 120 -ignore = F821 ; TODO remove me when all examples in docstrings will be executable +ignore = F821, F401 ; TODO remove me when all examples in docstrings will be executable exclude=.venv, .git, .tox, dist, doc, build, gensim/models/deprecated [pytest] From ad6002f2343ad6c15190d92a2a90e99658b6ea85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Wed, 28 Oct 2020 01:07:55 +0100 Subject: [PATCH 15/20] py3k: `class X(object):` -> `class X:` --- .../core/run_corpora_and_vector_spaces.ipynb | 2 +- .../core/run_corpora_and_vector_spaces.py | 2 +- .../core/run_corpora_and_vector_spaces.py.md5 | 2 +- .../core/run_corpora_and_vector_spaces.rst | 74 ++-- .../auto_examples/core/sg_execution_times.rst | 4 +- .../tutorials/run_word2vec.ipynb | 2 +- .../auto_examples/tutorials/run_word2vec.py | 4 +- .../tutorials/run_word2vec.py.md5 | 2 +- .../auto_examples/tutorials/run_word2vec.rst | 400 +++--------------- .../tutorials/sg_execution_times.rst | 28 +- .../core/run_corpora_and_vector_spaces.py | 2 +- docs/src/gallery/tutorials/run_word2vec.py | 4 +- gensim/examples/dmlcz/dmlcorpus.py | 2 +- gensim/examples/dmlcz/sources.py | 2 +- gensim/matutils.py | 8 +- gensim/models/basemodel.py | 3 +- gensim/models/callbacks.py | 6 +- gensim/models/doc2vec.py | 4 +- gensim/models/hdpmodel.py | 4 +- gensim/models/keyedvectors.py | 2 +- gensim/models/lda_dispatcher.py | 2 +- gensim/models/lda_worker.py | 2 +- gensim/models/lsi_worker.py | 387 +++++++++-------- gensim/models/poincare.py | 12 +- gensim/models/word2vec.py | 8 +- gensim/parsing/porter.py | 2 +- gensim/test/svd_error.py | 2 +- gensim/test/test_big.py | 2 +- gensim/test/test_corpora.py | 2 +- gensim/test/test_probability_estimation.py | 2 +- gensim/test/test_similarities.py | 4 +- gensim/test/test_text_analysis.py | 2 +- gensim/test/utils.py | 2 +- .../indirect_confirmation_measure.py | 2 +- gensim/topic_coherence/text_analysis.py | 2 +- 35 files changed, 350 insertions(+), 640 deletions(-) diff --git a/docs/src/auto_examples/core/run_corpora_and_vector_spaces.ipynb b/docs/src/auto_examples/core/run_corpora_and_vector_spaces.ipynb index 998115a80e..40a3324206 100644 --- a/docs/src/auto_examples/core/run_corpora_and_vector_spaces.ipynb +++ b/docs/src/auto_examples/core/run_corpora_and_vector_spaces.ipynb @@ -152,7 +152,7 @@ }, "outputs": [], "source": [ - "from smart_open import open # for transparently opening remote files\n\n\nclass MyCorpus(object):\n def __iter__(self):\n for line in open('https://radimrehurek.com/gensim/mycorpus.txt'):\n # assume there's one document per line, tokens separated by whitespace\n yield dictionary.doc2bow(line.lower().split())" + "from smart_open import open # for transparently opening remote files\n\n\nclass MyCorpus:\n def __iter__(self):\n for line in open('https://radimrehurek.com/gensim/mycorpus.txt'):\n # assume there's one document per line, tokens separated by whitespace\n yield dictionary.doc2bow(line.lower().split())" ] }, { diff --git a/docs/src/auto_examples/core/run_corpora_and_vector_spaces.py b/docs/src/auto_examples/core/run_corpora_and_vector_spaces.py index 5a77b4e637..0a49614123 100644 --- a/docs/src/auto_examples/core/run_corpora_and_vector_spaces.py +++ b/docs/src/auto_examples/core/run_corpora_and_vector_spaces.py @@ -136,7 +136,7 @@ from smart_open import open # for transparently opening remote files -class MyCorpus(object): +class MyCorpus: def __iter__(self): for line in open('https://radimrehurek.com/gensim/mycorpus.txt'): # assume there's one document per line, tokens separated by whitespace diff --git a/docs/src/auto_examples/core/run_corpora_and_vector_spaces.py.md5 b/docs/src/auto_examples/core/run_corpora_and_vector_spaces.py.md5 index 9e8401aae5..935e0357af 100644 --- a/docs/src/auto_examples/core/run_corpora_and_vector_spaces.py.md5 +++ b/docs/src/auto_examples/core/run_corpora_and_vector_spaces.py.md5 @@ -1 +1 @@ -c239d5c523ea2b3af1f6d4c6c51e7925 \ No newline at end of file +6b98413399bca9fd1ed8fe420da85692 \ No newline at end of file diff --git a/docs/src/auto_examples/core/run_corpora_and_vector_spaces.rst b/docs/src/auto_examples/core/run_corpora_and_vector_spaces.rst index 4b55ff959e..7f8d25cfec 100644 --- a/docs/src/auto_examples/core/run_corpora_and_vector_spaces.rst +++ b/docs/src/auto_examples/core/run_corpora_and_vector_spaces.rst @@ -159,10 +159,10 @@ between the questions and ids is called a dictionary: .. code-block:: none - 2020-10-19 01:23:37,722 : INFO : adding document #0 to Dictionary(0 unique tokens: []) - 2020-10-19 01:23:37,722 : INFO : built Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...) from 9 documents (total 29 corpus positions) - 2020-10-19 01:23:37,722 : INFO : saving Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...) under /tmp/deerwester.dict, separately None - 2020-10-19 01:23:37,723 : INFO : saved /tmp/deerwester.dict + 2020-10-28 00:52:02,550 : INFO : adding document #0 to Dictionary(0 unique tokens: []) + 2020-10-28 00:52:02,550 : INFO : built Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...) from 9 documents (total 29 corpus positions) + 2020-10-28 00:52:02,550 : INFO : saving Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...) under /tmp/deerwester.dict, separately None + 2020-10-28 00:52:02,552 : INFO : saved /tmp/deerwester.dict Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...) @@ -244,11 +244,11 @@ therefore reads: in the document `"Human computer interaction"`, the words `comp .. code-block:: none - 2020-10-19 01:23:38,012 : INFO : storing corpus in Matrix Market format to /tmp/deerwester.mm - 2020-10-19 01:23:38,013 : INFO : saving sparse matrix to /tmp/deerwester.mm - 2020-10-19 01:23:38,013 : INFO : PROGRESS: saving document #0 - 2020-10-19 01:23:38,016 : INFO : saved 9x12 matrix, density=25.926% (28/108) - 2020-10-19 01:23:38,016 : INFO : saving MmCorpus index to /tmp/deerwester.mm.index + 2020-10-28 00:52:02,830 : INFO : storing corpus in Matrix Market format to /tmp/deerwester.mm + 2020-10-28 00:52:02,832 : INFO : saving sparse matrix to /tmp/deerwester.mm + 2020-10-28 00:52:02,832 : INFO : PROGRESS: saving document #0 + 2020-10-28 00:52:02,834 : INFO : saved 9x12 matrix, density=25.926% (28/108) + 2020-10-28 00:52:02,834 : INFO : saving MmCorpus index to /tmp/deerwester.mm.index [[(0, 1), (1, 1), (2, 1)], [(0, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1)], [(2, 1), (5, 1), (7, 1), (8, 1)], [(1, 1), (5, 2), (8, 1)], [(3, 1), (6, 1), (7, 1)], [(9, 1)], [(9, 1), (10, 1)], [(9, 1), (10, 1), (11, 1)], [(4, 1), (10, 1), (11, 1)]] @@ -276,7 +276,7 @@ only requires that a corpus must be able to return one document vector at a time from smart_open import open # for transparently opening remote files - class MyCorpus(object): + class MyCorpus: def __iter__(self): for line in open('https://radimrehurek.com/gensim/mycorpus.txt'): # assume there's one document per line, tokens separated by whitespace @@ -334,7 +334,7 @@ then convert the tokens via a dictionary to their ids and yield the resulting sp .. code-block:: none - <__main__.MyCorpus object at 0x117e06828> + <__main__.MyCorpus object at 0x11e77bb38> @@ -406,8 +406,8 @@ Similarly, to construct the dictionary without loading all texts into memory: .. code-block:: none - 2020-10-19 01:23:38,980 : INFO : adding document #0 to Dictionary(0 unique tokens: []) - 2020-10-19 01:23:38,981 : INFO : built Dictionary(42 unique tokens: ['abc', 'applications', 'computer', 'for', 'human']...) from 9 documents (total 69 corpus positions) + 2020-10-28 00:52:04,241 : INFO : adding document #0 to Dictionary(0 unique tokens: []) + 2020-10-28 00:52:04,243 : INFO : built Dictionary(42 unique tokens: ['abc', 'applications', 'computer', 'for', 'human']...) from 9 documents (total 69 corpus positions) Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...) @@ -454,11 +454,11 @@ create a toy corpus of 2 documents, as a plain Python list .. code-block:: none - 2020-10-19 01:23:39,099 : INFO : storing corpus in Matrix Market format to /tmp/corpus.mm - 2020-10-19 01:23:39,100 : INFO : saving sparse matrix to /tmp/corpus.mm - 2020-10-19 01:23:39,100 : INFO : PROGRESS: saving document #0 - 2020-10-19 01:23:39,101 : INFO : saved 2x2 matrix, density=25.000% (1/4) - 2020-10-19 01:23:39,101 : INFO : saving MmCorpus index to /tmp/corpus.mm.index + 2020-10-28 00:52:04,368 : INFO : storing corpus in Matrix Market format to /tmp/corpus.mm + 2020-10-28 00:52:04,370 : INFO : saving sparse matrix to /tmp/corpus.mm + 2020-10-28 00:52:04,370 : INFO : PROGRESS: saving document #0 + 2020-10-28 00:52:04,370 : INFO : saved 2x2 matrix, density=25.000% (1/4) + 2020-10-28 00:52:04,370 : INFO : saving MmCorpus index to /tmp/corpus.mm.index @@ -486,16 +486,16 @@ Other formats include `Joachim's SVMlight format .. code-block:: none - 2020-10-19 01:23:39,152 : INFO : converting corpus to SVMlight format: /tmp/corpus.svmlight - 2020-10-19 01:23:39,153 : INFO : saving SvmLightCorpus index to /tmp/corpus.svmlight.index - 2020-10-19 01:23:39,154 : INFO : no word id mapping provided; initializing from corpus - 2020-10-19 01:23:39,154 : INFO : storing corpus in Blei's LDA-C format into /tmp/corpus.lda-c - 2020-10-19 01:23:39,154 : INFO : saving vocabulary of 2 words to /tmp/corpus.lda-c.vocab - 2020-10-19 01:23:39,154 : INFO : saving BleiCorpus index to /tmp/corpus.lda-c.index - 2020-10-19 01:23:39,206 : INFO : no word id mapping provided; initializing from corpus - 2020-10-19 01:23:39,207 : INFO : storing corpus in List-Of-Words format into /tmp/corpus.low - 2020-10-19 01:23:39,207 : WARNING : List-of-words format can only save vectors with integer elements; 1 float entries were truncated to integer value - 2020-10-19 01:23:39,207 : INFO : saving LowCorpus index to /tmp/corpus.low.index + 2020-10-28 00:52:04,425 : INFO : converting corpus to SVMlight format: /tmp/corpus.svmlight + 2020-10-28 00:52:04,426 : INFO : saving SvmLightCorpus index to /tmp/corpus.svmlight.index + 2020-10-28 00:52:04,427 : INFO : no word id mapping provided; initializing from corpus + 2020-10-28 00:52:04,427 : INFO : storing corpus in Blei's LDA-C format into /tmp/corpus.lda-c + 2020-10-28 00:52:04,427 : INFO : saving vocabulary of 2 words to /tmp/corpus.lda-c.vocab + 2020-10-28 00:52:04,427 : INFO : saving BleiCorpus index to /tmp/corpus.lda-c.index + 2020-10-28 00:52:04,481 : INFO : no word id mapping provided; initializing from corpus + 2020-10-28 00:52:04,481 : INFO : storing corpus in List-Of-Words format into /tmp/corpus.low + 2020-10-28 00:52:04,482 : WARNING : List-of-words format can only save vectors with integer elements; 1 float entries were truncated to integer value + 2020-10-28 00:52:04,482 : INFO : saving LowCorpus index to /tmp/corpus.low.index @@ -518,9 +518,9 @@ Conversely, to load a corpus iterator from a Matrix Market file: .. code-block:: none - 2020-10-19 01:23:39,260 : INFO : loaded corpus index from /tmp/corpus.mm.index - 2020-10-19 01:23:39,262 : INFO : initializing cython corpus reader from /tmp/corpus.mm - 2020-10-19 01:23:39,262 : INFO : accepted corpus with 2 documents, 2 features, 1 non-zero entries + 2020-10-28 00:52:04,538 : INFO : loaded corpus index from /tmp/corpus.mm.index + 2020-10-28 00:52:04,540 : INFO : initializing cython corpus reader from /tmp/corpus.mm + 2020-10-28 00:52:04,540 : INFO : accepted corpus with 2 documents, 2 features, 1 non-zero entries @@ -619,10 +619,10 @@ To save the same Matrix Market document stream in Blei's LDA-C format, .. code-block:: none - 2020-10-19 01:23:39,634 : INFO : no word id mapping provided; initializing from corpus - 2020-10-19 01:23:39,636 : INFO : storing corpus in Blei's LDA-C format into /tmp/corpus.lda-c - 2020-10-19 01:23:39,636 : INFO : saving vocabulary of 2 words to /tmp/corpus.lda-c.vocab - 2020-10-19 01:23:39,636 : INFO : saving BleiCorpus index to /tmp/corpus.lda-c.index + 2020-10-28 00:52:04,921 : INFO : no word id mapping provided; initializing from corpus + 2020-10-28 00:52:04,922 : INFO : storing corpus in Blei's LDA-C format into /tmp/corpus.lda-c + 2020-10-28 00:52:04,923 : INFO : saving vocabulary of 2 words to /tmp/corpus.lda-c.vocab + 2020-10-28 00:52:04,923 : INFO : saving BleiCorpus index to /tmp/corpus.lda-c.index @@ -710,9 +710,9 @@ Optimize converting between corpora and NumPy/SciPy arrays?), see the :ref:`apir .. rst-class:: sphx-glr-timing - **Total running time of the script:** ( 0 minutes 2.979 seconds) + **Total running time of the script:** ( 0 minutes 4.010 seconds) -**Estimated memory usage:** 39 MB +**Estimated memory usage:** 40 MB .. _sphx_glr_download_auto_examples_core_run_corpora_and_vector_spaces.py: diff --git a/docs/src/auto_examples/core/sg_execution_times.rst b/docs/src/auto_examples/core/sg_execution_times.rst index d346e546cb..9e36b38b09 100644 --- a/docs/src/auto_examples/core/sg_execution_times.rst +++ b/docs/src/auto_examples/core/sg_execution_times.rst @@ -5,10 +5,10 @@ Computation times ================= -**00:02.979** total execution time for **auto_examples_core** files: +**00:04.010** total execution time for **auto_examples_core** files: +--------------------------------------------------------------------------------------------------------------+-----------+---------+ -| :ref:`sphx_glr_auto_examples_core_run_corpora_and_vector_spaces.py` (``run_corpora_and_vector_spaces.py``) | 00:02.979 | 38.7 MB | +| :ref:`sphx_glr_auto_examples_core_run_corpora_and_vector_spaces.py` (``run_corpora_and_vector_spaces.py``) | 00:04.010 | 39.8 MB | +--------------------------------------------------------------------------------------------------------------+-----------+---------+ | :ref:`sphx_glr_auto_examples_core_run_core_concepts.py` (``run_core_concepts.py``) | 00:00.000 | 0.0 MB | +--------------------------------------------------------------------------------------------------------------+-----------+---------+ diff --git a/docs/src/auto_examples/tutorials/run_word2vec.ipynb b/docs/src/auto_examples/tutorials/run_word2vec.ipynb index 9f132e84c9..13f779c2c2 100644 --- a/docs/src/auto_examples/tutorials/run_word2vec.ipynb +++ b/docs/src/auto_examples/tutorials/run_word2vec.ipynb @@ -177,7 +177,7 @@ }, "outputs": [], "source": [ - "from gensim.test.utils import datapath\nfrom gensim import utils\n\nclass MyCorpus(object):\n \"\"\"An interator that yields sentences (lists of str).\"\"\"\n\n def __iter__(self):\n corpus_path = datapath('lee_background.cor')\n for line in open(corpus_path):\n # assume there's one document per line, tokens separated by whitespace\n yield utils.simple_preprocess(line)" + "from gensim.test.utils import datapath\nfrom gensim import utils\n\nclass MyCorpus:\n \"\"\"An iterator that yields sentences (lists of str).\"\"\"\n\n def __iter__(self):\n corpus_path = datapath('lee_background.cor')\n for line in open(corpus_path):\n # assume there's one document per line, tokens separated by whitespace\n yield utils.simple_preprocess(line)" ] }, { diff --git a/docs/src/auto_examples/tutorials/run_word2vec.py b/docs/src/auto_examples/tutorials/run_word2vec.py index 01b0e2bb86..c5ef323bb2 100644 --- a/docs/src/auto_examples/tutorials/run_word2vec.py +++ b/docs/src/auto_examples/tutorials/run_word2vec.py @@ -197,8 +197,8 @@ from gensim.test.utils import datapath from gensim import utils -class MyCorpus(object): - """An interator that yields sentences (lists of str).""" +class MyCorpus: + """An iterator that yields sentences (lists of str).""" def __iter__(self): corpus_path = datapath('lee_background.cor') diff --git a/docs/src/auto_examples/tutorials/run_word2vec.py.md5 b/docs/src/auto_examples/tutorials/run_word2vec.py.md5 index cbd7db4cf6..6d0ea3457b 100644 --- a/docs/src/auto_examples/tutorials/run_word2vec.py.md5 +++ b/docs/src/auto_examples/tutorials/run_word2vec.py.md5 @@ -1 +1 @@ -559f9ed4b873b99bf4882096b146691d \ No newline at end of file +4598eccb1c465c724d8cfa99e216689d \ No newline at end of file diff --git a/docs/src/auto_examples/tutorials/run_word2vec.rst b/docs/src/auto_examples/tutorials/run_word2vec.rst index 7d7ea275e1..dd40ba3ddf 100644 --- a/docs/src/auto_examples/tutorials/run_word2vec.rst +++ b/docs/src/auto_examples/tutorials/run_word2vec.rst @@ -159,15 +159,6 @@ this vector algebra for yourself. That demo runs ``word2vec`` on the -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - 2020-09-30 17:00:40,474 : INFO : loading projection weights from /Users/kofola3/gensim-data/word2vec-google-news-300/word2vec-google-news-300.gz - 2020-09-30 17:01:46,484 : INFO : loaded (3000000, 300) matrix from /Users/kofola3/gensim-data/word2vec-google-news-300/word2vec-google-news-300.gz - @@ -351,8 +342,8 @@ would handle a larger corpus. from gensim.test.utils import datapath from gensim import utils - class MyCorpus(object): - """An interator that yields sentences (lists of str).""" + class MyCorpus: + """An iterator that yields sentences (lists of str).""" def __iter__(self): corpus_path = datapath('lee_background.cor') @@ -364,15 +355,6 @@ would handle a larger corpus. -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - 2020-09-30 17:02:00,362 : INFO : adding document #0 to Dictionary(0 unique tokens: []) - 2020-09-30 17:02:00,366 : INFO : built Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...) from 9 documents (total 29 corpus positions) - @@ -398,46 +380,6 @@ training parameters much for now, we'll revisit them later. -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - 2020-09-30 17:02:00,550 : INFO : collecting all words and their counts - 2020-09-30 17:02:00,551 : INFO : PROGRESS: at sentence #0, processed 0 words, keeping 0 word types - 2020-09-30 17:02:00,657 : INFO : collected 6981 word types from a corpus of 58152 raw words and 300 sentences - 2020-09-30 17:02:00,657 : INFO : Loading a fresh vocabulary - 2020-09-30 17:02:00,668 : INFO : effective_min_count=5 retains 1750 unique words (25% of original 6981, drops 5231) - 2020-09-30 17:02:00,668 : INFO : effective_min_count=5 leaves 49335 word corpus (84% of original 58152, drops 8817) - 2020-09-30 17:02:00,683 : INFO : deleting the raw counts dictionary of 6981 items - 2020-09-30 17:02:00,741 : INFO : sample=0.001 downsamples 51 most-common words - 2020-09-30 17:02:00,741 : INFO : downsampling leaves estimated 35935 word corpus (72.8% of prior 49335) - 2020-09-30 17:02:00,769 : INFO : estimated required memory for 1750 words and 100 dimensions: 2275000 bytes - 2020-09-30 17:02:00,770 : INFO : resetting layer weights - 2020-09-30 17:02:00,875 : INFO : training model with 3 workers on 1750 vocabulary and 100 features, using sg=0 hs=0 sample=0.001 negative=5 window=5 - 2020-09-30 17:02:00,993 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:00,994 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:00,999 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:00,999 : INFO : EPOCH - 1 : training on 58152 raw words (35967 effective words) took 0.1s, 305737 effective words/s - 2020-09-30 17:02:01,099 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:01,103 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:01,106 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:01,106 : INFO : EPOCH - 2 : training on 58152 raw words (35955 effective words) took 0.1s, 343839 effective words/s - 2020-09-30 17:02:01,210 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:01,218 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:01,220 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:01,220 : INFO : EPOCH - 3 : training on 58152 raw words (35878 effective words) took 0.1s, 316674 effective words/s - 2020-09-30 17:02:01,326 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:01,333 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:01,336 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:01,336 : INFO : EPOCH - 4 : training on 58152 raw words (35809 effective words) took 0.1s, 312256 effective words/s - 2020-09-30 17:02:01,434 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:01,438 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:01,441 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:01,441 : INFO : EPOCH - 5 : training on 58152 raw words (35998 effective words) took 0.1s, 344237 effective words/s - 2020-09-30 17:02:01,441 : INFO : training on a 290760 raw words (179607 effective words) took 0.6s, 317010 effective words/s - @@ -522,20 +464,6 @@ You can store/load models using the standard gensim methods: -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - 2020-09-30 17:02:01,737 : INFO : saving Word2Vec object under /var/folders/w0/f7blghz9277068cnyyd3nd200000gn/T/gensim-model-36yeu47d, separately None - 2020-09-30 17:02:01,740 : INFO : not storing attribute cum_table - 2020-09-30 17:02:01,785 : INFO : saved /var/folders/w0/f7blghz9277068cnyyd3nd200000gn/T/gensim-model-36yeu47d - 2020-09-30 17:02:01,786 : INFO : loading Word2Vec object from /var/folders/w0/f7blghz9277068cnyyd3nd200000gn/T/gensim-model-36yeu47d - 2020-09-30 17:02:01,801 : INFO : loading wv recursively from /var/folders/w0/f7blghz9277068cnyyd3nd200000gn/T/gensim-model-36yeu47d.wv.* with mmap=None - 2020-09-30 17:02:01,801 : INFO : setting ignored attribute cum_table to None - 2020-09-30 17:02:01,821 : INFO : loaded /var/folders/w0/f7blghz9277068cnyyd3nd200000gn/T/gensim-model-36yeu47d - @@ -575,46 +503,6 @@ default value of min_count=5 -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - 2020-09-30 17:02:01,918 : INFO : collecting all words and their counts - 2020-09-30 17:02:01,921 : INFO : PROGRESS: at sentence #0, processed 0 words, keeping 0 word types - 2020-09-30 17:02:02,011 : INFO : collected 6981 word types from a corpus of 58152 raw words and 300 sentences - 2020-09-30 17:02:02,011 : INFO : Loading a fresh vocabulary - 2020-09-30 17:02:02,018 : INFO : effective_min_count=10 retains 889 unique words (12% of original 6981, drops 6092) - 2020-09-30 17:02:02,018 : INFO : effective_min_count=10 leaves 43776 word corpus (75% of original 58152, drops 14376) - 2020-09-30 17:02:02,028 : INFO : deleting the raw counts dictionary of 6981 items - 2020-09-30 17:02:02,029 : INFO : sample=0.001 downsamples 55 most-common words - 2020-09-30 17:02:02,029 : INFO : downsampling leaves estimated 29691 word corpus (67.8% of prior 43776) - 2020-09-30 17:02:02,041 : INFO : estimated required memory for 889 words and 100 dimensions: 1155700 bytes - 2020-09-30 17:02:02,041 : INFO : resetting layer weights - 2020-09-30 17:02:02,083 : INFO : training model with 3 workers on 889 vocabulary and 100 features, using sg=0 hs=0 sample=0.001 negative=5 window=5 - 2020-09-30 17:02:02,184 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:02,190 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:02,192 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:02,192 : INFO : EPOCH - 1 : training on 58152 raw words (29629 effective words) took 0.1s, 276020 effective words/s - 2020-09-30 17:02:02,287 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:02,292 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:02,295 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:02,295 : INFO : EPOCH - 2 : training on 58152 raw words (29624 effective words) took 0.1s, 290768 effective words/s - 2020-09-30 17:02:02,394 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:02,397 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:02,400 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:02,400 : INFO : EPOCH - 3 : training on 58152 raw words (29769 effective words) took 0.1s, 286475 effective words/s - 2020-09-30 17:02:02,496 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:02,499 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:02,501 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:02,502 : INFO : EPOCH - 4 : training on 58152 raw words (29578 effective words) took 0.1s, 293835 effective words/s - 2020-09-30 17:02:02,598 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:02,601 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:02,604 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:02,604 : INFO : EPOCH - 5 : training on 58152 raw words (29707 effective words) took 0.1s, 292782 effective words/s - 2020-09-30 17:02:02,604 : INFO : training on a 290760 raw words (148307 effective words) took 0.5s, 284858 effective words/s - @@ -639,46 +527,6 @@ accurate) models. Reasonable values are in the tens to hundreds. -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - 2020-09-30 17:02:02,626 : INFO : collecting all words and their counts - 2020-09-30 17:02:02,628 : INFO : PROGRESS: at sentence #0, processed 0 words, keeping 0 word types - 2020-09-30 17:02:02,722 : INFO : collected 6981 word types from a corpus of 58152 raw words and 300 sentences - 2020-09-30 17:02:02,722 : INFO : Loading a fresh vocabulary - 2020-09-30 17:02:02,734 : INFO : effective_min_count=5 retains 1750 unique words (25% of original 6981, drops 5231) - 2020-09-30 17:02:02,734 : INFO : effective_min_count=5 leaves 49335 word corpus (84% of original 58152, drops 8817) - 2020-09-30 17:02:02,748 : INFO : deleting the raw counts dictionary of 6981 items - 2020-09-30 17:02:02,748 : INFO : sample=0.001 downsamples 51 most-common words - 2020-09-30 17:02:02,748 : INFO : downsampling leaves estimated 35935 word corpus (72.8% of prior 49335) - 2020-09-30 17:02:02,770 : INFO : estimated required memory for 1750 words and 200 dimensions: 3675000 bytes - 2020-09-30 17:02:02,770 : INFO : resetting layer weights - 2020-09-30 17:02:02,864 : INFO : training model with 3 workers on 1750 vocabulary and 200 features, using sg=0 hs=0 sample=0.001 negative=5 window=5 - 2020-09-30 17:02:02,973 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:02,979 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:02,982 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:02,982 : INFO : EPOCH - 1 : training on 58152 raw words (35994 effective words) took 0.1s, 307729 effective words/s - 2020-09-30 17:02:03,087 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:03,093 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:03,097 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:03,097 : INFO : EPOCH - 2 : training on 58152 raw words (35944 effective words) took 0.1s, 317636 effective words/s - 2020-09-30 17:02:03,202 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:03,208 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:03,212 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:03,212 : INFO : EPOCH - 3 : training on 58152 raw words (36007 effective words) took 0.1s, 314282 effective words/s - 2020-09-30 17:02:03,320 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:03,327 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:03,330 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:03,330 : INFO : EPOCH - 4 : training on 58152 raw words (35992 effective words) took 0.1s, 307219 effective words/s - 2020-09-30 17:02:03,436 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:03,442 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:03,445 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:03,446 : INFO : EPOCH - 5 : training on 58152 raw words (36003 effective words) took 0.1s, 314793 effective words/s - 2020-09-30 17:02:03,446 : INFO : training on a 290760 raw words (179940 effective words) took 0.6s, 309327 effective words/s - @@ -701,51 +549,6 @@ is for training parallelization, to speed up training: -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - 2020-09-30 17:02:03,470 : INFO : collecting all words and their counts - 2020-09-30 17:02:03,472 : INFO : PROGRESS: at sentence #0, processed 0 words, keeping 0 word types - 2020-09-30 17:02:03,571 : INFO : collected 6981 word types from a corpus of 58152 raw words and 300 sentences - 2020-09-30 17:02:03,571 : INFO : Loading a fresh vocabulary - 2020-09-30 17:02:03,582 : INFO : effective_min_count=5 retains 1750 unique words (25% of original 6981, drops 5231) - 2020-09-30 17:02:03,582 : INFO : effective_min_count=5 leaves 49335 word corpus (84% of original 58152, drops 8817) - 2020-09-30 17:02:03,595 : INFO : deleting the raw counts dictionary of 6981 items - 2020-09-30 17:02:03,595 : INFO : sample=0.001 downsamples 51 most-common words - 2020-09-30 17:02:03,595 : INFO : downsampling leaves estimated 35935 word corpus (72.8% of prior 49335) - 2020-09-30 17:02:03,616 : INFO : estimated required memory for 1750 words and 100 dimensions: 2275000 bytes - 2020-09-30 17:02:03,616 : INFO : resetting layer weights - 2020-09-30 17:02:03,704 : INFO : training model with 4 workers on 1750 vocabulary and 100 features, using sg=0 hs=0 sample=0.001 negative=5 window=5 - 2020-09-30 17:02:03,809 : INFO : worker thread finished; awaiting finish of 3 more threads - 2020-09-30 17:02:03,810 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:03,810 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:03,815 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:03,816 : INFO : EPOCH - 1 : training on 58152 raw words (35953 effective words) took 0.1s, 326539 effective words/s - 2020-09-30 17:02:03,912 : INFO : worker thread finished; awaiting finish of 3 more threads - 2020-09-30 17:02:03,913 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:03,915 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:03,920 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:03,920 : INFO : EPOCH - 2 : training on 58152 raw words (35895 effective words) took 0.1s, 348415 effective words/s - 2020-09-30 17:02:04,017 : INFO : worker thread finished; awaiting finish of 3 more threads - 2020-09-30 17:02:04,018 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:04,021 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:04,024 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:04,024 : INFO : EPOCH - 3 : training on 58152 raw words (35907 effective words) took 0.1s, 347822 effective words/s - 2020-09-30 17:02:04,127 : INFO : worker thread finished; awaiting finish of 3 more threads - 2020-09-30 17:02:04,127 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:04,128 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:04,134 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:04,134 : INFO : EPOCH - 4 : training on 58152 raw words (35909 effective words) took 0.1s, 333947 effective words/s - 2020-09-30 17:02:04,232 : INFO : worker thread finished; awaiting finish of 3 more threads - 2020-09-30 17:02:04,232 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:04,233 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:04,238 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:04,238 : INFO : EPOCH - 5 : training on 58152 raw words (35957 effective words) took 0.1s, 347693 effective words/s - 2020-09-30 17:02:04,238 : INFO : training on a 290760 raw words (179621 effective words) took 0.5s, 335988 effective words/s - @@ -811,21 +614,8 @@ Gensim supports the same evaluation set, in exactly the same format: .. code-block:: none - 2020-09-30 17:02:04,350 : INFO : Evaluating word analogies for top 300000 words in the model on /Volumes/work/workspace/gensim/trunk/gensim/test/test_data/questions-words.txt - 2020-09-30 17:02:04,358 : INFO : capital-common-countries: 0.0% (0/6) - 2020-09-30 17:02:04,376 : INFO : capital-world: 0.0% (0/2) - 2020-09-30 17:02:04,392 : INFO : family: 0.0% (0/6) - 2020-09-30 17:02:04,409 : INFO : gram3-comparative: 0.0% (0/20) - 2020-09-30 17:02:04,416 : INFO : gram4-superlative: 0.0% (0/12) - 2020-09-30 17:02:04,423 : INFO : gram5-present-participle: 0.0% (0/20) - 2020-09-30 17:02:04,435 : INFO : gram6-nationality-adjective: 0.0% (0/30) - 2020-09-30 17:02:04,445 : INFO : gram7-past-tense: 0.0% (0/20) - 2020-09-30 17:02:04,457 : INFO : gram8-plural: 3.3% (1/30) - 2020-09-30 17:02:04,462 : INFO : Quadruplets with out-of-vocabulary words: 99.3% - 2020-09-30 17:02:04,465 : INFO : NB: analogies containing OOV words were skipped from evaluation! To change this behavior, use "dummy4unknown=True" - 2020-09-30 17:02:04,465 : INFO : Total accuracy: 0.7% (1/146) - (0.00684931506849315, [{'section': 'capital-common-countries', 'correct': [], 'incorrect': [('CANBERRA', 'AUSTRALIA', 'KABUL', 'AFGHANISTAN'), ('CANBERRA', 'AUSTRALIA', 'PARIS', 'FRANCE'), ('KABUL', 'AFGHANISTAN', 'PARIS', 'FRANCE'), ('KABUL', 'AFGHANISTAN', 'CANBERRA', 'AUSTRALIA'), ('PARIS', 'FRANCE', 'CANBERRA', 'AUSTRALIA'), ('PARIS', 'FRANCE', 'KABUL', 'AFGHANISTAN')]}, {'section': 'capital-world', 'correct': [], 'incorrect': [('CANBERRA', 'AUSTRALIA', 'KABUL', 'AFGHANISTAN'), ('KABUL', 'AFGHANISTAN', 'PARIS', 'FRANCE')]}, {'section': 'currency', 'correct': [], 'incorrect': []}, {'section': 'city-in-state', 'correct': [], 'incorrect': []}, {'section': 'family', 'correct': [], 'incorrect': [('HE', 'SHE', 'HIS', 'HER'), ('HE', 'SHE', 'MAN', 'WOMAN'), ('HIS', 'HER', 'MAN', 'WOMAN'), ('HIS', 'HER', 'HE', 'SHE'), ('MAN', 'WOMAN', 'HE', 'SHE'), ('MAN', 'WOMAN', 'HIS', 'HER')]}, {'section': 'gram1-adjective-to-adverb', 'correct': [], 'incorrect': []}, {'section': 'gram2-opposite', 'correct': [], 'incorrect': []}, {'section': 'gram3-comparative', 'correct': [], 'incorrect': [('GOOD', 'BETTER', 'GREAT', 'GREATER'), ('GOOD', 'BETTER', 'LONG', 'LONGER'), ('GOOD', 'BETTER', 'LOW', 'LOWER'), ('GOOD', 'BETTER', 'SMALL', 'SMALLER'), ('GREAT', 'GREATER', 'LONG', 'LONGER'), ('GREAT', 'GREATER', 'LOW', 'LOWER'), ('GREAT', 'GREATER', 'SMALL', 'SMALLER'), ('GREAT', 'GREATER', 'GOOD', 'BETTER'), ('LONG', 'LONGER', 'LOW', 'LOWER'), ('LONG', 'LONGER', 'SMALL', 'SMALLER'), ('LONG', 'LONGER', 'GOOD', 'BETTER'), ('LONG', 'LONGER', 'GREAT', 'GREATER'), ('LOW', 'LOWER', 'SMALL', 'SMALLER'), ('LOW', 'LOWER', 'GOOD', 'BETTER'), ('LOW', 'LOWER', 'GREAT', 'GREATER'), ('LOW', 'LOWER', 'LONG', 'LONGER'), ('SMALL', 'SMALLER', 'GOOD', 'BETTER'), ('SMALL', 'SMALLER', 'GREAT', 'GREATER'), ('SMALL', 'SMALLER', 'LONG', 'LONGER'), ('SMALL', 'SMALLER', 'LOW', 'LOWER')]}, {'section': 'gram4-superlative', 'correct': [], 'incorrect': [('BIG', 'BIGGEST', 'GOOD', 'BEST'), ('BIG', 'BIGGEST', 'GREAT', 'GREATEST'), ('BIG', 'BIGGEST', 'LARGE', 'LARGEST'), ('GOOD', 'BEST', 'GREAT', 'GREATEST'), ('GOOD', 'BEST', 'LARGE', 'LARGEST'), ('GOOD', 'BEST', 'BIG', 'BIGGEST'), ('GREAT', 'GREATEST', 'LARGE', 'LARGEST'), ('GREAT', 'GREATEST', 'BIG', 'BIGGEST'), ('GREAT', 'GREATEST', 'GOOD', 'BEST'), ('LARGE', 'LARGEST', 'BIG', 'BIGGEST'), ('LARGE', 'LARGEST', 'GOOD', 'BEST'), ('LARGE', 'LARGEST', 'GREAT', 'GREATEST')]}, {'section': 'gram5-present-participle', 'correct': [], 'incorrect': [('GO', 'GOING', 'LOOK', 'LOOKING'), ('GO', 'GOING', 'PLAY', 'PLAYING'), ('GO', 'GOING', 'RUN', 'RUNNING'), ('GO', 'GOING', 'SAY', 'SAYING'), ('LOOK', 'LOOKING', 'PLAY', 'PLAYING'), ('LOOK', 'LOOKING', 'RUN', 'RUNNING'), ('LOOK', 'LOOKING', 'SAY', 'SAYING'), ('LOOK', 'LOOKING', 'GO', 'GOING'), ('PLAY', 'PLAYING', 'RUN', 'RUNNING'), ('PLAY', 'PLAYING', 'SAY', 'SAYING'), ('PLAY', 'PLAYING', 'GO', 'GOING'), ('PLAY', 'PLAYING', 'LOOK', 'LOOKING'), ('RUN', 'RUNNING', 'SAY', 'SAYING'), ('RUN', 'RUNNING', 'GO', 'GOING'), ('RUN', 'RUNNING', 'LOOK', 'LOOKING'), ('RUN', 'RUNNING', 'PLAY', 'PLAYING'), ('SAY', 'SAYING', 'GO', 'GOING'), ('SAY', 'SAYING', 'LOOK', 'LOOKING'), ('SAY', 'SAYING', 'PLAY', 'PLAYING'), ('SAY', 'SAYING', 'RUN', 'RUNNING')]}, {'section': 'gram6-nationality-adjective', 'correct': [], 'incorrect': [('AUSTRALIA', 'AUSTRALIAN', 'FRANCE', 'FRENCH'), ('AUSTRALIA', 'AUSTRALIAN', 'INDIA', 'INDIAN'), ('AUSTRALIA', 'AUSTRALIAN', 'ISRAEL', 'ISRAELI'), ('AUSTRALIA', 'AUSTRALIAN', 'JAPAN', 'JAPANESE'), ('AUSTRALIA', 'AUSTRALIAN', 'SWITZERLAND', 'SWISS'), ('FRANCE', 'FRENCH', 'INDIA', 'INDIAN'), ('FRANCE', 'FRENCH', 'ISRAEL', 'ISRAELI'), ('FRANCE', 'FRENCH', 'JAPAN', 'JAPANESE'), ('FRANCE', 'FRENCH', 'SWITZERLAND', 'SWISS'), ('FRANCE', 'FRENCH', 'AUSTRALIA', 'AUSTRALIAN'), ('INDIA', 'INDIAN', 'ISRAEL', 'ISRAELI'), ('INDIA', 'INDIAN', 'JAPAN', 'JAPANESE'), ('INDIA', 'INDIAN', 'SWITZERLAND', 'SWISS'), ('INDIA', 'INDIAN', 'AUSTRALIA', 'AUSTRALIAN'), ('INDIA', 'INDIAN', 'FRANCE', 'FRENCH'), ('ISRAEL', 'ISRAELI', 'JAPAN', 'JAPANESE'), ('ISRAEL', 'ISRAELI', 'SWITZERLAND', 'SWISS'), ('ISRAEL', 'ISRAELI', 'AUSTRALIA', 'AUSTRALIAN'), ('ISRAEL', 'ISRAELI', 'FRANCE', 'FRENCH'), ('ISRAEL', 'ISRAELI', 'INDIA', 'INDIAN'), ('JAPAN', 'JAPANESE', 'SWITZERLAND', 'SWISS'), ('JAPAN', 'JAPANESE', 'AUSTRALIA', 'AUSTRALIAN'), ('JAPAN', 'JAPANESE', 'FRANCE', 'FRENCH'), ('JAPAN', 'JAPANESE', 'INDIA', 'INDIAN'), ('JAPAN', 'JAPANESE', 'ISRAEL', 'ISRAELI'), ('SWITZERLAND', 'SWISS', 'AUSTRALIA', 'AUSTRALIAN'), ('SWITZERLAND', 'SWISS', 'FRANCE', 'FRENCH'), ('SWITZERLAND', 'SWISS', 'INDIA', 'INDIAN'), ('SWITZERLAND', 'SWISS', 'ISRAEL', 'ISRAELI'), ('SWITZERLAND', 'SWISS', 'JAPAN', 'JAPANESE')]}, {'section': 'gram7-past-tense', 'correct': [], 'incorrect': [('GOING', 'WENT', 'PAYING', 'PAID'), ('GOING', 'WENT', 'PLAYING', 'PLAYED'), ('GOING', 'WENT', 'SAYING', 'SAID'), ('GOING', 'WENT', 'TAKING', 'TOOK'), ('PAYING', 'PAID', 'PLAYING', 'PLAYED'), ('PAYING', 'PAID', 'SAYING', 'SAID'), ('PAYING', 'PAID', 'TAKING', 'TOOK'), ('PAYING', 'PAID', 'GOING', 'WENT'), ('PLAYING', 'PLAYED', 'SAYING', 'SAID'), ('PLAYING', 'PLAYED', 'TAKING', 'TOOK'), ('PLAYING', 'PLAYED', 'GOING', 'WENT'), ('PLAYING', 'PLAYED', 'PAYING', 'PAID'), ('SAYING', 'SAID', 'TAKING', 'TOOK'), ('SAYING', 'SAID', 'GOING', 'WENT'), ('SAYING', 'SAID', 'PAYING', 'PAID'), ('SAYING', 'SAID', 'PLAYING', 'PLAYED'), ('TAKING', 'TOOK', 'GOING', 'WENT'), ('TAKING', 'TOOK', 'PAYING', 'PAID'), ('TAKING', 'TOOK', 'PLAYING', 'PLAYED'), ('TAKING', 'TOOK', 'SAYING', 'SAID')]}, {'section': 'gram8-plural', 'correct': [('CAR', 'CARS', 'BUILDING', 'BUILDINGS')], 'incorrect': [('BUILDING', 'BUILDINGS', 'CAR', 'CARS'), ('BUILDING', 'BUILDINGS', 'CHILD', 'CHILDREN'), ('BUILDING', 'BUILDINGS', 'MAN', 'MEN'), ('BUILDING', 'BUILDINGS', 'ROAD', 'ROADS'), ('BUILDING', 'BUILDINGS', 'WOMAN', 'WOMEN'), ('CAR', 'CARS', 'CHILD', 'CHILDREN'), ('CAR', 'CARS', 'MAN', 'MEN'), ('CAR', 'CARS', 'ROAD', 'ROADS'), ('CAR', 'CARS', 'WOMAN', 'WOMEN'), ('CHILD', 'CHILDREN', 'MAN', 'MEN'), ('CHILD', 'CHILDREN', 'ROAD', 'ROADS'), ('CHILD', 'CHILDREN', 'WOMAN', 'WOMEN'), ('CHILD', 'CHILDREN', 'BUILDING', 'BUILDINGS'), ('CHILD', 'CHILDREN', 'CAR', 'CARS'), ('MAN', 'MEN', 'ROAD', 'ROADS'), ('MAN', 'MEN', 'WOMAN', 'WOMEN'), ('MAN', 'MEN', 'BUILDING', 'BUILDINGS'), ('MAN', 'MEN', 'CAR', 'CARS'), ('MAN', 'MEN', 'CHILD', 'CHILDREN'), ('ROAD', 'ROADS', 'WOMAN', 'WOMEN'), ('ROAD', 'ROADS', 'BUILDING', 'BUILDINGS'), ('ROAD', 'ROADS', 'CAR', 'CARS'), ('ROAD', 'ROADS', 'CHILD', 'CHILDREN'), ('ROAD', 'ROADS', 'MAN', 'MEN'), ('WOMAN', 'WOMEN', 'BUILDING', 'BUILDINGS'), ('WOMAN', 'WOMEN', 'CAR', 'CARS'), ('WOMAN', 'WOMEN', 'CHILD', 'CHILDREN'), ('WOMAN', 'WOMEN', 'MAN', 'MEN'), ('WOMAN', 'WOMEN', 'ROAD', 'ROADS')]}, {'section': 'gram9-plural-verbs', 'correct': [], 'incorrect': []}, {'section': 'Total accuracy', 'correct': [('CAR', 'CARS', 'BUILDING', 'BUILDINGS')], 'incorrect': [('CANBERRA', 'AUSTRALIA', 'KABUL', 'AFGHANISTAN'), ('CANBERRA', 'AUSTRALIA', 'PARIS', 'FRANCE'), ('KABUL', 'AFGHANISTAN', 'PARIS', 'FRANCE'), ('KABUL', 'AFGHANISTAN', 'CANBERRA', 'AUSTRALIA'), ('PARIS', 'FRANCE', 'CANBERRA', 'AUSTRALIA'), ('PARIS', 'FRANCE', 'KABUL', 'AFGHANISTAN'), ('CANBERRA', 'AUSTRALIA', 'KABUL', 'AFGHANISTAN'), ('KABUL', 'AFGHANISTAN', 'PARIS', 'FRANCE'), ('HE', 'SHE', 'HIS', 'HER'), ('HE', 'SHE', 'MAN', 'WOMAN'), ('HIS', 'HER', 'MAN', 'WOMAN'), ('HIS', 'HER', 'HE', 'SHE'), ('MAN', 'WOMAN', 'HE', 'SHE'), ('MAN', 'WOMAN', 'HIS', 'HER'), ('GOOD', 'BETTER', 'GREAT', 'GREATER'), ('GOOD', 'BETTER', 'LONG', 'LONGER'), ('GOOD', 'BETTER', 'LOW', 'LOWER'), ('GOOD', 'BETTER', 'SMALL', 'SMALLER'), ('GREAT', 'GREATER', 'LONG', 'LONGER'), ('GREAT', 'GREATER', 'LOW', 'LOWER'), ('GREAT', 'GREATER', 'SMALL', 'SMALLER'), ('GREAT', 'GREATER', 'GOOD', 'BETTER'), ('LONG', 'LONGER', 'LOW', 'LOWER'), ('LONG', 'LONGER', 'SMALL', 'SMALLER'), ('LONG', 'LONGER', 'GOOD', 'BETTER'), ('LONG', 'LONGER', 'GREAT', 'GREATER'), ('LOW', 'LOWER', 'SMALL', 'SMALLER'), ('LOW', 'LOWER', 'GOOD', 'BETTER'), ('LOW', 'LOWER', 'GREAT', 'GREATER'), ('LOW', 'LOWER', 'LONG', 'LONGER'), ('SMALL', 'SMALLER', 'GOOD', 'BETTER'), ('SMALL', 'SMALLER', 'GREAT', 'GREATER'), ('SMALL', 'SMALLER', 'LONG', 'LONGER'), ('SMALL', 'SMALLER', 'LOW', 'LOWER'), ('BIG', 'BIGGEST', 'GOOD', 'BEST'), ('BIG', 'BIGGEST', 'GREAT', 'GREATEST'), ('BIG', 'BIGGEST', 'LARGE', 'LARGEST'), ('GOOD', 'BEST', 'GREAT', 'GREATEST'), ('GOOD', 'BEST', 'LARGE', 'LARGEST'), ('GOOD', 'BEST', 'BIG', 'BIGGEST'), ('GREAT', 'GREATEST', 'LARGE', 'LARGEST'), ('GREAT', 'GREATEST', 'BIG', 'BIGGEST'), ('GREAT', 'GREATEST', 'GOOD', 'BEST'), ('LARGE', 'LARGEST', 'BIG', 'BIGGEST'), ('LARGE', 'LARGEST', 'GOOD', 'BEST'), ('LARGE', 'LARGEST', 'GREAT', 'GREATEST'), ('GO', 'GOING', 'LOOK', 'LOOKING'), ('GO', 'GOING', 'PLAY', 'PLAYING'), ('GO', 'GOING', 'RUN', 'RUNNING'), ('GO', 'GOING', 'SAY', 'SAYING'), ('LOOK', 'LOOKING', 'PLAY', 'PLAYING'), ('LOOK', 'LOOKING', 'RUN', 'RUNNING'), ('LOOK', 'LOOKING', 'SAY', 'SAYING'), ('LOOK', 'LOOKING', 'GO', 'GOING'), ('PLAY', 'PLAYING', 'RUN', 'RUNNING'), ('PLAY', 'PLAYING', 'SAY', 'SAYING'), ('PLAY', 'PLAYING', 'GO', 'GOING'), ('PLAY', 'PLAYING', 'LOOK', 'LOOKING'), ('RUN', 'RUNNING', 'SAY', 'SAYING'), ('RUN', 'RUNNING', 'GO', 'GOING'), ('RUN', 'RUNNING', 'LOOK', 'LOOKING'), ('RUN', 'RUNNING', 'PLAY', 'PLAYING'), ('SAY', 'SAYING', 'GO', 'GOING'), ('SAY', 'SAYING', 'LOOK', 'LOOKING'), ('SAY', 'SAYING', 'PLAY', 'PLAYING'), ('SAY', 'SAYING', 'RUN', 'RUNNING'), ('AUSTRALIA', 'AUSTRALIAN', 'FRANCE', 'FRENCH'), ('AUSTRALIA', 'AUSTRALIAN', 'INDIA', 'INDIAN'), ('AUSTRALIA', 'AUSTRALIAN', 'ISRAEL', 'ISRAELI'), ('AUSTRALIA', 'AUSTRALIAN', 'JAPAN', 'JAPANESE'), ('AUSTRALIA', 'AUSTRALIAN', 'SWITZERLAND', 'SWISS'), ('FRANCE', 'FRENCH', 'INDIA', 'INDIAN'), ('FRANCE', 'FRENCH', 'ISRAEL', 'ISRAELI'), ('FRANCE', 'FRENCH', 'JAPAN', 'JAPANESE'), ('FRANCE', 'FRENCH', 'SWITZERLAND', 'SWISS'), ('FRANCE', 'FRENCH', 'AUSTRALIA', 'AUSTRALIAN'), ('INDIA', 'INDIAN', 'ISRAEL', 'ISRAELI'), ('INDIA', 'INDIAN', 'JAPAN', 'JAPANESE'), ('INDIA', 'INDIAN', 'SWITZERLAND', 'SWISS'), ('INDIA', 'INDIAN', 'AUSTRALIA', 'AUSTRALIAN'), ('INDIA', 'INDIAN', 'FRANCE', 'FRENCH'), ('ISRAEL', 'ISRAELI', 'JAPAN', 'JAPANESE'), ('ISRAEL', 'ISRAELI', 'SWITZERLAND', 'SWISS'), ('ISRAEL', 'ISRAELI', 'AUSTRALIA', 'AUSTRALIAN'), ('ISRAEL', 'ISRAELI', 'FRANCE', 'FRENCH'), ('ISRAEL', 'ISRAELI', 'INDIA', 'INDIAN'), ('JAPAN', 'JAPANESE', 'SWITZERLAND', 'SWISS'), ('JAPAN', 'JAPANESE', 'AUSTRALIA', 'AUSTRALIAN'), ('JAPAN', 'JAPANESE', 'FRANCE', 'FRENCH'), ('JAPAN', 'JAPANESE', 'INDIA', 'INDIAN'), ('JAPAN', 'JAPANESE', 'ISRAEL', 'ISRAELI'), ('SWITZERLAND', 'SWISS', 'AUSTRALIA', 'AUSTRALIAN'), ('SWITZERLAND', 'SWISS', 'FRANCE', 'FRENCH'), ('SWITZERLAND', 'SWISS', 'INDIA', 'INDIAN'), ('SWITZERLAND', 'SWISS', 'ISRAEL', 'ISRAELI'), ('SWITZERLAND', 'SWISS', 'JAPAN', 'JAPANESE'), ('GOING', 'WENT', 'PAYING', 'PAID'), ('GOING', 'WENT', 'PLAYING', 'PLAYED'), ('GOING', 'WENT', 'SAYING', 'SAID'), ('GOING', 'WENT', 'TAKING', 'TOOK'), ('PAYING', 'PAID', 'PLAYING', 'PLAYED'), ('PAYING', 'PAID', 'SAYING', 'SAID'), ('PAYING', 'PAID', 'TAKING', 'TOOK'), ('PAYING', 'PAID', 'GOING', 'WENT'), ('PLAYING', 'PLAYED', 'SAYING', 'SAID'), ('PLAYING', 'PLAYED', 'TAKING', 'TOOK'), ('PLAYING', 'PLAYED', 'GOING', 'WENT'), ('PLAYING', 'PLAYED', 'PAYING', 'PAID'), ('SAYING', 'SAID', 'TAKING', 'TOOK'), ('SAYING', 'SAID', 'GOING', 'WENT'), ('SAYING', 'SAID', 'PAYING', 'PAID'), ('SAYING', 'SAID', 'PLAYING', 'PLAYED'), ('TAKING', 'TOOK', 'GOING', 'WENT'), ('TAKING', 'TOOK', 'PAYING', 'PAID'), ('TAKING', 'TOOK', 'PLAYING', 'PLAYED'), ('TAKING', 'TOOK', 'SAYING', 'SAID'), ('BUILDING', 'BUILDINGS', 'CAR', 'CARS'), ('BUILDING', 'BUILDINGS', 'CHILD', 'CHILDREN'), ('BUILDING', 'BUILDINGS', 'MAN', 'MEN'), ('BUILDING', 'BUILDINGS', 'ROAD', 'ROADS'), ('BUILDING', 'BUILDINGS', 'WOMAN', 'WOMEN'), ('CAR', 'CARS', 'CHILD', 'CHILDREN'), ('CAR', 'CARS', 'MAN', 'MEN'), ('CAR', 'CARS', 'ROAD', 'ROADS'), ('CAR', 'CARS', 'WOMAN', 'WOMEN'), ('CHILD', 'CHILDREN', 'MAN', 'MEN'), ('CHILD', 'CHILDREN', 'ROAD', 'ROADS'), ('CHILD', 'CHILDREN', 'WOMAN', 'WOMEN'), ('CHILD', 'CHILDREN', 'BUILDING', 'BUILDINGS'), ('CHILD', 'CHILDREN', 'CAR', 'CARS'), ('MAN', 'MEN', 'ROAD', 'ROADS'), ('MAN', 'MEN', 'WOMAN', 'WOMEN'), ('MAN', 'MEN', 'BUILDING', 'BUILDINGS'), ('MAN', 'MEN', 'CAR', 'CARS'), ('MAN', 'MEN', 'CHILD', 'CHILDREN'), ('ROAD', 'ROADS', 'WOMAN', 'WOMEN'), ('ROAD', 'ROADS', 'BUILDING', 'BUILDINGS'), ('ROAD', 'ROADS', 'CAR', 'CARS'), ('ROAD', 'ROADS', 'CHILD', 'CHILDREN'), ('ROAD', 'ROADS', 'MAN', 'MEN'), ('WOMAN', 'WOMEN', 'BUILDING', 'BUILDINGS'), ('WOMAN', 'WOMEN', 'CAR', 'CARS'), ('WOMAN', 'WOMEN', 'CHILD', 'CHILDREN'), ('WOMAN', 'WOMEN', 'MAN', 'MEN'), ('WOMAN', 'WOMEN', 'ROAD', 'ROADS')]}]) + (0.0, [{'section': 'capital-common-countries', 'correct': [], 'incorrect': [('CANBERRA', 'AUSTRALIA', 'KABUL', 'AFGHANISTAN'), ('CANBERRA', 'AUSTRALIA', 'PARIS', 'FRANCE'), ('KABUL', 'AFGHANISTAN', 'PARIS', 'FRANCE'), ('KABUL', 'AFGHANISTAN', 'CANBERRA', 'AUSTRALIA'), ('PARIS', 'FRANCE', 'CANBERRA', 'AUSTRALIA'), ('PARIS', 'FRANCE', 'KABUL', 'AFGHANISTAN')]}, {'section': 'capital-world', 'correct': [], 'incorrect': [('CANBERRA', 'AUSTRALIA', 'KABUL', 'AFGHANISTAN'), ('KABUL', 'AFGHANISTAN', 'PARIS', 'FRANCE')]}, {'section': 'currency', 'correct': [], 'incorrect': []}, {'section': 'city-in-state', 'correct': [], 'incorrect': []}, {'section': 'family', 'correct': [], 'incorrect': [('HE', 'SHE', 'HIS', 'HER'), ('HE', 'SHE', 'MAN', 'WOMAN'), ('HIS', 'HER', 'MAN', 'WOMAN'), ('HIS', 'HER', 'HE', 'SHE'), ('MAN', 'WOMAN', 'HE', 'SHE'), ('MAN', 'WOMAN', 'HIS', 'HER')]}, {'section': 'gram1-adjective-to-adverb', 'correct': [], 'incorrect': []}, {'section': 'gram2-opposite', 'correct': [], 'incorrect': []}, {'section': 'gram3-comparative', 'correct': [], 'incorrect': [('GOOD', 'BETTER', 'GREAT', 'GREATER'), ('GOOD', 'BETTER', 'LONG', 'LONGER'), ('GOOD', 'BETTER', 'LOW', 'LOWER'), ('GOOD', 'BETTER', 'SMALL', 'SMALLER'), ('GREAT', 'GREATER', 'LONG', 'LONGER'), ('GREAT', 'GREATER', 'LOW', 'LOWER'), ('GREAT', 'GREATER', 'SMALL', 'SMALLER'), ('GREAT', 'GREATER', 'GOOD', 'BETTER'), ('LONG', 'LONGER', 'LOW', 'LOWER'), ('LONG', 'LONGER', 'SMALL', 'SMALLER'), ('LONG', 'LONGER', 'GOOD', 'BETTER'), ('LONG', 'LONGER', 'GREAT', 'GREATER'), ('LOW', 'LOWER', 'SMALL', 'SMALLER'), ('LOW', 'LOWER', 'GOOD', 'BETTER'), ('LOW', 'LOWER', 'GREAT', 'GREATER'), ('LOW', 'LOWER', 'LONG', 'LONGER'), ('SMALL', 'SMALLER', 'GOOD', 'BETTER'), ('SMALL', 'SMALLER', 'GREAT', 'GREATER'), ('SMALL', 'SMALLER', 'LONG', 'LONGER'), ('SMALL', 'SMALLER', 'LOW', 'LOWER')]}, {'section': 'gram4-superlative', 'correct': [], 'incorrect': [('BIG', 'BIGGEST', 'GOOD', 'BEST'), ('BIG', 'BIGGEST', 'GREAT', 'GREATEST'), ('BIG', 'BIGGEST', 'LARGE', 'LARGEST'), ('GOOD', 'BEST', 'GREAT', 'GREATEST'), ('GOOD', 'BEST', 'LARGE', 'LARGEST'), ('GOOD', 'BEST', 'BIG', 'BIGGEST'), ('GREAT', 'GREATEST', 'LARGE', 'LARGEST'), ('GREAT', 'GREATEST', 'BIG', 'BIGGEST'), ('GREAT', 'GREATEST', 'GOOD', 'BEST'), ('LARGE', 'LARGEST', 'BIG', 'BIGGEST'), ('LARGE', 'LARGEST', 'GOOD', 'BEST'), ('LARGE', 'LARGEST', 'GREAT', 'GREATEST')]}, {'section': 'gram5-present-participle', 'correct': [], 'incorrect': [('GO', 'GOING', 'LOOK', 'LOOKING'), ('GO', 'GOING', 'PLAY', 'PLAYING'), ('GO', 'GOING', 'RUN', 'RUNNING'), ('GO', 'GOING', 'SAY', 'SAYING'), ('LOOK', 'LOOKING', 'PLAY', 'PLAYING'), ('LOOK', 'LOOKING', 'RUN', 'RUNNING'), ('LOOK', 'LOOKING', 'SAY', 'SAYING'), ('LOOK', 'LOOKING', 'GO', 'GOING'), ('PLAY', 'PLAYING', 'RUN', 'RUNNING'), ('PLAY', 'PLAYING', 'SAY', 'SAYING'), ('PLAY', 'PLAYING', 'GO', 'GOING'), ('PLAY', 'PLAYING', 'LOOK', 'LOOKING'), ('RUN', 'RUNNING', 'SAY', 'SAYING'), ('RUN', 'RUNNING', 'GO', 'GOING'), ('RUN', 'RUNNING', 'LOOK', 'LOOKING'), ('RUN', 'RUNNING', 'PLAY', 'PLAYING'), ('SAY', 'SAYING', 'GO', 'GOING'), ('SAY', 'SAYING', 'LOOK', 'LOOKING'), ('SAY', 'SAYING', 'PLAY', 'PLAYING'), ('SAY', 'SAYING', 'RUN', 'RUNNING')]}, {'section': 'gram6-nationality-adjective', 'correct': [], 'incorrect': [('AUSTRALIA', 'AUSTRALIAN', 'FRANCE', 'FRENCH'), ('AUSTRALIA', 'AUSTRALIAN', 'INDIA', 'INDIAN'), ('AUSTRALIA', 'AUSTRALIAN', 'ISRAEL', 'ISRAELI'), ('AUSTRALIA', 'AUSTRALIAN', 'JAPAN', 'JAPANESE'), ('AUSTRALIA', 'AUSTRALIAN', 'SWITZERLAND', 'SWISS'), ('FRANCE', 'FRENCH', 'INDIA', 'INDIAN'), ('FRANCE', 'FRENCH', 'ISRAEL', 'ISRAELI'), ('FRANCE', 'FRENCH', 'JAPAN', 'JAPANESE'), ('FRANCE', 'FRENCH', 'SWITZERLAND', 'SWISS'), ('FRANCE', 'FRENCH', 'AUSTRALIA', 'AUSTRALIAN'), ('INDIA', 'INDIAN', 'ISRAEL', 'ISRAELI'), ('INDIA', 'INDIAN', 'JAPAN', 'JAPANESE'), ('INDIA', 'INDIAN', 'SWITZERLAND', 'SWISS'), ('INDIA', 'INDIAN', 'AUSTRALIA', 'AUSTRALIAN'), ('INDIA', 'INDIAN', 'FRANCE', 'FRENCH'), ('ISRAEL', 'ISRAELI', 'JAPAN', 'JAPANESE'), ('ISRAEL', 'ISRAELI', 'SWITZERLAND', 'SWISS'), ('ISRAEL', 'ISRAELI', 'AUSTRALIA', 'AUSTRALIAN'), ('ISRAEL', 'ISRAELI', 'FRANCE', 'FRENCH'), ('ISRAEL', 'ISRAELI', 'INDIA', 'INDIAN'), ('JAPAN', 'JAPANESE', 'SWITZERLAND', 'SWISS'), ('JAPAN', 'JAPANESE', 'AUSTRALIA', 'AUSTRALIAN'), ('JAPAN', 'JAPANESE', 'FRANCE', 'FRENCH'), ('JAPAN', 'JAPANESE', 'INDIA', 'INDIAN'), ('JAPAN', 'JAPANESE', 'ISRAEL', 'ISRAELI'), ('SWITZERLAND', 'SWISS', 'AUSTRALIA', 'AUSTRALIAN'), ('SWITZERLAND', 'SWISS', 'FRANCE', 'FRENCH'), ('SWITZERLAND', 'SWISS', 'INDIA', 'INDIAN'), ('SWITZERLAND', 'SWISS', 'ISRAEL', 'ISRAELI'), ('SWITZERLAND', 'SWISS', 'JAPAN', 'JAPANESE')]}, {'section': 'gram7-past-tense', 'correct': [], 'incorrect': [('GOING', 'WENT', 'PAYING', 'PAID'), ('GOING', 'WENT', 'PLAYING', 'PLAYED'), ('GOING', 'WENT', 'SAYING', 'SAID'), ('GOING', 'WENT', 'TAKING', 'TOOK'), ('PAYING', 'PAID', 'PLAYING', 'PLAYED'), ('PAYING', 'PAID', 'SAYING', 'SAID'), ('PAYING', 'PAID', 'TAKING', 'TOOK'), ('PAYING', 'PAID', 'GOING', 'WENT'), ('PLAYING', 'PLAYED', 'SAYING', 'SAID'), ('PLAYING', 'PLAYED', 'TAKING', 'TOOK'), ('PLAYING', 'PLAYED', 'GOING', 'WENT'), ('PLAYING', 'PLAYED', 'PAYING', 'PAID'), ('SAYING', 'SAID', 'TAKING', 'TOOK'), ('SAYING', 'SAID', 'GOING', 'WENT'), ('SAYING', 'SAID', 'PAYING', 'PAID'), ('SAYING', 'SAID', 'PLAYING', 'PLAYED'), ('TAKING', 'TOOK', 'GOING', 'WENT'), ('TAKING', 'TOOK', 'PAYING', 'PAID'), ('TAKING', 'TOOK', 'PLAYING', 'PLAYED'), ('TAKING', 'TOOK', 'SAYING', 'SAID')]}, {'section': 'gram8-plural', 'correct': [], 'incorrect': [('BUILDING', 'BUILDINGS', 'CAR', 'CARS'), ('BUILDING', 'BUILDINGS', 'CHILD', 'CHILDREN'), ('BUILDING', 'BUILDINGS', 'MAN', 'MEN'), ('BUILDING', 'BUILDINGS', 'ROAD', 'ROADS'), ('BUILDING', 'BUILDINGS', 'WOMAN', 'WOMEN'), ('CAR', 'CARS', 'CHILD', 'CHILDREN'), ('CAR', 'CARS', 'MAN', 'MEN'), ('CAR', 'CARS', 'ROAD', 'ROADS'), ('CAR', 'CARS', 'WOMAN', 'WOMEN'), ('CAR', 'CARS', 'BUILDING', 'BUILDINGS'), ('CHILD', 'CHILDREN', 'MAN', 'MEN'), ('CHILD', 'CHILDREN', 'ROAD', 'ROADS'), ('CHILD', 'CHILDREN', 'WOMAN', 'WOMEN'), ('CHILD', 'CHILDREN', 'BUILDING', 'BUILDINGS'), ('CHILD', 'CHILDREN', 'CAR', 'CARS'), ('MAN', 'MEN', 'ROAD', 'ROADS'), ('MAN', 'MEN', 'WOMAN', 'WOMEN'), ('MAN', 'MEN', 'BUILDING', 'BUILDINGS'), ('MAN', 'MEN', 'CAR', 'CARS'), ('MAN', 'MEN', 'CHILD', 'CHILDREN'), ('ROAD', 'ROADS', 'WOMAN', 'WOMEN'), ('ROAD', 'ROADS', 'BUILDING', 'BUILDINGS'), ('ROAD', 'ROADS', 'CAR', 'CARS'), ('ROAD', 'ROADS', 'CHILD', 'CHILDREN'), ('ROAD', 'ROADS', 'MAN', 'MEN'), ('WOMAN', 'WOMEN', 'BUILDING', 'BUILDINGS'), ('WOMAN', 'WOMEN', 'CAR', 'CARS'), ('WOMAN', 'WOMEN', 'CHILD', 'CHILDREN'), ('WOMAN', 'WOMEN', 'MAN', 'MEN'), ('WOMAN', 'WOMEN', 'ROAD', 'ROADS')]}, {'section': 'gram9-plural-verbs', 'correct': [], 'incorrect': []}, {'section': 'Total accuracy', 'correct': [], 'incorrect': [('CANBERRA', 'AUSTRALIA', 'KABUL', 'AFGHANISTAN'), ('CANBERRA', 'AUSTRALIA', 'PARIS', 'FRANCE'), ('KABUL', 'AFGHANISTAN', 'PARIS', 'FRANCE'), ('KABUL', 'AFGHANISTAN', 'CANBERRA', 'AUSTRALIA'), ('PARIS', 'FRANCE', 'CANBERRA', 'AUSTRALIA'), ('PARIS', 'FRANCE', 'KABUL', 'AFGHANISTAN'), ('CANBERRA', 'AUSTRALIA', 'KABUL', 'AFGHANISTAN'), ('KABUL', 'AFGHANISTAN', 'PARIS', 'FRANCE'), ('HE', 'SHE', 'HIS', 'HER'), ('HE', 'SHE', 'MAN', 'WOMAN'), ('HIS', 'HER', 'MAN', 'WOMAN'), ('HIS', 'HER', 'HE', 'SHE'), ('MAN', 'WOMAN', 'HE', 'SHE'), ('MAN', 'WOMAN', 'HIS', 'HER'), ('GOOD', 'BETTER', 'GREAT', 'GREATER'), ('GOOD', 'BETTER', 'LONG', 'LONGER'), ('GOOD', 'BETTER', 'LOW', 'LOWER'), ('GOOD', 'BETTER', 'SMALL', 'SMALLER'), ('GREAT', 'GREATER', 'LONG', 'LONGER'), ('GREAT', 'GREATER', 'LOW', 'LOWER'), ('GREAT', 'GREATER', 'SMALL', 'SMALLER'), ('GREAT', 'GREATER', 'GOOD', 'BETTER'), ('LONG', 'LONGER', 'LOW', 'LOWER'), ('LONG', 'LONGER', 'SMALL', 'SMALLER'), ('LONG', 'LONGER', 'GOOD', 'BETTER'), ('LONG', 'LONGER', 'GREAT', 'GREATER'), ('LOW', 'LOWER', 'SMALL', 'SMALLER'), ('LOW', 'LOWER', 'GOOD', 'BETTER'), ('LOW', 'LOWER', 'GREAT', 'GREATER'), ('LOW', 'LOWER', 'LONG', 'LONGER'), ('SMALL', 'SMALLER', 'GOOD', 'BETTER'), ('SMALL', 'SMALLER', 'GREAT', 'GREATER'), ('SMALL', 'SMALLER', 'LONG', 'LONGER'), ('SMALL', 'SMALLER', 'LOW', 'LOWER'), ('BIG', 'BIGGEST', 'GOOD', 'BEST'), ('BIG', 'BIGGEST', 'GREAT', 'GREATEST'), ('BIG', 'BIGGEST', 'LARGE', 'LARGEST'), ('GOOD', 'BEST', 'GREAT', 'GREATEST'), ('GOOD', 'BEST', 'LARGE', 'LARGEST'), ('GOOD', 'BEST', 'BIG', 'BIGGEST'), ('GREAT', 'GREATEST', 'LARGE', 'LARGEST'), ('GREAT', 'GREATEST', 'BIG', 'BIGGEST'), ('GREAT', 'GREATEST', 'GOOD', 'BEST'), ('LARGE', 'LARGEST', 'BIG', 'BIGGEST'), ('LARGE', 'LARGEST', 'GOOD', 'BEST'), ('LARGE', 'LARGEST', 'GREAT', 'GREATEST'), ('GO', 'GOING', 'LOOK', 'LOOKING'), ('GO', 'GOING', 'PLAY', 'PLAYING'), ('GO', 'GOING', 'RUN', 'RUNNING'), ('GO', 'GOING', 'SAY', 'SAYING'), ('LOOK', 'LOOKING', 'PLAY', 'PLAYING'), ('LOOK', 'LOOKING', 'RUN', 'RUNNING'), ('LOOK', 'LOOKING', 'SAY', 'SAYING'), ('LOOK', 'LOOKING', 'GO', 'GOING'), ('PLAY', 'PLAYING', 'RUN', 'RUNNING'), ('PLAY', 'PLAYING', 'SAY', 'SAYING'), ('PLAY', 'PLAYING', 'GO', 'GOING'), ('PLAY', 'PLAYING', 'LOOK', 'LOOKING'), ('RUN', 'RUNNING', 'SAY', 'SAYING'), ('RUN', 'RUNNING', 'GO', 'GOING'), ('RUN', 'RUNNING', 'LOOK', 'LOOKING'), ('RUN', 'RUNNING', 'PLAY', 'PLAYING'), ('SAY', 'SAYING', 'GO', 'GOING'), ('SAY', 'SAYING', 'LOOK', 'LOOKING'), ('SAY', 'SAYING', 'PLAY', 'PLAYING'), ('SAY', 'SAYING', 'RUN', 'RUNNING'), ('AUSTRALIA', 'AUSTRALIAN', 'FRANCE', 'FRENCH'), ('AUSTRALIA', 'AUSTRALIAN', 'INDIA', 'INDIAN'), ('AUSTRALIA', 'AUSTRALIAN', 'ISRAEL', 'ISRAELI'), ('AUSTRALIA', 'AUSTRALIAN', 'JAPAN', 'JAPANESE'), ('AUSTRALIA', 'AUSTRALIAN', 'SWITZERLAND', 'SWISS'), ('FRANCE', 'FRENCH', 'INDIA', 'INDIAN'), ('FRANCE', 'FRENCH', 'ISRAEL', 'ISRAELI'), ('FRANCE', 'FRENCH', 'JAPAN', 'JAPANESE'), ('FRANCE', 'FRENCH', 'SWITZERLAND', 'SWISS'), ('FRANCE', 'FRENCH', 'AUSTRALIA', 'AUSTRALIAN'), ('INDIA', 'INDIAN', 'ISRAEL', 'ISRAELI'), ('INDIA', 'INDIAN', 'JAPAN', 'JAPANESE'), ('INDIA', 'INDIAN', 'SWITZERLAND', 'SWISS'), ('INDIA', 'INDIAN', 'AUSTRALIA', 'AUSTRALIAN'), ('INDIA', 'INDIAN', 'FRANCE', 'FRENCH'), ('ISRAEL', 'ISRAELI', 'JAPAN', 'JAPANESE'), ('ISRAEL', 'ISRAELI', 'SWITZERLAND', 'SWISS'), ('ISRAEL', 'ISRAELI', 'AUSTRALIA', 'AUSTRALIAN'), ('ISRAEL', 'ISRAELI', 'FRANCE', 'FRENCH'), ('ISRAEL', 'ISRAELI', 'INDIA', 'INDIAN'), ('JAPAN', 'JAPANESE', 'SWITZERLAND', 'SWISS'), ('JAPAN', 'JAPANESE', 'AUSTRALIA', 'AUSTRALIAN'), ('JAPAN', 'JAPANESE', 'FRANCE', 'FRENCH'), ('JAPAN', 'JAPANESE', 'INDIA', 'INDIAN'), ('JAPAN', 'JAPANESE', 'ISRAEL', 'ISRAELI'), ('SWITZERLAND', 'SWISS', 'AUSTRALIA', 'AUSTRALIAN'), ('SWITZERLAND', 'SWISS', 'FRANCE', 'FRENCH'), ('SWITZERLAND', 'SWISS', 'INDIA', 'INDIAN'), ('SWITZERLAND', 'SWISS', 'ISRAEL', 'ISRAELI'), ('SWITZERLAND', 'SWISS', 'JAPAN', 'JAPANESE'), ('GOING', 'WENT', 'PAYING', 'PAID'), ('GOING', 'WENT', 'PLAYING', 'PLAYED'), ('GOING', 'WENT', 'SAYING', 'SAID'), ('GOING', 'WENT', 'TAKING', 'TOOK'), ('PAYING', 'PAID', 'PLAYING', 'PLAYED'), ('PAYING', 'PAID', 'SAYING', 'SAID'), ('PAYING', 'PAID', 'TAKING', 'TOOK'), ('PAYING', 'PAID', 'GOING', 'WENT'), ('PLAYING', 'PLAYED', 'SAYING', 'SAID'), ('PLAYING', 'PLAYED', 'TAKING', 'TOOK'), ('PLAYING', 'PLAYED', 'GOING', 'WENT'), ('PLAYING', 'PLAYED', 'PAYING', 'PAID'), ('SAYING', 'SAID', 'TAKING', 'TOOK'), ('SAYING', 'SAID', 'GOING', 'WENT'), ('SAYING', 'SAID', 'PAYING', 'PAID'), ('SAYING', 'SAID', 'PLAYING', 'PLAYED'), ('TAKING', 'TOOK', 'GOING', 'WENT'), ('TAKING', 'TOOK', 'PAYING', 'PAID'), ('TAKING', 'TOOK', 'PLAYING', 'PLAYED'), ('TAKING', 'TOOK', 'SAYING', 'SAID'), ('BUILDING', 'BUILDINGS', 'CAR', 'CARS'), ('BUILDING', 'BUILDINGS', 'CHILD', 'CHILDREN'), ('BUILDING', 'BUILDINGS', 'MAN', 'MEN'), ('BUILDING', 'BUILDINGS', 'ROAD', 'ROADS'), ('BUILDING', 'BUILDINGS', 'WOMAN', 'WOMEN'), ('CAR', 'CARS', 'CHILD', 'CHILDREN'), ('CAR', 'CARS', 'MAN', 'MEN'), ('CAR', 'CARS', 'ROAD', 'ROADS'), ('CAR', 'CARS', 'WOMAN', 'WOMEN'), ('CAR', 'CARS', 'BUILDING', 'BUILDINGS'), ('CHILD', 'CHILDREN', 'MAN', 'MEN'), ('CHILD', 'CHILDREN', 'ROAD', 'ROADS'), ('CHILD', 'CHILDREN', 'WOMAN', 'WOMEN'), ('CHILD', 'CHILDREN', 'BUILDING', 'BUILDINGS'), ('CHILD', 'CHILDREN', 'CAR', 'CARS'), ('MAN', 'MEN', 'ROAD', 'ROADS'), ('MAN', 'MEN', 'WOMAN', 'WOMEN'), ('MAN', 'MEN', 'BUILDING', 'BUILDINGS'), ('MAN', 'MEN', 'CAR', 'CARS'), ('MAN', 'MEN', 'CHILD', 'CHILDREN'), ('ROAD', 'ROADS', 'WOMAN', 'WOMEN'), ('ROAD', 'ROADS', 'BUILDING', 'BUILDINGS'), ('ROAD', 'ROADS', 'CAR', 'CARS'), ('ROAD', 'ROADS', 'CHILD', 'CHILDREN'), ('ROAD', 'ROADS', 'MAN', 'MEN'), ('WOMAN', 'WOMEN', 'BUILDING', 'BUILDINGS'), ('WOMAN', 'WOMEN', 'CAR', 'CARS'), ('WOMAN', 'WOMEN', 'CHILD', 'CHILDREN'), ('WOMAN', 'WOMEN', 'MAN', 'MEN'), ('WOMAN', 'WOMEN', 'ROAD', 'ROADS')]}]) @@ -859,11 +649,8 @@ are less similar because they are related but not interchangeable. .. code-block:: none - 2020-09-30 17:02:04,681 : INFO : Pearson correlation coefficient against /Volumes/work/workspace/gensim/trunk/gensim/test/test_data/wordsim353.tsv: 0.1072 - 2020-09-30 17:02:04,682 : INFO : Spearman rank-order correlation coefficient against /Volumes/work/workspace/gensim/trunk/gensim/test/test_data/wordsim353.tsv: 0.0977 - 2020-09-30 17:02:04,682 : INFO : Pairs with unknown words ratio: 83.0% - ((0.10718629411012633, 0.41498744701424156), SpearmanrResult(correlation=0.09773516803468056, pvalue=0.4575366217424267), 83.0028328611898) + ((0.1014236962315867, 0.44065378924434523), SpearmanrResult(correlation=0.07441989763914543, pvalue=0.5719973648460552), 83.0028328611898) @@ -901,50 +688,6 @@ and `new vocabulary words `_: -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - 2020-09-30 17:02:04,775 : INFO : loading Word2Vec object from /var/folders/w0/f7blghz9277068cnyyd3nd200000gn/T/gensim-model-36yeu47d - 2020-09-30 17:02:04,788 : INFO : loading wv recursively from /var/folders/w0/f7blghz9277068cnyyd3nd200000gn/T/gensim-model-36yeu47d.wv.* with mmap=None - 2020-09-30 17:02:04,789 : INFO : setting ignored attribute cum_table to None - 2020-09-30 17:02:04,809 : INFO : loaded /var/folders/w0/f7blghz9277068cnyyd3nd200000gn/T/gensim-model-36yeu47d - 2020-09-30 17:02:04,809 : INFO : collecting all words and their counts - 2020-09-30 17:02:04,809 : INFO : PROGRESS: at sentence #0, processed 0 words, keeping 0 word types - 2020-09-30 17:02:04,810 : INFO : collected 13 word types from a corpus of 13 raw words and 1 sentences - 2020-09-30 17:02:04,810 : INFO : Updating model with new vocabulary - 2020-09-30 17:02:04,819 : INFO : New added 0 unique words (0% of original 13) and increased the count of 0 pre-existing words (0% of original 13) - 2020-09-30 17:02:04,819 : INFO : deleting the raw counts dictionary of 13 items - 2020-09-30 17:02:04,819 : INFO : sample=0.001 downsamples 0 most-common words - 2020-09-30 17:02:04,819 : INFO : downsampling leaves estimated 0 word corpus (0.0% of prior 0) - 2020-09-30 17:02:04,838 : INFO : estimated required memory for 1750 words and 100 dimensions: 2275000 bytes - 2020-09-30 17:02:04,838 : INFO : updating layer weights - 2020-09-30 17:02:04,839 : WARNING : Effective 'alpha' higher than previous training cycles - 2020-09-30 17:02:04,839 : INFO : training model with 3 workers on 1750 vocabulary and 100 features, using sg=0 hs=0 sample=0.001 negative=5 window=5 - 2020-09-30 17:02:04,842 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:04,843 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:04,843 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:04,843 : INFO : EPOCH - 1 : training on 13 raw words (6 effective words) took 0.0s, 5326 effective words/s - 2020-09-30 17:02:04,844 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:04,845 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:04,845 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:04,845 : INFO : EPOCH - 2 : training on 13 raw words (5 effective words) took 0.0s, 6975 effective words/s - 2020-09-30 17:02:04,846 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:04,846 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:04,846 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:04,846 : INFO : EPOCH - 3 : training on 13 raw words (5 effective words) took 0.0s, 8539 effective words/s - 2020-09-30 17:02:04,847 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:04,847 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:04,847 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:04,848 : INFO : EPOCH - 4 : training on 13 raw words (6 effective words) took 0.0s, 11100 effective words/s - 2020-09-30 17:02:04,848 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:04,849 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:04,849 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:04,849 : INFO : EPOCH - 5 : training on 13 raw words (5 effective words) took 0.0s, 9718 effective words/s - 2020-09-30 17:02:04,849 : INFO : training on a 65 raw words (27 effective words) took 0.0s, 2900 effective words/s - @@ -994,40 +737,7 @@ attribute ``running_training_loss`` and can be retrieved using the function .. code-block:: none - 2020-09-30 17:02:05,025 : INFO : collecting all words and their counts - 2020-09-30 17:02:05,027 : INFO : PROGRESS: at sentence #0, processed 0 words, keeping 0 word types - 2020-09-30 17:02:05,112 : INFO : collected 6981 word types from a corpus of 58152 raw words and 300 sentences - 2020-09-30 17:02:05,112 : INFO : Loading a fresh vocabulary - 2020-09-30 17:02:05,152 : INFO : effective_min_count=1 retains 6981 unique words (100% of original 6981, drops 0) - 2020-09-30 17:02:05,152 : INFO : effective_min_count=1 leaves 58152 word corpus (100% of original 58152, drops 0) - 2020-09-30 17:02:05,207 : INFO : deleting the raw counts dictionary of 6981 items - 2020-09-30 17:02:05,207 : INFO : sample=0.001 downsamples 43 most-common words - 2020-09-30 17:02:05,207 : INFO : downsampling leaves estimated 45723 word corpus (78.6% of prior 58152) - 2020-09-30 17:02:05,294 : INFO : estimated required memory for 6981 words and 100 dimensions: 9075300 bytes - 2020-09-30 17:02:05,294 : INFO : resetting layer weights - 2020-09-30 17:02:05,651 : INFO : training model with 3 workers on 6981 vocabulary and 100 features, using sg=1 hs=0 sample=0.001 negative=5 window=5 - 2020-09-30 17:02:05,800 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:05,839 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:05,841 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:05,841 : INFO : EPOCH - 1 : training on 58152 raw words (45692 effective words) took 0.2s, 242729 effective words/s - 2020-09-30 17:02:06,028 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:06,032 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:06,037 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:06,037 : INFO : EPOCH - 2 : training on 58152 raw words (45778 effective words) took 0.2s, 234367 effective words/s - 2020-09-30 17:02:06,218 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:06,222 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:06,225 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:06,225 : INFO : EPOCH - 3 : training on 58152 raw words (45684 effective words) took 0.2s, 244363 effective words/s - 2020-09-30 17:02:06,400 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:06,407 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:06,409 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:06,409 : INFO : EPOCH - 4 : training on 58152 raw words (45651 effective words) took 0.2s, 249862 effective words/s - 2020-09-30 17:02:06,558 : INFO : worker thread finished; awaiting finish of 2 more threads - 2020-09-30 17:02:06,597 : INFO : worker thread finished; awaiting finish of 1 more threads - 2020-09-30 17:02:06,600 : INFO : worker thread finished; awaiting finish of 0 more threads - 2020-09-30 17:02:06,600 : INFO : EPOCH - 5 : training on 58152 raw words (45745 effective words) took 0.2s, 240328 effective words/s - 2020-09-30 17:02:06,600 : INFO : training on a 290760 raw words (228550 effective words) took 0.9s, 240759 effective words/s - 1365568.125 + 1369454.25 @@ -1165,55 +875,55 @@ standard deviation of the test duration. .. code-block:: none - Word2vec model #0: {'train_data': '25kB', 'compute_loss': True, 'sg': 0, 'hs': 0, 'train_time_mean': 0.3307774066925049, 'train_time_std': 0.00578659163388716} - Word2vec model #1: {'train_data': '25kB', 'compute_loss': False, 'sg': 0, 'hs': 0, 'train_time_mean': 0.3314487934112549, 'train_time_std': 0.004201913501261655} - Word2vec model #2: {'train_data': '25kB', 'compute_loss': True, 'sg': 0, 'hs': 1, 'train_time_mean': 0.5213752587636312, 'train_time_std': 0.008047867089155704} - Word2vec model #3: {'train_data': '25kB', 'compute_loss': False, 'sg': 0, 'hs': 1, 'train_time_mean': 0.5293020407358805, 'train_time_std': 0.005368254032954145} - Word2vec model #4: {'train_data': '25kB', 'compute_loss': True, 'sg': 1, 'hs': 0, 'train_time_mean': 0.571751594543457, 'train_time_std': 0.001023259266794945} - Word2vec model #5: {'train_data': '25kB', 'compute_loss': False, 'sg': 1, 'hs': 0, 'train_time_mean': 0.5736987590789795, 'train_time_std': 0.00740075638673385} - Word2vec model #6: {'train_data': '25kB', 'compute_loss': True, 'sg': 1, 'hs': 1, 'train_time_mean': 1.1089734236399333, 'train_time_std': 0.029923990619945186} - Word2vec model #7: {'train_data': '25kB', 'compute_loss': False, 'sg': 1, 'hs': 1, 'train_time_mean': 1.2068419456481934, 'train_time_std': 0.006783016321594606} - Word2vec model #8: {'train_data': '1MB', 'compute_loss': True, 'sg': 0, 'hs': 0, 'train_time_mean': 0.9139569600423177, 'train_time_std': 0.04541121423444599} - Word2vec model #9: {'train_data': '1MB', 'compute_loss': False, 'sg': 0, 'hs': 0, 'train_time_mean': 0.9152584075927734, 'train_time_std': 0.05191135337399049} - Word2vec model #10: {'train_data': '1MB', 'compute_loss': True, 'sg': 0, 'hs': 1, 'train_time_mean': 1.6703286170959473, 'train_time_std': 0.11292966925292192} - Word2vec model #11: {'train_data': '1MB', 'compute_loss': False, 'sg': 0, 'hs': 1, 'train_time_mean': 1.583152135213216, 'train_time_std': 0.04577290669842482} - Word2vec model #12: {'train_data': '1MB', 'compute_loss': True, 'sg': 1, 'hs': 0, 'train_time_mean': 1.811710516611735, 'train_time_std': 0.01081321887556254} - Word2vec model #13: {'train_data': '1MB', 'compute_loss': False, 'sg': 1, 'hs': 0, 'train_time_mean': 1.8143157164255779, 'train_time_std': 0.026406013455100835} - Word2vec model #14: {'train_data': '1MB', 'compute_loss': True, 'sg': 1, 'hs': 1, 'train_time_mean': 3.5845812956492105, 'train_time_std': 0.08968344917541199} - Word2vec model #15: {'train_data': '1MB', 'compute_loss': False, 'sg': 1, 'hs': 1, 'train_time_mean': 3.6167975266774497, 'train_time_std': 0.14609390508721276} - Word2vec model #16: {'train_data': '10MB', 'compute_loss': True, 'sg': 0, 'hs': 0, 'train_time_mean': 8.021462361017862, 'train_time_std': 0.21593094159548987} - Word2vec model #17: {'train_data': '10MB', 'compute_loss': False, 'sg': 0, 'hs': 0, 'train_time_mean': 7.931290070215861, 'train_time_std': 0.25084118769867136} - Word2vec model #18: {'train_data': '10MB', 'compute_loss': True, 'sg': 0, 'hs': 1, 'train_time_mean': 15.51533571879069, 'train_time_std': 0.8857355166766315} - Word2vec model #19: {'train_data': '10MB', 'compute_loss': False, 'sg': 0, 'hs': 1, 'train_time_mean': 15.930208921432495, 'train_time_std': 0.6417048653898146} - Word2vec model #20: {'train_data': '10MB', 'compute_loss': True, 'sg': 1, 'hs': 0, 'train_time_mean': 21.687038342158, 'train_time_std': 0.3261330075856754} - Word2vec model #21: {'train_data': '10MB', 'compute_loss': False, 'sg': 1, 'hs': 0, 'train_time_mean': 21.280882279078167, 'train_time_std': 0.12885843584913614} - Word2vec model #22: {'train_data': '10MB', 'compute_loss': True, 'sg': 1, 'hs': 1, 'train_time_mean': 43.11969208717346, 'train_time_std': 0.8133788671881127} - Word2vec model #23: {'train_data': '10MB', 'compute_loss': False, 'sg': 1, 'hs': 1, 'train_time_mean': 40.59294398625692, 'train_time_std': 0.47622639550838375} + Word2vec model #0: {'train_data': '25kB', 'compute_loss': True, 'sg': 0, 'hs': 0, 'train_time_mean': 0.25217413902282715, 'train_time_std': 0.020226552024939795} + Word2vec model #1: {'train_data': '25kB', 'compute_loss': False, 'sg': 0, 'hs': 0, 'train_time_mean': 0.25898512204488117, 'train_time_std': 0.026276375796854143} + Word2vec model #2: {'train_data': '25kB', 'compute_loss': True, 'sg': 0, 'hs': 1, 'train_time_mean': 0.4194076855977376, 'train_time_std': 0.0021983060310549808} + Word2vec model #3: {'train_data': '25kB', 'compute_loss': False, 'sg': 0, 'hs': 1, 'train_time_mean': 0.4308760166168213, 'train_time_std': 0.0009999532723555815} + Word2vec model #4: {'train_data': '25kB', 'compute_loss': True, 'sg': 1, 'hs': 0, 'train_time_mean': 0.47211599349975586, 'train_time_std': 0.015136686417800442} + Word2vec model #5: {'train_data': '25kB', 'compute_loss': False, 'sg': 1, 'hs': 0, 'train_time_mean': 0.4695216814676921, 'train_time_std': 0.0033446725418043747} + Word2vec model #6: {'train_data': '25kB', 'compute_loss': True, 'sg': 1, 'hs': 1, 'train_time_mean': 0.9502590497334799, 'train_time_std': 0.005153258425238986} + Word2vec model #7: {'train_data': '25kB', 'compute_loss': False, 'sg': 1, 'hs': 1, 'train_time_mean': 0.9424160321553549, 'train_time_std': 0.009776048211734903} + Word2vec model #8: {'train_data': '1MB', 'compute_loss': True, 'sg': 0, 'hs': 0, 'train_time_mean': 0.6441135406494141, 'train_time_std': 0.00934594899599891} + Word2vec model #9: {'train_data': '1MB', 'compute_loss': False, 'sg': 0, 'hs': 0, 'train_time_mean': 0.656217098236084, 'train_time_std': 0.02703627277086478} + Word2vec model #10: {'train_data': '1MB', 'compute_loss': True, 'sg': 0, 'hs': 1, 'train_time_mean': 1.3150715033213298, 'train_time_std': 0.09457246701267184} + Word2vec model #11: {'train_data': '1MB', 'compute_loss': False, 'sg': 0, 'hs': 1, 'train_time_mean': 1.205832560857137, 'train_time_std': 0.005158620074483131} + Word2vec model #12: {'train_data': '1MB', 'compute_loss': True, 'sg': 1, 'hs': 0, 'train_time_mean': 1.5065066814422607, 'train_time_std': 0.036966116484319765} + Word2vec model #13: {'train_data': '1MB', 'compute_loss': False, 'sg': 1, 'hs': 0, 'train_time_mean': 1.537813663482666, 'train_time_std': 0.01020688183426915} + Word2vec model #14: {'train_data': '1MB', 'compute_loss': True, 'sg': 1, 'hs': 1, 'train_time_mean': 3.302257219950358, 'train_time_std': 0.04523242606424026} + Word2vec model #15: {'train_data': '1MB', 'compute_loss': False, 'sg': 1, 'hs': 1, 'train_time_mean': 3.4928714434305825, 'train_time_std': 0.19327551634697} + Word2vec model #16: {'train_data': '10MB', 'compute_loss': True, 'sg': 0, 'hs': 0, 'train_time_mean': 7.446084260940552, 'train_time_std': 0.7894319693665308} + Word2vec model #17: {'train_data': '10MB', 'compute_loss': False, 'sg': 0, 'hs': 0, 'train_time_mean': 7.060012976328532, 'train_time_std': 0.2136692186366028} + Word2vec model #18: {'train_data': '10MB', 'compute_loss': True, 'sg': 0, 'hs': 1, 'train_time_mean': 14.277136087417603, 'train_time_std': 0.7441633349142932} + Word2vec model #19: {'train_data': '10MB', 'compute_loss': False, 'sg': 0, 'hs': 1, 'train_time_mean': 13.758649031321207, 'train_time_std': 0.37393987718126326} + Word2vec model #20: {'train_data': '10MB', 'compute_loss': True, 'sg': 1, 'hs': 0, 'train_time_mean': 20.35730775197347, 'train_time_std': 0.41241047454786994} + Word2vec model #21: {'train_data': '10MB', 'compute_loss': False, 'sg': 1, 'hs': 0, 'train_time_mean': 21.380844751993816, 'train_time_std': 1.6909472056783184} + Word2vec model #22: {'train_data': '10MB', 'compute_loss': True, 'sg': 1, 'hs': 1, 'train_time_mean': 44.4877184232076, 'train_time_std': 1.1314265197889173} + Word2vec model #23: {'train_data': '10MB', 'compute_loss': False, 'sg': 1, 'hs': 1, 'train_time_mean': 44.517534812291466, 'train_time_std': 1.4472790491207064} compute_loss hs sg train_data train_time_mean train_time_std - 4 True 0 1 25kB 0.571752 0.001023 - 5 False 0 1 25kB 0.573699 0.007401 - 6 True 1 1 25kB 1.108973 0.029924 - 7 False 1 1 25kB 1.206842 0.006783 - 0 True 0 0 25kB 0.330777 0.005787 - 1 False 0 0 25kB 0.331449 0.004202 - 2 True 1 0 25kB 0.521375 0.008048 - 3 False 1 0 25kB 0.529302 0.005368 - 12 True 0 1 1MB 1.811711 0.010813 - 13 False 0 1 1MB 1.814316 0.026406 - 14 True 1 1 1MB 3.584581 0.089683 - 15 False 1 1 1MB 3.616798 0.146094 - 8 True 0 0 1MB 0.913957 0.045411 - 9 False 0 0 1MB 0.915258 0.051911 - 10 True 1 0 1MB 1.670329 0.112930 - 11 False 1 0 1MB 1.583152 0.045773 - 20 True 0 1 10MB 21.687038 0.326133 - 21 False 0 1 10MB 21.280882 0.128858 - 22 True 1 1 10MB 43.119692 0.813379 - 23 False 1 1 10MB 40.592944 0.476226 - 16 True 0 0 10MB 8.021462 0.215931 - 17 False 0 0 10MB 7.931290 0.250841 - 18 True 1 0 10MB 15.515336 0.885736 - 19 False 1 0 10MB 15.930209 0.641705 + 4 True 0 1 25kB 0.472116 0.015137 + 5 False 0 1 25kB 0.469522 0.003345 + 6 True 1 1 25kB 0.950259 0.005153 + 7 False 1 1 25kB 0.942416 0.009776 + 0 True 0 0 25kB 0.252174 0.020227 + 1 False 0 0 25kB 0.258985 0.026276 + 2 True 1 0 25kB 0.419408 0.002198 + 3 False 1 0 25kB 0.430876 0.001000 + 12 True 0 1 1MB 1.506507 0.036966 + 13 False 0 1 1MB 1.537814 0.010207 + 14 True 1 1 1MB 3.302257 0.045232 + 15 False 1 1 1MB 3.492871 0.193276 + 8 True 0 0 1MB 0.644114 0.009346 + 9 False 0 0 1MB 0.656217 0.027036 + 10 True 1 0 1MB 1.315072 0.094572 + 11 False 1 0 1MB 1.205833 0.005159 + 20 True 0 1 10MB 20.357308 0.412410 + 21 False 0 1 10MB 21.380845 1.690947 + 22 True 1 1 10MB 44.487718 1.131427 + 23 False 1 1 10MB 44.517535 1.447279 + 16 True 0 0 10MB 7.446084 0.789432 + 17 False 0 0 10MB 7.060013 0.213669 + 18 True 1 0 10MB 14.277136 0.744163 + 19 False 1 0 10MB 13.758649 0.373940 @@ -1333,9 +1043,9 @@ Links .. rst-class:: sphx-glr-timing - **Total running time of the script:** ( 11 minutes 46.634 seconds) + **Total running time of the script:** ( 11 minutes 26.674 seconds) -**Estimated memory usage:** 6399 MB +**Estimated memory usage:** 7177 MB .. _sphx_glr_download_auto_examples_tutorials_run_word2vec.py: diff --git a/docs/src/auto_examples/tutorials/sg_execution_times.rst b/docs/src/auto_examples/tutorials/sg_execution_times.rst index af55f3f18a..7003c2957e 100644 --- a/docs/src/auto_examples/tutorials/sg_execution_times.rst +++ b/docs/src/auto_examples/tutorials/sg_execution_times.rst @@ -5,18 +5,18 @@ Computation times ================= -**00:07.863** total execution time for **auto_examples_tutorials** files: +**11:26.674** total execution time for **auto_examples_tutorials** files: -+-----------------------------------------------------------------------------------------------+-----------+----------+ -| :ref:`sphx_glr_auto_examples_tutorials_run_annoy.py` (``run_annoy.py``) | 14:40.672 | 752.8 MB | -+-----------------------------------------------------------------------------------------------+-----------+----------+ -| :ref:`sphx_glr_auto_examples_tutorials_run_doc2vec_lee.py` (``run_doc2vec_lee.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+----------+ -| :ref:`sphx_glr_auto_examples_tutorials_run_fasttext.py` (``run_fasttext.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+----------+ -| :ref:`sphx_glr_auto_examples_tutorials_run_lda.py` (``run_lda.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+----------+ -| :ref:`sphx_glr_auto_examples_tutorials_run_wmd.py` (``run_wmd.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+----------+ -| :ref:`sphx_glr_auto_examples_tutorials_run_word2vec.py` (``run_word2vec.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+----------+ ++-------------------------------------------------------------------------------------+-----------+-----------+ +| :ref:`sphx_glr_auto_examples_tutorials_run_word2vec.py` (``run_word2vec.py``) | 11:26.674 | 7177.5 MB | ++-------------------------------------------------------------------------------------+-----------+-----------+ +| :ref:`sphx_glr_auto_examples_tutorials_run_annoy.py` (``run_annoy.py``) | 00:00.000 | 0.0 MB | ++-------------------------------------------------------------------------------------+-----------+-----------+ +| :ref:`sphx_glr_auto_examples_tutorials_run_doc2vec_lee.py` (``run_doc2vec_lee.py``) | 00:00.000 | 0.0 MB | ++-------------------------------------------------------------------------------------+-----------+-----------+ +| :ref:`sphx_glr_auto_examples_tutorials_run_fasttext.py` (``run_fasttext.py``) | 00:00.000 | 0.0 MB | ++-------------------------------------------------------------------------------------+-----------+-----------+ +| :ref:`sphx_glr_auto_examples_tutorials_run_lda.py` (``run_lda.py``) | 00:00.000 | 0.0 MB | ++-------------------------------------------------------------------------------------+-----------+-----------+ +| :ref:`sphx_glr_auto_examples_tutorials_run_wmd.py` (``run_wmd.py``) | 00:00.000 | 0.0 MB | ++-------------------------------------------------------------------------------------+-----------+-----------+ diff --git a/docs/src/gallery/core/run_corpora_and_vector_spaces.py b/docs/src/gallery/core/run_corpora_and_vector_spaces.py index 5a77b4e637..0a49614123 100644 --- a/docs/src/gallery/core/run_corpora_and_vector_spaces.py +++ b/docs/src/gallery/core/run_corpora_and_vector_spaces.py @@ -136,7 +136,7 @@ from smart_open import open # for transparently opening remote files -class MyCorpus(object): +class MyCorpus: def __iter__(self): for line in open('https://radimrehurek.com/gensim/mycorpus.txt'): # assume there's one document per line, tokens separated by whitespace diff --git a/docs/src/gallery/tutorials/run_word2vec.py b/docs/src/gallery/tutorials/run_word2vec.py index 01b0e2bb86..c5ef323bb2 100644 --- a/docs/src/gallery/tutorials/run_word2vec.py +++ b/docs/src/gallery/tutorials/run_word2vec.py @@ -197,8 +197,8 @@ from gensim.test.utils import datapath from gensim import utils -class MyCorpus(object): - """An interator that yields sentences (lists of str).""" +class MyCorpus: + """An iterator that yields sentences (lists of str).""" def __iter__(self): corpus_path = datapath('lee_background.cor') diff --git a/gensim/examples/dmlcz/dmlcorpus.py b/gensim/examples/dmlcz/dmlcorpus.py index a0d9007fa3..d76c622c95 100644 --- a/gensim/examples/dmlcz/dmlcorpus.py +++ b/gensim/examples/dmlcz/dmlcorpus.py @@ -20,7 +20,7 @@ logger = logging.getLogger('gensim.corpora.dmlcorpus') -class DmlConfig(object): +class DmlConfig: """ DmlConfig contains parameters necessary for the abstraction of a 'corpus of articles' (see the `DmlCorpus` class). diff --git a/gensim/examples/dmlcz/sources.py b/gensim/examples/dmlcz/sources.py index c9782f80c4..4c6eb8a048 100644 --- a/gensim/examples/dmlcz/sources.py +++ b/gensim/examples/dmlcz/sources.py @@ -32,7 +32,7 @@ logger = logging.getLogger('gensim.corpora.sources') -class ArticleSource(object): +class ArticleSource: """ Objects of this class describe a single source of articles. diff --git a/gensim/matutils.py b/gensim/matutils.py index dbdd3f1439..48a7ee180a 100644 --- a/gensim/matutils.py +++ b/gensim/matutils.py @@ -336,7 +336,7 @@ def scipy2sparse(vec, eps=1e-9): return [(int(pos), float(val)) for pos, val in zip(vec.indices, vec.data) if np.abs(val) > eps] -class Scipy2Corpus(object): +class Scipy2Corpus: """Convert a sequence of dense/sparse vectors into a streamed Gensim corpus object. See Also @@ -508,7 +508,7 @@ def corpus2dense(corpus, num_terms, num_docs=None, dtype=np.float32): return result.astype(dtype) -class Dense2Corpus(object): +class Dense2Corpus: """Treat dense numpy array as a streamed Gensim corpus in the bag-of-words format. Notes @@ -555,7 +555,7 @@ def __len__(self): return len(self.dense) -class Sparse2Corpus(object): +class Sparse2Corpus: """Convert a matrix in scipy.sparse format into a streaming Gensim corpus. See Also @@ -1132,7 +1132,7 @@ def qr_destroy(la): return q, r -class MmWriter(object): +class MmWriter: """Store a corpus in `Matrix Market format `_, using :class:`~gensim.corpora.mmcorpus.MmCorpus`. diff --git a/gensim/models/basemodel.py b/gensim/models/basemodel.py index 04422f8199..01466f68f9 100644 --- a/gensim/models/basemodel.py +++ b/gensim/models/basemodel.py @@ -1,4 +1,5 @@ -class BaseTopicModel(object): +class BaseTopicModel: + def print_topic(self, topicno, topn=10): """Get a single topic as a formatted string. diff --git a/gensim/models/callbacks.py b/gensim/models/callbacks.py index c07f981848..ab2bb05d8e 100644 --- a/gensim/models/callbacks.py +++ b/gensim/models/callbacks.py @@ -106,7 +106,7 @@ VISDOM_INSTALLED = False -class Metric(object): +class Metric: """Base Metric class for topic model evaluation metrics. Concrete implementations include: @@ -442,7 +442,7 @@ def get_value(self, **kwargs): return np.sum(diff_diagonal) -class Callback(object): +class Callback: """A class representing routines called reactively at specific phases during trained. These can be used to log or visualize the training progress using any of the metric scores developed before. @@ -568,7 +568,7 @@ def on_epoch_end(self, epoch, topics=None): return current_metrics -class CallbackAny2Vec(object): +class CallbackAny2Vec: """Base class to build callbacks for :class:`~gensim.models.word2vec.Word2Vec` & subclasses. Callbacks are used to apply custom functions over the model at specific points diff --git a/gensim/models/doc2vec.py b/gensim/models/doc2vec.py index 453f704401..51fdfdce43 100644 --- a/gensim/models/doc2vec.py +++ b/gensim/models/doc2vec.py @@ -1085,7 +1085,7 @@ class Doc2VecTrainables(utils.SaveLoad): """Obsolete class retained for now as load-compatibility state capture""" -class TaggedBrownCorpus(object): +class TaggedBrownCorpus: def __init__(self, dirname): """Reader for the `Brown corpus (part of NLTK data) `_. @@ -1123,7 +1123,7 @@ def __iter__(self): yield TaggedDocument(words, ['%s_SENT_%s' % (fname, item_no)]) -class TaggedLineDocument(object): +class TaggedLineDocument: def __init__(self, source): """Iterate over a file that contains documents: one line = :class:`~gensim.models.doc2vec.TaggedDocument` object. diff --git a/gensim/models/hdpmodel.py b/gensim/models/hdpmodel.py index c29e0a0737..5e0fbfe3e2 100755 --- a/gensim/models/hdpmodel.py +++ b/gensim/models/hdpmodel.py @@ -140,7 +140,7 @@ def lda_e_step(doc_word_ids, doc_word_counts, alpha, beta, max_iter=100): return likelihood, gamma -class SuffStats(object): +class SuffStats: """Stores sufficient statistics for the current chunk of document(s) whenever Hdp model is updated with new corpus. These stats are used when updating lambda and top level sticks. The statistics include number of documents in the chunk, length of words in the documents and top level truncation level. @@ -953,7 +953,7 @@ def evaluate_test_corpus(self, corpus): return score -class HdpTopicFormatter(object): +class HdpTopicFormatter: """Helper class for :class:`gensim.models.hdpmodel.HdpModel` to format the output of topics.""" (STYLE_GENSIM, STYLE_PRETTY) = (1, 2) diff --git a/gensim/models/keyedvectors.py b/gensim/models/keyedvectors.py index 0e22fe9a46..193c5f8f0f 100644 --- a/gensim/models/keyedvectors.py +++ b/gensim/models/keyedvectors.py @@ -1720,7 +1720,7 @@ def similarity_unseen_docs(self, *args, **kwargs): EuclideanKeyedVectors = KeyedVectors -class CompatVocab(object): +class CompatVocab: def __init__(self, **kwargs): """A single vocabulary item, used internally for collecting per-word frequency/sampling info, and for constructing binary trees (incl. both word leaves and inner nodes). diff --git a/gensim/models/lda_dispatcher.py b/gensim/models/lda_dispatcher.py index f81cd806eb..41dc3e632b 100755 --- a/gensim/models/lda_dispatcher.py +++ b/gensim/models/lda_dispatcher.py @@ -87,7 +87,7 @@ LDA_DISPATCHER_PREFIX = 'gensim.lda_dispatcher' -class Dispatcher(object): +class Dispatcher: """Dispatcher object that communicates and coordinates individual workers. Warnings diff --git a/gensim/models/lda_worker.py b/gensim/models/lda_worker.py index cac24c2698..25d787738e 100755 --- a/gensim/models/lda_worker.py +++ b/gensim/models/lda_worker.py @@ -78,7 +78,7 @@ LDA_WORKER_PREFIX = 'gensim.lda_worker' -class Worker(object): +class Worker: """Used as a Pyro4 class with exposed methods. Exposes every non-private method and property of the class automatically to be available for remote access. diff --git a/gensim/models/lsi_worker.py b/gensim/models/lsi_worker.py index 4a38ba8e2d..a3b5845f19 100755 --- a/gensim/models/lsi_worker.py +++ b/gensim/models/lsi_worker.py @@ -1,194 +1,193 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2010 Radim Rehurek -# Licensed under the GNU LGPL v2.1 - http://www.gnu.org/licenses/lgpl.html - -"""Worker ("slave") process used in computing distributed Latent Semantic Indexing (LSI, -:class:`~gensim.models.lsimodel.LsiModel`) models. - -Run this script on every node in your cluster. If you wish, you may even run it multiple times on a single machine, -to make better use of multiple cores (just beware that memory footprint increases linearly). - - -How to use distributed LSI --------------------------- - -#. Install needed dependencies (Pyro4) :: - - pip install gensim[distributed] - -#. Setup serialization (on each machine) :: - - export PYRO_SERIALIZERS_ACCEPTED=pickle - export PYRO_SERIALIZER=pickle - -#. Run nameserver :: - - python -m Pyro4.naming -n 0.0.0.0 & - -#. Run workers (on each machine) :: - - python -m gensim.models.lsi_worker & - -#. Run dispatcher :: - - python -m gensim.models.lsi_dispatcher & - -#. Run :class:`~gensim.models.lsimodel.LsiModel` in distributed mode: - - .. sourcecode:: pycon - - >>> from gensim.test.utils import common_corpus, common_dictionary - >>> from gensim.models import LsiModel - >>> - >>> model = LsiModel(common_corpus, id2word=common_dictionary, distributed=True) - - -Command line arguments ----------------------- - -.. program-output:: python -m gensim.models.lsi_worker --help - :ellipsis: 0, -3 - -""" - -from __future__ import with_statement -import os -import sys -import logging -import argparse -import threading -import tempfile -try: - import Queue -except ImportError: - import queue as Queue -import Pyro4 -from gensim.models import lsimodel -from gensim import utils - -logger = logging.getLogger(__name__) - - -SAVE_DEBUG = 0 # save intermediate models after every SAVE_DEBUG updates (0 for never) - - -class Worker(object): - def __init__(self): - """Partly initialize the model. - - A full initialization requires a call to :meth:`~gensim.models.lsi_worker.Worker.initialize`. - - """ - self.model = None - - @Pyro4.expose - def initialize(self, myid, dispatcher, **model_params): - """Fully initialize the worker. - - Parameters - ---------- - myid : int - An ID number used to identify this worker in the dispatcher object. - dispatcher : :class:`~gensim.models.lsi_dispatcher.Dispatcher` - The dispatcher responsible for scheduling this worker. - **model_params - Keyword parameters to initialize the inner LSI model, see :class:`~gensim.models.lsimodel.LsiModel`. - - """ - self.lock_update = threading.Lock() - self.jobsdone = 0 # how many jobs has this worker completed? - # id of this worker in the dispatcher; just a convenience var for easy access/logging TODO remove? - self.myid = myid - self.dispatcher = dispatcher - self.finished = False - logger.info("initializing worker #%s", myid) - self.model = lsimodel.LsiModel(**model_params) - - @Pyro4.expose - @Pyro4.oneway - def requestjob(self): - """Request jobs from the dispatcher, in a perpetual loop until :meth:`~gensim.models.lsi_worker.Worker.getstate` - is called. - - Raises - ------ - RuntimeError - If `self.model` is None (i.e. worker not initialized). - - """ - if self.model is None: - raise RuntimeError("worker must be initialized before receiving jobs") - - job = None - while job is None and not self.finished: - try: - job = self.dispatcher.getjob(self.myid) - except Queue.Empty: - # no new job: try again, unless we're finished with all work - continue - if job is not None: - logger.info("worker #%s received job #%i", self.myid, self.jobsdone) - self.processjob(job) - self.dispatcher.jobdone(self.myid) - else: - logger.info("worker #%i stopping asking for jobs", self.myid) - - @utils.synchronous('lock_update') - def processjob(self, job): - """Incrementally process the job and potentially logs progress. - - Parameters - ---------- - job : iterable of list of (int, float) - Corpus in BoW format. - - """ - self.model.add_documents(job) - self.jobsdone += 1 - if SAVE_DEBUG and self.jobsdone % SAVE_DEBUG == 0: - fname = os.path.join(tempfile.gettempdir(), 'lsi_worker.pkl') - self.model.save(fname) - - @Pyro4.expose - @utils.synchronous('lock_update') - def getstate(self): - """Log and get the LSI model's current projection. - - Returns - ------- - :class:`~gensim.models.lsimodel.Projection` - The current projection. - - """ - logger.info("worker #%i returning its state after %s jobs", self.myid, self.jobsdone) - assert isinstance(self.model.projection, lsimodel.Projection) - self.finished = True - return self.model.projection - - @Pyro4.expose - @utils.synchronous('lock_update') - def reset(self): - """Reset the worker by deleting its current projection.""" - logger.info("resetting worker #%i", self.myid) - self.model.projection = self.model.projection.empty_like() - self.finished = False - - @Pyro4.oneway - def exit(self): - """Terminate the worker.""" - logger.info("terminating worker #%i", self.myid) - os._exit(0) - - -if __name__ == '__main__': - """The main script. """ - logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO) - - parser = argparse.ArgumentParser(description=__doc__[:-135], formatter_class=argparse.RawTextHelpFormatter) - _ = parser.parse_args() - - logger.info("running %s", " ".join(sys.argv)) - utils.pyro_daemon('gensim.lsi_worker', Worker(), random_suffix=True) - logger.info("finished running %s", parser.prog) +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) 2010 Radim Rehurek +# Licensed under the GNU LGPL v2.1 - http://www.gnu.org/licenses/lgpl.html + +"""Worker ("slave") process used in computing distributed Latent Semantic Indexing (LSI, +:class:`~gensim.models.lsimodel.LsiModel`) models. + +Run this script on every node in your cluster. If you wish, you may even run it multiple times on a single machine, +to make better use of multiple cores (just beware that memory footprint increases linearly). + + +How to use distributed LSI +-------------------------- + +#. Install needed dependencies (Pyro4) :: + + pip install gensim[distributed] + +#. Setup serialization (on each machine) :: + + export PYRO_SERIALIZERS_ACCEPTED=pickle + export PYRO_SERIALIZER=pickle + +#. Run nameserver :: + + python -m Pyro4.naming -n 0.0.0.0 & + +#. Run workers (on each machine) :: + + python -m gensim.models.lsi_worker & + +#. Run dispatcher :: + + python -m gensim.models.lsi_dispatcher & + +#. Run :class:`~gensim.models.lsimodel.LsiModel` in distributed mode: + + .. sourcecode:: pycon + + >>> from gensim.test.utils import common_corpus, common_dictionary + >>> from gensim.models import LsiModel + >>> + >>> model = LsiModel(common_corpus, id2word=common_dictionary, distributed=True) + + +Command line arguments +---------------------- + +.. program-output:: python -m gensim.models.lsi_worker --help + :ellipsis: 0, -3 + +""" + +import os +import sys +import logging +import argparse +import threading +import tempfile +import queue as Queue + +import Pyro4 + +from gensim.models import lsimodel +from gensim import utils + + +logger = logging.getLogger(__name__) + + +SAVE_DEBUG = 0 # save intermediate models after every SAVE_DEBUG updates (0 for never) + + +class Worker: + def __init__(self): + """Partly initialize the model. + + A full initialization requires a call to :meth:`~gensim.models.lsi_worker.Worker.initialize`. + + """ + self.model = None + + @Pyro4.expose + def initialize(self, myid, dispatcher, **model_params): + """Fully initialize the worker. + + Parameters + ---------- + myid : int + An ID number used to identify this worker in the dispatcher object. + dispatcher : :class:`~gensim.models.lsi_dispatcher.Dispatcher` + The dispatcher responsible for scheduling this worker. + **model_params + Keyword parameters to initialize the inner LSI model, see :class:`~gensim.models.lsimodel.LsiModel`. + + """ + self.lock_update = threading.Lock() + self.jobsdone = 0 # how many jobs has this worker completed? + # id of this worker in the dispatcher; just a convenience var for easy access/logging TODO remove? + self.myid = myid + self.dispatcher = dispatcher + self.finished = False + logger.info("initializing worker #%s", myid) + self.model = lsimodel.LsiModel(**model_params) + + @Pyro4.expose + @Pyro4.oneway + def requestjob(self): + """Request jobs from the dispatcher, in a perpetual loop until :meth:`~gensim.models.lsi_worker.Worker.getstate` + is called. + + Raises + ------ + RuntimeError + If `self.model` is None (i.e. worker not initialized). + + """ + if self.model is None: + raise RuntimeError("worker must be initialized before receiving jobs") + + job = None + while job is None and not self.finished: + try: + job = self.dispatcher.getjob(self.myid) + except Queue.Empty: + # no new job: try again, unless we're finished with all work + continue + if job is not None: + logger.info("worker #%s received job #%i", self.myid, self.jobsdone) + self.processjob(job) + self.dispatcher.jobdone(self.myid) + else: + logger.info("worker #%i stopping asking for jobs", self.myid) + + @utils.synchronous('lock_update') + def processjob(self, job): + """Incrementally process the job and potentially logs progress. + + Parameters + ---------- + job : iterable of list of (int, float) + Corpus in BoW format. + + """ + self.model.add_documents(job) + self.jobsdone += 1 + if SAVE_DEBUG and self.jobsdone % SAVE_DEBUG == 0: + fname = os.path.join(tempfile.gettempdir(), 'lsi_worker.pkl') + self.model.save(fname) + + @Pyro4.expose + @utils.synchronous('lock_update') + def getstate(self): + """Log and get the LSI model's current projection. + + Returns + ------- + :class:`~gensim.models.lsimodel.Projection` + The current projection. + + """ + logger.info("worker #%i returning its state after %s jobs", self.myid, self.jobsdone) + assert isinstance(self.model.projection, lsimodel.Projection) + self.finished = True + return self.model.projection + + @Pyro4.expose + @utils.synchronous('lock_update') + def reset(self): + """Reset the worker by deleting its current projection.""" + logger.info("resetting worker #%i", self.myid) + self.model.projection = self.model.projection.empty_like() + self.finished = False + + @Pyro4.oneway + def exit(self): + """Terminate the worker.""" + logger.info("terminating worker #%i", self.myid) + os._exit(0) + + +if __name__ == '__main__': + """The main script. """ + logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO) + + parser = argparse.ArgumentParser(description=__doc__[:-135], formatter_class=argparse.RawTextHelpFormatter) + _ = parser.parse_args() + + logger.info("running %s", " ".join(sys.argv)) + utils.pyro_daemon('gensim.lsi_worker', Worker(), random_suffix=True) + logger.info("finished running %s", parser.prog) diff --git a/gensim/models/poincare.py b/gensim/models/poincare.py index 050aa52e9b..136fd6b6d5 100644 --- a/gensim/models/poincare.py +++ b/gensim/models/poincare.py @@ -699,7 +699,7 @@ def _train_batchwise(self, epochs, batch_size=10, print_every=1000, check_gradie avg_loss = 0.0 -class PoincareBatch(object): +class PoincareBatch: """Compute Poincare distances, gradients and loss for a training batch. Store intermediate state to avoid recomputing multiple times. @@ -1305,7 +1305,7 @@ def difference_in_hierarchy(self, node_or_vector_1, node_or_vector_2): return self.norm(node_or_vector_2) - self.norm(node_or_vector_1) -class PoincareRelations(object): +class PoincareRelations: """Stream relations for `PoincareModel` from a tsv-like file.""" def __init__(self, file_path, encoding='utf8', delimiter='\t'): @@ -1354,7 +1354,7 @@ def __iter__(self): yield tuple(row) -class NegativesBuffer(object): +class NegativesBuffer: """Buffer and return negative samples.""" def __init__(self, items): @@ -1405,7 +1405,7 @@ def get_items(self, num_items): return self._items[start_index:end_index] -class ReconstructionEvaluation(object): +class ReconstructionEvaluation: """Evaluate reconstruction on given network for given embedding.""" def __init__(self, file_path, embedding): @@ -1508,7 +1508,7 @@ def evaluate_mean_rank_and_map(self, max_n=None): return np.mean(ranks), np.mean(avg_precision_scores) -class LinkPredictionEvaluation(object): +class LinkPredictionEvaluation: """Evaluate reconstruction on given network for given embedding.""" def __init__(self, train_path, test_path, embedding): @@ -1619,7 +1619,7 @@ def evaluate_mean_rank_and_map(self, max_n=None): return np.mean(ranks), np.mean(avg_precision_scores) -class LexicalEntailmentEvaluation(object): +class LexicalEntailmentEvaluation: """Evaluate reconstruction on given network for any embedding.""" def __init__(self, filepath): diff --git a/gensim/models/word2vec.py b/gensim/models/word2vec.py index 1a0879f163..c53d252bf4 100755 --- a/gensim/models/word2vec.py +++ b/gensim/models/word2vec.py @@ -1965,7 +1965,7 @@ def get_latest_training_loss(self): return self.running_training_loss -class BrownCorpus(object): +class BrownCorpus: def __init__(self, dirname): """Iterate over sentences from the `Brown corpus `_ (part of `NLTK data `_). @@ -1991,7 +1991,7 @@ def __iter__(self): yield words -class Text8Corpus(object): +class Text8Corpus: def __init__(self, fname, max_sentence_length=MAX_WORDS_IN_BATCH): """Iterate over sentences from the "text8" corpus, unzipped from http://mattmahoney.net/dc/text8.zip.""" self.fname = fname @@ -2019,7 +2019,7 @@ def __iter__(self): sentence = sentence[self.max_sentence_length:] -class LineSentence(object): +class LineSentence: def __init__(self, source, max_sentence_length=MAX_WORDS_IN_BATCH, limit=None): """Iterate over a file that contains sentences: one line = one sentence. Words must be already preprocessed and separated by whitespace. @@ -2068,7 +2068,7 @@ def __iter__(self): i += self.max_sentence_length -class PathLineSentences(object): +class PathLineSentences: def __init__(self, source, max_sentence_length=MAX_WORDS_IN_BATCH, limit=None): """Like :class:`~gensim.models.word2vec.LineSentence`, but process all files in a directory in alphabetical order by filename. diff --git a/gensim/parsing/porter.py b/gensim/parsing/porter.py index 528103a874..81c465e1b7 100644 --- a/gensim/parsing/porter.py +++ b/gensim/parsing/porter.py @@ -30,7 +30,7 @@ """ -class PorterStemmer(object): +class PorterStemmer: """Class contains implementation of Porter stemming algorithm. Attributes diff --git a/gensim/test/svd_error.py b/gensim/test/svd_error.py index e6ab11bb78..1763866e00 100755 --- a/gensim/test/svd_error.py +++ b/gensim/test/svd_error.py @@ -72,7 +72,7 @@ def print_error(name, aat, u, s, ideal_nf, ideal_n2): sys.stdout.flush() -class ClippedCorpus(object): +class ClippedCorpus: def __init__(self, corpus, max_docs, max_terms): self.corpus = corpus self.max_docs, self.max_terms = max_docs, max_terms diff --git a/gensim/test/test_big.py b/gensim/test/test_big.py index d6c5bd9d18..1716285c10 100644 --- a/gensim/test/test_big.py +++ b/gensim/test/test_big.py @@ -19,7 +19,7 @@ from gensim.test.utils import get_tmpfile -class BigCorpus(object): +class BigCorpus: """A corpus of a large number of docs & large vocab""" def __init__(self, words_only=False, num_terms=200000, num_docs=1000000, doc_len=100): diff --git a/gensim/test/test_corpora.py b/gensim/test/test_corpora.py index e13e06ca36..611cc875eb 100644 --- a/gensim/test/test_corpora.py +++ b/gensim/test/test_corpora.py @@ -30,7 +30,7 @@ AZURE = bool(os.environ.get('PIPELINE_WORKSPACE')) -class DummyTransformer(object): +class DummyTransformer: def __getitem__(self, bow): if len(next(iter(bow))) == 2: # single bag of words diff --git a/gensim/test/test_probability_estimation.py b/gensim/test/test_probability_estimation.py index 1e674415f3..73820d8df5 100644 --- a/gensim/test/test_probability_estimation.py +++ b/gensim/test/test_probability_estimation.py @@ -16,7 +16,7 @@ from gensim.topic_coherence import probability_estimation -class BaseTestCases(object): +class BaseTestCases: class ProbabilityEstimationBase(unittest.TestCase): texts = [ diff --git a/gensim/test/test_similarities.py b/gensim/test/test_similarities.py index 6a0321fdbe..819493a3fe 100644 --- a/gensim/test/test_similarities.py +++ b/gensim/test/test_similarities.py @@ -556,7 +556,7 @@ def testWord2Vec(self): self.assertLoadedIndexEqual(index, model) def testFastText(self): - class LeeReader(object): + class LeeReader: def __init__(self, fn): self.fn = fn @@ -715,7 +715,7 @@ def test_word2vec(self): self.assertLoadedIndexEqual(index, model) def test_fasttext(self): - class LeeReader(object): + class LeeReader: def __init__(self, fn): self.fn = fn diff --git a/gensim/test/test_text_analysis.py b/gensim/test/test_text_analysis.py index 83df8ece57..2f4524aacc 100644 --- a/gensim/test/test_text_analysis.py +++ b/gensim/test/test_text_analysis.py @@ -8,7 +8,7 @@ from gensim.test.utils import common_texts -class BaseTestCases(object): +class BaseTestCases: class TextAnalyzerTestBase(unittest.TestCase): texts = [ diff --git a/gensim/test/utils.py b/gensim/test/utils.py index 158c0989b8..526d3a436a 100644 --- a/gensim/test/utils.py +++ b/gensim/test/utils.py @@ -208,7 +208,7 @@ def temporary_file(name=""): common_corpus = [common_dictionary.doc2bow(text) for text in common_texts] -class LeeCorpus(object): +class LeeCorpus: def __iter__(self): with open(datapath('lee_background.cor')) as f: for line in f: diff --git a/gensim/topic_coherence/indirect_confirmation_measure.py b/gensim/topic_coherence/indirect_confirmation_measure.py index 76077813d0..3e96c8fbc2 100644 --- a/gensim/topic_coherence/indirect_confirmation_measure.py +++ b/gensim/topic_coherence/indirect_confirmation_measure.py @@ -182,7 +182,7 @@ def cosine_similarity(segmented_topics, accumulator, topics, measure='nlr', return topic_coherences -class ContextVectorComputer(object): +class ContextVectorComputer: """Lazily compute context vectors for topic segments. Parameters diff --git a/gensim/topic_coherence/text_analysis.py b/gensim/topic_coherence/text_analysis.py index fb4fda99b8..83cbdc6471 100644 --- a/gensim/topic_coherence/text_analysis.py +++ b/gensim/topic_coherence/text_analysis.py @@ -67,7 +67,7 @@ def _ids_to_words(ids, dictionary): return top_words -class BaseAnalyzer(object): +class BaseAnalyzer: """Base class for corpus and text analyzers. Attributes From 8935c58bc50d0c6f2abd67e172499c3b09b78cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Wed, 28 Oct 2020 01:32:04 +0100 Subject: [PATCH 16/20] work around issues with flake8-rst --- .../images/sphx_glr_run_word2vec_001.png | Bin 97798 -> 109697 bytes .../thumb/sphx_glr_run_word2vec_thumb.png | Bin 22362 -> 24438 bytes gensim/models/fasttext.py | 2 +- tox.ini | 22 ++++++++++++++---- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/docs/src/auto_examples/tutorials/images/sphx_glr_run_word2vec_001.png b/docs/src/auto_examples/tutorials/images/sphx_glr_run_word2vec_001.png index 6fafecbcf37142eea6f9c0350f574fe647556e0d..35e81eff9254c4a8069bd9a87d1721c23a99d343 100644 GIT binary patch literal 109697 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≤6q(>tsFV6kt`3f3%^_xmQj!8_9ahwu&hwd~NLOfoN9)UOsTNovB!t}Y|A z>hE>KLW0i-%Iz{Fp6zYEO8&)wBH8qAn1)P`g3=uAkWZ?x+U}vs9TttefQrZ89;ztt zbK7Ey@Ok?Azh|Ud|GXrdT&{TG*<@62MCXa^elG2_S_{9ZJ^as&pB^W z4KyC4bD;$&UMP3f8vDvSl$EqS*nZ8>dU>h#7?z-?x3Js%Z5T@hZ9$s`PZegCv%xu< zAt4(_lGD#Kzg6?5@Q>4DY6M}jY1@n3eW`VA3rouu|i~C^OrNn0Z zDLKCbjE9G(WZVW80H%nWUp|?Ok!Noyw;bN{-~^bx^oZ;YIB~z{5i$ z<0=UW@p@9ADDG&+!@Dc?vC2*RZ0a1{1KSAcm`ZZxT+71brNuuH#HLVUv28c znzudcCT-bJw~k8fs^{;twYSfM#RC&oK5xO?JrYb$kKHX7`r=VI7&^%;Eyc5MJY(3Y zKTwjCmPU8!0aK1GKku{BW>V&t^n@&-KnwA01>Ab{r4vEAB@0FrO#{A(bB62KLm`W~$&7>iNFf_Yx-w+HJZZ zJ^0Jx;nL+WCBl9;7>BB(-|v{q2Yk^fx45{YD~^TJ^cOCy85(rj5fl&*2>JN&nUN7C zFjz`~X_N6OAtdB6F>y03?Z#Wo?oWy7#+V$xHBx`*uJ8gmpg)V;(kcEBW+yYc7^ER0 zm*4Y8&+aFg5wa;3o7U9TxzQR=w2t8P+^>=cTqGeO&!csQ`%NwXo}N)qewUO_?uBnM zw`L94_h^i4d7yOV>J&~m+?S{FBKrBE9`RKom{wSr-2ZCRnA3hnI5sZsReLDGc5#+k z-V^U*8&;!wVld(-{pQX0^xdeCklYK0dmzAYOe*f`7^%#Bof~cbMIofduT~5H!*hi`mi8(Qdp_O5gP8Ws#R)xvnh39GquP z*Hxbhd6lh8B2ikK`+Q75t-@GC4lNe*L+2d9OAc21a_+C$T|L`@k|Qj?^41el^E;QK zQKB1Pv-I&*xo-GT`M5qvK2C3&vQ{hM@1*uraCYVbW7~niFP#U2fG_t#L2zKB=txS6 zD42)B!k8*j?;0TmFvx`q=>8^7B7U@adit2BxRx8KJ#KW{ukbh4FINT!X~~gc@M%@M z9*Q}E+O)~A`r0zgN$k`PEbR@4qY^p=;`lX;B=ChbBry9*1!iFPPMU5+s88rXFw5P4 ziHCRe#3>Ypu5W9?qD7=h&8tSgd1@WRxM1!-K~rP+!cLrBXSxmmNd8OIoye5D&gg#T z{UP(XkVq|)W!tQ1aFYNgIlYg!0%jvY02Y*l2!Q}xEWmKk7DOxweP&^J{^4C9L&6+^ zL#ep8qVK&!(*6(21SRNoPu0pHELFw0>o(U2!S$cVf#8Gg-huEcV@pHiuha0?;p*$^ zK}*{GwOE!~OO5UEIxE@W?`>P91o~a2rW21l_jguNnupf!5IQhsic0rXV;$$rX5wJ~ zv@)4xprysM-FhyA)VYHr`4*(ab|?&`xlMCY#Ew&=c_zH%MP^wX@^Q18Px-`dpEf4i z++}z)ZqbW^(V&Cg#Z8;Nmzfefuy9b;;S!s2M6*<&C6Vd_pK}i_dMB_2br|z z=9yZBd?`TOghFvM20=uNFaeU0;B>&**|&&*SQ(!!OS9+hG%uH?C<+!vJPW5C+g5c@ zk#wHgJ_I1@uw~P*wevopp|AT>`Ljf;fmh0AJfV?kXfOTk@!3sQK_u6;ebPUHHJy55 z!N3&=8RGAUPfPEAUP4U~nPnX(hz6^kV{(TOjr`H9q+wP`&z~K1Wrb?YBO^iFMjr(K z(x;lX<(h>qs~){7=`j)Q*)ISi@pSg=n5@W_%~5Rq)~4^pjU zSe)A19P{k1+H|oNmgs7P1QU#y@`BWT{$0#H2tH_-Raz)lx4mH{02G3)3}x{;*I1mzkuKunK0UM*-;tLb zAp;TwFgtdtew19!M@b_)LBdty66--zC>*Tce4n4b@C$vv7QrFI?+;y@D<2fvm`G~d zqwN_{fG6B3Seaf|YEVC|YugEYEiTtX4zVJdK~+J>vmzjM*r)M6hU7MYEdEaFvfYT^ z)~_6=Hm@eX_eEcAf9@PE=p$yg%>dyo62$q%|2UuhsJIQeF74g(%!?l}jF0=}<~cmhK%q8!S1pX$Ab^@S^CgJPkX&>YR<756 zewKA}u{u5?9DIgPA1_Tk>$1Y%nE)@et{iUwj@X@PB13XWQD&7CeKj*7y`1 zQ2ZWPgePte$Z1mscbt90whkVc{G7Dij@Q%p7^!BWr1g|giE`&u*gPsMBm`NJ1_POe zOAY!~#{bD+KMHw~@U?AE{#dF^eXjy*3fnuE_zG^&^X!}G?wOpO;1Bhqh-MP%)NwS} zM52SR$Rh&2>`EM&Gg2I|(juI>ruo)CLzNr%b$9oc>xQDaRu*2r&ygZf^(iN1u_wcV z84+oPguHtTAKaRV$jyz@y9cv|=(e9+&{_7SBb}3vlyN4w8m9c` zLi8!`b$=4=6bFiqag2VX&Xs$lBX|F=;iADi?SL!q?5q|R@pB=7^}nbJ-%3f2Nc?8| z&c4d;Un|paHp|SK;v)cP^_T*_U)wI(+|IknbJVL-{j7F44tB9|@%NpR0?%4?Y82S& zy&U#e)U|k_vn2N0#Xq+SANmmiNp75Yd(w~XBO;2s1SR&p&KxBy?dg5*DzJ(k=RHM< zx(PJ1uDOd-e1kbdIGP%0C@DF@6+(e!o{jZ9tAA z+B5B9I9i|Opojl4bR_J*+0+-lf$x@F{L;1K1Pm;DOTaH*hd)Tw2fqwM@aNS)V|Ux} zo{H`vb2`v7-cumUIxb-IrqUW}Xzb7XWL=$`zxkfo?dN+L4E)R&D1Z8jLTp;zkFze^~Ov;88UI*Gx*HYzlWJM<8&hn6+QL6j&9xk4$GEaNP=Tz58 z-PeneJ+D3*I*9?~AHNmv&wzLbx|p5BsTtjzi>fgY_V&08P1vePszr11r1qI{Si^C&d{Kqzz&m<*jZ#5!Ko1XfP7-pN2 zVjAXzm!NWJHD0TTIQ@yR@}vNvQsb1hiUN{1HTxr}O@uGlKXW{xCAZNxdqvARwQEWs z?uI!7KmwrX*doUh#Y*H41$*!Pswp1b2`$q(EBz1E&*Ue{&G5qKz!yGVd(xdICle8c(coqGl6y30o>N)sK_-htv+m<#SWNq>R)zJxE4ZJz?j8Xj#uKf}>l2H88 z|6maKefjb!%Y3tR)q=-r%8L81P*4aAM8ZAd=FEUaboA&OsH6<$+u7ZD_3JwL;U+K^iDFQ*rbgQk9+KQD7d6uu6^woUbXb)c$25YLB zVNZdc{bN&C_k{6@pxcTIB<{4yFg_#zZ!-*+s}pBC=JnQzvfQ)h3X(ZoC9q09Mq1js zVxy4#Htkg-aHQeXa~a8z-fYZt^f2V+PV`U2c?i@cujz&buu&p`a(R%ui zM#6-=HS5|fdVPm;{?#9SO|0g|3g4e*Q${k954&z-?ZpSP7vN~DUy{Z|L~kz`jDpNX zMV9u79XHd@d{%2EnP6+&$H?2D?1e#M12C{(Q{MfR^LRV5U|6#T;*7!3!i$I zTBLx6gOPs;id7IEZu>Fh{0AW9cm=Z2>DDNX$$?PM+YA123z&+aa7CKtO-y;n<}IJD zg#Q6VSz?0m#10Rq_|cYa7E;Fa@e2S^c=buuR(0Lh=l9@_uE`;}yF-?lwcZ#;Y#fiF zdZ%>P14}90`e%TS_lwezC(7RSP12ZE`4Atgc zfHL-V2*9J4uBuXXw6zP1;PKoSwq*~K6VBh8x>Lw{%-IT*y)17{t4;Wzlc)O4n+{yl~87bs!v@2ab-cPOz{Bh4!ACW1BXB(M@_lWp>5(7gO` zuGyG&;G&qy@BkFF@%P0Ew6#peYDGjlD_`xPCNvWPxyYtw=r+xjxJ3Ra=Hd$9rm>On zW3KltZ9_JS-GcQ8JtY-+e1f2fj!L&@Oq^jGpkSdEU?T18#=67~*D4mLYC;UR*x6>XULuxUqaMhYQT|fWw-!Y6(h<_n`e*HGU z!25T(s!r*0)aT3I< zMt>k6Qc6oB-H3!Vh=6oUcS?7sAYDp}v>@Fg-3?MocM8(o@%F*{f8Y0><2oFA^_+dq zS$oBtbFJ+%)q6wHX4k}1hPX6WyPh2e9P;4JB-T9 z=iDl{lro9~_bVmOF zy+@=2EJO_7 z;8Pz^J&WQXfG`UxE5T@NE&Dr@83W+etg8vF%-;p(Wa384)xtObZ1}Eh1o{n(^tJVQ zA0!XGe7MRB9NXNh92Ig)H>}%hA)^2vRsa^3N+Fc`g@;S^qxMa;ehle(2<=S&jO@Pc ziSZB3R(#9OhV=*G*u%O#U7LBpmp9mTtAmOp^LOiWYZ7q54Mkndw!W}Y4m6$Y?R9qZ zd6A^jp!hi@<~~ZKuE4+pC0E41G9@ZGN|FuJ51!k*gn&`-0_o3Xi`B~6S|h6*@W%)` z#FkQ6n34vd$e=?;>Oe9rOsh-|8g#|N>5jjz=B6@Pf~64c#&RCTAZ||Va{HgZ<5ZpJ zO0MFEqElYnsn}CjMGNXb>xoEJMwuHRRa^!?;q~oZDJbZn;Ddu;=$DsUl**u=j;7~q z4iAv9gWgs$Hpgp)Zp+)UN5b=FZ=SO@t5no@S-)lkiAxqJ_AlOJgOB+YJOKokOd$9e z^bvtKeZ=aOsA&ydqTKyX5=Tw7QWX#LMB{&Ohzk^*nui0+*vY=5Oj^plov7{+)V1?O zgMkp)3W6U?Rjna~3bHbTzWFh0y)-rfl635u<1v06qXQ}ecxAkWvMp&}$C9qj7G0Tf z==E(|urR-U$loZ)ugRb%N?qw=5d~|l7 zaAL-J1hXL2)B*oP-=S|17=$zwZ&9+q8*pJxjzD*$)jzq52;`!fEoJsZ2^4T-FpD6S z&L!F&a_1h`UI=@6=Slnz^tQKEeF3T^zad{&56*-Oq6O1^KDzd)JH#~6btw6w)7%>43p+cTnbVl zu^}z&F61lZCw;lTiBrVF%Vc!iN^dF;Vt(puJsw6#l`A@eUkn2~@Q6uUT6S%-e${*< z2NU>?-i%PzzguJR98}sYsi>g#+WCVz>mebU8N~^z!@O_Jvt0y4%R7W%_28i%(i!j;+y~HR8t&fkrwO3++caSvvEbyL8H2n(Kn*;$ znez#kN4aArjVAMj4oeGZho-JV)Fd+J;P^|vitcl7S-Zke%Bch zHNw7M>ALvNy)$nE1(h>@cX6O74#RyKC$fAhw4O}hKwD!r#0jb*;==6rX-_S)+Q7b; z)3I|NF^CvGaWszE$uAN=7^#G9zp4dp#eo_y2A2&HILyb%5=l(56`Q&)_~nJqs`0QC z<+};haqMP2WvB*}UyV`!MpG}((H=*baE~9gz_uIvt<_lay)Or5=Xt4r{q^{vMt5Zs zE+*zD+xs0`w$?;@x8YD)Er}BbWz@0rBC%@z=kD)9Jn8k7^vrS&~yT(*@i}RD4z7h(~{>|J1ZpxN5sKr$7 zU6JuWr>~1z;N#U2lDJD4jH`uFh3X(l!iuMlE_xcD6jB&|WGii`hM!9fwx8JUfL01> zZZuKyFbf}_peA~YCv&0xl=muHcpbK4bSDfCQ}JWG%4ct+9FVV3b%^RuWc9jPy2clk zd^oLBPIWCPApqOv;Fr!y#)PN`NnzzKot!iXd0{DEs=1GFX5qJwg0md3br-yg`nzgf z-cSqD3G`;|ijGp=r^Fw72UK{yOCEvhS+X4SMJaL8m?9gy6(ESzUkofB6`)L33x;4@ zfoI?3W~<=@4AzU_DWc4fA?D9M)VjU0uEr+Lh>+hrls@>|+7i!5PJx1OADx);(;NKa zl18XrR?<7FQyeGv_*m&Hx2^R8m*|gNOY&!Px3i}7OP%IlWL$7=b~kEp*2J$x zM+u-kibG|%{>s+6k}r9LN>_Q?W>pvV<7>w@>y_vQ3R4O{v1gR(O7ok+Wn*hfme6Ps zt84(Mwt$3@B8%mZuC(RU0MgHXR`gAQMEp3Tf>+&p-V~cIP~MLCzIrfV&?&jcB~a;% zxcGF+Jr7{^h1I0u<7<)-ZhhGEK52iO3pgiU4&Bbc@|uaNX#nD4llkntNJ|td6#a)@ z4ah+EvWWx4LBDH`(Nd7oq?ar&Z_hh(5y^Os3SYd)zokx`UzdQ8ekZRNdR&CdUIHJ z8iFlStA&x{#O38=tBL|STl={GQaBhkc}%i44RZ>8GV1C z*xg&^#uL7$^|minYC0pcrO;}y`^nriKU6+y0fB6P_|ki_;f`t?hop-?bj6ZL3y@~; zV5CX>31?^zr72`mNwa=~IJwrIb0i2@`g-QLS|(=M?=r)~_iG~+SdE}NV4g53&7hY8 z&g&{_qGx`5UH&2fut_+?$2w%+AysPP4GoT80tW&LDMuHFh1o9;ONP<_W59B6`(NZY-dD{Vt%cPMATg=$)pJ%|xq}+* z&2Ufcm@}Zygsy&L^hT5tmf_94S&m*IzXKKyJ)PUlI z_@J!eE<&(lUz{_jFyIOMIyipTEBrVZ_#53}@3jp^Ik>D81XeX+VM!c>& zVO9m1TExpct-$!|$UoX2LZA&9Lpd2JHCNgUxG@W&X?$ON9y6QJ8T3?3vs8hJ?MkG? z+9q7uf~^DXrE1b>+{(t;Ehk{;m~g`4VR#<0#={l{Kq8IGM?6N{_|G=`@2}fB zu_^;c{!AR*v2i^kmKKzD#@X*kqQNti?(#EiX|p*>+bp@c7KSr4G_lamK#RRBi5i{X z4hbZZD#u&-$o?lLV?H>=5@TipQm!-@ISqf22_(jT^z%zrdqw>4&Ab*9D^cCz<6{nRPB6Y}AZ(z&ILx z?2iTY4}^gN^6{&gN$L!%NMIq0?EWMP+f$hYpnm^17hrgG9F7vW>n2*hx6#1BjM`@( z)x2aR0K8eo?0V?qrmkH|GmY8QyvI;fpb+}!IUPrn37-&!M&J}v21ubf^v(@dAO0A@ znmJqzY%U>~Cj;K%Jk>o1#*4F$;zIHq>~s|Cf8v!-JWQCrNu~glA`n}nX&`N(*sF>x zuDPmewBmR@`j8DUgc3CW#4>_B=ajI;Z)}O=j_QW>u(%rdi;cLYkZ2`oUFp)$4n|Ux zui;`--jZa=Fy+)c4MkpADiHeveb+n0YDWKpdr};VqnZAfU<9+Ul%X0JekHKgLg}oX z`3K7l6ftK#>4u^&L3UWSrBU0#afC{56gL3G+{*LXjK2MjF;7!Nqt#9bIe%9*!SVsN z|1&o@Bk~i*$ExN9I;u`_?iXD!{S|y#V>8=DQ5R?`{8>@di4|| zJN_Tj2=`E`odldG-Y7)x(r5y~(`2&Sw$%ewe3ISc$+^8Xk7$pn*q(oy429h8*I)_W zT5tGhudv8+x>Aaap|k@$QH}6ByxPn+3KPo}{m{87{?`K~0e_ z8rXDgG|0NNCWAUR9XtL?v9;&#JYC{TWtcvBS~J?m`~bKnLypKHDH|rk=*z2Jx1LK- zEr{YE51xotCw$rO+BG668TwoFqZ}7(1n^r1IvkYVtw&`;(EwtHQkrdttS9Y|#o|-H zHPvAJVEIGmr}3f6Szqep*pPBiB0x3Z{q(XQcL_=P?z=bod@|sk82#f`(C4xs(jz^BHCZvZaT ztEwdPVFHcSKE7;YM!BM7ow(swR~{r`00wPh@(Heqy#`z|1b#p{*bFuaHX!1bw8>EM z^~fh4QcP!7C>3o$-W=x%+(RpkDiItXtu}1EEd7|PB8-j8!WhoG- zRlI<`W68n3+o^=cI@4z^6kgf5{!LnT=uz|d{_TCzvbH^@XknbXxH$nBU~gq|R2Kgd zg+*h-^XL?$>nw{YBB3z9&spmY!4I&^69hSuW7y9`__cW_(Ouslg;gf63^xx8Fx&@J=eqAUHe~c8K5SGSmrWb zEiF0pac>O)NxPHmqe<~%IZe#f(4LmK6rWX{nD+ot>FP-xO5_LK^QRl z?_ns)xyEhhh5Rn@3iZ}Y<`k!PdHyL~#6YGG&nZf=Nrh)m3;dJTkJ$5BKmw>+`)?a1 zdS6E_tN?sa^6<`K$bS5nY5U$w@3~A*fWd*v86+LV+Aa@nT@Tk%n-V~nhdAaTtMZ{E zfWu8~2jzW%!b=aT-jv*+hE&bIuU@xH2iQ2hcl`oyAl1#@%lKAp)@Jb!vsX|`;QSIW z&fPwO@RZKw73}kk8fWPY4fSUTgeetuli+fm&+jkiTaoJjDL>oKJ0|W^mNS3iJsSB) z{w+cFARLQLAP2zqnwm$Q!5aTm)Fi24|{Xh^5_33|&GH*eouW)1p)mdXqO4 zyU9X_w{uK8lb>C{OSj_4a*Hvkh6mVgec(oL{Q48b0)rh_aeNXTZK3_F07<|A4FXw>!iE7~)R`~ebA)}orN|Gj)FLO_v9|Px=Cyy1NdUxCP!8h*K&r#MoY9i%#Tc;Im zY>woM^RKXs-=bN7{e@DOd1ZdpCkQE^Tq2N(k&?&no|`por&KO!35vmfKBn{Y`j@+e zd7|?9+~>w{17777V4HN=Jg)k9fFf~a@IyRqFntLoy|#m4u^+&wK-V*c5dR?H^EMs- zvA?@)8AeW9EE|k7=Di#bRITU}o%ev%!pPkPMp6n{JBLa~t1TCpIBj&a5lB;C5cf*5 z?NoH9T+}z(?-beh5VS7>I0o}XunCXuW`tzG1_uQZ408LRWmB8ezb8AI3Tcckamq2` zO0B5i@as`c@0B)D@9j%w9yupVtgd~dd`6?K>hc>rldwy{yuCoGmMl^u4J5-f`a6){ zL!2<&onj&jOu zrMJks&V?6g?Y32>kM;Ghqlt7sb-rDfi zi5nREHazZ99@kklp&Nd8vvAkB5-o&Ltcsc{7YwA3Ji797KcX+jwQK`LGVS>B8o@Ag z2|2kS@vp6*ciMh;mZ#hD?z~&*xySK4Q8BS+Y;2fd`0p!kZ|~e&BvGAE=u5L-7e7Fp z3{W;ajm#YW*Lb!(oca2EyK=~G#=4pZ&p1>B&Nu&wV*1D@LPW_MiUw05IB3%hce)SR zIIPQGtwlv>5r3&c$MWkg4qsN4Fx3U0L{X1|_VrxiJ{)~Wvj+_qN!8NJW~~oBJrY#Z z)CSWXLuqs7_0&h4%b6Pr8aeGaj$W`3Zt>j$8gSBwYVwc8Xk!M?8w(I#S3|4b>xKMY3!Skp46V11{;0Og_FbrYa9@Dw{ zANQq(sWt`pr9R%c5*H(NV5O`wi{$FkMb1FDgHg01yG|t-~o<6#!UeP zD#%Pc(OPh4N{5GC;!uY13uHMgjx})QpYi}_5wNv3Kp=L>p*^eI@%9H`87olgzHDiEk$zQysp%xcT1c(>Bu28b`y#@W z*G(e-PEL711&Im2hirC#cK7d^_^?yNSuvE!EiHikm_!0m8IWmWv5%%UMmRCeDs0-9 ztVNFe`T(SNNsi7hU@fND`{2xrWzd$;@%pjA2Qb5Y84Sy82NruUX%zh`KdzaFfrp0x z%$azts)`48|HqFX7mrfF@OMM-XXijN9tGwE>w`lRxE=qXiANHy-F>0lq?r|&?B>7P zu6!!w!*6J0#0E~~m<40(&%ulW?I?2#i#C5m)Q?F?A>dGgB`~ABJ6}1s&b&kP5D0(% z4@Ku$%($lg(BdT3{QUKx#Jj9f(&)2J8rW6Tj3qKo0s))-m)Cz=lt~^8?0qnR&QmC zkQzG2AucXXADD5{OIuQ~Nw|C=g$_1VAqMO zwg`skcYq=1eqf~i$U?Q~s5K7!mFX!x=wC|WaijqwLZW~C;JOB+EAE+W6CNqyzk~<`FudtA}9&;Yf*rqvg5Hq2BWP%705^;XOOm1a5FAV?C^)}1`ToJfHscqPy1BKr1kTRREO#Mw z0H2?-eCDz)De`8}761I?`CSR!TYPCM)2!b790(N@Jq#tueBbi(VR)ZxN;Rf4?18%X zBrtphRn;KS^W(C~3%cEyI0z$G7Qpajcn%SYJ-PH)e6K^Nl-VP(bn%X?z9GnT^H-Z&L zVTVfopq^f$xs6SP$seh|!fJ?)Q$K@JUdU%H=S{)%Zmw=(B=>V$=={ z+J*dWdlU&@88}!Cq*4#TnwS>l1O}T{I6ubfcyDS~8VkU!dmuTOUx^_wg;0<4z!ud9 zwA@k~&`OQWwn*+0zexU(?;?N}bCCeDerea-hu3xB_Ep_5RkGN`#D_rB1WseZ1G94u zKzcIoNL=Z0VlfM*_tbzPJ8b5^sKB@II$sK&!^X{{iV38p`^OkeS$5RydF#kZVLUiH`6>L@b; z1%h{!bdh6*62o&wqr9Q53iWF1J4yR-DWeEd$d959#n)406MzhFE2Vgiru$C7 zxeIi_{MUz9WC>+7pYA$plLTQpD0k`#EE>)6d8Lr{T_mAqdh9bz`{2wu$XIK9mBJ=g zIvu%u?BRhdE`8?oMKEeXz)3oOo~?21ntJXE4|Eeh@2eUB8?77e&7UcM zDCA9hWm01Msc1oJbOI8oKC>=(73}ty^V=#`^#NeJf%5l|21Q&t)~GPO+S;?pfqB5UNt@}8#F8E1CO46-}Lp)$L}eL2<&LS|X@`bG+2 zN(vNjgL^D$aK9Qm)AiPbk@_UuPbsryN z-5qfN_*=`w0sTB@Ce$k@bKPE1lx4mTK+LDuWCDdZfb_eruYbwK*Q@IoKh|eX;ZON| zGP(|x@FK}VsmKBc)w;N_<8XzgmwPjO1cH~haG;M9c?j1BRoY0pz84TEiz^T2t7)1* zM^-wilYnX1E8Vjp;cIlrrO=f@D3Wm>ZfesYkO~?X&kiQ5gR4WYx|lK*Ikk48@K40}5$Dwzb0Eb~cQ^!|B~$osHq{)@^D!1KV8c~)H#Pdim;1%{~Z zB{5kaX{vSOXm?Kv66R(PEO}fxoG?Ut=a$uU7M7KU`YsyX8F7Z39Kb)#N~0hCe8{vd z=S=`v=wSz;@~x)Z-1BWs4g&Db5-l5JzRWLWeNhS=yZKyG^ROPQToAPrinxkHRMqw0 ziLDl2dy|CMU@P{-DjP{jjj!EMS0;kL1@Xc|BNjk@^xDtw#54Nqw@lg7s?-OHfck!C zH2QqvYBzxncN?o)S;?g9ucPeKCo@e7{LqI!;WrfbHVd!iGkQR_SqKSKpUK-q(tk>s zRs=Y{Mk4J}^~;Esj{d7F+y;2<2hbk^7URS{s+tV~12LpKKsyyErF;I_b;uL;%?I(J z&c`y|!X>Y9ET9VtB#+Sm=^0vV4kkcO-(86Tr;_}Bb%;Ubjm4V_Pw!Mwat5=X)NYHx znxLnyZ^eDSi|UpH`j-H1_DEshluZy%5mU`Cs&%5Ki+2KSD}YHqSc&ETYgGN z2m&=78}e70O%13t&)9mmp93&9kmbfqy#=C-1i6>wd~f&EBI#3qyE|Msdc&nXPz3+_ zDIYhSybVi0ZByq#!+dvA_AN%!;IsP=CH6B9AALmJK-b4Sxa4GWkRgI3gjg1`=`UH#@S zg!Bn~fL;T~dvxwG_*B3~B3^H(@ApFM>hUc>2V_|&0>B6wKqnc~>^?5!VY|I`bXN z+&>q)UGaqsmB+t;Om9OfB=jRmLq!$G(l#yYVn@2~d$RHQfC3UC`;r60*o@?4LZ|{2 z1@Hto7zyh01}7!99b9VJHU^%byIpVT-L-+U!-m0GT*hW*?eC7839uAh^?@Vx&th-I zuN9k0)p``($>uB=W|X|8b#S?B^gnO}OY{iGuF%@5llEbxAbYiFnuRHD0s)v)q-B3* z=~)g$+n~e>t=C%!FHDcy|sTarns&yZi@=q;|Yur%+u2)Gk(b3S{ z^gzIv;H|xT)L=s9yAtz>=4@|q@1BDV@d)~-t%^2zE^1vR-ZC8&B3)v~|5AN|?5lVb z3`WfBglu47aQ;``chgM(U__u+ZUN2I#6#dfEu+aYgQ#wgM$%mQbc~;0o}s(|P;XYo zhRnX$HN_dOf>O);+vlJn2IoN%NE*_p16^0e&_Sp6g8!QZAy|uUnGaz7pO0OT0(6N0 z;GS<>2@m!b^W7S9&wySJbk6|YE07300F}51Tu(tQ1MkFWkcBih5I&VUzfH{_E2+l; zs3F4p6BT+62*UMmo3MxhT{%%I_baHvLWDt(J&257&eENX`JI_4B?srO%>e1`tQffW zfOXP)HG&dV`kGH7QVvQuT8$pQhPLYF#ph zLRIf9E!)BQC?ut7YHBN>>3$6?hRhQ}s}XTt zIs~MFK1ScNOuLER@%zA-&7v|r`YnVF?j-dJ*)ewNn#Dm(psxvVIt+Nx4|0r)&HAD5rnB%piq|#EUEjsiBnp|7g{`hh@_r{E+ni>kCw;lrBQA0?Z%C z79>>dPl4>l$N413?W(!k8_zG@Qx-+{Dq4UWujsMDfdGiXpWib;oY zrCA+EYN{6@jja}PDBT7q`9N-GC_YUN0^hci@HZf+=A@&>GnEesZ2??cIiR28G9=9&NCO2Hp3jpAZVPWVw2w0^y~>TwR_h&acC9VNb|*JW{yC zBNO)sgM9_g$f0wP-lY29D|1uL1xp#R5EdWveBF0!7uM+RBdO;8pBCWiw;}|Kg@}A9 z6_>bu;)(*ATwFOGQJ|PW$~J+Z+2SC8YZ~he-OK{sKoxyTA?LeS80Ev&R)dvotW*ii! zChb5+Ro_2l9k7Uxc~@mnJM|f9tTxvd^dX@;{#)Q`m(D}?G9$*xJ!H5z)D}V$*t-?( zrYzs_UNB#FimpJQ4mbwVY@62wBV3R>q|f*I(T_hKqG&G`XYs#~tIs?Uu)z90F%&3* zi*y9ObZtQZ%h}aNAsK|Zzq?!_8uhv5(v*3V5fS$K8258X`Y|J2`%Y_?V~&=>+1eY0 z@h_NUrL7QB3Z3YgB;d&fO)*Kd#7I8lZR2<_;_&CGg-b)|AF`(RA|#=CarP2P*Oqx% zJAvHR%(Bn#uBbVPS%SC(F~UjjNK_lHF*0O>T>5TyZn^Gty`WbN#IG4nkZmpVv zipmGAy{5-NMhOVz2QUs2p^zV%lt_b@LR4~|I434z+;`5HF#Wk1qUYc^TmF+#<>!Qv z;J>Fp%`r|$Dc9VLGoohvN@%@QqRt&N*_STZeTxz1XKIA_Q>>K2$B<>*=8`xtFffV3 z91Es@`5+wAzE|Ry$nyabtJ}i>{Duc_t+1?Q*X=D<$esx9zu54tB7AUX##3}s#a-zh zztTAFb&8bS#M<8DnI6A})!bUp`7ihxmmSesY~L{`q59zQp8 z=l#Gg%hO8XbH%V6FKX4hJydJ3s>9j*pqht$9760xJ-EaAVR+oX!#w&G0cq%&TtT_V zfSz4{1i@1PcB`;~i9ROALho`114Q!udF_$2Scsy(tvr14B_T315$%IijtJmOoOnrK z8O^f7mVbjo*tElI4%opk?;Ua~nOd^kaaQqV^v7+Qu3c%bIIZ}V-e^bJ15DRumK)%Q zX?NQXg>jL@)Dcu}u!#3Ml`bE(J=6~Rkbcv5puHUVc*S_$>U*-h$e4Wi(ZjpQ>@Pmy zLPE*m-&F)43qm91e;WG+y@ej&shi0q(asU~iRNjCxCHD;rqW{TiJtQYuSaAfF_K~) z6u#@?)YmQ4?AemPe90u>!l-&9UrYR3^G0CwffBLSC8&$-WjGO@Se^O}2f|d{ekst! z;j4WGD;swB!wvhpybcoegGiy}pVbQ)P1o$XY6!w*nZ>6#6tTabd?SFZEc{u{VgGG^ z++{WEu~p2iZ*`p1Hs?`?B1_xU6)JR>HD_tfDUNJC;8%r?dP_Tl8TadcLJmRP2x{QMUj7|(|(DDzHozYko=y7z#yy4O`xr9 z)NLog*TA#?`BP@uGOpC_UdrGDpEkQ$b<^S_0kdweRUJzhKzqE!nxHOJ%RAqZNz38Uq!Qf>FoQ)sQ?~DGL-7i>u;{(XYj- zaeBDc;rNIaT2(vM`r-ac(YE0ks^;$vjY1VZJrxZlXQO+9J^T^T@pY7J1z)pJ8fqcx(?K==q>)-nEZ!KdVOGgDJTa5QBSpDWAq^72P;Y*}YG zz7aSMu4XBLY?;zX5aBg(9Z{30*+91hqqg6VcF+B*$1mI6Y*?JSM4h}2Fv-J0c(A#{ z*&YWs?m8ZSPw~@#E`p!_AzRvP>G-x+q-!4M9^fzz^fV=?`<`zc7z0`4zLDh$`aT z*otS9bSH|_?x8W*4$XVfn??z}Ii2V$Abf7SW0O84HWE5s(Y!KxTfM|RhwN?05Odh{ zz_Imgs%0~f3`b!-Yf6p4xR~y%x${c&w zM0L$2?k~ac*mRkI$T;TPZp* z^i>(2TzjbxWX5BAVB7zY$5W)b_YNpjWffl1)WmW_&Y6-L=4Hu|3YtTh!&<&~t(5F# zOM~=o9yX+0vpk4H^Dkcg=F#G<6Y%*_EQy!qf#ae0a-V(sen%w! zYnWG4`tcEoGCL;;JMqLlY(G*+HxZ^2o@>;es=OaS|FzA-ishS9_Wu?@QSI?{;*q+C z4hC$EeCXGf!xN&fuV1q-FO8@ zgyK-TFXPuVhmy^SILe`$ykL2rjNm7DJ=F2|*D&~kGgtXQmL9pp)H;gp8~*uqr^i3s z&mPkCRb@Tz&f-o`|Ld7Y^6%=B8ABUV*`(^)GC2~!Brq?i5o30B)k@5-k}qARhHenu z<4!-JdgXKw4R62YrCVRkAM_*Cm4f4h!6DB0RTdh&_j>Hx4MsHp!7O+SN#3EjLpwzn zmrub3TR$ix({FR%Jo9Kg>9wD&zcp%pPi{#j!)DJd7TuDljAP%gC%9j~z$la)k=|IY zXKx|}`XEG?vpQ9pg2jb^ zQ2vuCdv|)km0U_!pDRY8&AM(KKFj=+EJiMJ;S{o#bgq@KtW;nSZ0t)Naz2k49hdvR;VPc&@5`G{f=usCU7)jEc?Ec97; z3A%EN#gXQBlg-}}`?_7R$B~w(HT=a>8(lgme#n{1O38*{@)mvadnq3HMX(#~v_6D; zW)$=!0;DD-%%QkutDq?3%y!RVamWXW15*qo;R)6!Q_ZbyPz$Fti|{f4 zKg&e%OQxXm;UacNjE}B|PL$;d&1lBJKKX1V) zRGa&g8ToM0E(~ZC)aK+uT@}C(GVp4&+v3-TEZ_*ypbSNpSPm1sy|OcI`@4wpr=N(| z54P|sN6ebYHf|%licmFM*UCc}Ek`S{tOZ9jV+jdG7X zGOoM|gmeV*MWhWSa)yt%nX$RNoC`fw-?Z*bCh(I>1UilP>FmEJMM4ht4fZ{#p8gRp z!kRht6}lX}2fohSLo$sEG-=E*(7KQ zh8SMX5-6gG6%|hB9rWB{m9-#RRL|CrZ%B;diAlG*S)$rw9=_;MHj*1AvH zt>bKK@~6J^fn3}sy9Kl0_d^V?DNWw;mSTLS`>ey*hdl7Dr6uD}Q+7>F&5tQ5{KJW_ zpV@JXX&;Qbbjnb}HEM|0^H<;UJZp0oq`7bgoe0k1`>lw{e>yyxjidyko=ZfWv_a`g! zOzj1_M!A-XDV`cno!UQ^wmiyxW~y{sj6ciuUEe;yGCX;w{5K%}Y3@Yaduo%=+J~EQ zQj8E|7t)pwf?*qRc(>!mLp=`tHNM~g-n8SC=G?lG6@s*PNOVDGE5TS*?+&K6d zeWWUcmwT*6twlgf=5Nja?py2{RxPl) z^1-t2nIbn-IBpKhtR{YZL{_Ua5qofCyPpnu9dc+iiajB=1jVgj+kn21N{>H`UpGp~L@nR7e z#y(i{kM4{RFyb`pnOt#^oW+MGcVCkEn+uNUUVpjV5G~zv@;pbIX;xRJj>!fY1X{Ne&90hbAk5AuK(ax;?hHEzRA<|Z*zU>tGmfJOw{J}tlbn+G+jA0Rw&@|F zuP+_7EX;X*`;DISgI-e(mX3hj7#f{9a6*LnI+e#qF&g-W^3GqsiO0WBK$zCtX&CwE z;2t@>=fts!esvQG1TN3yENiu8z3Yd}q<&v~Px@r^X-;jknEFzKs{q7r5G6TY2AsJL z;8kLRj}zEkP1?~=Rd2sgcm>rw_ddv~R6p71Q2ZW!_s$VY=WHLLOQU$(Q@%hrMhee<iXEb*qm>V zsCHJg_1h1Y*~weVk*(=Q6BcIM>9O!s5n@DeJr&R~28QlJ@L6DZY4CyL`S)f?Rex*~;`ej4{H+K%`Ny-(lvd1yA}yjWd~A62#h$*JwW)Uqyy`p47~cO_}5hF6Yv4D?C& zbrXleY`SDHEdeKDS;Eh{C)M%;@UXE0)U5X{pwNKh)?#he*Qx#Hz#sa3?r84ad%tkqFI(ysuP~?AA6&NW zhtwCtw}@JX!@`Ext`rU1t-p`f$ zFTh-H#je2omO||x5H`U3B}!SsV9X>spdjd4_kc&&g=;L7-hHW)^OK#i8{yuW#JO$7 z@^*qw@cNI1<7(rLiA*EH`XETc!=@hj(;o!EHDu`ykjzc$j6F&CwimPRs=D$^F`x83 z{hlPVmFj(kG}5+&bFd-w_`{mIW-vKsAQ3RgRffzXj3-jJnBNu?V zk-{;^J%%d6tasl*_~9^5ncj&WecbRZ5z}%VR%-4(shy+ z17RM2{&-mdV8Z9QN!+&`>tY#SFxr+PYlE6u)zW16Ot8vRs9su#wUH&5nd@B(h}9e& zh+6G7oJ8fOK7yuEXA6th-};*{?Sc}oWF7k4|CUj8=i69v60uS9kswa}?U9imc8coy zeF`fD6Np1X-t8khl}~3(EKPl3Jt43$Ub3SMg8^5HBStL8wn(%3e!Pq|B_T53D5y4S z$M)?TFy8WwUOwp&t(u9!(JgQEm%@KrULnp>4D4NA&y<30J3VwM0Jt3Me7AW6nFGgD z#5(o4`88n+5n^C3gG=H#_8?Uc!*WnYD7JY;P7UI#J|_`p>CXs~Ppb@nK^@Ydtyx@G zik!z4fdd0INwBN0AUfDc7qe9Hgg@)|d?(&&kS>fEMos+RH~DRMvzjl5@iHr<1AH4g zazyur2a+HhFsZ9WfltxteF8<;{t+*hzclI~f-|N~M}Yu?wwpEdWMoFcdvAmW$2iwW zZe9ZX;%V%fA5RtrOPkTyIUvc&NFn6P_-6;S0{9PO_&VtWaPq-Z5U!5;^Zzmfp}1{H z1>*tkn&!dwz=c9Tic30g7S40jKy434a?Y#W1x1uTdT$aqE8%}eIOJWf*&oY_?@k{B zvP_Pi3)Dji0y)nDqPNlPjt#hle{>kGEO*hz;LZoaP=aQqrgfWd{#=O(w^9FnTttDUwNQ&=^lh@%>e~op0LYChXh`IcfioDGg1=r- zP_c?N|la(0eF8k_NE2ilq?26F4sSF#f-c; zT9wZRT>k+##IM5{cFRvwJATwM6@h1^hWVSol!-*vL`+)SL;q|T6x61qqMfkInxp^C z^BDbjV861)DWjqU!#vEMrKbm&hmZ3hDZfT+1VNM2CC}*8MvR~y? zp-r9mYCD8b2|tFI-D1%08x0Z9x3wdeSMZ5HQlkcMqdUIs&pOJM;f;)q1}(STH}tp{ z>*fY8ZN=P}e&k*XxO~E$(U8sm^GN#N37J4-n;+of=cB$r}0Yyjfr05s5==s7Vx<9TYtIxEKdLg=~vZWkfl@f$K8r46{JAC;IU^d zaYmEP&qqg1_T8P3K}cw*;sWdlH8mD|(theQqCon63Xo+2TSP~hAb4)#UXnNPf#L;y zyNibhk|qY_h5ltmm_$-iz=*HVvJXB#Wt|NhTsznv&ik-SY6Guu$L4YvcK zKXK=sv4V`TD>!BZb!abgpB<;%Tn?Gi!q0Kz!wc9J%05@mG|7Rz5w1i8Fd49T6WY!I zm$Li*E3Cs+VB*w1ea!)Qwss4yUsGcR1=#T%=VbsJlX_6fJdyRxefex;Vv5WT%5<5L zq)SU@qREuxOhvxz!IJZZ1GfBGW*N?kcnkz)M^#Tz4%2vSPGMfsV~V) zYe3#S_`STQ@F+cAzwMhPbHK}MtC0b{Vdj#6o!kFJKAL9FCnlCQ+H99@Fab^nL@dZi z|GTi?h1Nxu4gz{2z`X;zx7hVYW zx zmLVP)19qtV;`iwry0^^HkQZXOpRzkJ7S5{6-sUG_mXf6DTuj^A{O-CKmj9i?tv-Hv zIuwWg!twRQe?MFM&-$z<402D9sXB$2G;v6y+}?ip_G zz4lxa9Ef?~22CGGc#`jtL{^)32baII z7%(P0@Kg%DFQ<7vLNf3W7aY&sN6`3SPN~nm#lIRjEb`+)6($u~%i%Jx>ZQH^=Te{N z*yI0qrO@8*=kBJ;<}G3LldZS&dg8W{lU0xR@Q`DZYYiCmG;mTOx+rjOENgyny-}9_ zZ{?M$(Ow4j_32jNufp6~PF&wjGkXDiLs;)*D~bnR+|Xl3K@uDogjA6Cj4{bMbD0e) zLi-9PP{zeV0w9p+5kD}-LJBJ4fJ-pL8B?C3HC9H7McyZ`MtAbvxqF<^AUSqVp7XRj zx{0pPqP@a0WbODDgZ!2&A1s4>k&VD!cE&k}`)59of7I7Wca>MXm1*aO{R#D0XaSxPR>hkZNGyGvP>k~ge0%G-`v8R}%tFV4C;yI&*2O$QQSSLJug#geOh9BqZB#rEUE`Y4Hu69Xr1Akn*8P6~UGe>d@my{>=F*oxn2)_1M#%cbp2@g!lUK zzZw4ZYsV;K8ZCU*$nkWj9prHY?DaklYJ?_H*rnJ1{L!c)bqn`rSq}<*0z?TmaP+B1 z(sm^$Gh#!lVsFqZ$6?5RRb*WIM%jeIYtj8}mz8)TAv^Ck-(UBgcLILy1}mjEb$)6r z43S} zJ*nWUcIEZ{(JYr6ez*~Oc*ZBnWtTT4qTEM5-wb_n^x#Ddobop;KiK)f{p!2A?P;v^ zq5f6)3y`WxP?pqe$<8BHJ{@1$h`V2CQLO+}7jOM~nSV~4VC|(@tQBN{B1A=X;O^gJ z{EK;xih{&!wxpA@VUDOc3>l^p#FhSWQ3p0ek<@o_xk!)t{E!rZ$sO)C zd@}@@OUsF;iOPFLx$3+BA{cxa?v8COfD>PR8Rbrd#;noy(8Gv8q^S$WK4k3|K8$p)=g6IUpULzXRR^$d+1;ABAY6s;LE>#H(IzKaZ^sg zzCb`K?hVVgQ1dwsj!G1Ek7x4GIcl97gdB&%zp>Q=Y=QD80hrb&kxQ9~y0RLHqL^qj z>NT#-VU)62%tX(kraqamGo!-`Tji{6qNVUae2~o6y-|8G3Zsa>@__^KK@9=$%o5-S zSOJA*wJ^`A1W(ZUwCaNr0PG+h?DZEy>Y=w#&Q~k*DYKv2fP=nAh61e3{;_DIv{Itx z?-%LtF5{$v(j&lNjks~no&K(O_|JR1Ss*}h)k*8(BITe1ZkH~gmy=t8^|@-GEVaO` z=ngpA%mNf^k}uZM&gW>qZzIB;=O6s2T|5oLTJ9}Tu@+#4FXtCuI8DITNzZ@TX~E~y z?*81Zs+nv1e+y*@GDM$cv})Knw!2AW(IHS;2IEDPK7ad>?3plQ-k>CNpRq7VYTNbW z`nvo_jWIoEt@EmFQ?z;OQV*9Jj1`0##uL7f*-wxa&x7~6&p#~zl1W0oSH1_BD4le7 zTZEqq#{WWd(D5kM52U+1j6EKw-4WNA?*ozlZL^Yw2K8L2-Bmje@=TC=z}V^4>f^FX z@TrWtYKLL4#sx}QH^3MFOa+X(Ic*}bbZ;A9D&6`l`O_EVC%D=T7;-fd_rd}p;EVtc zf42@}%IW~(-C=4*{0UJB|E;^!tJBfBIrOU8FQ8xylpJH9ZD7iRv?#I8#r1cOz3uK2 zQIAFz9>mn|u@YdWBQq{sZ{>F8zQ1Druag4^+@c=G%92Lk=t5@8m*deSB7L_?R*Uq^ zYk+FZfbRnzWcefQ;GK%=5$4N+)kbB70!1VkumM79M7hdQTYXvc*EFz)RH}~M`&u-4 z{D}r&^!tHD)Vmab@dy`L{gFr8^)=qM;EaxTVh^z^O&OuDdDL|M&^gvxR^L9f+(CQ)a$%MS;5?!gLxL%n!YsMW1*NiUIE zlorU+>*%#$zySnoSn&S;;~NL3CfRaw(p84uU5v|?GQv_#SlVrl=1<0uA`W49WC9`H z_TSroh%pDg%n=53?v(z`hX)FQ`=PHfTE2FM+!6>EZPdG_4$gZHSpB(}^hefArnO81 zJ6Ja`-m{QQ>Ml)#-q;Of+R>Xk_c9h24`Sw6x^yKeUOBPN9Ic_RG$NWqOu%>Fu^9F8hfP`Xi&wzYcDgk6$E6iuxlnH75-2vN9P!1lrx z)=v7mIv)L`RTBUHu7&x^aqh5JboX>y%JUM;TgXG z?q%uapgc&84ci+Xz@w0Y@FJ1_L4uzA%45j1_LT$;*swQY%6RAcbqH}3UO>xI zk+qHk0eGR83p(Y?nz z6iC>zL=eZTWSJsnC}4}PA}OZxyGI|~oc-U; zp~`{@XY?eF9AMqmloK(-02N{ zu!iZ7s53{YI)u8r4TR|}kiakk`f{&*xsc4&9hk~71MRMq zg#RltO8@ers@D&2+tH_j5I~{*lR_k=V?%!YXbukaq`4BQu6AuwPX zcRy5_vHh3`AJL2b7YGr4Nmw#>(<{VfR2=NLOj>Xm9(F2;rv9xQr4NS^zN2_UO{|$2 zhj-fnwh~tWUAXs&Yfvyt6!ZD;Jsdj?)sxFoW(_RjB*XLVZHKeoNT!9H;(Qp(uyFbd z#iwrC<6VtpT>BY0AOq1SL8w=MH0cd@L>m-0@Crd|t_h(P3evNygYyRI_o0qRML*{D z3spkG=-5DFtiLq3Xdsw(CeUhmaz;haxe1h8z;}&807al7=&`fv0e!A;@G;77n2PcW zWld4KXwY~0)>t#TXezW47&j2;YovlX9eTzukf-fFyk^Esl;w|m$R?~#rN{wGE&RTFD^Xk+$<`GDNA`?@!t$3Re^H0e6W@o1Be$8T++5sT zPuRxzStjkD_Dz_*3gS>rrwrijJ>9fjz%um76~9=IGBcjF8V z;U-rcT%yiuTkyF(fQ_q6CVBK%o5x9i;Z8Q z+QsnhwC?^5zV@KxKx=3C;O(9O{0?CiZZv+RD1b~9E_&-I!{5QoWRZ3T^2R{T8nnvV1WAjagR^?%k#xd~fNFgxC+ zP$c0k=1$uD%u*1r3uanBcP!~&1@2QTeoza{yYDZ&Ln)s@O#97lS#?nL(Tsl4FKv_W z#j6+kW5(C@XJc|FuxYO?Bu8!}5EjEFTLV%~^7lXpdl1sM!ZQi+7DFHV+Zy!E7aIEc ziU$VSE;v6LTKRf1Y%aOb>Uuwz54fMv*|eOiH{TvMxq&HxCuidd2#~^}qOVCwydqEp zaqkEaF#FWzH!3;O2TWRZE`(*nBrf;t-Dx{b2H3Zp1R67n7eTclnlhdV2$sHf&z<<- zXce6Qd@3S?y68Zr&DSwn|BCbOlASgVZlP81UkF(NW;a$4BDjuZd;g2 z=4Do)u(6b+GU;JD>l5bh>L@zY`0|6`8>ySeHY8YJ6p``Sqk|A7T$J8-BN5YPRB&yH5c`x{2{8BSMh9i%JBbD|E%KWms?1wX_m?$-o@kmF0ieF zaR?BR9o)!qe6=)}*bLy*+a(ulnZb_>iPx=ew{E2)fnltd4?GBG`&hu-G zgWYZOYb_YKVfF5GIQ|!@m?-(vz0{c~>HydyY^lX=o4vIH$Tir|n-Ywd+2ayJrK;k`XYbsnbJy~ zak)C(k{&$OmU8PdCKq%WUVo;qt)oN~zxR?lt9@`4UkStt?{6)@4@ijXXK90Uuod05 z2SKwck?O7g--?^$*+6hoX&YFZX<#-D(4o`O{?#GW$<@oUt5z4 zWAF(EFP~XrKBjN5l~y8ID+??7RVWZcGo z`xx^L?TZ&@v#ylHm;iE_P*}JX9!Pb2qaH_kVZQtNzW9QXHtVw85yZzDjx!HA6RIE4 z2MXS6JJ?be<%S&sI-Yd#y*Lnh?3Lv>Q=HboLZ&}PF*rq1+6gxt9Ilbpi@$xnNK*X2 zNMBG34g(e~az5V#4s!cxG(%NKiI)Ff8wc?j^ee&|w}XBfA5l$_Z)nt8W1KTqzwy6E z$>6cUellpido^uJ#4%H$-EnPXWVC8$_INADkqA2j*z4puD({dXX)XDTCNw6STAyqK zmgLiRJ5!p!{>ZxuGaZ^9TOvCJ`f3$tAjtw5pk1A;NJ&EriLJ&Ai(~VoExYGVyNiM| zjT~B7XfU1c{r7d*5#+2-b}W{M+h`Wh@r#v`v2Kb%4wO6(PAV3L887NjnNfMqVCrSXh{}oLr!Mj~GL^ zJj~X!=A!JxvtyeptGMiBTETQJka*SbEuk)3?Od$K1y|BYYtwvM88})9RpjY|%Mj|j zA=wUWbT(WP8ef%(F*(rf+@bha?)H=>TSmy9M1Lupj5N=dfboAd9ulxYE2w<$??}35+t!1>V2dYp*)CQY;U`m z4Gk%K+A#uZr@2P!TdF65>meTDcNnt`8ygYqr{DjuaD?Z-5aPGwX<-on7isOU@aMo* znUZ!U=%*Q#;B`5ifJ8t~omZjxDz9SMof(__Y?Coj`?agc^X0eM6pk2SH;RFun-$WpUSqB{aU?e-o2N< zT3?1E4u^&HZ?!0LTIv}7E9DqWUk1%rwhnLlB96(f~XO$80v;`u;8WW=rQ)w=J|Ww=wdNw1#Wt0aD*6%T?(e zQoWJ~DlOrKoa-5H(bvfw-P^}~(X?v-13~Z*M3Aw8i}_gw<4FOkW(0y^SnLeI4DLLk z1~LG}jhJo;EKT4ZQ}c`}wgFbyTY4|Bdcozer6j;w=k<5IIW7K^E9k^+=>J8q1Eq?f zdaC))Lh;h}o19_}s9^bmvB`_yT$vgc|JJKVueS1OLC%t(ipG!7q766sic8&1K;ivI z5qZ2YWHD=9Qdi=qABu5B-0>b!-?HW{E$WqgDS-IyixLQwj4&oo!{743Hfiwz%y(gNF_V8I@aMg3g0loqLE z#hBD5+HxUzf8A~CfMSo=4e1Q|5TLre20+gc8sn*id4co}Q71_SL=L4!Z<4+TdQLGY zbUI(c%u0W$1ta*M!CP;+wU?k62cjQ7nVCHw=6^`(d8$fVO6D82%O1=x=Ro?(B+sy) zw$`Vi^?^;Gmu{XvGIB|Vp+;C3Waa|ZCnC_x6gkf4cJ407Y1g*jm#qeMgi{O|kGdHCmXVh#O4DUS5- z>%2Xl9;i+CrEMz`2mv!9BBf4qNW6y5CwD2RfjwyJssrm+Xs`m&LZzvKn~AQght`-OgXhl(ixPl5rKiYHDCzn)>^WnzesWmjxJl$Ax{f&4QM9$%r5_&xN2h?SnOGu2TDl5qlM z&idPrj@fj=x{aqia(DQcxhGCw7?Pgv@en_TCEarKBuD<1O8#Im;KuhJj^@Y*_vY$_ z6Zib_xp2D3sd3d;o`?BuKBb^MGUh^Z+uj-?12+)Jdgqc3lASUSE-{yYeKI-b4cAsg z;S&bRVBi&P6d-MDRUq|Z-Qj*2KE3*eN$L+4T*Fx)EdmHg^z`SwqMG+-om-R2tr#Kn<@$E(q>GU|~qK&zPk#JKJ z-ol5W=hlDbTQL*abrPAWO0vqIn)ea_;XPiDByyC917~F9H0#-yw5eDg?+ip5qUO(u zIZKSXf7eMyKeP~8qsYdvo=Szv^!d4;MwWVG;+4KNb>^KDo)4;b915u_LdX}s#%3$M zfBuL4F9fnvMJ{qsRd*}sYj{|vlcYnhu^6o4S(j0Ci1TMS*>C(d+(4QnY{Fc4U(oi3 zdqm9_v&6WJo_zS*g0}kOx+}8_lFwaB^&!B%2660d&lrvQ7>oryeO-Dc7(rTb(NMy!)M|3Oh0t4IgXBEee`0};`5;7BQvA-Bs)ky z2v~DM5SPLhm*W1Mxb$ufq-$-Xf%T5v4Hwfrv{bJKA6w>F1p3dH8#QS@YvTQBRDgpt zl0e0Zor`-e?5FHw)>=aGf6G~xk4M#L@_1wFdO+uF(bQBtqkD#FwGLpa0O3|P4Cehp zw5#UT+N@6Qjxr#=xGa90S!2H#Bqq*5+Vs_+yKLUG1)0;x4&p4tf+v^{R{{?ltzYlt zrsCp5Xne8n#`+9riOw@WvUns*$kJcr)&qa1+Q7_(yFtdMLXuEgddmRiUTna_x(|E(DwdU{uh2#N%FG7O+wQ< zEkZbUU5QT36m71GuaU-X#)$i>jeLQoSz*bo!YZ2S=-VsTu`SEx*!1mZ1-nCMf?6G| zACwqK?+tIm=ce*rlKxK%0FB)zkaLP3dVIx!FZg$W9RwzyK^Iiea-_m^IL*H`M^scU zsS||4c0BhXpR0wBL&#ArERMRjG$pJy_nxSs)c;+MC@ zL97G5r8F44obpOKhk(8OcMoW=7K}pf27#5L!&U(Fgw=5z^n7oc=(>jI%m<0U;KD+q zu|he_Qv4WLb0WpXh9-Y5H^Q5b`yh6N{)JW3ZjIivU=IIsPtb*HGRALx_(aPG@ z#Vw(DK!~a}dB!FQ2XU%6ktWp(?IvUXJ)*lFXldl zd|KyIyKhEHrZLBM<~SNGRJcz_Zv)LI{fe0%{AH%Su+gmb46Fw|A$~+Q>7QLXgLCoe zbjG75e;Wsa+LZF`^LtSWcAaTc!%yxTQ=48C@s*|X)7ZG?d<3ksKrBGLNFL^%AE1*E z+FZ>%4na)x47=oxD6p=Yci4}l`ftlJ?RzlnQY`$I;=ar{4oTf5%4l-kQm5Q(mf6jd z3IFPaK0XzDNBZqe19G0d%1U)zQI0^kL1wzD-sSHRNdHuP*( zuUW$T(e2r$&jrPWRO?2;fjC1P_T08{(|;mQwbF+dX&G;laRl+rlTsEbnjZxn!u{X( z9WsM`htDG#CmDnTx4pX?(EI5Z=>6#r`WY{sUt8BL25)YfSj|=U9$rY2!Q4VH(f5BB#AoTzv0$pQL3rP&csv}inU zU(8^}F5hi(YgUC~Cpo~N? zH$lCmodLpQ?fRJs^bY_k&|P$0xYhJOxiy)mRl`CNVR*FEf`VkZxw%*ON50XZr7g1a zke#kZ{SbldMIB_N)izRes$3j!?bl4~k@yzN>`yEEQ3|~jgtXp0S$?D=E3z1##`t7h}pU0;#p{ZVi1iqT4m^66+Jyl$P8z1P%9pbcW zk|78I$`_WcKDnAg$XbAi-gw0dw4bjr^3wv2H^iiZS7J` z-IN&{Q$^ldChs}g^1mqOylcRKlxnzIux$cczTz*ORg=7G@s8lBbMqB6<8 z2BQk!_47)aw8)s|)M29Os5IiT1Xda(ZX^5s3`#w`+>?Q8;zQ9OEW;?!&J z8wK+?Qc~=kraqS;peFX%#GMIdv^Vdag+3@vr|&?gCZ^^cRq21{zeL@(3x`$DPIe7# zxu~ywv&{iRzZ_M|_-9`2`+pio`IejavPzC`N~A6aK%+I6A)TJzA%bU5`C5wffE}S zTv}#1qIhSDYJURDRbcQHSz6GL5ekkeS%i^VdgkC^TV@|Z{Z10uGhRjlde6s5Tc5wl zrE9NVzFb|(_3ca-Haq4`%gHZza*z&NNKv>lMv(WuS_Fj?;8?)8YrVL z9Xr2}%84VD`z^KgIhyv-Ey5HaU1P+}KkZtS%@;mu828q?9luG{uDLJIOLL62E^Om$ zQ199=1ww0>G}}Wc*Y69IyxgH0F=e4D;m+E%ICJqa*t@L>TGHfC_wiLY7&-VgI@zWX zP0#n9)91Qh@0Upx6*Dt-S67!%g zA3XCv468AFw902#!ROvJoPi2J-nHVU_B?4zObR*dF4KQ3d|Eq$c4c<^WZ~~PicXLB zenpQWa95M*2a;cAFWn%Nd>%3O2MC%M!YVOe@k3T+Bn7JZ3G$V@SBd0&4!#yLeHVg< zb+S+{O^NP)6o>%CA$jWe4gxyrEKx~Iz2w$Ewttexx7%UY&&N+B;`s=vdg_!yf0aS13quYuJJ?3Y zRYP1AumU^i#mexGVIBTHEexe7D&PEhJI9|5akm^~|x_0i6_ z<4?}&gudekb#=Uv&n?#9xqzhg_8{q{YwN2dM&=`{av&n|z7eAT@WBB!|6mbFl%}%L zpq`41FLhgc3hPQxqOhe`z6q9u-oS*K_c?V**;{>T-f#Jxi2v}>KA~t6tXl}!=ucRS zW@wE}Z&nY>_N>j^=>d%1teub|dlO-dxIa$V+B;br8c^eY{z51z!j*KketMd)fy*QWFl&$=03^C|8#= z`55{ohX;6EBT%qO4%hI>2(y)cmE_7LDu@6{9063)XZe7FR9b%dx}H_>;&ks46Ph0u zLfxT`LlTF@^Q-UJ{?ye)cD{ePCs;fF9M9lce3;6{V?f4uM~u%Kr#yToYajFjHBTJZ z!!C%2#zb`UqmX1Yc_bLAf)8Oi%;H<{2r)f=4Vtc)7o33d2*dGKt>}uKr#l8G`3l8w z;bDupOmTmg-=4!+Gea~h3*fPAo-1TJ*!C@rjS|E|vQU3tU}H$gHn-c>{!sm~ zuj>vZYR?{S-{OnH5Llxzr$qfhz}FJ#c~kUQLOY{JkVaf`h)PIbNA$I zK>$;M%}}l1>9-2tdzC%xBfrypWWW#KpnKg&Xx$^!l|9`2^vv}Y zb(a5Dnt73gp$=wRy}f|YPaDhzqOYFO4Dp#Nl+BOLFs%nDRX=kC8rJv=oA zi=db%uVeeu1DCGjD69^g_`>n@tJf?kN4!8tV}fsZS+p1Y_2wgl}|0o0|oiA0KWtD?g!ubRCAC=VoJQV^3tx7fB_Q z{oR@^`l#Pu8Q}Jpn*%c@IHQNF0+5tLMY>TF?do)T1jb&D;*GA1VAe+XK>J zjH20X*V~6b6VIA=Ez7*mjKy_AQUEv#>R*6pH%d>}6?cm6&OOG%9b^no#g)EH_*$C9 zSXf&J&00yy$zgnpjYYX}KwbbXHZY4^RIe8gm&|AD4F^~>!cRYs7F=x}xzgnsV1Ukn zExq}-wbXtUu@w}n;6A)8hXDgSV`<3XG z`bT~(VE*~ODfZT}?5{_+!=ocTrzi?Fjhpx`;o!57Taz#6SMLsn5wLXs+r(g(W-Rh# zBy9XgEzwF+mJZO9&b<{8x9xK~YTdVeg<`O;zktb z+2Kx0v)0}_pvTB2lwMrvGq^2_idMUNtOc8XpL-g%j8;!V(R;IReQ+D4U7lwZPL9LU zq2o@vCG$W8x&Al7dwzN$xi(}THfaWyMGX!P8VGY?Sv!cr3LK^ehI=Xp(|=7_xO&^j zM0Hfo62Szbm4(4nM9s1wA2h0Z^SO&O8dTpOetfh~M;`bP{tiDCm6}bS4##o54EK z`ePQUICeEK;0L5LGtJPU{8RnjV$z&fot60nN^w95ME3>$W4pRGnFEDhsq;ixoqiwO zp2ECZt$^H~3ruZiu{(czc9oS)!q)-^szJJ+30jqy9`VNu4aJ2asBTDAw4xx(&7bK4o-N6Cqbq#O@R=^y`Xmc^;>WZ7;8 zBho-EW$8_uZk%No2*N~<8)-4%?Lc9q55+}|5M_fc(SQ(8Il6($fd*aD`_Y?lGwnwl zz#&K)_5Qs&Rp4G*--CY6{>#C5t0y@b{y4nU(!;H`{D|P2njBqOtJcTLEgc^Jh`@PYps3FVBArT0^9M_J^j)ceTXqN;L6&!J6+P%aRDRU zee?MzV`G>INLoflw9aOc#d3-fjH_%0suwUzYJ0YdHqH0JJ;AZ%w2$E#j~!*T787jn z)W8o;jICik;*8TF{v%2%s`isAx3tM34H`~P0>0EIU|>{xgX7kxR{pG!&<__Msn)Zi zr}Z_{UlcF=e)SVG*p}BytRtkDcO>y z%#8qTlq!&vZyu5@#{^_u7miqEv)`VD6M@x_9v1omX6Z{GZx+n~n;j9@wBIuj`Ej z*xVM_WS1`_+)qIJ<8r+~F@Na8c^TleVZR1jN`Z?RBR9|(`^B=Hxj8*-)RfgiJuaYr zug=SSBSH7_Q5qh}31TnfS=Sft&=HzPl4U$u5@t=ip7|y+;oCx?V+{`(aTtvLEQtMz z##Cu_$#3xkSORjbJ!n$1=W|1r+z7%VtR`6oCAWP>$gK)%1-&5jGccoX8gh?j6ZY&D z30jVSV+r>xtxZM^pJ#eMt+;gKyo_B_cw}9t~wR>Rvfs?U<=H z#{*55OY8rjGwRgi%-7kvB9{9+-Y)Z(vV&bQEOg#uU6(?zWsDXTr?#r*yI$3;Ggo}uEL?}LdxzjFAFRlJktE&5+$~Qfo)srscor~;H zHHOS6<@)AQuoHKW@pE4Fuw{U0?r`hztwi_w-4g^&q=Vl)yUp!xbZ9Qf%OssYva1us zc`i7{3Emj0iSh>Lzsx)v5ls>HC0}f6S}Fq#!xgo(cCUCjIVW*d;r(=5JVXmr#WEG^ zn_X_s%zK8lYpvR0qkN89Z=clE)YRLp!UO0&2a?<#uD8C%#eF8@chSE&+W`{8cuf6kzE?`x-}-nQd=6Tb z%-<}hQ;Uifqth_!W-C+as|E`uB0<36XPK16zCAg|i4Xlv1YSeSe_@l9m>wZovUV=<&`m zE+N4P)&LVsfqJ-Ienj?O03)h0b90f(S}urT!7#9zM%Sks2F(sx7x}8Fum__eds{ZX z5;8x%p7uU772g%)PwlmSEv18X|s$^fSQ~xAL?5*O3H)4;-S*BrMI6$f2jVUL@P`61@HgvUAUvw5Ksw`9U4%*%P zRQnIXY@y?R)l`lY~qE8ftt29m^+993P7%|t}a?r zLRB=i!U`B%t`}_4d{ciYQX z1B(5&StuIS)!pw3!B`nI^| zrQpzN`o4h;smw-j?Dcg1bXRqseOM#0?Y+##nJ&`0?{p*UIF5t57v)

1h3*y;_g6 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 z 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 literal 22362 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

WMIZgH4V>1zW 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 diff --git a/gensim/models/fasttext.py b/gensim/models/fasttext.py index e83e85ab59..38dd4172f6 100644 --- a/gensim/models/fasttext.py +++ b/gensim/models/fasttext.py @@ -99,7 +99,7 @@ >>> from gensim import utils >>> >>> - >>> class MyIter(object): + >>> class MyIter: ... def __iter__(self): ... path = datapath('crime-and-punishment.txt') ... with utils.open(path, 'r', encoding='utf-8') as fin: diff --git a/tox.ini b/tox.ini index e076698942..db3bc986d0 100644 --- a/tox.ini +++ b/tox.ini @@ -5,20 +5,29 @@ skipsdist = True platform = linux: linux win: win64 + [flake8] ignore = E12, W503 max-line-length = 120 show-source = True + [flake8-rst] filename = *.rst *.py max-line-length = 120 -ignore = F821, F401 ; TODO remove me when all examples in docstrings will be executable -exclude=.venv, .git, .tox, dist, doc, build, gensim/models/deprecated +ignore = E203, # space before : + E402, # module level import not at top of file + # Classes / functions in a docstring block generate those errors + E302, # expected 2 blank lines, found 0 + E305, # expected 2 blank lines after class or function definition, found 0 +# F821, # undefined name +exclude = .venv, .git, .tox, dist, doc, build, gensim/models/deprecated + [pytest] addopts = -rfxEXs --durations=20 --showlocals + [testenv] recreate = True @@ -51,14 +60,19 @@ commands = [testenv:flake8] recreate = True deps = - flake8==3.7.9 # 3.8.0 triggers "AttributeError: 'Namespace' object has no attribute 'output_file'" + # Pinned to 3.7.9 because >3.8.0 triggers "AttributeError: 'Namespace' object has no attribute 'output_file'" + # in flake8-rst. Apparently some bug in flake8-rst: + # https://gitlab.com/pycqa/flake8/-/issues/641 + # https://github.com/kataev/flake8-rst/pull/23/files + flake8==3.7.9 commands = flake8 gensim/ {posargs} + [testenv:flake8-docs] recreate = True deps = - flake8-rst==0.4.3 + flake8-rst==0.7.2 flake8==3.7.9 commands = flake8-rst gensim/ docs/ {posargs} From 7462453561abbe9c39748d13d386add72b247d0a Mon Sep 17 00:00:00 2001 From: Michael Penkov Date: Wed, 28 Oct 2020 11:21:45 +0900 Subject: [PATCH 17/20] add issues without a PR --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0945020a66..067a361c29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -93,6 +93,8 @@ Production stability is important to Gensim, so we're improving the process of * * [#2940](https://github.com/RaRe-Technologies/gensim/pull/2940); Fix deprecations in SoftCosineSimilarity, by [@Witiko](https://github.com/Witiko) * [#2944](https://github.com/RaRe-Technologies/gensim/pull/2944): Fix `save_facebook_model` failure after update-vocab & other initialization streamlining, by [@gojomo](https://github.com/gojomo) * [#2846](https://github.com/RaRe-Technologies/gensim/pull/2846): Fix for Python 3.9/3.10: remove `xml.etree.cElementTree`, by [@hugovk](https://github.com/hugovk) +* [#2973](https://github.com/RaRe-Technologies/gensim/issues/2973): phrases.export_phrases() doesn't yield all bigrams +* [#2942](https://github.com/RaRe-Technologies/gensim/issues/2942): Segfault when training doc2vec ### :warning: Removed functionality & deprecations From 74f28d0db32c58321adc77f620ecbc83c833cba6 Mon Sep 17 00:00:00 2001 From: Michael Penkov Date: Wed, 28 Oct 2020 11:22:01 +0900 Subject: [PATCH 18/20] improve changelog script --- release/generate_changelog.py | 68 +++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/release/generate_changelog.py b/release/generate_changelog.py index e47f7155e3..ce57dd7975 100644 --- a/release/generate_changelog.py +++ b/release/generate_changelog.py @@ -1,13 +1,26 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Author: Gensim Contributors +# Copyright (C) 2020 RaRe Technologies s.r.o. +# Licensed under the GNU LGPL v2.1 - http://www.gnu.org/licenses/lgpl.html + """Generate changelog entries for all PRs merged since the last release.""" +import re import requests + +# +# The releases get sorted in reverse chronological order, so the first release +# in the list is the most recent. +# get = requests.get('https://api.github.com/repos/RaRe-Technologies/gensim/releases') get.raise_for_status() - -last_release_date = get.json()[0]['published_at'][:10] +most_recent_release = get.json()[0] +release_timestamp = most_recent_release['published_at'] -def g(): +def iter_merged_prs(since=release_timestamp): page = 1 done = False @@ -22,17 +35,60 @@ def g(): break for i, pr in enumerate(pulls): - if pr['created_at'] < last_release_date: + if pr['created_at'] < since: done = True break - if pr['merged_at'] and pr['merged_at'] > last_release_date: + if pr['merged_at'] and pr['merged_at'] > since: yield pr page += 1 -for pr in g(): +def iter_closed_issues(since=release_timestamp): + page = 1 + done = False + while not done: + get = requests.get( + 'https://api.github.com/repos/RaRe-Technologies/gensim/issues', + params={'state': 'closed', 'page': page, 'since': since}, + ) + get.raise_for_status() + issues = get.json() + if not issues: + break + + for i, issue in enumerate(issues): + # + # In the github API, all pull requests are issues, but not vice versa. + # + if 'pull_request' not in issue and issue['closed_at'] > since: + yield issue + + page += 1 + + +fixed_issue_numbers = set() +for pr in iter_merged_prs(since=release_timestamp): pr['user_login'] = pr['user']['login'] pr['user_html_url'] = pr['user']['html_url'] print('* [#%(number)d](%(html_url)s): %(title)s, by [@%(user_login)s](%(user_html_url)s)' % pr) + + # + # Unfortunately, the GitHub API doesn't link PRs to issues that they fix, + # so we have do it ourselves. + # + for match in re.finditer(r'fix(es)? #(?P\d+)\b', pr['body'], flags=re.IGNORECASE): + fixed_issue_numbers.add(int(match.group('number'))) + + +print() +print('### :question: Closed issues') +print() +print('TODO: move each issue to its appropriate section or delete if irrelevant') +print() + +for issue in iter_closed_issues(since=release_timestamp): + if 'pull_request' in issue or issue['number'] in fixed_issue_numbers: + continue + print('* [#%(number)d](%(html_url)s): %(title)s' % issue) From a1b05778787c993920c1c68e2809bf6f81089f18 Mon Sep 17 00:00:00 2001 From: Michael Penkov Date: Wed, 28 Oct 2020 11:28:40 +0900 Subject: [PATCH 19/20] simplify pagination --- release/generate_changelog.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/release/generate_changelog.py b/release/generate_changelog.py index ce57dd7975..72b03c7cda 100644 --- a/release/generate_changelog.py +++ b/release/generate_changelog.py @@ -22,9 +22,7 @@ def iter_merged_prs(since=release_timestamp): page = 1 - done = False - - while not done: + while True: get = requests.get( 'https://api.github.com/repos/RaRe-Technologies/gensim/pulls', params={'state': 'closed', 'page': page}, @@ -35,10 +33,6 @@ def iter_merged_prs(since=release_timestamp): break for i, pr in enumerate(pulls): - if pr['created_at'] < since: - done = True - break - if pr['merged_at'] and pr['merged_at'] > since: yield pr @@ -47,8 +41,7 @@ def iter_merged_prs(since=release_timestamp): def iter_closed_issues(since=release_timestamp): page = 1 - done = False - while not done: + while True: get = requests.get( 'https://api.github.com/repos/RaRe-Technologies/gensim/issues', params={'state': 'closed', 'page': page, 'since': since}, @@ -64,7 +57,6 @@ def iter_closed_issues(since=release_timestamp): # if 'pull_request' not in issue and issue['closed_at'] > since: yield issue - page += 1 From 9cf8bb59f13fb7cea5269c44b15a6a5e7e086003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20=C5=98eh=C5=AF=C5=99ek?= Date: Wed, 28 Oct 2020 10:27:36 +0100 Subject: [PATCH 20/20] more flake8-rst fixing --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index db3bc986d0..f73dedf3d7 100644 --- a/tox.ini +++ b/tox.ini @@ -20,7 +20,7 @@ ignore = E203, # space before : # Classes / functions in a docstring block generate those errors E302, # expected 2 blank lines, found 0 E305, # expected 2 blank lines after class or function definition, found 0 -# F821, # undefined name + F821, # undefined name; remove once all docstrings are fully executable exclude = .venv, .git, .tox, dist, doc, build, gensim/models/deprecated