From 15f9282ecccf7fc470f5942e608de830fb4f2ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Novotn=C3=BD?= Date: Sun, 28 Feb 2021 18:02:37 +0100 Subject: [PATCH] Run run_scm.py --- docs/src/auto_examples/howtos/run_doc.ipynb | 6 +- docs/src/auto_examples/howtos/run_doc.py | 2 +- docs/src/auto_examples/howtos/run_doc.py.md5 | 2 +- docs/src/auto_examples/howtos/run_doc.rst | 31 +- .../howtos/sg_execution_times.rst | 15 +- docs/src/auto_examples/index.rst | 120 +++---- .../tutorials/images/sphx_glr_run_wmd_001.png | Bin 14951 -> 31931 bytes .../images/thumb/sphx_glr_run_wmd_thumb.png | Bin 16911 -> 17172 bytes .../src/auto_examples/tutorials/run_scm.ipynb | 176 ++++++++++ docs/src/auto_examples/tutorials/run_scm.py | 153 +++++++++ .../auto_examples/tutorials/run_scm.py.md5 | 1 + docs/src/auto_examples/tutorials/run_scm.rst | 313 ++++++++++++++++++ .../src/auto_examples/tutorials/run_wmd.ipynb | 24 +- docs/src/auto_examples/tutorials/run_wmd.py | 31 +- .../auto_examples/tutorials/run_wmd.py.md5 | 2 +- docs/src/auto_examples/tutorials/run_wmd.rst | 138 +++----- .../tutorials/sg_execution_times.rst | 22 +- docs/src/gallery/tutorials/run_scm.py | 29 +- 18 files changed, 797 insertions(+), 268 deletions(-) create mode 100644 docs/src/auto_examples/tutorials/run_scm.ipynb create mode 100644 docs/src/auto_examples/tutorials/run_scm.py create mode 100644 docs/src/auto_examples/tutorials/run_scm.py.md5 create mode 100644 docs/src/auto_examples/tutorials/run_scm.rst diff --git a/docs/src/auto_examples/howtos/run_doc.ipynb b/docs/src/auto_examples/howtos/run_doc.ipynb index 48820b593a..7d3be48ac2 100644 --- a/docs/src/auto_examples/howtos/run_doc.ipynb +++ b/docs/src/auto_examples/howtos/run_doc.ipynb @@ -15,7 +15,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "\nHow to Author Gensim Documentation\n==================================\n\nHow to author documentation for Gensim.\n\n" + "\nHow to Author Gensim Documentation\n==================================\n\nHow to author documentation for Gensim.\n" ] }, { @@ -54,7 +54,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Authoring Workflow\n------------------\n\nThere are several ways to author documentation.\nThe simplest and most straightforward is to author your ``script.py`` from scratch.\nYou'll have the following cycle:\n\n1. Make changes\n2. Run ``python script.py``\n3. Check standard output, standard error and return code\n4. If everything works well, stop.\n5. Otherwise, go back to step 1).\n\nIf the above is not your cup of tea, you can also author your documentation as a Jupyter notebook.\nThis is a more flexible approach that enables you to tweak parts of the documentation and re-run them as necessary.\n\nOnce you're happy with the notebook, convert it to a script.py.\nThere's a helpful `script `__ that will do it for you.\nTo use it::\n\n python to_python.py < notebook.ipynb > script.py\n\nYou may have to touch up the resulting ``script.py``.\nMore specifically:\n\n- Update the title\n- Update the description\n- Fix any issues that the markdown-to-RST converter could not deal with\n\nOnce your script.py works, put it in a suitable subdirectory.\nPlease don't include your original Jupyter notebook in the repository - we won't be using it.\n\n" + "Authoring Workflow\n------------------\n\nThere are several ways to author documentation.\nThe simplest and most straightforward is to author your ``script.py`` from scratch.\nYou'll have the following cycle:\n\n1. Make changes\n2. Run ``python script.py``\n3. Check standard output, standard error and return code\n4. If everything works well, stop.\n5. Otherwise, go back to step 1).\n\nIf the above is not your cup of tea, you can also author your documentation as a Jupyter notebook.\nThis is a more flexible approach that enables you to tweak parts of the documentation and re-run them as necessary.\n\nOnce you're happy with the notebook, convert it to a script.py.\nThere's a helpful `script `__ that will do it for you.\nTo use it::\n\n python to_python.py < notebook.ipynb > script.py\n\nYou may have to touch up the resulting ``script.py``.\nMore specifically:\n\n- Update the title\n- Update the description\n- Fix any issues that the markdown-to-RST converter could not deal with\n\nOnce your script.py works, put it in a suitable subdirectory.\nPlease don't include your original Jupyter notebook in the repository - we won't be using it.\n\n" ] }, { @@ -81,7 +81,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.7.3" } }, "nbformat": 4, diff --git a/docs/src/auto_examples/howtos/run_doc.py b/docs/src/auto_examples/howtos/run_doc.py index 7e07ab74bd..15e870f1be 100644 --- a/docs/src/auto_examples/howtos/run_doc.py +++ b/docs/src/auto_examples/howtos/run_doc.py @@ -111,7 +111,7 @@ # This is a more flexible approach that enables you to tweak parts of the documentation and re-run them as necessary. # # Once you're happy with the notebook, convert it to a script.py. -# There's a helpful `script `__ that will do it for you. +# There's a helpful `script `__ that will do it for you. # To use it:: # # python to_python.py < notebook.ipynb > script.py diff --git a/docs/src/auto_examples/howtos/run_doc.py.md5 b/docs/src/auto_examples/howtos/run_doc.py.md5 index d81fe9d241..979aa0eb5e 100644 --- a/docs/src/auto_examples/howtos/run_doc.py.md5 +++ b/docs/src/auto_examples/howtos/run_doc.py.md5 @@ -1 +1 @@ -b3db0b66859316de13e1a36fa6181657 \ No newline at end of file +512a76ce743dd12482d21784a76b60fe \ No newline at end of file diff --git a/docs/src/auto_examples/howtos/run_doc.rst b/docs/src/auto_examples/howtos/run_doc.rst index 88d1904295..c763ca1de0 100644 --- a/docs/src/auto_examples/howtos/run_doc.rst +++ b/docs/src/auto_examples/howtos/run_doc.rst @@ -1,12 +1,10 @@ -.. only:: html - - .. note:: - :class: sphx-glr-download-link-note +.. note:: + :class: sphx-glr-download-link-note - Click :ref:`here ` to download the full example code - .. rst-class:: sphx-glr-example-title + Click :ref:`here ` to download the full example code +.. rst-class:: sphx-glr-example-title - .. _sphx_glr_auto_examples_howtos_run_doc.py: +.. _sphx_glr_auto_examples_howtos_run_doc.py: How to Author Gensim Documentation @@ -80,15 +78,6 @@ At the very top, you need a docstring describing what your script does. -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - - '\nTitle\n=====\n\nBrief description.\n' - The title is what will show up in the gallery. @@ -135,7 +124,7 @@ If the above is not your cup of tea, you can also author your documentation as a This is a more flexible approach that enables you to tweak parts of the documentation and re-run them as necessary. Once you're happy with the notebook, convert it to a script.py. -There's a helpful `script `__ that will do it for you. +There's a helpful `script `__ that will do it for you. To use it:: python to_python.py < notebook.ipynb > script.py @@ -207,9 +196,9 @@ At that stage, give yourself a pat on the back: you're done! .. rst-class:: sphx-glr-timing - **Total running time of the script:** ( 0 minutes 0.112 seconds) + **Total running time of the script:** ( 0 minutes 1.226 seconds) -**Estimated memory usage:** 6 MB +**Estimated memory usage:** 9 MB .. _sphx_glr_download_auto_examples_howtos_run_doc.py: @@ -222,13 +211,13 @@ At that stage, give yourself a pat on the back: you're done! - .. container:: sphx-glr-download sphx-glr-download-python + .. container:: sphx-glr-download :download:`Download Python source code: run_doc.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter + .. container:: sphx-glr-download :download:`Download Jupyter notebook: run_doc.ipynb ` diff --git a/docs/src/auto_examples/howtos/sg_execution_times.rst b/docs/src/auto_examples/howtos/sg_execution_times.rst index 628fe13c1f..ec9ea90bd7 100644 --- a/docs/src/auto_examples/howtos/sg_execution_times.rst +++ b/docs/src/auto_examples/howtos/sg_execution_times.rst @@ -5,14 +5,9 @@ Computation times ================= -**52:12.903** total execution time for **auto_examples_howtos** files: +**00:01.226** total execution time for **auto_examples_howtos** files: -+----------------------------------------------------------------------------------------+-----------+-----------+ -| :ref:`sphx_glr_auto_examples_howtos_run_doc2vec_imdb.py` (``run_doc2vec_imdb.py``) | 52:12.903 | 3494.0 MB | -+----------------------------------------------------------------------------------------+-----------+-----------+ -| :ref:`sphx_glr_auto_examples_howtos_run_compare_lda.py` (``run_compare_lda.py``) | 00:00.000 | 0.0 MB | -+----------------------------------------------------------------------------------------+-----------+-----------+ -| :ref:`sphx_glr_auto_examples_howtos_run_doc.py` (``run_doc.py``) | 00:00.000 | 0.0 MB | -+----------------------------------------------------------------------------------------+-----------+-----------+ -| :ref:`sphx_glr_auto_examples_howtos_run_downloader_api.py` (``run_downloader_api.py``) | 00:00.000 | 0.0 MB | -+----------------------------------------------------------------------------------------+-----------+-----------+ +- **00:01.226**: :ref:`sphx_glr_auto_examples_howtos_run_doc.py` (``run_doc.py``) +- **00:00.000**: :ref:`sphx_glr_auto_examples_howtos_run_compare_lda.py` (``run_compare_lda.py``) +- **00:00.000**: :ref:`sphx_glr_auto_examples_howtos_run_doc2vec_imdb.py` (``run_doc2vec_imdb.py``) +- **00:00.000**: :ref:`sphx_glr_auto_examples_howtos_run_downloader_api.py` (``run_downloader_api.py``) diff --git a/docs/src/auto_examples/index.rst b/docs/src/auto_examples/index.rst index ca3c1ec019..1ec9276242 100644 --- a/docs/src/auto_examples/index.rst +++ b/docs/src/auto_examples/index.rst @@ -13,7 +13,7 @@ If you're thinking about contributing documentation, please see :ref:`sphx_glr_a .. raw:: html -
+
@@ -33,10 +33,9 @@ Understanding this functionality is vital for using gensim effectively. .. only:: html - .. figure:: /auto_examples/core/images/thumb/sphx_glr_run_core_concepts_thumb.png - :alt: Core Concepts + .. figure:: /auto_examples/core/images/thumb/sphx_glr_run_core_concepts_thumb.png - :ref:`sphx_glr_auto_examples_core_run_core_concepts.py` + :ref:`sphx_glr_auto_examples_core_run_core_concepts.py` .. raw:: html @@ -54,10 +53,9 @@ Understanding this functionality is vital for using gensim effectively. .. only:: html - .. figure:: /auto_examples/core/images/thumb/sphx_glr_run_corpora_and_vector_spaces_thumb.png - :alt: Corpora and Vector Spaces + .. figure:: /auto_examples/core/images/thumb/sphx_glr_run_corpora_and_vector_spaces_thumb.png - :ref:`sphx_glr_auto_examples_core_run_corpora_and_vector_spaces.py` + :ref:`sphx_glr_auto_examples_core_run_corpora_and_vector_spaces.py` .. raw:: html @@ -71,14 +69,13 @@ Understanding this functionality is vital for using gensim effectively. .. raw:: html -
+
.. only:: html - .. figure:: /auto_examples/core/images/thumb/sphx_glr_run_topics_and_transformations_thumb.png - :alt: Topics and Transformations + .. figure:: /auto_examples/core/images/thumb/sphx_glr_run_topics_and_transformations_thumb.png - :ref:`sphx_glr_auto_examples_core_run_topics_and_transformations.py` + :ref:`sphx_glr_auto_examples_core_run_topics_and_transformations.py` .. raw:: html @@ -92,14 +89,13 @@ Understanding this functionality is vital for using gensim effectively. .. raw:: html -
+
.. only:: html - .. figure:: /auto_examples/core/images/thumb/sphx_glr_run_similarity_queries_thumb.png - :alt: Similarity Queries + .. figure:: /auto_examples/core/images/thumb/sphx_glr_run_similarity_queries_thumb.png - :ref:`sphx_glr_auto_examples_core_run_similarity_queries.py` + :ref:`sphx_glr_auto_examples_core_run_similarity_queries.py` .. raw:: html @@ -112,7 +108,7 @@ Understanding this functionality is vital for using gensim effectively. /auto_examples/core/run_similarity_queries .. raw:: html -
+
@@ -131,10 +127,9 @@ Learning-oriented lessons that introduce a particular gensim feature, e.g. a mod .. only:: html - .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_word2vec_thumb.png - :alt: Word2Vec Model + .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_word2vec_thumb.png - :ref:`sphx_glr_auto_examples_tutorials_run_word2vec.py` + :ref:`sphx_glr_auto_examples_tutorials_run_word2vec.py` .. raw:: html @@ -152,10 +147,9 @@ Learning-oriented lessons that introduce a particular gensim feature, e.g. a mod .. only:: html - .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_doc2vec_lee_thumb.png - :alt: Doc2Vec Model + .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_doc2vec_lee_thumb.png - :ref:`sphx_glr_auto_examples_tutorials_run_doc2vec_lee.py` + :ref:`sphx_glr_auto_examples_tutorials_run_doc2vec_lee.py` .. raw:: html @@ -169,14 +163,13 @@ Learning-oriented lessons that introduce a particular gensim feature, e.g. a mod .. raw:: html -
+
.. only:: html - .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_fasttext_thumb.png - :alt: FastText Model + .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_fasttext_thumb.png - :ref:`sphx_glr_auto_examples_tutorials_run_fasttext.py` + :ref:`sphx_glr_auto_examples_tutorials_run_fasttext.py` .. raw:: html @@ -190,14 +183,13 @@ Learning-oriented lessons that introduce a particular gensim feature, e.g. a mod .. raw:: html -
+
.. only:: html - .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_annoy_thumb.png - :alt: Fast Similarity Queries with Annoy and Word2Vec + .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_annoy_thumb.png - :ref:`sphx_glr_auto_examples_tutorials_run_annoy.py` + :ref:`sphx_glr_auto_examples_tutorials_run_annoy.py` .. raw:: html @@ -215,10 +207,9 @@ Learning-oriented lessons that introduce a particular gensim feature, e.g. a mod .. only:: html - .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_lda_thumb.png - :alt: LDA Model + .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_lda_thumb.png - :ref:`sphx_glr_auto_examples_tutorials_run_lda.py` + :ref:`sphx_glr_auto_examples_tutorials_run_lda.py` .. raw:: html @@ -236,10 +227,9 @@ Learning-oriented lessons that introduce a particular gensim feature, e.g. a mod .. only:: html - .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_wmd_thumb.png - :alt: Word Mover's Distance + .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_wmd_thumb.png - :ref:`sphx_glr_auto_examples_tutorials_run_wmd.py` + :ref:`sphx_glr_auto_examples_tutorials_run_wmd.py` .. raw:: html @@ -250,9 +240,29 @@ Learning-oriented lessons that introduce a particular gensim feature, e.g. a mod :hidden: /auto_examples/tutorials/run_wmd + +.. raw:: html + +
+ +.. only:: html + + .. figure:: /auto_examples/tutorials/images/thumb/sphx_glr_run_scm_thumb.png + + :ref:`sphx_glr_auto_examples_tutorials_run_scm.py` + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /auto_examples/tutorials/run_scm .. raw:: html -
+
@@ -267,14 +277,13 @@ These **goal-oriented guides** demonstrate how to **solve a specific problem** u .. raw:: html -
+
.. only:: html - .. figure:: /auto_examples/howtos/images/thumb/sphx_glr_run_downloader_api_thumb.png - :alt: How to download pre-trained models and corpora + .. figure:: /auto_examples/howtos/images/thumb/sphx_glr_run_downloader_api_thumb.png - :ref:`sphx_glr_auto_examples_howtos_run_downloader_api.py` + :ref:`sphx_glr_auto_examples_howtos_run_downloader_api.py` .. raw:: html @@ -288,14 +297,13 @@ These **goal-oriented guides** demonstrate how to **solve a specific problem** u .. raw:: html -
+
.. only:: html - .. figure:: /auto_examples/howtos/images/thumb/sphx_glr_run_doc_thumb.png - :alt: How to Author Gensim Documentation + .. figure:: /auto_examples/howtos/images/thumb/sphx_glr_run_doc_thumb.png - :ref:`sphx_glr_auto_examples_howtos_run_doc.py` + :ref:`sphx_glr_auto_examples_howtos_run_doc.py` .. raw:: html @@ -313,10 +321,9 @@ These **goal-oriented guides** demonstrate how to **solve a specific problem** u .. only:: html - .. figure:: /auto_examples/howtos/images/thumb/sphx_glr_run_doc2vec_imdb_thumb.png - :alt: How to reproduce the doc2vec 'Paragraph Vector' paper + .. figure:: /auto_examples/howtos/images/thumb/sphx_glr_run_doc2vec_imdb_thumb.png - :ref:`sphx_glr_auto_examples_howtos_run_doc2vec_imdb.py` + :ref:`sphx_glr_auto_examples_howtos_run_doc2vec_imdb.py` .. raw:: html @@ -334,10 +341,9 @@ These **goal-oriented guides** demonstrate how to **solve a specific problem** u .. only:: html - .. figure:: /auto_examples/howtos/images/thumb/sphx_glr_run_compare_lda_thumb.png - :alt: How to Compare LDA Models + .. figure:: /auto_examples/howtos/images/thumb/sphx_glr_run_compare_lda_thumb.png - :ref:`sphx_glr_auto_examples_howtos_run_compare_lda.py` + :ref:`sphx_glr_auto_examples_howtos_run_compare_lda.py` .. raw:: html @@ -350,7 +356,7 @@ These **goal-oriented guides** demonstrate how to **solve a specific problem** u /auto_examples/howtos/run_compare_lda .. raw:: html -
+
@@ -393,7 +399,7 @@ Blog posts, tutorial videos, hackathons and other useful Gensim resources, from .. raw:: html -
+
@@ -403,15 +409,15 @@ Blog posts, tutorial videos, hackathons and other useful Gensim resources, from :class: sphx-glr-footer-gallery - .. container:: sphx-glr-download sphx-glr-download-python + .. container:: sphx-glr-download - :download:`Download all examples in Python source code: auto_examples_python.zip ` + :download:`Download all examples in Python source code: auto_examples_python.zip ` - .. container:: sphx-glr-download sphx-glr-download-jupyter + .. container:: sphx-glr-download - :download:`Download all examples in Jupyter notebooks: auto_examples_jupyter.zip ` + :download:`Download all examples in Jupyter notebooks: auto_examples_jupyter.zip ` .. only:: html diff --git a/docs/src/auto_examples/tutorials/images/sphx_glr_run_wmd_001.png b/docs/src/auto_examples/tutorials/images/sphx_glr_run_wmd_001.png index 779c1df3692c78049f8f0ece76c7b1ded52f89f0..7d7ea7db56c5c8dc4d14f7739370a485d74c9814 100644 GIT binary patch literal 31931 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 F{|n>cW(fcQ diff --git a/docs/src/auto_examples/tutorials/images/thumb/sphx_glr_run_wmd_thumb.png b/docs/src/auto_examples/tutorials/images/thumb/sphx_glr_run_wmd_thumb.png index 78c25f381ec81818979cbaf460841e04f7421275..381d4a9d592148dda9d9dd0066687d998ad6059c 100644 GIT binary patch literal 17172 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 diff --git a/docs/src/auto_examples/tutorials/run_scm.ipynb b/docs/src/auto_examples/tutorials/run_scm.ipynb new file mode 100644 index 0000000000..91fb6f86bd --- /dev/null +++ b/docs/src/auto_examples/tutorials/run_scm.ipynb @@ -0,0 +1,176 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\nSoft Cosine Measure\n===================\n\nDemonstrates using Gensim's implemenation of the SCM.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Soft Cosine Measure (SCM) is a promising new tool in machine learning that\nallows us to submit a query and return the most relevant documents. This\ntutorial introduces SCM and shows how you can compute the SCM similarities\nbetween two documents using the ``inner_product`` method.\n\nSoft Cosine Measure basics\n--------------------------\n\nSoft Cosine Measure (SCM) is a method that allows us to assess the similarity\nbetween two documents in a meaningful way, even when they have no words in\ncommon. It uses a measure of similarity between words, which can be derived\n[2] using [word2vec][] [4] vector embeddings of words. It has been shown to\noutperform many of the state-of-the-art methods in the semantic text\nsimilarity task in the context of community question answering [2].\n\n\nSCM is illustrated below for two very similar sentences. The sentences have\nno words in common, but by modeling synonymy, SCM is able to accurately\nmeasure the similarity between the two sentences. The method also uses the\nbag-of-words vector representation of the documents (simply put, the word's\nfrequencies in the documents). The intution behind the method is that we\ncompute standard cosine similarity assuming that the document vectors are\nexpressed in a non-orthogonal basis, where the angle between two basis\nvectors is derived from the angle between the word2vec embeddings of the\ncorresponding words.\n\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nimg = mpimg.imread('scm-hello.png')\nimgplot = plt.imshow(img)\nplt.axis('off')\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This method was perhaps first introduced in the article \u201cSoft Measure and\nSoft Cosine Measure: Measure of Features in Vector Space Model\u201d by Grigori\nSidorov, Alexander Gelbukh, Helena Gomez-Adorno, and David Pinto.\n\nIn this tutorial, we will learn how to use Gensim's SCM functionality, which\nconsists of the ``inner_product`` method for one-off computation, and the\n``SoftCosineSimilarity`` class for corpus-based similarity queries.\n\n.. Important::\n If you use Gensim's SCM functionality, please consider citing [1], [2] and [3].\n\nComputing the Soft Cosine Measure\n---------------------------------\nTo use SCM, you need some existing word embeddings.\nYou could train your own Word2Vec model, but that is beyond the scope of this tutorial\n(check out `sphx_glr_auto_examples_tutorials_run_word2vec.py` if you're interested).\nFor this tutorial, we'll be using an existing Word2Vec model.\n\nLet's take some sentences to compute the distance between.\n\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Initialize logging.\nimport logging\nlogging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)\n\nsentence_obama = 'Obama speaks to the media in Illinois'\nsentence_president = 'The president greets the press in Chicago'\nsentence_orange = 'Oranges are my favorite fruit'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The first two sentences sentences have very similar content, and as such the\nSCM should be high. By contrast, the third sentence is unrelated to the first\ntwo and the SCM should be low.\n\nBefore we compute the SCM, we want to remove stopwords (\"the\", \"to\", etc.),\nas these do not contribute a lot to the information in the sentences.\n\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Import and download stopwords from NLTK.\nfrom nltk.corpus import stopwords\nfrom nltk import download\ndownload('stopwords') # Download stopwords list.\nstop_words = stopwords.words('english')\n\ndef preprocess(sentence):\n return [w for w in sentence.lower().split() if w not in stop_words]\n\nsentence_obama = preprocess(sentence_obama)\nsentence_president = preprocess(sentence_president)\nsentence_orange = preprocess(sentence_orange)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we will build a dictionary and a TF-IDF model, and we will convert the\nsentences to the bag-of-words format.\n\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from gensim.corpora import Dictionary\ndocuments = [sentence_obama, sentence_president, sentence_orange]\ndictionary = Dictionary(documents)\n\nsentence_obama = dictionary.doc2bow(sentence_obama)\nsentence_president = dictionary.doc2bow(sentence_president)\nsentence_orange = dictionary.doc2bow(sentence_orange)\n\nfrom gensim.models import TfidfModel\ndocuments = [sentence_obama, sentence_president, sentence_orange]\ntfidf = TfidfModel(documents)\n\nsentence_obama = tfidf[sentence_obama]\nsentence_president = tfidf[sentence_president]\nsentence_orange = tfidf[sentence_orange]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, as mentioned earlier, we will be using some downloaded pre-trained\nembeddings. We load these into a Gensim Word2Vec model class and we build\na term similarity mextrix using the embeddings.\n\n.. Important::\n The embeddings we have chosen here require a lot of memory.\n\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import gensim.downloader as api\nmodel = api.load('word2vec-google-news-300')\n\nfrom gensim.similarities import SparseTermSimilarityMatrix, WordEmbeddingSimilarityIndex\ntermsim_index = WordEmbeddingSimilarityIndex(model)\ntermsim_matrix = SparseTermSimilarityMatrix(termsim_index, dictionary, tfidf)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So let's compute SCM using the ``inner_product`` method.\n\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "similarity = termsim_matrix.inner_product(sentence_obama, sentence_president, normalized=(True, True))\nprint('similarity = %.4f' % similarity)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's try the same thing with two completely unrelated sentences.\nNotice that the similarity is smaller.\n\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "similarity = termsim_matrix.inner_product(sentence_obama, sentence_orange, normalized=(True, True))\nprint('similarity = %.4f' % similarity)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "References\n----------\n\n1. Grigori Sidorov et al. *Soft Similarity and Soft Cosine Measure: Similarity of Features in Vector Space Model*, 2014.\n2. Delphine Charlet and Geraldine Damnati, SimBow at SemEval-2017 Task 3: Soft-Cosine Semantic Similarity between Questions for Community Question Answering, 2017.\n3. V\u00edt Novotn\u00fd. *Implementation Notes for the Soft Cosine Measure*, 2018.\n4. Tom\u00e1\u0161 Mikolov et al. Efficient Estimation of Word Representations in Vector Space, 2013.\n\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/src/auto_examples/tutorials/run_scm.py b/docs/src/auto_examples/tutorials/run_scm.py new file mode 100644 index 0000000000..d57c9f6a1e --- /dev/null +++ b/docs/src/auto_examples/tutorials/run_scm.py @@ -0,0 +1,153 @@ +r""" +Soft Cosine Measure +=================== + +Demonstrates using Gensim's implemenation of the SCM. + +""" + +############################################################################### +# Soft Cosine Measure (SCM) is a promising new tool in machine learning that +# allows us to submit a query and return the most relevant documents. This +# tutorial introduces SCM and shows how you can compute the SCM similarities +# between two documents using the ``inner_product`` method. +# +# Soft Cosine Measure basics +# -------------------------- +# +# Soft Cosine Measure (SCM) is a method that allows us to assess the similarity +# between two documents in a meaningful way, even when they have no words in +# common. It uses a measure of similarity between words, which can be derived +# [2] using [word2vec][] [4] vector embeddings of words. It has been shown to +# outperform many of the state-of-the-art methods in the semantic text +# similarity task in the context of community question answering [2]. +# +# +# SCM is illustrated below for two very similar sentences. The sentences have +# no words in common, but by modeling synonymy, SCM is able to accurately +# measure the similarity between the two sentences. The method also uses the +# bag-of-words vector representation of the documents (simply put, the word's +# frequencies in the documents). The intution behind the method is that we +# compute standard cosine similarity assuming that the document vectors are +# expressed in a non-orthogonal basis, where the angle between two basis +# vectors is derived from the angle between the word2vec embeddings of the +# corresponding words. +# + +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +img = mpimg.imread('scm-hello.png') +imgplot = plt.imshow(img) +plt.axis('off') +plt.show() + +############################################################################### +# This method was perhaps first introduced in the article “Soft Measure and +# Soft Cosine Measure: Measure of Features in Vector Space Model” by Grigori +# Sidorov, Alexander Gelbukh, Helena Gomez-Adorno, and David Pinto. +# +# In this tutorial, we will learn how to use Gensim's SCM functionality, which +# consists of the ``inner_product`` method for one-off computation, and the +# ``SoftCosineSimilarity`` class for corpus-based similarity queries. +# +# .. Important:: +# If you use Gensim's SCM functionality, please consider citing [1], [2] and [3]. +# +# Computing the Soft Cosine Measure +# --------------------------------- +# To use SCM, you need some existing word embeddings. +# You could train your own Word2Vec model, but that is beyond the scope of this tutorial +# (check out :ref:`sphx_glr_auto_examples_tutorials_run_word2vec.py` if you're interested). +# For this tutorial, we'll be using an existing Word2Vec model. +# +# Let's take some sentences to compute the distance between. +# + +# Initialize logging. +import logging +logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) + +sentence_obama = 'Obama speaks to the media in Illinois' +sentence_president = 'The president greets the press in Chicago' +sentence_orange = 'Oranges are my favorite fruit' + +############################################################################### +# The first two sentences sentences have very similar content, and as such the +# SCM should be high. By contrast, the third sentence is unrelated to the first +# two and the SCM should be low. +# +# Before we compute the SCM, we want to remove stopwords ("the", "to", etc.), +# as these do not contribute a lot to the information in the sentences. +# + +# Import and download stopwords from NLTK. +from nltk.corpus import stopwords +from nltk import download +download('stopwords') # Download stopwords list. +stop_words = stopwords.words('english') + +def preprocess(sentence): + return [w for w in sentence.lower().split() if w not in stop_words] + +sentence_obama = preprocess(sentence_obama) +sentence_president = preprocess(sentence_president) +sentence_orange = preprocess(sentence_orange) + +############################################################################### +# Next, we will build a dictionary and a TF-IDF model, and we will convert the +# sentences to the bag-of-words format. +# +from gensim.corpora import Dictionary +documents = [sentence_obama, sentence_president, sentence_orange] +dictionary = Dictionary(documents) + +sentence_obama = dictionary.doc2bow(sentence_obama) +sentence_president = dictionary.doc2bow(sentence_president) +sentence_orange = dictionary.doc2bow(sentence_orange) + +from gensim.models import TfidfModel +documents = [sentence_obama, sentence_president, sentence_orange] +tfidf = TfidfModel(documents) + +sentence_obama = tfidf[sentence_obama] +sentence_president = tfidf[sentence_president] +sentence_orange = tfidf[sentence_orange] + +############################################################################### +# Now, as mentioned earlier, we will be using some downloaded pre-trained +# embeddings. We load these into a Gensim Word2Vec model class and we build +# a term similarity mextrix using the embeddings. +# +# .. Important:: +# The embeddings we have chosen here require a lot of memory. +# +import gensim.downloader as api +model = api.load('word2vec-google-news-300') + +from gensim.similarities import SparseTermSimilarityMatrix, WordEmbeddingSimilarityIndex +termsim_index = WordEmbeddingSimilarityIndex(model) +termsim_matrix = SparseTermSimilarityMatrix(termsim_index, dictionary, tfidf) + +############################################################################### +# So let's compute SCM using the ``inner_product`` method. +# +similarity = termsim_matrix.inner_product(sentence_obama, sentence_president, normalized=(True, True)) +print('similarity = %.4f' % similarity) + +############################################################################### +# Let's try the same thing with two completely unrelated sentences. +# Notice that the similarity is smaller. +# +similarity = termsim_matrix.inner_product(sentence_obama, sentence_orange, normalized=(True, True)) +print('similarity = %.4f' % similarity) + +############################################################################### +# +# References +# ---------- +# +# 1. Grigori Sidorov et al. *Soft Similarity and Soft Cosine Measure: Similarity of Features in Vector Space Model*, 2014. +# 2. Delphine Charlet and Geraldine Damnati, SimBow at SemEval-2017 Task 3: Soft-Cosine Semantic Similarity between Questions for Community Question Answering, 2017. +# 3. Vít Novotný. *Implementation Notes for the Soft Cosine Measure*, 2018. +# 4. Tomáš Mikolov et al. Efficient Estimation of Word Representations in Vector Space, 2013. +# diff --git a/docs/src/auto_examples/tutorials/run_scm.py.md5 b/docs/src/auto_examples/tutorials/run_scm.py.md5 new file mode 100644 index 0000000000..c6a7a736cb --- /dev/null +++ b/docs/src/auto_examples/tutorials/run_scm.py.md5 @@ -0,0 +1 @@ +0bbd28e31784997fb257771856183106 \ No newline at end of file diff --git a/docs/src/auto_examples/tutorials/run_scm.rst b/docs/src/auto_examples/tutorials/run_scm.rst new file mode 100644 index 0000000000..ee5bd4fc6c --- /dev/null +++ b/docs/src/auto_examples/tutorials/run_scm.rst @@ -0,0 +1,313 @@ +.. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` to download the full example code +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_auto_examples_tutorials_run_scm.py: + + +Soft Cosine Measure +=================== + +Demonstrates using Gensim's implemenation of the SCM. + +Soft Cosine Measure (SCM) is a promising new tool in machine learning that +allows us to submit a query and return the most relevant documents. This +tutorial introduces SCM and shows how you can compute the SCM similarities +between two documents using the ``inner_product`` method. + +Soft Cosine Measure basics +-------------------------- + +Soft Cosine Measure (SCM) is a method that allows us to assess the similarity +between two documents in a meaningful way, even when they have no words in +common. It uses a measure of similarity between words, which can be derived +[2] using [word2vec][] [4] vector embeddings of words. It has been shown to +outperform many of the state-of-the-art methods in the semantic text +similarity task in the context of community question answering [2]. + + +SCM is illustrated below for two very similar sentences. The sentences have +no words in common, but by modeling synonymy, SCM is able to accurately +measure the similarity between the two sentences. The method also uses the +bag-of-words vector representation of the documents (simply put, the word's +frequencies in the documents). The intution behind the method is that we +compute standard cosine similarity assuming that the document vectors are +expressed in a non-orthogonal basis, where the angle between two basis +vectors is derived from the angle between the word2vec embeddings of the +corresponding words. + + + +.. code-block:: default + + + import matplotlib.pyplot as plt + import matplotlib.image as mpimg + img = mpimg.imread('scm-hello.png') + imgplot = plt.imshow(img) + plt.axis('off') + plt.show() + + + + +.. image:: /auto_examples/tutorials/images/sphx_glr_run_scm_001.png + :class: sphx-glr-single-img + + + + +This method was perhaps first introduced in the article “Soft Measure and +Soft Cosine Measure: Measure of Features in Vector Space Model” by Grigori +Sidorov, Alexander Gelbukh, Helena Gomez-Adorno, and David Pinto. + +In this tutorial, we will learn how to use Gensim's SCM functionality, which +consists of the ``inner_product`` method for one-off computation, and the +``SoftCosineSimilarity`` class for corpus-based similarity queries. + +.. Important:: + If you use Gensim's SCM functionality, please consider citing [1], [2] and [3]. + +Computing the Soft Cosine Measure +--------------------------------- +To use SCM, you need some existing word embeddings. +You could train your own Word2Vec model, but that is beyond the scope of this tutorial +(check out :ref:`sphx_glr_auto_examples_tutorials_run_word2vec.py` if you're interested). +For this tutorial, we'll be using an existing Word2Vec model. + +Let's take some sentences to compute the distance between. + + + +.. code-block:: default + + + # Initialize logging. + import logging + logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) + + sentence_obama = 'Obama speaks to the media in Illinois' + sentence_president = 'The president greets the press in Chicago' + sentence_orange = 'Oranges are my favorite fruit' + + + + + + + +The first two sentences sentences have very similar content, and as such the +SCM should be high. By contrast, the third sentence is unrelated to the first +two and the SCM should be low. + +Before we compute the SCM, we want to remove stopwords ("the", "to", etc.), +as these do not contribute a lot to the information in the sentences. + + + +.. code-block:: default + + + # Import and download stopwords from NLTK. + from nltk.corpus import stopwords + from nltk import download + download('stopwords') # Download stopwords list. + stop_words = stopwords.words('english') + + def preprocess(sentence): + return [w for w in sentence.lower().split() if w not in stop_words] + + sentence_obama = preprocess(sentence_obama) + sentence_president = preprocess(sentence_president) + sentence_orange = preprocess(sentence_orange) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/feature_extraction/image.py:167: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + dtype=np.int): + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:30: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + method='lar', copy_X=True, eps=np.finfo(np.float).eps, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:167: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + method='lar', copy_X=True, eps=np.finfo(np.float).eps, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:284: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + eps=np.finfo(np.float).eps, copy_Gram=True, verbose=0, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:862: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + eps=np.finfo(np.float).eps, copy_X=True, fit_path=True, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1101: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + eps=np.finfo(np.float).eps, copy_X=True, fit_path=True, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1127: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + eps=np.finfo(np.float).eps, positive=False): + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1362: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + max_n_alphas=1000, n_jobs=None, eps=np.finfo(np.float).eps, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1602: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + max_n_alphas=1000, n_jobs=None, eps=np.finfo(np.float).eps, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1738: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + eps=np.finfo(np.float).eps, copy_X=True, positive=False): + [nltk_data] Downloading package stopwords to /home/witiko/nltk_data... + [nltk_data] Package stopwords is already up-to-date! + + + +Next, we will build a dictionary and a TF-IDF model, and we will convert the +sentences to the bag-of-words format. + + + +.. code-block:: default + + from gensim.corpora import Dictionary + documents = [sentence_obama, sentence_president, sentence_orange] + dictionary = Dictionary(documents) + + sentence_obama = dictionary.doc2bow(sentence_obama) + sentence_president = dictionary.doc2bow(sentence_president) + sentence_orange = dictionary.doc2bow(sentence_orange) + + from gensim.models import TfidfModel + documents = [sentence_obama, sentence_president, sentence_orange] + tfidf = TfidfModel(documents) + + sentence_obama = tfidf[sentence_obama] + sentence_president = tfidf[sentence_president] + sentence_orange = tfidf[sentence_orange] + + + + + + + +Now, as mentioned earlier, we will be using some downloaded pre-trained +embeddings. We load these into a Gensim Word2Vec model class and we build +a term similarity mextrix using the embeddings. + +.. Important:: + The embeddings we have chosen here require a lot of memory. + + + +.. code-block:: default + + import gensim.downloader as api + model = api.load('word2vec-google-news-300') + + from gensim.similarities import SparseTermSimilarityMatrix, WordEmbeddingSimilarityIndex + termsim_index = WordEmbeddingSimilarityIndex(model) + termsim_matrix = SparseTermSimilarityMatrix(termsim_index, dictionary, tfidf) + + + + + + + +So let's compute SCM using the ``inner_product`` method. + + + +.. code-block:: default + + similarity = termsim_matrix.inner_product(sentence_obama, sentence_president, normalized=(True, True)) + print('similarity = %.4f' % similarity) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + similarity = 0.2575 + + + +Let's try the same thing with two completely unrelated sentences. +Notice that the similarity is smaller. + + + +.. code-block:: default + + similarity = termsim_matrix.inner_product(sentence_obama, sentence_orange, normalized=(True, True)) + print('similarity = %.4f' % similarity) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + similarity = 0.0000 + + + +References +---------- + +1. Grigori Sidorov et al. *Soft Similarity and Soft Cosine Measure: Similarity of Features in Vector Space Model*, 2014. +2. Delphine Charlet and Geraldine Damnati, SimBow at SemEval-2017 Task 3: Soft-Cosine Semantic Similarity between Questions for Community Question Answering, 2017. +3. Vít Novotný. *Implementation Notes for the Soft Cosine Measure*, 2018. +4. Tomáš Mikolov et al. Efficient Estimation of Word Representations in Vector Space, 2013. + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 56.707 seconds) + +**Estimated memory usage:** 7701 MB + + +.. _sphx_glr_download_auto_examples_tutorials_run_scm.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download + + :download:`Download Python source code: run_scm.py ` + + + + .. container:: sphx-glr-download + + :download:`Download Jupyter notebook: run_scm.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/src/auto_examples/tutorials/run_wmd.ipynb b/docs/src/auto_examples/tutorials/run_wmd.ipynb index bb80fc3bab..99711a9278 100644 --- a/docs/src/auto_examples/tutorials/run_wmd.ipynb +++ b/docs/src/auto_examples/tutorials/run_wmd.ipynb @@ -15,7 +15,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "\nWord Mover's Distance\n=====================\n\nDemonstrates using Gensim's implemenation of the WMD.\n\n\n" + "\nWord Mover's Distance\n=====================\n\nDemonstrates using Gensim's implemenation of the WMD.\n" ] }, { @@ -130,25 +130,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Normalizing word2vec vectors\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nWhen using the ``wmdistance`` method, it is beneficial to normalize the\nword2vec vectors first, so they all have equal length. To do this, simply\ncall ``model.init_sims(replace=True)`` and Gensim will take care of that for\nyou.\n\nUsually, one measures the distance between two Word2Vec vectors using the\ncosine distance (see `cosine similarity\n`_), which measures the\nangle between vectors. WMD, on the other hand, uses the Euclidean distance.\nThe Euclidean distance between two vectors might be large because their\nlengths differ, but the cosine distance is small because the angle between\nthem is small; we can mitigate some of this by normalizing the vectors.\n\n.. Important::\n Note that normalizing the vectors can take some time, especially if you have\n a large vocabulary and/or large vectors.\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "model.init_sims(replace=True) # Normalizes the vectors in the word2vec class.\n\ndistance = model.wmdistance(sentence_obama, sentence_president) # Compute WMD as normal.\nprint('distance: %r' % distance)\n\ndistance = model.wmdistance(sentence_obama, sentence_orange)\nprint('distance = %.4f' % distance)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "References\n----------\n\n1. Ofir Pele and Michael Werman, *A linear time histogram metric for improved SIFT matching*, 2008.\n2. Ofir Pele and Michael Werman, *Fast and robust earth mover's distances*, 2009.\n3. Matt Kusner et al. *From Embeddings To Document Distances*, 2015.\n4. Thomas Mikolov et al. *Efficient Estimation of Word Representations in Vector Space*, 2013.\n\n\n" + "References\n----------\n\n1. Ofir Pele and Michael Werman, *A linear time histogram metric for improved SIFT matching*, 2008.\n2. Ofir Pele and Michael Werman, *Fast and robust earth mover's distances*, 2009.\n3. Matt Kusner et al. *From Embeddings To Document Distances*, 2015.\n4. Tom\u00e1\u0161 Mikolov et al. *Efficient Estimation of Word Representations in Vector Space*, 2013.\n\n\n" ] } ], @@ -168,7 +150,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.7.3" } }, "nbformat": 4, diff --git a/docs/src/auto_examples/tutorials/run_wmd.py b/docs/src/auto_examples/tutorials/run_wmd.py index ac471848b2..06e263063a 100644 --- a/docs/src/auto_examples/tutorials/run_wmd.py +++ b/docs/src/auto_examples/tutorials/run_wmd.py @@ -114,35 +114,6 @@ def preprocess(sentence): distance = model.wmdistance(sentence_obama, sentence_orange) print('distance = %.4f' % distance) -############################################################################### -# Normalizing word2vec vectors -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -# -# When using the ``wmdistance`` method, it is beneficial to normalize the -# word2vec vectors first, so they all have equal length. To do this, simply -# call ``model.init_sims(replace=True)`` and Gensim will take care of that for -# you. -# -# Usually, one measures the distance between two Word2Vec vectors using the -# cosine distance (see `cosine similarity -# `_), which measures the -# angle between vectors. WMD, on the other hand, uses the Euclidean distance. -# The Euclidean distance between two vectors might be large because their -# lengths differ, but the cosine distance is small because the angle between -# them is small; we can mitigate some of this by normalizing the vectors. -# -# .. Important:: -# Note that normalizing the vectors can take some time, especially if you have -# a large vocabulary and/or large vectors. -# -model.init_sims(replace=True) # Normalizes the vectors in the word2vec class. - -distance = model.wmdistance(sentence_obama, sentence_president) # Compute WMD as normal. -print('distance: %r' % distance) - -distance = model.wmdistance(sentence_obama, sentence_orange) -print('distance = %.4f' % distance) - ############################################################################### # References # ---------- @@ -150,5 +121,5 @@ def preprocess(sentence): # 1. Ofir Pele and Michael Werman, *A linear time histogram metric for improved SIFT matching*, 2008. # 2. Ofir Pele and Michael Werman, *Fast and robust earth mover's distances*, 2009. # 3. Matt Kusner et al. *From Embeddings To Document Distances*, 2015. -# 4. Thomas Mikolov et al. *Efficient Estimation of Word Representations in Vector Space*, 2013. +# 4. Tomáš Mikolov et al. *Efficient Estimation of Word Representations in Vector Space*, 2013. # diff --git a/docs/src/auto_examples/tutorials/run_wmd.py.md5 b/docs/src/auto_examples/tutorials/run_wmd.py.md5 index da8b056d38..382c5b9954 100644 --- a/docs/src/auto_examples/tutorials/run_wmd.py.md5 +++ b/docs/src/auto_examples/tutorials/run_wmd.py.md5 @@ -1 +1 @@ -3885f6df5a8f72a6d5dd1336c54560a4 \ No newline at end of file +45521a352637a0f53e62f3e19e61fc07 \ No newline at end of file diff --git a/docs/src/auto_examples/tutorials/run_wmd.rst b/docs/src/auto_examples/tutorials/run_wmd.rst index a5117f11ac..cc62e120dd 100644 --- a/docs/src/auto_examples/tutorials/run_wmd.rst +++ b/docs/src/auto_examples/tutorials/run_wmd.rst @@ -1,12 +1,10 @@ -.. only:: html - - .. note:: - :class: sphx-glr-download-link-note +.. note:: + :class: sphx-glr-download-link-note - Click :ref:`here ` to download the full example code - .. rst-class:: sphx-glr-example-title + Click :ref:`here ` to download the full example code +.. rst-class:: sphx-glr-example-title - .. _sphx_glr_auto_examples_tutorials_run_wmd.py: +.. _sphx_glr_auto_examples_tutorials_run_wmd.py: Word Mover's Distance @@ -14,7 +12,6 @@ Word Mover's Distance Demonstrates using Gensim's implemenation of the WMD. - Word Mover's Distance (WMD) is a promising new tool in machine learning that allows us to submit a query and return the most relevant documents. This tutorial introduces WMD and shows how you can compute the WMD distance @@ -57,20 +54,9 @@ distribution of document 1 to the distribution of document 2. .. image:: /auto_examples/tutorials/images/sphx_glr_run_wmd_001.png - :alt: run wmd :class: sphx-glr-single-img -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - /Volumes/work/workspace/vew/gensim3.6/lib/python3.6/site-packages/matplotlib/figure.py:445: UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure. - % get_backend()) - - This method was introduced in the article "From Word Embeddings To Document @@ -114,7 +100,6 @@ Let's take some sentences to compute the distance between. - These sentences have very similar content, and as such the WMD should be low. Before we compute the WMD, we want to remove stopwords ("the", "to", etc.), as these do not contribute a lot to the information in the sentences. @@ -146,13 +131,41 @@ as these do not contribute a lot to the information in the sentences. .. code-block:: none - [nltk_data] Downloading package stopwords to - [nltk_data] /Users/kofola3/nltk_data... + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/feature_extraction/image.py:167: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + dtype=np.int): + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:30: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + method='lar', copy_X=True, eps=np.finfo(np.float).eps, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:167: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + method='lar', copy_X=True, eps=np.finfo(np.float).eps, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:284: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + eps=np.finfo(np.float).eps, copy_Gram=True, verbose=0, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:862: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + eps=np.finfo(np.float).eps, copy_X=True, fit_path=True, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1101: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + eps=np.finfo(np.float).eps, copy_X=True, fit_path=True, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1127: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + eps=np.finfo(np.float).eps, positive=False): + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1362: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + max_n_alphas=1000, n_jobs=None, eps=np.finfo(np.float).eps, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1602: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + max_n_alphas=1000, n_jobs=None, eps=np.finfo(np.float).eps, + /home/witiko/.virtualenvs/gensim4/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1738: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. + Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations + eps=np.finfo(np.float).eps, copy_X=True, positive=False): + [nltk_data] Downloading package stopwords to /home/witiko/nltk_data... [nltk_data] Package stopwords is already up-to-date! - Now, as mentioned earlier, we will be using some downloaded pre-trained embeddings. We load these into a Gensim Word2Vec model class. @@ -170,16 +183,6 @@ embeddings. We load these into a Gensim Word2Vec model class. -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - 2020-09-30 19:33:05,053 : INFO : loading projection weights from /Users/kofola3/gensim-data/word2vec-google-news-300/word2vec-google-news-300.gz - 2020-09-30 19:34:10,211 : INFO : loaded (3000000, 300) matrix from /Users/kofola3/gensim-data/word2vec-google-news-300/word2vec-google-news-300.gz - - So let's compute WMD using the ``wmdistance`` method. @@ -201,13 +204,10 @@ So let's compute WMD using the ``wmdistance`` method. .. code-block:: none - 2020-09-30 19:34:11,705 : INFO : adding document #0 to Dictionary(0 unique tokens: []) - 2020-09-30 19:34:11,707 : INFO : built Dictionary(8 unique tokens: ['illinois', 'media', 'obama', 'speaks', 'chicago']...) from 2 documents (total 8 corpus positions) distance = 1.0175 - Let's try the same thing with two completely unrelated sentences. Notice that the distance is larger. @@ -228,81 +228,25 @@ Let's try the same thing with two completely unrelated sentences. Notice that th .. code-block:: none - 2020-09-30 19:34:23,254 : INFO : adding document #0 to Dictionary(0 unique tokens: []) - 2020-09-30 19:34:23,256 : INFO : built Dictionary(7 unique tokens: ['illinois', 'media', 'obama', 'speaks', 'favorite']...) from 2 documents (total 7 corpus positions) - distance = 1.3663 - - - - -Normalizing word2vec vectors -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -When using the ``wmdistance`` method, it is beneficial to normalize the -word2vec vectors first, so they all have equal length. To do this, simply -call ``model.init_sims(replace=True)`` and Gensim will take care of that for -you. - -Usually, one measures the distance between two Word2Vec vectors using the -cosine distance (see `cosine similarity -`_), which measures the -angle between vectors. WMD, on the other hand, uses the Euclidean distance. -The Euclidean distance between two vectors might be large because their -lengths differ, but the cosine distance is small because the angle between -them is small; we can mitigate some of this by normalizing the vectors. - -.. Important:: - Note that normalizing the vectors can take some time, especially if you have - a large vocabulary and/or large vectors. - - - -.. code-block:: default - - model.init_sims(replace=True) # Normalizes the vectors in the word2vec class. - - distance = model.wmdistance(sentence_obama, sentence_president) # Compute WMD as normal. - print('distance: %r' % distance) - - distance = model.wmdistance(sentence_obama, sentence_orange) - print('distance = %.4f' % distance) - - - - - -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - 2020-09-30 19:34:23,443 : WARNING : destructive init_sims(replace=True) deprecated & no longer required for space-efficiency - 2020-09-30 19:34:27,347 : INFO : adding document #0 to Dictionary(0 unique tokens: []) - 2020-09-30 19:34:27,348 : INFO : built Dictionary(8 unique tokens: ['illinois', 'media', 'obama', 'speaks', 'chicago']...) from 2 documents (total 8 corpus positions) - distance: 1.0174646259300113 - 2020-09-30 19:34:27,353 : INFO : adding document #0 to Dictionary(0 unique tokens: []) - 2020-09-30 19:34:27,353 : INFO : built Dictionary(7 unique tokens: ['illinois', 'media', 'obama', 'speaks', 'favorite']...) from 2 documents (total 7 corpus positions) distance = 1.3663 - References ---------- 1. Ofir Pele and Michael Werman, *A linear time histogram metric for improved SIFT matching*, 2008. 2. Ofir Pele and Michael Werman, *Fast and robust earth mover's distances*, 2009. 3. Matt Kusner et al. *From Embeddings To Document Distances*, 2015. -4. Thomas Mikolov et al. *Efficient Estimation of Word Representations in Vector Space*, 2013. +4. Tomáš Mikolov et al. *Efficient Estimation of Word Representations in Vector Space*, 2013. .. rst-class:: sphx-glr-timing - **Total running time of the script:** ( 1 minutes 25.936 seconds) + **Total running time of the script:** ( 0 minutes 55.983 seconds) -**Estimated memory usage:** 7158 MB +**Estimated memory usage:** 7537 MB .. _sphx_glr_download_auto_examples_tutorials_run_wmd.py: @@ -315,13 +259,13 @@ References - .. container:: sphx-glr-download sphx-glr-download-python + .. container:: sphx-glr-download :download:`Download Python source code: run_wmd.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter + .. container:: sphx-glr-download :download:`Download Jupyter notebook: run_wmd.ipynb ` diff --git a/docs/src/auto_examples/tutorials/sg_execution_times.rst b/docs/src/auto_examples/tutorials/sg_execution_times.rst index 7003c2957e..4757a47562 100644 --- a/docs/src/auto_examples/tutorials/sg_execution_times.rst +++ b/docs/src/auto_examples/tutorials/sg_execution_times.rst @@ -5,18 +5,12 @@ Computation times ================= -**11:26.674** total execution time for **auto_examples_tutorials** files: +**00:56.707** total execution time for **auto_examples_tutorials** files: -+-------------------------------------------------------------------------------------+-----------+-----------+ -| :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 | -+-------------------------------------------------------------------------------------+-----------+-----------+ +- **00:56.707**: :ref:`sphx_glr_auto_examples_tutorials_run_scm.py` (``run_scm.py``) +- **00:00.000**: :ref:`sphx_glr_auto_examples_tutorials_run_annoy.py` (``run_annoy.py``) +- **00:00.000**: :ref:`sphx_glr_auto_examples_tutorials_run_doc2vec_lee.py` (``run_doc2vec_lee.py``) +- **00:00.000**: :ref:`sphx_glr_auto_examples_tutorials_run_fasttext.py` (``run_fasttext.py``) +- **00:00.000**: :ref:`sphx_glr_auto_examples_tutorials_run_lda.py` (``run_lda.py``) +- **00:00.000**: :ref:`sphx_glr_auto_examples_tutorials_run_wmd.py` (``run_wmd.py``) +- **00:00.000**: :ref:`sphx_glr_auto_examples_tutorials_run_word2vec.py` (``run_word2vec.py``) diff --git a/docs/src/gallery/tutorials/run_scm.py b/docs/src/gallery/tutorials/run_scm.py index e9cdef851e..d57c9f6a1e 100644 --- a/docs/src/gallery/tutorials/run_scm.py +++ b/docs/src/gallery/tutorials/run_scm.py @@ -44,8 +44,7 @@ ############################################################################### # This method was perhaps first introduced in the article “Soft Measure and # Soft Cosine Measure: Measure of Features in Vector Space Model” by Grigori -# Sidorov, Alexander Gelbukh, Helena Gomez-Adorno, and David Pinto (`link to -# PDF `_). +# Sidorov, Alexander Gelbukh, Helena Gomez-Adorno, and David Pinto. # # In this tutorial, we will learn how to use Gensim's SCM functionality, which # consists of the ``inner_product`` method for one-off computation, and the @@ -99,14 +98,20 @@ def preprocess(sentence): # sentences to the bag-of-words format. # from gensim.corpora import Dictionary +documents = [sentence_obama, sentence_president, sentence_orange] +dictionary = Dictionary(documents) + +sentence_obama = dictionary.doc2bow(sentence_obama) +sentence_president = dictionary.doc2bow(sentence_president) +sentence_orange = dictionary.doc2bow(sentence_orange) + from gensim.models import TfidfModel documents = [sentence_obama, sentence_president, sentence_orange] -dictionary = corpora.Dictionary(documents) tfidf = TfidfModel(documents) -sentence_obama = tfidf[dictionary.doc2bow(sentence_obama)] -sentence_president = tfidf[dictionary.doc2bow(sentence_president)] -sentence_orange = tfidf[dictionary.doc2bow(sentence_orange)] +sentence_obama = tfidf[sentence_obama] +sentence_president = tfidf[sentence_president] +sentence_orange = tfidf[sentence_orange] ############################################################################### # Now, as mentioned earlier, we will be using some downloaded pre-trained @@ -126,14 +131,14 @@ def preprocess(sentence): ############################################################################### # So let's compute SCM using the ``inner_product`` method. # -similarity = termsim_matrix.inner_product(sentence_obama, sentence_president, normalized=True) +similarity = termsim_matrix.inner_product(sentence_obama, sentence_president, normalized=(True, True)) print('similarity = %.4f' % similarity) ############################################################################### # Let's try the same thing with two completely unrelated sentences. # Notice that the similarity is smaller. # -similarity = termsim_matrix.inner_product(sentence_obama, sentence_orange, normalized=True) +similarity = termsim_matrix.inner_product(sentence_obama, sentence_orange, normalized=(True, True)) print('similarity = %.4f' % similarity) ############################################################################### @@ -141,8 +146,8 @@ def preprocess(sentence): # References # ---------- # -# 1. Grigori Sidorov et al. *Soft Similarity and Soft Cosine Measure: Similarity of Features in Vector Space Model*, 2014. (`link to PDF `_) -# 2. Delphine Charlet and Geraldine Damnati, SimBow at SemEval-2017 Task 3: Soft-Cosine Semantic Similarity between Questions for Community Question Answering, 2017. (`link to PDF `_) -# 3. Vít Novotný. *Implementation Notes for the Soft Cosine Measure*, 2018. (`link to PDF `_) -# 4. Tomáš Mikolov et al. Efficient Estimation of Word Representations in Vector Space, 2013. (`link to PDF `_) +# 1. Grigori Sidorov et al. *Soft Similarity and Soft Cosine Measure: Similarity of Features in Vector Space Model*, 2014. +# 2. Delphine Charlet and Geraldine Damnati, SimBow at SemEval-2017 Task 3: Soft-Cosine Semantic Similarity between Questions for Community Question Answering, 2017. +# 3. Vít Novotný. *Implementation Notes for the Soft Cosine Measure*, 2018. +# 4. Tomáš Mikolov et al. Efficient Estimation of Word Representations in Vector Space, 2013. #