{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Cosine Similarity (Version A)\n",
    "\n",
    "- Loads embeddings (pre-computed from texts)\n",
    "- Computes **mean of embedding**-arrays\n",
    "- Computes **cosine-similarity of embedding-means** of two points in time\n",
    "- **Results**: Similarities of categories between two points in time\n",
    "  - **0.9956** **American films** (2010 .. 2020)\n",
    "  - **0.9936** **British films** (2010 .. 2020)\n",
    "  - **0.9930** **Indian films** (2010 .. 2020)\n",
    "- Results can be used in further experiments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "numpy:   1.19.2\n",
      "sklearn: 0.23.2\n"
     ]
    }
   ],
   "source": [
    "import numpy\n",
    "print(\"numpy:   \" + numpy.version.version)\n",
    "\n",
    "import sklearn\n",
    "import sklearn.metrics\n",
    "print(\"sklearn: \" + sklearn.__version__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# IDs for loading data below\n",
    "embeddingsDir = \"/home/eml4u/EML4U/data/wikipedia-embeddings/\"\n",
    "\n",
    "idAmericanA = \"20100408-american-films\"\n",
    "idAmericanB = \"20201101-american-films\"\n",
    "idBritishA  = \"20100408-british-films\"\n",
    "idBritishB  = \"20201101-british-films\"\n",
    "idIndianA   = \"20100408-indian-films\"\n",
    "idIndianB   = \"20201101-indian-films\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/home/eml4u/EML4U/data/wikipedia-embeddings/20100408-american-films.txt\n",
      "/home/eml4u/EML4U/data/wikipedia-embeddings/20201101-american-films.txt\n",
      "/home/eml4u/EML4U/data/wikipedia-embeddings/20100408-british-films.txt\n",
      "/home/eml4u/EML4U/data/wikipedia-embeddings/20201101-british-films.txt\n",
      "/home/eml4u/EML4U/data/wikipedia-embeddings/20100408-indian-films.txt\n",
      "/home/eml4u/EML4U/data/wikipedia-embeddings/20201101-indian-films.txt\n"
     ]
    }
   ],
   "source": [
    "# Load text files containing embeddings\n",
    "def getTextfile(dir, id, printfile = True):\n",
    "    file = dir + id + \".txt\"\n",
    "    if printfile:\n",
    "        print(file)\n",
    "    return file\n",
    "\n",
    "fileEmbeddingsAmericanA = getTextfile(embeddingsDir, idAmericanA)\n",
    "fileEmbeddingsAmericanB = getTextfile(embeddingsDir, idAmericanB)\n",
    "fileEmbeddingsBritishA  = getTextfile(embeddingsDir, idBritishA)\n",
    "fileEmbeddingsBritishB  = getTextfile(embeddingsDir, idBritishB)\n",
    "fileEmbeddingsIndianA   = getTextfile(embeddingsDir, idIndianA)\n",
    "fileEmbeddingsIndianB   = getTextfile(embeddingsDir, idIndianB)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(11020, 768) AmericanA\n",
      "(11020, 768) AmericanB\n",
      "(2147, 768) BritishA\n",
      "(2147, 768) BritishB\n",
      "(3596, 768) IndianA\n",
      "(3596, 768) IndianB\n",
      "(3, 5) TestA\n",
      "(3, 5) TestB\n"
     ]
    }
   ],
   "source": [
    "# Load embeddings\n",
    "def loadEmbeddings(file, note = \"\", printinfo = True):\n",
    "    embeddings = numpy.loadtxt(file)\n",
    "    if printinfo:\n",
    "        print(str(embeddings.shape) + \" \" + note)\n",
    "    return embeddings\n",
    "\n",
    "embeddingsAmericanA = loadEmbeddings(fileEmbeddingsAmericanA, \"AmericanA\")\n",
    "embeddingsAmericanB = loadEmbeddings(fileEmbeddingsAmericanB, \"AmericanB\")\n",
    "embeddingsBritishA  = loadEmbeddings(fileEmbeddingsBritishA, \"BritishA\")\n",
    "embeddingsBritishB  = loadEmbeddings(fileEmbeddingsBritishB, \"BritishB\")\n",
    "embeddingsIndianA   = loadEmbeddings(fileEmbeddingsIndianA, \"IndianA\")\n",
    "embeddingsIndianB   = loadEmbeddings(fileEmbeddingsIndianB, \"IndianB\")\n",
    "\n",
    "# Create test embeddings (A,B: 2 points of time ; 3 entries/texts each ; 5 dimensions)\n",
    "embeddingsTestA = numpy.array([[-2.2, -1.1, 0, 1.1, 2.2], [-2.2, -1.1, 0, 3.3, 4.4], [-2.2, -1.1, 0, 5.5, 6.6]])\n",
    "embeddingsTestB = numpy.array([[-2.2, -1.1, 0, 1.1, 2.2], [-5.5, -4.4, 0, 1.1, 2.2], [-8.8, -4.4, 0, 1.1, 2.2]])\n",
    "print(str(embeddingsTestA.shape) + \" TestA\")\n",
    "print(str(embeddingsTestB.shape) + \" TestB\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'> (768,) AmericanA\n",
      "<class 'numpy.ndarray'> (768,) AmericanB\n",
      "<class 'numpy.ndarray'> (768,) BritishA\n",
      "<class 'numpy.ndarray'> (768,) BritishB\n",
      "<class 'numpy.ndarray'> (768,) IndianA\n",
      "<class 'numpy.ndarray'> (768,) IndianB\n",
      "<class 'numpy.ndarray'> (5,) TestA\n",
      "<class 'numpy.ndarray'> (5,) TestB\n",
      "\n",
      "Testing computation of means\n",
      "[[-2.2 -1.1  0.   1.1  2.2]\n",
      " [-2.2 -1.1  0.   3.3  4.4]\n",
      " [-2.2 -1.1  0.   5.5  6.6]] embeddingsTestA (input)\n",
      "[-2.2 -1.1  0.   3.3  4.4] meanTestA\n",
      "[[-2.2 -1.1  0.   1.1  2.2]\n",
      " [-5.5 -4.4  0.   1.1  2.2]\n",
      " [-8.8 -4.4  0.   1.1  2.2]] embeddingsTestB (input)\n",
      "[-5.5 -3.3  0.   1.1  2.2] meanTestB\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Compute means\n",
    "# https://numpy.org/doc/1.19/reference/generated/numpy.mean.html?highlight=mean#numpy.mean\n",
    "# https://numpy.org/doc/1.19/reference/generated/numpy.reshape.html?highlight=reshape#numpy.reshape\n",
    "def getMean(embeddings, note = \"\", printinfo = True):\n",
    "    mean = numpy.mean(embeddings, axis=0)\n",
    "    if printinfo:\n",
    "        print(str(type(mean)) + \" \" + str(mean.shape) + \" \" +  note)\n",
    "    return mean\n",
    "\n",
    "# Compute means\n",
    "meanAmericanA = getMean(embeddingsAmericanA, \"AmericanA\")\n",
    "meanAmericanB = getMean(embeddingsAmericanB, \"AmericanB\")\n",
    "meanBritishA  = getMean(embeddingsBritishA, \"BritishA\")\n",
    "meanBritishB  = getMean(embeddingsBritishB, \"BritishB\")\n",
    "meanIndianA   = getMean(embeddingsIndianA, \"IndianA\")\n",
    "meanIndianB   = getMean(embeddingsIndianB, \"IndianB\")\n",
    "meanTestA = getMean(embeddingsTestA, \"TestA\")\n",
    "meanTestB = getMean(embeddingsTestB, \"TestB\")\n",
    "print()\n",
    "\n",
    "# Check means of test embeddings\n",
    "if True:\n",
    "    print(\"Testing computation of means\")\n",
    "    print(embeddingsTestA, \"embeddingsTestA (input)\")\n",
    "    print(meanTestA, \"meanTestA\")\n",
    "    print(embeddingsTestB, \"embeddingsTestB (input)\")\n",
    "    print(meanTestB, \"meanTestB\")\n",
    "    print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Tests:\n",
      "\n",
      "Test 0 input \n",
      " [-2.2 -1.1  0.   1.1  2.2] \n",
      " [-2.2 -1.1  0.   1.1  2.2]\n",
      "1.0 Test 0\n",
      "Test 1 input \n",
      " [-2.2 -1.1  0.   3.3  4.4] \n",
      " [-5.5 -4.4  0.   1.1  2.2]\n",
      "0.6729773775727068 Test 1\n",
      "Test 2 input \n",
      " [-2.2 -1.1  0.   5.5  6.6] \n",
      " [-8.8 -4.4  0.   1.1  2.2]\n",
      "0.4939924295969613 Test 2\n",
      "\n",
      "0.9525117010449139 American 0\n",
      "0.9715444013842313 American 1\n",
      "0.9724710753091028 American 10\n",
      "0.9772824870224932 American 100\n",
      "0.9393622073417478 American 500\n",
      "0.9867714675621426 American 600\n",
      "\n",
      "0.9618288510169046 British 0\n",
      "0.9325135174538641 British 1\n",
      "0.9473581782691437 British 10\n",
      "0.9680476495788866 British 100\n",
      "0.9310833202893275 British 500\n",
      "0.8651356315148098 British 600\n",
      "\n",
      "0.9760882993008546 Indian 0\n",
      "0.9805102425307188 Indian 1\n",
      "0.7447943708902642 Indian 10\n",
      "0.6380358748619926 Indian 100\n",
      "0.8617119348355946 Indian 500\n",
      "0.8981347803389674 Indian 600\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Cosine similarity single entries\n",
    "def getCosineSimilarity(a, b, indexA, indexB, note = \"\", printinfo = True):\n",
    "    cosSim = sklearn.metrics.pairwise.cosine_similarity(a[indexA].reshape(1, -1), b[indexB].reshape(1, -1), dense_output=True)[0][0]\n",
    "    if printinfo:\n",
    "        print(str(cosSim) + \" \" + note)\n",
    "    return cosSim\n",
    "\n",
    "print(\"\\nTests:\\n\")\n",
    "\n",
    "if True:\n",
    "    print(\"Test 0 input\", \"\\n\", embeddingsTestA[0], \"\\n\", embeddingsTestB[0])\n",
    "    getCosineSimilarity(embeddingsTestA, embeddingsTestB, 0, 0, \"Test 0\")\n",
    "    print(\"Test 1 input\", \"\\n\", embeddingsTestA[1], \"\\n\", embeddingsTestB[1])\n",
    "    getCosineSimilarity(embeddingsTestA, embeddingsTestB, 1, 1, \"Test 1\")\n",
    "    print(\"Test 2 input\", \"\\n\", embeddingsTestA[2], \"\\n\", embeddingsTestB[2])\n",
    "    getCosineSimilarity(embeddingsTestA, embeddingsTestB, 2, 2, \"Test 2\")\n",
    "    print()\n",
    "    \n",
    "if True:\n",
    "    getCosineSimilarity(embeddingsAmericanA, embeddingsAmericanB, 0, 0, \"American 0\")\n",
    "    getCosineSimilarity(embeddingsAmericanA, embeddingsAmericanB, 1, 1, \"American 1\")\n",
    "    getCosineSimilarity(embeddingsAmericanA, embeddingsAmericanB, 10, 10, \"American 10\")\n",
    "    getCosineSimilarity(embeddingsAmericanA, embeddingsAmericanB, 100, 100, \"American 100\")\n",
    "    getCosineSimilarity(embeddingsAmericanA, embeddingsAmericanB, 500, 500, \"American 500\")\n",
    "    getCosineSimilarity(embeddingsAmericanA, embeddingsAmericanB, 600, 600, \"American 600\")\n",
    "    print()\n",
    "    getCosineSimilarity(embeddingsBritishA, embeddingsBritishB, 0, 0, \"British 0\")\n",
    "    getCosineSimilarity(embeddingsBritishA, embeddingsBritishB, 1, 1, \"British 1\")\n",
    "    getCosineSimilarity(embeddingsBritishA, embeddingsBritishB, 10, 10, \"British 10\")\n",
    "    getCosineSimilarity(embeddingsBritishA, embeddingsBritishB, 100, 100, \"British 100\")\n",
    "    getCosineSimilarity(embeddingsBritishA, embeddingsBritishB, 500, 500, \"British 500\")\n",
    "    getCosineSimilarity(embeddingsBritishA, embeddingsBritishB, 600, 600, \"British 600\")\n",
    "    print()\n",
    "    getCosineSimilarity(embeddingsIndianA, embeddingsIndianB, 0, 0, \"Indian 0\")\n",
    "    getCosineSimilarity(embeddingsIndianA, embeddingsIndianB, 1, 1, \"Indian 1\")\n",
    "    getCosineSimilarity(embeddingsIndianA, embeddingsIndianB, 10, 10, \"Indian 10\")\n",
    "    getCosineSimilarity(embeddingsIndianA, embeddingsIndianB, 100, 100, \"Indian 100\")\n",
    "    getCosineSimilarity(embeddingsIndianA, embeddingsIndianB, 500, 500, \"Indian 500\")\n",
    "    getCosineSimilarity(embeddingsIndianA, embeddingsIndianB, 600, 600, \"Indian 600\")\n",
    "    print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'> (1, 5)\n",
      "<class 'numpy.ndarray'> (1, 5)\n",
      "0.7016464154456232 Test\n",
      "(5,)\n",
      "(768,)\n",
      "\n",
      "Results:\n",
      "\n",
      "<class 'numpy.ndarray'> (1, 768)\n",
      "<class 'numpy.ndarray'> (1, 768)\n",
      "0.9956559319674793 American\n",
      "<class 'numpy.ndarray'> (1, 768)\n",
      "<class 'numpy.ndarray'> (1, 768)\n",
      "0.9936639191853995 British\n",
      "<class 'numpy.ndarray'> (1, 768)\n",
      "<class 'numpy.ndarray'> (1, 768)\n",
      "0.9930823325071297 Indian\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.9930823325071297"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Cosine similarity\n",
    "# https://scikit-learn.org/0.23/modules/generated/sklearn.metrics.pairwise.cosine_similarity.html#sklearn.metrics.pairwise.cosine_similarity\n",
    "# https://numpy.org/doc/1.19/reference/generated/numpy.reshape.html?highlight=reshape#numpy.reshape\n",
    "def getPairwiseCosineSimilarity(a, b, note = \"\", printinfo = True):\n",
    "    if printinfo:\n",
    "        print(str(type(a)) + \" \" + str(a.shape) + \"\\n\" + str(type(b)) + \" \" + str(b.shape))\n",
    "    cosSim = sklearn.metrics.pairwise.cosine_similarity(a, b, dense_output=True)[0][0]\n",
    "    if printinfo:\n",
    "        print(str(cosSim) + \" \" + note)\n",
    "    return cosSim\n",
    "    \n",
    "# https://scistatcalc.blogspot.com/2015/11/cosine-similarity-calculator.html\n",
    "# -2.2, -1.1, 0, 3.3, 4.4\n",
    "# -5.5, -3.3, 0, 1.1, 2.2\n",
    "# Cosine Similarity between vectors 1 and 2 is 0.701646, cosine of 0.793091 radians\n",
    "\n",
    "getPairwiseCosineSimilarity(meanTestA.reshape(1, -1), meanTestB.reshape(1, -1), \"Test\")\n",
    "print(meanTestA.shape)\n",
    "print(meanAmericanA.shape)\n",
    "\n",
    "print(\"\\nResults:\\n\")\n",
    "getPairwiseCosineSimilarity(meanAmericanA.reshape(1, -1), meanAmericanB.reshape(1, -1), \"American\")\n",
    "getPairwiseCosineSimilarity(meanBritishA.reshape(1, -1), meanBritishB.reshape(1, -1), \"British\")\n",
    "getPairwiseCosineSimilarity(meanIndianA.reshape(1, -1), meanIndianB.reshape(1, -1), \"Indian\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python (EML4U)",
   "language": "python",
   "name": "eml4u"
  },
  "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.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}