{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "_change_revision": 126,
    "_is_fork": false,
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "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.6.0"
    },
    "colab": {
      "provenance": [],
      "include_colab_link": true
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/Sahel-Eskandar/DataScience-Projects/blob/main/11_Sentiment.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "2E-KExc_WFTU",
        "outputId": "e5d360ea-6f46-420f-c593-23fb46dfeba6",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 127
        }
      },
      "source": [
        "import os, sys\n",
        "from google.colab import drive\n",
        "drive.mount('/content/drive')\n",
        "nb_path = '/content/notebooks'\n",
        "os.symlink('/content/drive/My Drive/Colab Notebooks', nb_path)\n",
        "sys.path.insert(0,nb_path)"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=947318989803-6bn6qk8qdgf4n4g3pfee6491hc0brc4i.apps.googleusercontent.com&redirect_uri=urn%3aietf%3awg%3aoauth%3a2.0%3aoob&response_type=code&scope=email%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdocs.test%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive.photos.readonly%20https%3a%2f%2fwww.googleapis.com%2fauth%2fpeopleapi.readonly\n",
            "\n",
            "Enter your authorization code:\n",
            "··········\n",
            "Mounted at /content/drive\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "cDhTFk8f08Xj",
        "outputId": "8a7669d3-5013-48fc-b7d9-7ef94c491fbd",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 53
        }
      },
      "source": [
        "!pip install nltk"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Requirement already satisfied: nltk in /usr/local/lib/python3.6/dist-packages (3.2.5)\n",
            "Requirement already satisfied: six in /usr/local/lib/python3.6/dist-packages (from nltk) (1.12.0)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Vj4YNhzK0whp",
        "outputId": "74c635a2-eafb-4d81-9524-46fd9702b8fc",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "import tensorflow as tf\n",
        "tf.test.gpu_device_name()"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "'/device:GPU:0'"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 3
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "WJZ12sE50yMt",
        "outputId": "09fbeb44-e1a5-4b9d-97b0-199ab04aa132",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 503
        }
      },
      "source": [
        "from tensorflow.python.client import device_lib\n",
        "device_lib.list_local_devices()"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[name: \"/device:CPU:0\"\n",
              " device_type: \"CPU\"\n",
              " memory_limit: 268435456\n",
              " locality {\n",
              " }\n",
              " incarnation: 8938786700750283639, name: \"/device:XLA_CPU:0\"\n",
              " device_type: \"XLA_CPU\"\n",
              " memory_limit: 17179869184\n",
              " locality {\n",
              " }\n",
              " incarnation: 5712421142814440001\n",
              " physical_device_desc: \"device: XLA_CPU device\", name: \"/device:XLA_GPU:0\"\n",
              " device_type: \"XLA_GPU\"\n",
              " memory_limit: 17179869184\n",
              " locality {\n",
              " }\n",
              " incarnation: 11361745823504704532\n",
              " physical_device_desc: \"device: XLA_GPU device\", name: \"/device:GPU:0\"\n",
              " device_type: \"GPU\"\n",
              " memory_limit: 15701463552\n",
              " locality {\n",
              "   bus_id: 1\n",
              "   links {\n",
              "   }\n",
              " }\n",
              " incarnation: 11059661873899384857\n",
              " physical_device_desc: \"device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0000:00:04.0, compute capability: 6.0\"]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 4
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "_cell_guid": "374fc92f-ce1c-740d-4ab5-786c9197e189",
        "id": "T-UE1SP5QU7o",
        "outputId": "eeebd209-720a-45a1-d17a-586686bb1617",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 303
        }
      },
      "source": [
        "import numpy as np # linear algebra\n",
        "import pandas as pd # data processing\n",
        "from sklearn.model_selection import train_test_split # function for splitting data to train and test sets\n",
        "\n",
        "import nltk\n",
        "from nltk.corpus import stopwords\n",
        "from nltk.classify import SklearnClassifier\n",
        "\n",
        "from wordcloud import WordCloud,STOPWORDS\n",
        "import matplotlib.pyplot as plt\n",
        "%matplotlib inline\n",
        "\n",
        "# Input data files are available in the \"../input/\" directory.\n",
        "# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n",
        "\n",
        "from subprocess import check_output"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "error",
          "ename": "KeyboardInterrupt",
          "evalue": "ignored",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-5-65fc63581245>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mnumpy\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mnp\u001b[0m \u001b[0;31m# linear algebra\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mpandas\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mpd\u001b[0m \u001b[0;31m# data processing\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0msklearn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodel_selection\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mtrain_test_split\u001b[0m \u001b[0;31m# function for splitting data to train and test sets\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mnltk\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/content/notebooks/sklearn/__init__.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     81\u001b[0m     \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0m__check_build\u001b[0m  \u001b[0;31m# noqa: F401\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     82\u001b[0m     \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mbase\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mclone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 83\u001b[0;31m     \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_show_versions\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mshow_versions\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     84\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     85\u001b[0m     __all__ = ['calibration', 'cluster', 'covariance', 'cross_decomposition',\n",
            "\u001b[0;32m/usr/lib/python3.6/importlib/_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load\u001b[0;34m(name, import_)\u001b[0m\n",
            "\u001b[0;32m/usr/lib/python3.6/importlib/_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load_unlocked\u001b[0;34m(name, import_)\u001b[0m\n",
            "\u001b[0;32m/usr/lib/python3.6/importlib/_bootstrap.py\u001b[0m in \u001b[0;36m_load_unlocked\u001b[0;34m(spec)\u001b[0m\n",
            "\u001b[0;32m/usr/lib/python3.6/importlib/_bootstrap_external.py\u001b[0m in \u001b[0;36mexec_module\u001b[0;34m(self, module)\u001b[0m\n",
            "\u001b[0;32m/usr/lib/python3.6/importlib/_bootstrap_external.py\u001b[0m in \u001b[0;36mget_code\u001b[0;34m(self, fullname)\u001b[0m\n",
            "\u001b[0;32m/usr/lib/python3.6/importlib/_bootstrap_external.py\u001b[0m in \u001b[0;36mget_data\u001b[0;34m(self, path)\u001b[0m\n",
            "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "7cf1dbb0-d445-de60-6737-7272df1e5978",
        "id": "9VTpF-RAQU7s"
      },
      "source": [
        "I decided to only do sentiment analysis on this dataset, therfore I dropped the unnecessary colunns, keeping only *sentiment* and *text*."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "_cell_guid": "ed8f4233-db8e-15c6-0568-c89cb6ba9d53",
        "id": "GlZIZI4ZQU7t"
      },
      "source": [
        "data = pd.read_csv('/content/drive/My Drive/App/Sentiment.csv')\n",
        "# Keeping only the neccessary columns\n",
        "data = data[['text','sentiment']]"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "23c5e618-fc4a-97da-8be6-cd98815bc4c7",
        "id": "uL9V95CoQU7w"
      },
      "source": [
        "First of all, splitting the dataset into a training and a testing set. The test set is the 10% of the original dataset. For this particular analysis I dropped the neutral tweets, as my goal was to only differentiate positive and negative tweets."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "_cell_guid": "8e60c228-ff93-e823-6d39-34c1b0fe3c3c",
        "id": "tV886D1MQU7w"
      },
      "source": [
        "# Splitting the dataset into train and test set\n",
        "train, test = train_test_split(data,test_size = 0.1)\n",
        "# Removing neutral sentiments\n",
        "train = train[train.sentiment != \"Neutral\"]"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "7598f1b2-7cad-3db3-746f-6f44e2dc7fa5",
        "id": "eDW8SyUeQU7z"
      },
      "source": [
        "As a next step I separated the Positive and Negative tweets of the training set in order to easily visualize their contained words.  After that I cleaned the text from hashtags, mentions  and links. Now they were ready for a WordCloud visualization which shows only the most emphatic words of the Positive and Negative tweets."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "_cell_guid": "516a52cc-dd69-3b5f-7487-1467a701f1e2",
        "id": "1qxS1UOmQU70"
      },
      "source": [
        "train_pos = train[ train['sentiment'] == 'Positive']\n",
        "train_pos = train_pos['text']\n",
        "train_neg = train[ train['sentiment'] == 'Negative']\n",
        "train_neg = train_neg['text']\n",
        "\n",
        "def wordcloud_draw(data, color = 'black'):\n",
        "    words = ' '.join(data)\n",
        "    cleaned_word = \" \".join([word for word in words.split()\n",
        "                            if 'http' not in word\n",
        "                                and not word.startswith('@')\n",
        "                                and not word.startswith('#')\n",
        "                                and word != 'RT'\n",
        "                            ])\n",
        "    wordcloud = WordCloud(stopwords=STOPWORDS,\n",
        "                      background_color=color,\n",
        "                      width=2500,\n",
        "                      height=2000\n",
        "                     ).generate(cleaned_word)\n",
        "    plt.figure(1,figsize=(13, 13))\n",
        "    plt.imshow(wordcloud)\n",
        "    plt.axis('off')\n",
        "    plt.show()\n",
        "    \n",
        "print(\"Positive words\")\n",
        "wordcloud_draw(train_pos,'white')\n",
        "print(\"Negative words\")\n",
        "wordcloud_draw(train_neg)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "3fe4c2c4-e40e-11c9-aae9-b0ea85797ad9",
        "id": "YmSCQ6r-QU74"
      },
      "source": [
        "Interesting to notice the following words and expressions in the positive word set:\n",
        " **truth**, **strong**, **legitimate**,  **together**, **love**, **job**\n",
        "\n",
        "In my interpretation, people tend to believe that their ideal candidate is truthful, legitimate, above good and bad.\n",
        "\n",
        "\n",
        "----------\n",
        "\n",
        "\n",
        "At the same time, negative tweets contains words like:\n",
        "**influence**, **news**, **elevator music**, **disappointing**, **softball**, **makeup**, **cherry picking**, **trying**\n",
        "\n",
        "In my understanding people missed the decisively acting and considered the scolded candidates too soft and cherry picking."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "42366853-8e0e-0c92-a60d-29109c10c697",
        "id": "HEklGbbPQU74"
      },
      "source": [
        "After the vizualization, I removed the hashtags, mentions, links and stopwords from the training set.\n",
        "\n",
        "**Stop Word:** Stop Words are words which do not contain important significance to be used in Search Queries. Usually these words are filtered out from search queries because they return vast amount of unnecessary information. ( the, for, this etc. )"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "lj20Mm0ISv16"
      },
      "source": [
        "import nltk\n",
        "nltk.download('stopwords')"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "_cell_guid": "b66995b2-8d9f-8c9e-6b0a-273dad7e75c1",
        "id": "-WzkIXwoQU75"
      },
      "source": [
        "                \n",
        "tweets = []\n",
        "stopwords_set = set(stopwords.words(\"english\"))\n",
        "\n",
        "for index, row in train.iterrows():\n",
        "    words_filtered = [e.lower() for e in row.text.split() if len(e) >= 3]\n",
        "    words_cleaned = [word for word in words_filtered\n",
        "        if 'http' not in word\n",
        "        and not word.startswith('@')\n",
        "        and not word.startswith('#')\n",
        "        and word != 'RT']\n",
        "    words_without_stopwords = [word for word in words_cleaned if not word in stopwords_set]\n",
        "    tweets.append((words_cleaned,row.sentiment))\n",
        "\n",
        "test_pos = test[ test['sentiment'] == 'Positive']\n",
        "test_pos = test_pos['text']\n",
        "test_neg = test[ test['sentiment'] == 'Negative']\n",
        "test_neg = test_neg['text']"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "fb9264bc-029f-85f3-d6e1-44b9d130d801",
        "id": "H7tGEKqzQU77"
      },
      "source": [
        "As a next step I extracted the so called features with nltk lib, first by measuring a frequent distribution and by selecting the resulting keys."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "_cell_guid": "253a2784-7de9-c1d4-293c-43b036627930",
        "id": "yYKfLlbhQU78"
      },
      "source": [
        "# Extracting word features\n",
        "def get_words_in_tweets(tweets):\n",
        "    all = []\n",
        "    for (words, sentiment) in tweets:\n",
        "        all.extend(words)\n",
        "    return all\n",
        "\n",
        "def get_word_features(wordlist):\n",
        "    wordlist = nltk.FreqDist(wordlist)\n",
        "    features = wordlist.keys()\n",
        "    return features\n",
        "w_features = get_word_features(get_words_in_tweets(tweets))\n",
        "\n",
        "def extract_features(document):\n",
        "    document_words = set(document)\n",
        "    features = {}\n",
        "    for word in w_features:\n",
        "        features['containts(%s)' % word] = (word in document_words)\n",
        "    return features"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "d4202bb1-ef8a-312c-e5a9-27bb282411eb",
        "id": "cpfWF7c9QU7_"
      },
      "source": [
        "Hereby I plotted the most frequently distributed words. The most words are centered around debate nights."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "_cell_guid": "1c8ac3c2-22ed-d267-d04c-931d9e2f9080",
        "id": "pQpuasv7QU8A"
      },
      "source": [
        "wordcloud_draw(w_features)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "dbf474bb-69f1-a2cf-5f37-265cba07a428",
        "id": "X65TZbVpQU8C"
      },
      "source": [
        "Using the nltk NaiveBayes Classifier I classified the extracted tweet word features."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "_cell_guid": "9b89e1a0-fb0b-3f6f-6577-5d20ecadcf58",
        "id": "bELuEOGGQU8D"
      },
      "source": [
        "# Training the Naive Bayes classifier\n",
        "training_set = nltk.classify.apply_features(extract_features,tweets)\n",
        "classifier = nltk.NaiveBayesClassifier.train(training_set)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "6dc107eb-d6b9-9260-23c4-83fad0d4c795",
        "id": "U-rVwMgdQU8F"
      },
      "source": [
        "Finally, with not-so-intelligent metrics, I tried to measure how the classifier algorithm scored."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "_cell_guid": "0db3c2eb-3a31-6d29-f9fa-7bf5cc899af1",
        "id": "eLrf7C8qQU8F"
      },
      "source": [
        "\n",
        "neg_cnt = 0\n",
        "pos_cnt = 0\n",
        "for obj in test_neg: \n",
        "    res =  classifier.classify(extract_features(obj.split()))\n",
        "    if(res == 'Negative'): \n",
        "        neg_cnt = neg_cnt + 1\n",
        "for obj in test_pos: \n",
        "    res =  classifier.classify(extract_features(obj.split()))\n",
        "    if(res == 'Positive'): \n",
        "        pos_cnt = pos_cnt + 1\n",
        "        \n",
        "print('[Negative]: %s/%s '  % (len(test_neg),neg_cnt))        \n",
        "print('[Positive]: %s/%s '  % (len(test_pos),pos_cnt))    "
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "1f29d2ef-48fa-0343-ff7a-58f5f2ac43ba",
        "id": "3zUW4UvvQU8I"
      },
      "source": [
        "## Epilog ##\n",
        "\n",
        "In this project I was curious how well nltk and the NaiveBayes Machine Learning algorithm performs for Sentiment Analysis. In my experience, it works rather well for negative comments. The problems arise when the tweets are ironic, sarcastic has reference or own difficult context.\n",
        "\n",
        "Consider the following tweet:\n",
        "*\"Muhaha, how sad that the Liberals couldn't destroy Trump.  Marching forward.\"*\n",
        "As you may already thought, the words **sad** and **destroy** highly influences the evaluation, although this tweet should be positive when observing its meaning and context. \n",
        "\n",
        "To improve the evalutation accuracy, we need something to take the context and references into consideration. As my project 2.0, I will try to build an LSTM network, and benchmark its results compared to this nltk Machine Learning implementation. Stay tuned. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "_cell_guid": "feda97ab-f4fe-24a5-34a9-a46926f77fe7",
        "id": "cxnnbl05QU8J"
      },
      "source": [],
      "execution_count": null,
      "outputs": []
    }
  ]
}