{
  "nbformat": 4,
  "nbformat_minor": 0,
  "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.6"
    },
    "colab": {
      "name": "LDA_training_only.ipynb",
      "provenance": []
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HcX6HdBFiaau"
      },
      "source": [
        "### TUTORIAL: Train LDA with OCTIS\n",
        "\n",
        "Welcome! This is a tutorial that allows you to train a topic model using OCTIS (Optimizing and Comparing Topic Models Is Simple). \n",
        "\n",
        "![](https://github.com/MIND-Lab/OCTIS/blob/master/logo.png?raw=true)\n",
        "\n",
        "A topic model allows you to discover the latent topics in your documents in a completely unsupervised way. Just use your documents and get topics out! It's very easy with OCTIS :)\n",
        "\n",
        "Let's start! First, we need to install OCTIS. (We are going to use the library version of OCTIS, but you can also use it through its dashboard. See https://github.com/mind-Lab/octis for more details.)"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "m47oOaBsiRlO"
      },
      "source": [
        "!pip install octis"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "TGi97q6Pj1iL"
      },
      "source": [
        "Let's import what we need. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "xgmokdyEiRlV"
      },
      "source": [
        "from octis.models.LDA import LDA\n",
        "from octis.dataset.dataset import Dataset\n",
        "from octis.evaluation_metrics.diversity_metrics import TopicDiversity\n",
        "from octis.evaluation_metrics.coherence_metrics import Coherence"
      ],
      "execution_count": 2,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "nJWNy-ulj-H7"
      },
      "source": [
        "We need some data to run a topic model. OCTIS already provides 4 already-preprocessed datasets. Let's use one of them."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "Zv05olCwiRlW"
      },
      "source": [
        "# Define dataset\n",
        "dataset = Dataset()\n",
        "dataset.fetch_dataset(\"20NewsGroup\")"
      ],
      "execution_count": 3,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LaAAPx1kkdWB"
      },
      "source": [
        "And now we need a model. We are going to use LDA because it is the most well-known, but OCTIS integrates other 8 topic model (including neural topic models!). \n",
        "\n",
        "We are going to set the number of topics to 20 and the hyperparameter alpha to 0.1. If you have no idea how to set your hyperparameters, you should definitely use OCTIS's optimization module. See this other tutorial for the optimization of hyperparameters: (link)"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "CC5N5nLBiRlW"
      },
      "source": [
        "# Create Model\n",
        "model = LDA(num_topics=20, alpha=0.1)"
      ],
      "execution_count": 4,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ky2sTIyIlO28"
      },
      "source": [
        "Now we're ready to train it. See that the output of a topic model comes as a dictionary composed of 4 elements:\n",
        "\n",
        "\n",
        "*   *topics*: the list of word topics\n",
        "*   *topic-word-matrix*: the distribution of the words of the vocabulary for each topic (dimensions: |num topics| x |vocabulary|)\n",
        "*   *topic-document-matrix*: the distribution of the topics for each document of the training set (dimensions: |num topics| x |training documents|)\n",
        "*   *test-document-topic-matrix*: the distribution of the topics for each document of the testing set (dimensions: |num topics| x |test documents|)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "R_mboM91iRlX",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "46826a8e-613d-401d-b211-54b54512dcad"
      },
      "source": [
        "# Train the model using default partitioning choice \n",
        "output = model.train_model(dataset)\n",
        "\n",
        "print(*list(output.keys()), sep=\"\\n\") # Print the output identifiers"
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "topic-word-matrix\n",
            "topics\n",
            "topic-document-matrix\n",
            "test-topic-document-matrix\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "N3OIsmNjqY1m"
      },
      "source": [
        "For  examples, these are a sample of 5 topics. Do you think they make sense?"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "k9PIWegniRlY",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "741363e3-3048-4f6a-f659-32a2ca0a87f4"
      },
      "source": [
        "for t in output['topics'][:5]:\n",
        "  print(\" \".join(t))"
      ],
      "execution_count": 6,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "weapon state firearm gun year case owner water ticket make\n",
            "buy hear people thing good work back service cable call\n",
            "people year armenian man woman time child kill leave happen\n",
            "make people time good love death give hell thing talk\n",
            "system user information internet key message mail site datum access\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "oogVvO9jq4UZ"
      },
      "source": [
        "To check if the topics are coherent, we can use a topic coherence measure. The most used one is NPMI and it is available in OCTIS. We are going to use the dataset itself to compute it. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "e8uXU4_hrE3G"
      },
      "source": [
        "# Initialize metric\n",
        "npmi = Coherence(texts=dataset.get_corpus(), topk=10, measure='c_npmi')"
      ],
      "execution_count": 7,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8Itz2zvHmGVe"
      },
      "source": [
        "Or we can test if the resulting topics are different from each other. The `TopicDiversity` measure computes the number of unique words in the top-words of the resulting topics. \n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "LY5ifLhriRlY"
      },
      "source": [
        "# Initialize metric\n",
        "topic_diversity = TopicDiversity(topk=10)"
      ],
      "execution_count": 8,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "o-fpDuLCoC5P"
      },
      "source": [
        "And with the method `score`, we can get their actual evaluation score. Just use the output of the topic model as input of the method."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "7dCL2fAOiRlZ",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "3c2cb1a5-f431-4d07-9a7c-8fe8e9ebd19f"
      },
      "source": [
        "# Retrieve metrics score\n",
        "topic_diversity_score = topic_diversity.score(output)\n",
        "print(\"Topic diversity: \"+str(topic_diversity_score))\n",
        "\n",
        "npmi_score = npmi.score(output)\n",
        "print(\"Coherence: \"+str(npmi_score))"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Topic diversity: 0.7\n",
            "Coherence: 0.06738848042285318\n"
          ],
          "name": "stdout"
        }
      ]
    }
  ]
}