{ "cells": [ { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "e0085648-0300-4087-9b12-ee7d2392ce4f" } }, "source": [ "# News classification with topic models in gensim\n", "News article classification is a task which is performed on a huge scale by news agencies all over the world. We will be looking into how topic modeling can be used to accurately classify news articles into different categories such as sports, technology, politics etc.\n", "\n", "Our aim in this tutorial is to come up with some topic model which can come up with topics that can easily be interpreted by us. Such a topic model can be used to discover hidden structure in the corpus and can also be used to determine the membership of a news article into one of the topics.\n", "\n", "For this tutorial, we will be using the Lee corpus which is a shortened version of the [Lee Background Corpus](http://www.socsci.uci.edu/~mdlee/lee_pincombe_welsh_document.PDF). The shortened version consists of 300 documents selected from the Australian Broadcasting Corporation's news mail service. It consists of texts of headline stories from around the year 2000-2001.\n", "\n", "Accompanying slides can be found [here](https://speakerdeck.com/dsquareindia/pycon-delhi-lightening).\n", "\n", "### Requirements\n", "In this tutorial we look at how different topic models can be easily created using [gensim](https://radimrehurek.com/gensim/).\n", "Following are the dependencies for this tutorial:\n", " - Gensim Version >=0.13.1 would be preferred since we will be using topic coherence metrics extensively here.\n", " - matplotlib\n", " - nltk.stopwords and nltk.wordnet\n", " - pyLDAVis\n", "We will be playing around with 4 different topic models here:\n", " - LSI (Latent Semantic Indexing)\n", " - HDP (Hierarchical Dirichlet Process)\n", " - LDA (Latent Dirichlet Allocation)\n", " - LDA (tweaked with topic coherence to find optimal number of topics) and\n", " - LDA as LSI with the help of topic coherence metrics\n", "First we'll fit those topic models on our existing data then we'll compare each against the other and see how they rank in terms of human interpretability.\n", "\n", "All can be found in gensim and can be easily used in a plug-and-play fashion. We will tinker with the LDA model using the newly added topic coherence metrics in gensim based on [this](http://svn.aksw.org/papers/2015/WSDM_Topic_Evaluation/public.pdf) paper by Roeder et al and see how the resulting topic model compares with the exsisting ones." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "nbpresent": { "id": "25997dab-04e3-4abc-b22f-b36944b208c2" } }, "outputs": [], "source": [ "import os\n", "import re\n", "import operator\n", "import matplotlib.pyplot as plt\n", "import warnings\n", "import gensim\n", "import numpy as np\n", "warnings.filterwarnings('ignore') # Let's not pay heed to them right now\n", "\n", "import nltk\n", "nltk.download('stopwords') # Let's make sure the 'stopword' package is downloaded & updated\n", "nltk.download('wordnet') # Let's also download wordnet, which will be used for lemmatization\n", "\n", "from gensim.models import CoherenceModel, LdaModel, LsiModel, HdpModel\n", "from gensim.models.wrappers import LdaMallet\n", "from gensim.corpora import Dictionary\n", "from pprint import pprint\n", "from smart_open import smart_open\n", "\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "nbpresent": { "id": "8778b874-a6d1-4f2f-ba02-35dc0fa10f0c" } }, "outputs": [], "source": [ "test_data_dir = '{}'.format(os.sep).join([gensim.__path__[0], 'test', 'test_data'])\n", "lee_train_file = test_data_dir + os.sep + 'lee_background.cor'" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "bcbc3313-3a57-4923-b330-69691eaf7535" } }, "source": [ "Analysing our corpus.\n", " - The first document talks about a bushfire that had occured in New South Wales.\n", " - The second talks about conflict between India and Pakistan in Kashmir.\n", " - The third talks about road accidents in the New South Wales area.\n", " - The fourth one talks about Argentina's economic and political crisis during that time.\n", " - The last one talks about the use of drugs by midwives in a Sydney hospital.\n", "Our final topic model should be giving us keywords which we can easily interpret and make a small summary out of. Without this the topic model cannot be of much practical use." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "nbpresent": { "id": "d447e236-b1b9-4cf7-bc39-8bfb499d4730" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['Hundreds of people have been forced to vacate their homes in the Southern Highlands of New South Wales as strong winds today pushed a huge bushfire towards the town of Hill Top. A new blaze near Goulburn, south-west of Sydney, has forced the closure of the Hume Highway. At about 4:00pm AEDT, a marked deterioration in the weather as a storm cell moved east across the Blue Mountains forced authorities to make a decision to evacuate people from homes in outlying streets at Hill Top in the New South Wales southern highlands. An estimated 500 residents have left their homes for nearby Mittagong. The New South Wales Rural Fire Service says the weather conditions which caused the fire to burn in a finger formation have now eased and about 60 fire units in and around Hill Top are optimistic of defending all properties. As more than 100 blazes burn on New Year\\'s Eve in New South Wales, fire crews have been called to new fire at Gunning, south of Goulburn. While few details are available at this stage, fire authorities says it has closed the Hume Highway in both directions. Meanwhile, a new fire in Sydney\\'s west is no longer threatening properties in the Cranebrook area. Rain has fallen in some parts of the Illawarra, Sydney, the Hunter Valley and the north coast. But the Bureau of Meteorology\\'s Claire Richards says the rain has done little to ease any of the hundred fires still burning across the state. \"The falls have been quite isolated in those areas and generally the falls have been less than about five millimetres,\" she said. \"In some places really not significant at all, less than a millimetre, so there hasn\\'t been much relief as far as rain is concerned. \"In fact, they\\'ve probably hampered the efforts of the firefighters more because of the wind gusts that are associated with those thunderstorms.\" \\n']\n", "[\"Indian security forces have shot dead eight suspected militants in a night-long encounter in southern Kashmir. The shootout took place at Dora village some 50 kilometers south of the Kashmiri summer capital Srinagar. The deaths came as Pakistani police arrested more than two dozen militants from extremist groups accused of staging an attack on India's parliament. India has accused Pakistan-based Lashkar-e-Taiba and Jaish-e-Mohammad of carrying out the attack on December 13 at the behest of Pakistani military intelligence. Military tensions have soared since the raid, with both sides massing troops along their border and trading tit-for-tat diplomatic sanctions. Yesterday, Pakistan announced it had arrested Lashkar-e-Taiba chief Hafiz Mohammed Saeed. Police in Karachi say it is likely more raids will be launched against the two groups as well as other militant organisations accused of targetting India. Military tensions between India and Pakistan have escalated to a level not seen since their 1971 war. \\n\"]\n", "['The national road toll for the Christmas-New Year holiday period stands at 45, eight fewer than for the same time last year. 20 people have died on New South Wales roads, with eight fatalities in both Queensland and Victoria. Western Australia, the Northern Territory and South Australia have each recorded three deaths, while the ACT and Tasmania remain fatality free. \\n']\n", "[\"Argentina's political and economic crisis has deepened with the resignation of its interim President who took office just a week ago. Aldolfo Rodregiuez Saa told a stunned nation that he could not rescue Argentina because key fellow Peronists would not support his default on massive foreign debt repayment or his plan for a new currency. It was only a week ago that he was promising a million new jobs to end four years of recession, days after his predecessor resigned following a series of failed rescue packages. After announcing that the senate leader, Ramon Puerta, would assume the presidency until congress appoints a new caretaker president, the government said he too had quit and another senior lawmaker would act in the role. Fresh elections are not scheduled until March leaving whoever assumes the presidency with the daunting task of tackling Argentina's worst crisis in 12 years, but this time, isolated by international lending agencies. \\n\"]\n", "['Six midwives have been suspended at Wollongong Hospital, south of Sydney, for inappropriate use of nitrous oxide during work hours, on some occasions while women were in labour. The Illawarra Area Health Service says that following an investigation of unprofessional conduct, a further four midwives have been relocated to other areas within the hospital. The service\\'s chief executive officer, Tony Sherbon, says no one was put at risk, because other staff not involved in the use of nitrous oxide were able to take over caring for women in labour. \"Well we\\'re very concerned and the body of midwives to the hospital - there are over 70 midwives that work in our service - are very annoyed and angry at the inappropriate behaviour of these very senior people who should know better,\" he said. \"And that\\'s why we\\'ve take the action of suspending them and we\\'ll consider further action next week.\" \\n']\n" ] } ], "source": [ "with smart_open(lee_train_file, 'rb') as f:\n", " for n, l in enumerate(f):\n", " if n < 5:\n", " print([l])" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true, "nbpresent": { "id": "f4d505e5-5e90-4770-aaae-04ae05d697b5" } }, "outputs": [], "source": [ "def build_texts(fname):\n", " \"\"\"\n", " Function to build tokenized texts from file\n", " \n", " Parameters:\n", " ----------\n", " fname: File to be read\n", " \n", " Returns:\n", " -------\n", " yields preprocessed line\n", " \"\"\"\n", " with smart_open(fname, 'rb') as f:\n", " for line in f:\n", " yield gensim.utils.simple_preprocess(line, deacc=True, min_len=3)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "nbpresent": { "id": "4dbde9d2-3a9d-4677-8dd4-90066c0cb7c4" } }, "outputs": [], "source": [ "train_texts = list(build_texts(lee_train_file))" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "nbpresent": { "id": "e7995c4c-f483-4cb5-9f53-3b8c5fef39c3" } }, "outputs": [ { "data": { "text/plain": [ "300" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(train_texts)" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "a6d40ad7-2abd-44e5-8839-62731fb5eab7" } }, "source": [ "### Preprocessing our data. Remember: Garbage In Garbage Out\n", " \"NLP is 80% preprocessing.\"\n", " -Lev Konstantinovskiy\n", "This is the single most important step in setting up a good topic modeling system. If the preprocessing is not good, the algorithm can't do much since we would be feeding it a lot of noise. In this tutorial, we will be filtering out the noise using the following steps in this order for each line:\n", "1. Stopword removal using NLTK's english stopwords dataset.\n", "2. Bigram collocation detection (frequently co-occuring tokens) using gensim's [Phrases](https://radimrehurek.com/gensim/models/phrases.html). This is our first attempt to find some hidden structure in the corpus. You can even try trigram collocation detection.\n", "3. Lemmatization (using gensim's [`lemmatize`](https://radimrehurek.com/gensim/utils.html#gensim.utils.lemmatize)) to only keep the nouns. Lemmatization is generally better than stemming in the case of topic modeling since the words after lemmatization still remain understable. However, generally stemming might be preferred if the data is being fed into a vectorizer and isn't intended to be viewed." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "nbpresent": { "id": "3ca3d45b-a28b-41c7-b5de-4c124c50d13d" } }, "outputs": [], "source": [ "bigram = gensim.models.Phrases(train_texts) # for bigram collocation detection" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "nbpresent": { "id": "862c087b-b918-47b9-b0cf-42b71996e061" } }, "outputs": [ { "data": { "text/plain": [ "[u'new_york', u'example']" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bigram[['new', 'york', 'example']]" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true, "nbpresent": { "id": "1181e3a8-6803-4f41-9d55-397f3d700c28" } }, "outputs": [], "source": [ "from gensim.utils import lemmatize\n", "from nltk.corpus import stopwords" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false, "nbpresent": { "id": "dbeeeabe-b6dd-477c-a798-fb7b39302ba9" } }, "outputs": [], "source": [ "stops = set(stopwords.words('english')) # nltk stopwords list" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true, "nbpresent": { "id": "3d784001-6875-4be5-b8e8-e6c490f5b7b4" } }, "outputs": [], "source": [ "def process_texts(texts):\n", " \"\"\"\n", " Function to process texts. Following are the steps we take:\n", " \n", " 1. Stopword Removal.\n", " 2. Collocation detection.\n", " 3. Lemmatization (not stem since stemming can reduce the interpretability).\n", " \n", " Parameters:\n", " ----------\n", " texts: Tokenized texts.\n", " \n", " Returns:\n", " -------\n", " texts: Pre-processed tokenized texts.\n", " \"\"\"\n", " texts = [[word for word in line if word not in stops] for line in texts]\n", " texts = [bigram[line] for line in texts]\n", " \n", " from nltk.stem import WordNetLemmatizer\n", " lemmatizer = WordNetLemmatizer()\n", "\n", " texts = [[word for word in lemmatizer.lemmatize(' '.join(line), pos='v').split()] for line in texts]\n", " return texts" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false, "nbpresent": { "id": "d8cfc39f-aa3b-469f-ae34-1ef99ef51a25" } }, "outputs": [ { "data": { "text/plain": [ "[['afghani',\n", " 'asylum_seeker',\n", " 'australia',\n", " 'return',\n", " 'home',\n", " 'environment',\n", " 'government',\n", " 'application',\n", " 'kabul',\n", " 'foreign_affair',\n", " 'downer',\n", " 'process',\n", " 'threat',\n", " 'person',\n", " 'asylum',\n", " 'afghan',\n", " 'australia',\n", " 'matter',\n", " 'britain',\n", " 'country',\n", " 'europe',\n", " 'taliban',\n", " 'power',\n", " 'afghanistan',\n", " 'taliban',\n", " 'airlift',\n", " 'detainee',\n", " 'christmas',\n", " 'island',\n", " 'island',\n", " 'nauru',\n", " 'total',\n", " 'person',\n", " 'island',\n", " 'operation',\n", " 'aircraft',\n", " 'airlift',\n", " 'today',\n", " 'asylum_seeker',\n", " 'claim',\n", " 'visa',\n", " 'department',\n", " 'immigration',\n", " 'detainee',\n", " 'christmas',\n", " 'island',\n", " 'spokesman',\n", " 'decision']]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_texts = process_texts(train_texts)\n", "train_texts[5:6]" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "0e5ca1a8-9c78-412a-9ab4-a4d0be5afd34" } }, "source": [ "Finalising our dictionary and corpus" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false, "nbpresent": { "id": "161e8770-8bc2-41ae-98f4-08d1c9311e82" } }, "outputs": [], "source": [ "dictionary = Dictionary(train_texts)\n", "corpus = [dictionary.doc2bow(text) for text in train_texts]" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "fe809373-e88b-44eb-9cb9-08be3dc5949a" } }, "source": [ "### Topic modeling with LSI\n", "This is a useful topic modeling algorithm in that it can rank topics by itself. Thus it outputs topics in a ranked order. However it does require a `num_topics` parameter (set to 200 by default) to determine the number of latent dimensions after the SVD." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false, "nbpresent": { "id": "58e7dda6-0dd2-4e4f-b81a-0b530c66b20b" } }, "outputs": [], "source": [ "lsimodel = LsiModel(corpus=corpus, num_topics=10, id2word=dictionary)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false, "nbpresent": { "id": "6b5572c0-2ab0-4b13-a08f-3db21b4c4f21" }, "scrolled": false }, "outputs": [ { "data": { "text/plain": [ "[(0,\n", " u'-0.241*\"person\" + -0.202*\"australia\" + -0.201*\"government\" + -0.193*\"afghanistan\" + -0.182*\"day\" + -0.174*\"attack\" + -0.156*\"force\" + -0.155*\"area\" + -0.154*\"man\" + -0.147*\"security\"'),\n", " (1,\n", " u'0.524*\"fire\" + 0.274*\"sydney\" + 0.269*\"area\" + 0.219*\"firefighter\" + 0.180*\"wale\" + 0.163*\"wind\" + -0.139*\"israel\" + -0.138*\"attack\" + 0.136*\"line\" + 0.126*\"today\"'),\n", " (2,\n", " u'-0.333*\"australia\" + 0.320*\"israel\" + 0.243*\"palestinian\" + -0.205*\"afghanistan\" + 0.204*\"fire\" + 0.177*\"attack\" + 0.174*\"sharon\" + 0.128*\"yasser_arafat\" + -0.122*\"company\" + 0.119*\"office\"'),\n", " (3,\n", " u'0.353*\"afghanistan\" + -0.301*\"australia\" + 0.236*\"pakistan\" + 0.221*\"force\" + 0.153*\"afghan\" + -0.152*\"test\" + -0.150*\"company\" + 0.146*\"area\" + -0.132*\"union\" + 0.114*\"tora_bora\"'),\n", " (4,\n", " u'-0.331*\"union\" + -0.327*\"company\" + 0.197*\"test\" + 0.193*\"australia\" + -0.190*\"worker\" + 0.189*\"day\" + -0.169*\"qanta\" + -0.150*\"pakistan\" + 0.136*\"wicket\" + -0.130*\"commission\"')]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lsimodel.show_topics(num_topics=5) # Showing only the top 5 topics" ] }, { "cell_type": "code", "execution_count": 93, "metadata": { "collapsed": true, "nbpresent": { "id": "b1a8c7b4-dc46-4bfe-b17b-d604f212b389" } }, "outputs": [], "source": [ "lsitopics = lsimodel.show_topics(formatted=False)" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "943a5fcd-7c2e-4c16-9879-34882a7a74d4" } }, "source": [ "### Topic modeling with [HDP](http://jmlr.csail.mit.edu/proceedings/papers/v15/wang11a/wang11a.pdf)\n", "An HDP model is fully unsupervised. It can also determine the ideal number of topics it needs through posterior inference." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false, "nbpresent": { "id": "b492de13-0053-416c-b314-1bbae21ca828" } }, "outputs": [], "source": [ "hdpmodel = HdpModel(corpus=corpus, id2word=dictionary)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false, "nbpresent": { "id": "92dbb672-adca-4535-8089-de23712828d8" } }, "outputs": [ { "data": { "text/plain": [ "[u'topic 0: 0.004*collapse + 0.004*afghanistan + 0.004*troop + 0.003*force + 0.003*government + 0.002*benefit + 0.002*operation + 0.002*taliban + 0.002*time + 0.002*today + 0.002*ypre + 0.002*tourism + 0.002*person + 0.002*help + 0.002*wayne + 0.002*fire + 0.002*peru + 0.002*day + 0.002*united_state + 0.002*hih',\n", " u'topic 1: 0.003*group + 0.003*government + 0.002*target + 0.002*palestinian + 0.002*end + 0.002*terrorism + 0.002*cease + 0.002*memorandum + 0.002*radio + 0.002*call + 0.002*official + 0.002*path + 0.002*security + 0.002*wayne + 0.002*attack + 0.002*human_right + 0.001*four + 0.001*gunman + 0.001*sharon + 0.001*subsidiary',\n", " u'topic 2: 0.003*rafter + 0.003*double + 0.003*team + 0.002*reality + 0.002*manager + 0.002*cup + 0.002*australia + 0.002*abc + 0.002*nomination + 0.002*user + 0.002*freeman + 0.002*herberton + 0.002*lung + 0.002*believe + 0.002*injury + 0.002*steve_waugh + 0.002*fact + 0.002*statement + 0.002*mouth + 0.002*alejandro',\n", " u'topic 3: 0.003*india + 0.003*sector + 0.002*anthony + 0.002*interview + 0.002*suicide_bomber + 0.002*union + 0.002*marconi + 0.002*imprisonment + 0.002*document + 0.002*mood + 0.002*remember + 0.002*repair + 0.002*vicki + 0.001*training + 0.001*dressing + 0.001*government + 0.001*indian + 0.001*law + 0.001*convention + 0.001*pair',\n", " u'topic 4: 0.003*airport + 0.003*commission + 0.002*marathon + 0.002*tonne + 0.002*citizen + 0.002*dickie + 0.002*arrest + 0.002*taliban + 0.002*opposition + 0.002*agha + 0.002*pitch + 0.002*tune + 0.002*regulation + 0.002*monday + 0.002*chile + 0.002*night + 0.002*foreign_affair + 0.002*charge + 0.002*county + 0.002*signature',\n", " u'topic 5: 0.005*company + 0.002*share + 0.002*version + 0.002*entitlement + 0.002*staff + 0.002*value + 0.002*tanzim + 0.002*bay + 0.002*beaumont + 0.002*cent + 0.002*world + 0.002*hass + 0.002*broker + 0.002*line + 0.002*tie + 0.002*plane + 0.002*flare + 0.001*creditor + 0.001*pay + 0.001*administrator',\n", " u'topic 6: 0.002*hiv + 0.002*aids + 0.002*margin + 0.002*worker + 0.002*horror + 0.002*claire + 0.002*nation + 0.002*person + 0.002*battleground + 0.002*christmas + 0.002*quarters + 0.002*day + 0.002*underdog + 0.002*festival + 0.002*devaluation + 0.002*immunity + 0.001*quirindi + 0.001*auditor + 0.001*europe + 0.001*board',\n", " u'topic 7: 0.002*david + 0.002*victim + 0.002*navy + 0.002*promise + 0.002*symbol + 0.002*site + 0.002*agenda + 0.002*endeavour + 0.002*hamas + 0.002*installation + 0.002*bulli + 0.002*quarrel + 0.002*israeli + 0.002*leaf + 0.002*space + 0.002*sharon + 0.002*spa + 0.002*dispute + 0.002*council + 0.002*tit',\n", " u'topic 8: 0.005*storm + 0.004*tree + 0.002*roger + 0.002*aedt + 0.002*minister + 0.002*service + 0.002*sydney + 0.002*electricity + 0.002*power + 0.002*split + 0.002*impact + 0.002*australia + 0.002*area + 0.002*quirindi + 0.002*expansion + 0.002*hornsby + 0.002*standing + 0.002*judgment + 0.002*search + 0.002*thank',\n", " u'topic 9: 0.003*australia + 0.003*economy + 0.002*ward + 0.002*game + 0.002*brought + 0.002*johnston + 0.002*supporter + 0.002*recession + 0.002*stray + 0.002*boat_people + 0.002*ritual + 0.002*thousand + 0.001*police + 0.001*box + 0.001*britain + 0.001*year + 0.001*thing + 0.001*kill + 0.001*tour + 0.001*junction',\n", " u'topic 10: 0.003*match + 0.003*crowd + 0.002*team + 0.002*rafter + 0.002*scrapping + 0.002*decision + 0.002*guarantee + 0.002*masood + 0.002*tennis + 0.002*forestry + 0.002*world + 0.002*france + 0.002*member + 0.002*career + 0.002*australia + 0.002*single + 0.002*rubber + 0.002*road + 0.002*tower + 0.002*attack',\n", " u'topic 11: 0.002*cycle + 0.002*communication + 0.002*spend + 0.002*airline + 0.002*flight + 0.002*amendment + 0.002*swift + 0.002*morning + 0.002*ansett + 0.002*mark + 0.002*platform + 0.002*administrator + 0.002*screen + 0.002*launceston + 0.002*airplane + 0.002*alarming + 0.002*worker + 0.001*tent + 0.001*severance + 0.001*wilton',\n", " u'topic 12: 0.003*summit + 0.003*indonesia + 0.002*john + 0.002*pitwater + 0.002*president + 0.002*week + 0.002*howard + 0.002*issue + 0.002*baptist + 0.002*city + 0.002*model + 0.002*mile + 0.002*talk + 0.002*australia + 0.002*network + 0.002*head + 0.002*passage + 0.002*quinlan + 0.002*start + 0.002*match',\n", " u'topic 13: 0.002*sorrow + 0.002*australia + 0.002*israelis + 0.002*middle_east + 0.002*deck + 0.002*sydney + 0.002*variety + 0.002*zimbabwean + 0.002*general + 0.002*calculation + 0.002*instrument + 0.002*piece + 0.002*treatment + 0.002*truce + 0.002*wicket + 0.002*submission + 0.002*line + 0.002*december + 0.002*showing + 0.001*father',\n", " u'topic 14: 0.002*game + 0.002*giuliani + 0.002*care + 0.002*java + 0.002*mystery + 0.002*session + 0.002*seeker + 0.002*distance + 0.002*tennessee + 0.002*transmission + 0.002*hamid + 0.002*cabinet + 0.002*day + 0.002*regret + 0.002*australia + 0.002*lifestyle + 0.002*afghanistan + 0.002*preview + 0.002*test + 0.002*hit',\n", " u'topic 15: 0.003*president + 0.002*rabbani + 0.002*maxi + 0.002*penalty + 0.002*show + 0.002*sibling + 0.002*adjournment + 0.002*new_delhi + 0.002*permission + 0.002*jackie + 0.002*arrest + 0.002*motive + 0.002*outcome + 0.002*shift + 0.002*spy + 0.002*beech + 0.002*beset + 0.002*need + 0.002*personnel + 0.002*mitchell',\n", " u'topic 16: 0.002*today + 0.002*matter + 0.002*work + 0.002*debate + 0.002*agreement + 0.002*mastermind + 0.002*member + 0.002*downer + 0.002*intercept + 0.002*bedside + 0.002*felix + 0.002*assembly + 0.002*afghan + 0.002*saudi + 0.002*burn + 0.002*franc + 0.002*modification + 0.002*spelt + 0.002*declared + 0.002*resist',\n", " u'topic 17: 0.002*margaret + 0.002*government + 0.002*disruption + 0.002*hingis + 0.002*section + 0.002*security + 0.002*corps + 0.002*pakistan + 0.002*front + 0.002*insurance + 0.002*maintenance + 0.002*order + 0.002*plume + 0.002*amendment + 0.002*demand + 0.001*hawke + 0.001*coal + 0.001*discontent + 0.001*modification + 0.001*distress',\n", " u'topic 18: 0.002*speaker + 0.002*love + 0.002*safety + 0.002*chaman + 0.002*coastguard + 0.002*salfit + 0.002*soccer + 0.002*payment + 0.002*complexity + 0.002*personnel + 0.002*flood + 0.002*employment + 0.002*morrow + 0.002*community + 0.002*darren + 0.002*context + 0.001*tunnel + 0.001*negotiation + 0.001*friendship + 0.001*sutherland',\n", " u'topic 19: 0.003*brain + 0.003*team + 0.003*olympic + 0.002*cell + 0.002*embryo + 0.002*suburb + 0.002*speaking + 0.002*macfarlane + 0.002*sheet + 0.002*overtime + 0.002*man + 0.002*finding + 0.002*canyon + 0.002*research + 0.002*manhattan + 0.002*brutality + 0.002*spot + 0.002*backdrop + 0.001*pervez + 0.001*sector']" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "hdpmodel.show_topics()" ] }, { "cell_type": "code", "execution_count": 94, "metadata": { "collapsed": true, "nbpresent": { "id": "85e46481-0245-448c-b4e2-e0c6e175357c" } }, "outputs": [], "source": [ "hdptopics = hdpmodel.show_topics(formatted=False)" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "380ef8b7-6de1-4822-ae30-7120e12b5955" } }, "source": [ "### Topic modeling using [LDA](https://www.cs.princeton.edu/~blei/papers/HoffmanBleiBach2010b.pdf)\n", "This is one the most popular topic modeling algorithms today. It is a generative model in that it assumes each document is a mixture of topics and in turn, each topic is a mixture of words. To understand it better you can watch [this](https://www.youtube.com/watch?v=DDq3OVp9dNA) lecture by David Blei. Let's choose 10 topics to initialize this." ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": true, "nbpresent": { "id": "a02b72fb-0049-4ec3-825f-179e396f3904" } }, "outputs": [], "source": [ "ldamodel = LdaModel(corpus=corpus, num_topics=10, id2word=dictionary)" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "672c009d-3dbc-4a1f-a789-2a0fe78729b9" } }, "source": [ "pyLDAvis is a great way to visualize an LDA model. To summarize in short, the area of the circles represent the prevelance of the topic. The length of the bars on the right represent the membership of a term in a particular topic. pyLDAvis is based on [this](http://nlp.stanford.edu/events/illvi2014/papers/sievert-illvi2014.pdf) paper." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": true, "nbpresent": { "id": "f7724653-52ef-41e8-aa22-6232be216b08" } }, "outputs": [], "source": [ "import pyLDAvis.gensim" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": true, "nbpresent": { "id": "2c5b03e0-ce0f-4999-8fe1-820a9fe06873" } }, "outputs": [], "source": [ "pyLDAvis.enable_notebook()" ] }, { "cell_type": "code", "execution_count": 88, "metadata": { "collapsed": false, "nbpresent": { "id": "7da56259-bbf2-4f63-93f6-033833ae4494" }, "scrolled": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "
\n", "" ], "text/plain": [ "PreparedData(topic_coordinates= Freq cluster topics x y\n", "topic \n", "5 15.818395 1 1 0.020284 -0.003740\n", "6 12.159659 1 2 -0.022615 0.092623\n", "9 11.567771 1 3 0.095137 -0.056635\n", "7 10.030019 1 4 -0.041509 -0.014137\n", "0 9.723180 1 5 -0.093849 -0.047330\n", "8 9.499227 1 6 0.003548 0.063112\n", "2 9.403690 1 7 -0.033738 -0.046082\n", "3 8.338908 1 8 0.011367 -0.027304\n", "1 6.964024 1 9 0.038242 0.009804\n", "4 6.495127 1 10 0.023133 0.029689, topic_info= Category Freq Term Total loglift logprob\n", "term \n", "965 Default 69.000000 afghanistan 69.000000 30.0000 30.0000\n", "1918 Default 46.000000 israel 46.000000 29.0000 29.0000\n", "2464 Default 112.000000 australia 112.000000 28.0000 28.0000\n", "3280 Default 33.000000 afghan 33.000000 27.0000 27.0000\n", "2354 Default 67.000000 fire 67.000000 26.0000 26.0000\n", "1458 Default 38.000000 pakistan 38.000000 25.0000 25.0000\n", "757 Default 38.000000 palestinian 38.000000 24.0000 24.0000\n", "851 Default 37.000000 test 37.000000 23.0000 23.0000\n", "574 Default 51.000000 union 51.000000 22.0000 22.0000\n", "1922 Default 59.000000 company 59.000000 21.0000 21.0000\n", "1853 Default 18.000000 qanta 18.000000 20.0000 20.0000\n", "3333 Default 99.000000 government 99.000000 19.0000 19.0000\n", "593 Default 44.000000 child 44.000000 18.0000 18.0000\n", "157 Default 29.000000 india 29.000000 17.0000 17.0000\n", "1201 Default 13.000000 space 13.000000 16.0000 16.0000\n", "545 Default 20.000000 south_africa 20.000000 15.0000 15.0000\n", "1462 Default 12.000000 cancer 12.000000 14.0000 14.0000\n", "2195 Default 8.000000 virus 8.000000 13.0000 13.0000\n", "2060 Default 15.000000 event 15.000000 12.0000 12.0000\n", "589 Default 27.000000 worker 27.000000 11.0000 11.0000\n", "2735 Default 24.000000 metre 24.000000 10.0000 10.0000\n", "3430 Default 30.000000 commission 30.000000 9.0000 9.0000\n", "1553 Default 26.000000 director 26.000000 8.0000 8.0000\n", "985 Default 23.000000 agreement 23.000000 7.0000 7.0000\n", "2549 Default 20.000000 wicket 20.000000 6.0000 6.0000\n", "1844 Default 20.000000 rate 20.000000 5.0000 5.0000\n", "1377 Default 12.000000 dispute 12.000000 4.0000 4.0000\n", "2605 Default 28.000000 peace 28.000000 3.0000 3.0000\n", "2989 Default 67.000000 attack 67.000000 2.0000 2.0000\n", "1149 Default 6.000000 farmer 6.000000 1.0000 1.0000\n", "... ... ... ... ... ... ...\n", "1214 Topic10 1.961223 possibility 5.635690 1.6786 -6.3127\n", "2269 Topic10 2.441073 harrison 7.646867 1.5923 -6.0938\n", "1553 Topic10 5.589432 director 26.667974 1.1715 -5.2654\n", "991 Topic10 4.603794 change 21.175656 1.2081 -5.4594\n", "1303 Topic10 1.659603 premier 4.774002 1.6775 -6.4797\n", "3289 Topic10 3.672805 weapon 15.957912 1.2651 -5.6853\n", "2840 Topic10 2.639075 tension 10.503602 1.3528 -6.0159\n", "2263 Topic10 3.590576 river 18.683428 1.0848 -5.7080\n", "1140 Topic10 6.490434 group 58.260255 0.5395 -5.1160\n", "2319 Topic10 3.892480 community 24.092294 0.9113 -5.6272\n", "1922 Topic10 6.169639 company 59.473519 0.4682 -5.1666\n", "1584 Topic10 4.137423 death 27.575597 0.8373 -5.5662\n", "157 Topic10 4.256485 india 29.854661 0.7862 -5.5378\n", "2422 Topic10 8.052329 person 125.100187 -0.0090 -4.9003\n", "949 Topic10 4.045679 team 31.873346 0.6700 -5.5886\n", "1893 Topic10 3.870061 action 32.053391 0.6200 -5.6330\n", "2344 Topic10 4.239250 meeting 42.681139 0.4247 -5.5419\n", "2605 Topic10 3.525193 peace 28.066990 0.6595 -5.7264\n", "2464 Topic10 5.517708 australia 112.829012 -0.2838 -5.2783\n", "3165 Topic10 3.623557 police 34.081096 0.4928 -5.6988\n", "1608 Topic10 3.922546 world 45.568210 0.2816 -5.6195\n", "194 Topic10 3.747631 president 44.732037 0.2546 -5.6652\n", "3333 Topic10 4.302260 government 99.282266 -0.4047 -5.5271\n", "546 Topic10 3.148621 country 30.045861 0.4784 -5.8393\n", "2307 Topic10 3.397572 united_state 47.946180 0.0871 -5.7632\n", "1931 Topic10 3.315484 hour 47.117280 0.0801 -5.7877\n", "2989 Topic10 3.477635 attack 67.204296 -0.2273 -5.7399\n", "1110 Topic10 3.375391 man 70.001434 -0.2979 -5.7698\n", "2904 Topic10 3.383324 day 91.814892 -0.5668 -5.7674\n", "1692 Topic10 3.248350 area 67.475462 -0.2995 -5.8081\n", "\n", "[756 rows x 6 columns], token_table= Topic Freq Term\n", "term \n", "311 4 0.821215 abbott\n", "1059 4 0.619885 abortion\n", "2850 1 0.071487 abuse\n", "2850 2 0.285947 abuse\n", "2850 4 0.357434 abuse\n", "2850 5 0.071487 abuse\n", "2850 7 0.071487 abuse\n", "2850 8 0.071487 abuse\n", "2850 10 0.142973 abuse\n", "1893 1 0.062396 action\n", "1893 2 0.093594 action\n", "1893 3 0.093594 action\n", "1893 4 0.187188 action\n", "1893 5 0.062396 action\n", "1893 6 0.062396 action\n", "1893 7 0.062396 action\n", "1893 8 0.155990 action\n", "1893 9 0.093594 action\n", "1893 10 0.124792 action\n", "844 5 0.212931 actor\n", "844 7 0.425862 actor\n", "1719 3 0.804982 advantage\n", "1173 6 0.614371 advent\n", "3280 1 0.270599 afghan\n", "3280 2 0.090200 afghan\n", "3280 3 0.030067 afghan\n", "3280 4 0.030067 afghan\n", "3280 5 0.450999 afghan\n", "3280 7 0.030067 afghan\n", "3280 9 0.030067 afghan\n", "... ... ... ...\n", "1192 4 0.031473 year\n", "1192 5 0.157364 year\n", "1192 6 0.110155 year\n", "1192 7 0.141628 year\n", "1192 8 0.078682 year\n", "1192 9 0.078682 year\n", "1192 10 0.047209 year\n", "1166 1 0.234873 year_old\n", "1166 2 0.039145 year_old\n", "1166 3 0.039145 year_old\n", "1166 5 0.156582 year_old\n", "1166 6 0.195727 year_old\n", "1166 7 0.078291 year_old\n", "1166 8 0.156582 year_old\n", "1166 9 0.039145 year_old\n", "1166 10 0.039145 year_old\n", "2408 1 0.165536 yesterday\n", "2408 2 0.094592 yesterday\n", "2408 3 0.165536 yesterday\n", "2408 4 0.094592 yesterday\n", "2408 5 0.118240 yesterday\n", "2408 6 0.070944 yesterday\n", "2408 7 0.118240 yesterday\n", "2408 8 0.094592 yesterday\n", "2408 9 0.047296 yesterday\n", "2408 10 0.047296 yesterday\n", "238 9 0.421611 zaccarias\n", "3339 1 0.261213 zimbabwe\n", "3339 4 0.261213 zimbabwe\n", "3339 10 0.522426 zimbabwe\n", "\n", "[2006 rows x 3 columns], R=30, lambda_step=0.01, plot_opts={'xlab': 'PC1', 'ylab': 'PC2'}, topic_order=[6, 7, 10, 8, 1, 9, 3, 4, 2, 5])" ] }, "execution_count": 88, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pyLDAvis.gensim.prepare(ldamodel, corpus, dictionary)" ] }, { "cell_type": "code", "execution_count": 95, "metadata": { "collapsed": true, "nbpresent": { "id": "13f462fd-b0c3-4a29-90f3-050e2317b72c" } }, "outputs": [], "source": [ "ldatopics = ldamodel.show_topics(formatted=False)" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "68d38063-fb92-4d36-b3fb-f2d3cbff9eb5" } }, "source": [ "### Finding out the optimal number of topics\n", "__Introduction to topic coherence__:\n", "\n", "Topic coherence in essence measures the human interpretability of a topic model. Traditionally [perplexity has been used](http://qpleple.com/perplexity-to-evaluate-topic-models/) to evaluate topic models however this does not correlate with human annotations at times. Topic coherence is another way to evaluate topic models with a much higher guarantee on human interpretability. Thus this can be used to compare different topic models among many other use-cases. Here's a short blog I wrote explaining topic coherence:\n", "[What is topic coherence?](https://rare-technologies.com/what-is-topic-coherence/)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": true, "nbpresent": { "id": "45b1a641-1152-4364-ad25-62d1f8187317" } }, "outputs": [], "source": [ "def evaluate_graph(dictionary, corpus, texts, limit):\n", " \"\"\"\n", " Function to display num_topics - LDA graph using c_v coherence\n", " \n", " Parameters:\n", " ----------\n", " dictionary : Gensim dictionary\n", " corpus : Gensim corpus\n", " limit : topic limit\n", " \n", " Returns:\n", " -------\n", " lm_list : List of LDA topic models\n", " c_v : Coherence values corresponding to the LDA model with respective number of topics\n", " \"\"\"\n", " c_v = []\n", " lm_list = []\n", " for num_topics in range(1, limit):\n", " lm = LdaModel(corpus=corpus, num_topics=num_topics, id2word=dictionary)\n", " lm_list.append(lm)\n", " cm = CoherenceModel(model=lm, texts=texts, dictionary=dictionary, coherence='c_v')\n", " c_v.append(cm.get_coherence())\n", " \n", " # Show graph\n", " x = range(1, limit)\n", " plt.plot(x, c_v)\n", " plt.xlabel(\"num_topics\")\n", " plt.ylabel(\"Coherence score\")\n", " plt.legend((\"c_v\"), loc='best')\n", " plt.show()\n", " \n", " return lm_list, c_v" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false, "nbpresent": { "id": "e8936716-d06c-4cef-ae87-5c5da9a25a85" } }, "outputs": [ { "data": { "image/png": "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\naZkWLdIXm4iknxIREck58Ti8/josX578cxcv9gLVeBxOOin9sYlIeikREZGcE4vBwoUweXLyz73m\nGsP+jNYAAA5tSURBVPj2W7j3XrVxF8kHSkREJOd07OinXJKtE5k82WtCrroKtt46M7GJSHopERGR\nnFO3rg/BS6ZOZMUKb+O+/fZw8cWZi01E0kuJiIjkpHgc3ngDli6t3uPvvBMmTfI27nXrZjY2EUkf\nJSIikpPicS88ffvttT/288/hiivgvPO8M6uI5A8lIiKSk3bdFZo2XXudSAhw9tmw/vpw3XXZiU1E\n0keJiIjkpNq1Yb/91p6IPPooPPccDBoE662XndhEJH2UiIhIzorF4K23YMmSyr8+fz5ccAEccwwc\ncUR2YxOR9FAiIiI5Kx6HX3/1ZKQyl17qXx84MLtxiUj6KBERkZy1ww7QvHnlx3hffx3uuw9uvBE2\n2ST7sYlIeigREZGcVauWb8+sXifyyy9wxhmwzz7eO0RE8pcSERHJabEYTJwIixb9fq1/f5g1C/79\nb09WRCR/6Z+wiOS0eNyH340d659/8AHccAP07g1t20Ybm4jUnBIREclp227rNSCvvgorV/qWTOvW\ncPnlUUcmIulQJ+oARETWxMxXRV55xSfqjhsHY8ZAvXpRRyYi6aBERERyXjwOI0bAzJm+IrLvvlFH\nJCLpoq0ZEcl5sZhvyzRs6Md1RaRwaEVERHLelltC9+5w/PE+f0ZECocSERHJCw8+GHUEIpIJ2poR\nERGRyCgRERERkcgoEREREZHIKBERERGRyCgRERERkcgoEREREZHIKBERERGRyCgRERERkcgoERER\nEZHIKBERERGRyCgRERERkcgoEREREZHIKBERERGRyCgRERERkcgoEREREZHIKBERERGRyCgRERER\nkcgoESlCI0aMiDqErCmW96r3WVj0PgtLsbzPVOVMImJm55rZLDNbYmbjzazjGh57lJm9bWbzzWyR\nmU02s+6VPK6vmX1jZovN7CUz2zqz7yI/FNM/imJ5r3qfhUXvs7AUy/tMVU4kImZ2LHArcDXQDngP\neMHMmlfxlHlAP2BPYCdgKDDUzLpWuOdlwHnAmcDuwM9l91wnU+9DREREkpMTiQjQE7g3hDAshDAD\nOAtYDJxS2YNDCGNCCCUhhJkhhFkhhIHAFGCfCg/rAVwbQhgZQpgKnAi0BI7M6DsRERGRaos8ETGz\n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\npybxyV0AAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 22.8 s, sys: 536 ms, total: 23.4 s\n", "Wall time: 22.9 s\n" ] } ], "source": [ "%%time\n", "lmlist, c_v = evaluate_graph(dictionary=dictionary, corpus=corpus, texts=train_texts, limit=10)" ] }, { "cell_type": "code", "execution_count": 97, "metadata": { "collapsed": false, "nbpresent": { "id": "c02b6f0a-801c-4a8f-aa8f-8c9d64df7a9a" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "
\n", "" ], "text/plain": [ "PreparedData(topic_coordinates= Freq cluster topics x y\n", "topic \n", "1 43.675712 1 1 0.030435 -0.011894\n", "0 28.636818 1 2 -0.026509 -0.018098\n", "2 27.687471 1 3 -0.003926 0.029991, topic_info= Category Freq Term Total loglift logprob\n", "term \n", "851 Default 37.000000 test 37.000000 30.0000 30.0000\n", "3437 Default 25.000000 airline 25.000000 29.0000 29.0000\n", "2422 Default 129.000000 person 129.000000 28.0000 28.0000\n", "1140 Default 56.000000 group 56.000000 27.0000 27.0000\n", "593 Default 43.000000 child 43.000000 26.0000 26.0000\n", "1853 Default 18.000000 qanta 18.000000 25.0000 25.0000\n", "757 Default 35.000000 palestinian 35.000000 24.0000 24.0000\n", "3183 Default 33.000000 wale 33.000000 23.0000 23.0000\n", "3044 Default 36.000000 centre 36.000000 22.0000 22.0000\n", "2351 Default 23.000000 flight 23.000000 21.0000 21.0000\n", "1931 Default 46.000000 hour 46.000000 20.0000 20.0000\n", "2464 Default 116.000000 australia 116.000000 19.0000 19.0000\n", "661 Default 17.000000 detainee 17.000000 18.0000 18.0000\n", "2457 Default 48.000000 sydney 48.000000 17.0000 17.0000\n", "2127 Default 25.000000 militant 25.000000 16.0000 16.0000\n", "325 Default 9.000000 refugee 9.000000 15.0000 15.0000\n", "2873 Default 11.000000 gunman 11.000000 14.0000 14.0000\n", "3143 Default 41.000000 state 41.000000 13.0000 13.0000\n", "2549 Default 19.000000 wicket 19.000000 12.0000 12.0000\n", "949 Default 32.000000 team 32.000000 11.0000 11.0000\n", "102 Default 16.000000 hamas 16.000000 10.0000 10.0000\n", "2111 Default 34.000000 number 34.000000 9.0000 9.0000\n", "2195 Default 9.000000 virus 9.000000 8.0000 8.0000\n", "1547 Default 36.000000 week 36.000000 7.0000 7.0000\n", "3254 Default 7.000000 woomera 7.000000 6.0000 6.0000\n", "2989 Default 68.000000 attack 68.000000 5.0000 5.0000\n", "965 Default 68.000000 afghanistan 68.000000 4.0000 4.0000\n", "1458 Default 40.000000 pakistan 40.000000 3.0000 3.0000\n", "109 Default 16.000000 army 16.000000 2.0000 2.0000\n", "1132 Default 25.000000 polouse 25.000000 1.0000 1.0000\n", "... ... ... ... ... ... ...\n", "791 Topic3 13.599766 way 33.653033 0.3781 -5.8262\n", "457 Topic3 9.772432 radio 21.961201 0.4745 -6.1567\n", "3469 Topic3 6.851469 problem 13.763973 0.5866 -6.5118\n", "1694 Topic3 7.397502 start 15.259331 0.5601 -6.4351\n", "142 Topic3 10.293808 work 23.795675 0.4462 -6.1047\n", "1038 Topic3 21.297940 today 63.918948 0.1852 -5.3776\n", "1931 Topic3 16.519764 hour 46.137796 0.2571 -5.6317\n", "1692 Topic3 21.211328 area 65.779869 0.1524 -5.3817\n", "884 Topic3 19.973123 time 61.517598 0.1593 -5.4418\n", "949 Topic3 12.593494 team 32.284527 0.3428 -5.9030\n", "2354 Topic3 20.102475 fire 63.934883 0.1272 -5.4354\n", "2904 Topic3 24.711735 day 91.674760 -0.0268 -5.2289\n", "3333 Topic3 25.261699 government 98.056135 -0.0721 -5.2069\n", "2169 Topic3 7.895483 new_south 17.051104 0.5143 -6.3699\n", "1853 Topic3 8.198638 qanta 18.098547 0.4923 -6.3322\n", "1346 Topic3 11.167314 per_cent 29.136717 0.3252 -6.0232\n", "3087 Topic3 11.842532 staff 32.048978 0.2886 -5.9645\n", "2408 Topic3 13.971238 yesterday 41.805680 0.1882 -5.7992\n", "1494 Topic3 11.557994 minister 31.327486 0.2871 -5.9888\n", "3437 Topic3 10.107526 airline 25.268230 0.3679 -6.1229\n", "713 Topic3 16.582083 security 56.237078 0.0629 -5.6279\n", "2344 Topic3 14.015395 meeting 43.123292 0.1603 -5.7961\n", "1608 Topic3 14.601073 world 46.283007 0.1305 -5.7551\n", "2307 Topic3 14.144147 united_state 47.424821 0.0743 -5.7869\n", "1922 Topic3 15.195149 company 61.156859 -0.1083 -5.7152\n", "41 Topic3 13.987025 force 53.790616 -0.0628 -5.7981\n", "1110 Topic3 15.221356 man 70.658805 -0.2510 -5.7135\n", "3382 Topic3 12.253432 leader 42.187497 0.0479 -5.9304\n", "2422 Topic3 17.046831 person 129.542161 -0.7439 -5.6003\n", "574 Topic3 12.523667 union 52.557544 -0.1501 -5.9086\n", "\n", "[259 rows x 6 columns], token_table= Topic Freq Term\n", "term \n", "1059 2 0.631342 abortion\n", "1059 3 0.315671 abortion\n", "1893 1 0.536429 action\n", "1893 2 0.238413 action\n", "1893 3 0.208611 action\n", "3280 1 0.622198 afghan\n", "3280 2 0.217769 afghan\n", "3280 3 0.186660 afghan\n", "965 1 0.700378 afghanistan\n", "965 2 0.145912 afghanistan\n", "965 3 0.145912 afghanistan\n", "985 1 0.612333 agreement\n", "985 2 0.174952 agreement\n", "985 3 0.218690 agreement\n", "3437 1 0.118726 airline\n", "3437 2 0.514480 airline\n", "3437 3 0.395754 airline\n", "2063 1 0.312281 alcohol\n", "2063 2 0.624561 alcohol\n", "207 1 0.249899 ambulance\n", "207 2 0.749696 ambulance\n", "207 3 0.249899 ambulance\n", "1957 2 0.838777 amendment\n", "2358 3 0.628736 anthony\n", "1841 3 0.836923 antibiotic\n", "1692 1 0.410460 area\n", "1692 2 0.258438 area\n", "1692 3 0.319247 area\n", "109 1 0.307961 army\n", "109 2 0.554330 army\n", "... ... ... ...\n", "3183 3 0.481597 wale\n", "794 1 0.433821 war\n", "794 2 0.371847 war\n", "794 3 0.185923 war\n", "791 1 0.416010 way\n", "791 2 0.178290 way\n", "791 3 0.416010 way\n", "1547 1 0.388289 week\n", "1547 2 0.194145 week\n", "1547 3 0.416024 week\n", "2549 1 0.200089 wicket\n", "2549 2 0.300133 wicket\n", "2549 3 0.500222 wicket\n", "3254 1 0.139154 woomera\n", "3254 2 0.695771 woomera\n", "3254 3 0.139154 woomera\n", "142 1 0.420244 work\n", "142 2 0.168098 work\n", "142 3 0.420244 work\n", "1608 1 0.453730 world\n", "1608 2 0.237668 world\n", "1608 3 0.324093 world\n", "2073 1 0.691764 world_heritage\n", "144 1 0.860906 worm\n", "1192 1 0.440823 year\n", "1192 2 0.204668 year\n", "1192 3 0.346361 year\n", "2408 1 0.382723 yesterday\n", "2408 2 0.287042 yesterday\n", "2408 3 0.334883 yesterday\n", "\n", "[434 rows x 3 columns], R=30, lambda_step=0.01, plot_opts={'xlab': 'PC1', 'ylab': 'PC2'}, topic_order=[2, 1, 3])" ] }, "execution_count": 97, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pyLDAvis.gensim.prepare(lmlist[2], corpus, dictionary)" ] }, { "cell_type": "code", "execution_count": 96, "metadata": { "collapsed": false, "nbpresent": { "id": "699e2ddb-add6-4134-a723-1bb37029f013" } }, "outputs": [], "source": [ "lmtopics = lmlist[5].show_topics(formatted=False)" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "caa35df4-b625-4246-bc1f-42c561f31486" } }, "source": [ "### LDA as LSI" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "d2aa5aac-acc7-41c9-96d4-5410c0d8a14b" } }, "source": [ "One of the problem with LDA is that if we train it on a large number of topics, the topics get \"lost\" among the numbers. Let us see if we can dig out the best topics from the best LDA model we can produce. The function below can be used to control the quality of the LDA model we produce." ] }, { "cell_type": "code", "execution_count": 76, "metadata": { "collapsed": false, "nbpresent": { "id": "c39406c8-1e69-4249-91ac-894338d4053b" } }, "outputs": [], "source": [ "def ret_top_model():\n", " \"\"\"\n", " Since LDAmodel is a probabilistic model, it comes up different topics each time we run it. To control the\n", " quality of the topic model we produce, we can see what the interpretability of the best topic is and keep\n", " evaluating the topic model until this threshold is crossed. \n", " \n", " Returns:\n", " -------\n", " lm: Final evaluated topic model\n", " top_topics: ranked topics in decreasing order. List of tuples\n", " \"\"\"\n", " top_topics = [(0, 0)]\n", " while top_topics[0][1] < 0.97:\n", " lm = LdaModel(corpus=corpus, id2word=dictionary)\n", " coherence_values = {}\n", " for n, topic in lm.show_topics(num_topics=-1, formatted=False):\n", " topic = [word for word, _ in topic]\n", " cm = CoherenceModel(topics=[topic], texts=train_texts, dictionary=dictionary, window_size=10)\n", " coherence_values[n] = cm.get_coherence()\n", " top_topics = sorted(coherence_values.items(), key=operator.itemgetter(1), reverse=True)\n", " return lm, top_topics" ] }, { "cell_type": "code", "execution_count": 70, "metadata": { "collapsed": true, "nbpresent": { "id": "6b8eef4a-a87d-42bd-84dd-586610828698" } }, "outputs": [], "source": [ "lm, top_topics = ret_top_model()" ] }, { "cell_type": "code", "execution_count": 79, "metadata": { "collapsed": false, "nbpresent": { "id": "43870992-c2ff-47cf-8b6b-f62855673b42" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[(91, 0.99286550077029223), (42, 0.96031455145699274), (54, 0.87011963575683104), (2, 0.84575428129030361), (10, 0.83238343784453017)]\n" ] } ], "source": [ "print(top_topics[:5])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Inference\n", "We can clearly see below that the first topic is about __cinema__, second is about __email malware__, third is about the land which was given back to the __Larrakia aboriginal community of Australia__ in 2000. Then there's one about __Australian cricket__. LDA as LSI has worked wonderfully in finding out the best topics from within LDA." ] }, { "cell_type": "code", "execution_count": 78, "metadata": { "collapsed": false, "nbpresent": { "id": "281d1434-ce22-46c6-ba53-71a24a476568" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[(u'actor', 0.034688196735986693),\n", " (u'picture', 0.023163878883499418),\n", " (u'award', 0.023163878883499418),\n", " (u'comedy', 0.023163878883499418),\n", " (u'globe', 0.023163878883499418),\n", " (u'nomination', 0.023163878883499418),\n", " (u'actress', 0.023163878883499418),\n", " (u'film', 0.023163878883499418),\n", " (u'drama', 0.011639561031012149),\n", " (u'winner', 0.011639561031012149)],\n", " [(u'virus', 0.064292949289013482),\n", " (u'user', 0.048074573973209883),\n", " (u'computer', 0.040350900997751814),\n", " (u'company', 0.028173623478117912),\n", " (u'email', 0.022580226976870982),\n", " (u'worm', 0.020928236506996975),\n", " (u'attachment', 0.014534311779706417),\n", " (u'outlook', 0.01260706654637953),\n", " (u'software', 0.011909411409069969),\n", " (u'list', 0.0088116041533348403)],\n", " [(u'claim', 0.0096511365969504694),\n", " (u'agreement', 0.0082836950379963047),\n", " (u'hectare', 0.0077564979304569235),\n", " (u'larrakia', 0.0065928813973845394),\n", " (u'rosebury', 0.006086042494624749),\n", " (u'term', 0.004880655853124416),\n", " (u'region', 0.004786636929111303),\n", " (u'title', 0.0045026307214029735),\n", " (u'palmerston', 0.0043726827115423677),\n", " (u'developer', 0.0040102561358092521)],\n", " [(u'government', 0.046880132726190141),\n", " (u'razor', 0.035772624674521684),\n", " (u'gang', 0.034958865711441162),\n", " (u'minister', 0.023615858300345904),\n", " (u'interest', 0.023531518290467797),\n", " (u'taxpayer', 0.023484887279677492),\n", " (u'nelson', 0.023408331025582648),\n", " (u'spending', 0.023363131530296326),\n", " (u'program', 0.022809499664362586),\n", " (u'colleague', 0.012039863390851384)],\n", " [(u'australia', 0.019022701887671096),\n", " (u'outlook', 0.012806577991883974),\n", " (u'price', 0.012017645637892888),\n", " (u'growth', 0.011021360611214826),\n", " (u'world', 0.010586500333515535),\n", " (u'imf', 0.0074848683800558145),\n", " (u'half', 0.0073080219523406773),\n", " (u'release', 0.0073069514968024446),\n", " (u'oil', 0.0071307771829650724),\n", " (u'weakening', 0.0067585126681211785)],\n", " [(u'role', 0.036823234375415084),\n", " (u'heart', 0.018676496748175567),\n", " (u'mcreddie', 0.018520830095514161),\n", " (u'sir', 0.018430691138823303),\n", " (u'actor', 0.018423768093119148),\n", " (u'attack', 0.018421603513127272),\n", " (u'minister', 0.018330977218667187),\n", " (u'cancer', 0.018246768643902407),\n", " (u'servant', 0.018246520413261125),\n", " (u'friend', 0.018230140539399531)],\n", " [(u'australia', 0.038230610979973961),\n", " (u'test', 0.03039802044037989),\n", " (u'day', 0.026478028361575149),\n", " (u'adam', 0.023237227270639361),\n", " (u'wicket', 0.018060239149805601),\n", " (u'match', 0.015652900511647725),\n", " (u'gilchrist', 0.015206348827236857),\n", " (u'steve_waugh', 0.01496754571623464),\n", " (u'south_africa', 0.013902623982144873),\n", " (u'selector', 0.012332915474867073)],\n", " [(u'product', 0.067729999063555119),\n", " (u'food', 0.033921347284742248),\n", " (u'consumer', 0.033921347284742241),\n", " (u'company', 0.033921347284742241),\n", " (u'hooke', 0.022651796691804622),\n", " (u'law', 0.022651796691804622),\n", " (u'grocery', 0.022651796691804622),\n", " (u'technology', 0.022651796691804622),\n", " (u'sultan', 0.014079780537934588),\n", " (u'stage', 0.013736597864617922)],\n", " [(u'credit', 0.020223411999648302),\n", " (u'way', 0.017706515460000523),\n", " (u'bank', 0.017459639386736926),\n", " (u'card', 0.016308335204832106),\n", " (u'consumer', 0.014565787979687885),\n", " (u'reserve_bank', 0.014365008462949415),\n", " (u'association', 0.011448453247788988),\n", " (u'rate', 0.010363334709658676),\n", " (u'movement', 0.010204675471073506),\n", " (u'inquiry', 0.0093452022355641085)],\n", " [(u'fire', 0.045611922604745642),\n", " (u'area', 0.021994719721821848),\n", " (u'firefighter', 0.018748173264525044),\n", " (u'sydney', 0.016599279291396325),\n", " (u'wind', 0.014270025525472343),\n", " (u'property', 0.0098028785236429564),\n", " (u'hour', 0.0097079779464512347),\n", " (u'today', 0.0093953004964965076),\n", " (u'year', 0.0089216764257795157),\n", " (u'state', 0.0086116373269496185)]]\n" ] } ], "source": [ "pprint([lm.show_topic(topicid) for topicid, c_v in top_topics[:10]])" ] }, { "cell_type": "code", "execution_count": 98, "metadata": { "collapsed": false, "nbpresent": { "id": "ada914a2-bacb-4300-8ce3-f1332843d24c" } }, "outputs": [], "source": [ "lda_lsi_topics = [[word for word, prob in lm.show_topic(topicid)] for topicid, c_v in top_topics]" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "4f313370-b5f0-4754-9744-157da0447fc4" } }, "source": [ "### Evaluating all the topic models\n", "Any topic model which can come up with topic terms can be plugged into the coherence pipeline. You can even plug in an [NMF topic model](http://derekgreene.com/nmf-topic/) created with scikit-learn." ] }, { "cell_type": "code", "execution_count": 99, "metadata": { "collapsed": false, "nbpresent": { "id": "4329af31-21b4-4570-903a-6df3715244c7" } }, "outputs": [], "source": [ "lsitopics = [[word for word, prob in topic] for topicid, topic in lsitopics]\n", "\n", "hdptopics = [[word for word, prob in topic] for topicid, topic in hdptopics]\n", "\n", "ldatopics = [[word for word, prob in topic] for topicid, topic in ldatopics]\n", "\n", "lmtopics = [[word for word, prob in topic] for topicid, topic in lmtopics]" ] }, { "cell_type": "code", "execution_count": 100, "metadata": { "collapsed": true, "nbpresent": { "id": "0924faf0-a957-4d12-b35c-b50ebb30f370" } }, "outputs": [], "source": [ "lsi_coherence = CoherenceModel(topics=lsitopics[:10], texts=train_texts, dictionary=dictionary, window_size=10).get_coherence()\n", "\n", "hdp_coherence = CoherenceModel(topics=hdptopics[:10], texts=train_texts, dictionary=dictionary, window_size=10).get_coherence()\n", "\n", "lda_coherence = CoherenceModel(topics=ldatopics, texts=train_texts, dictionary=dictionary, window_size=10).get_coherence()\n", "\n", "lm_coherence = CoherenceModel(topics=lmtopics, texts=train_texts, dictionary=dictionary, window_size=10).get_coherence()\n", "\n", "lda_lsi_coherence = CoherenceModel(topics=lda_lsi_topics[:10], texts=train_texts, dictionary=dictionary, window_size=10).get_coherence()" ] }, { "cell_type": "code", "execution_count": 101, "metadata": { "collapsed": true, "nbpresent": { "id": "59cc671f-041a-4d6f-a609-f1b9855aa05c" } }, "outputs": [], "source": [ "def evaluate_bar_graph(coherences, indices):\n", " \"\"\"\n", " Function to plot bar graph.\n", " \n", " coherences: list of coherence values\n", " indices: Indices to be used to mark bars. Length of this and coherences should be equal.\n", " \"\"\"\n", " assert len(coherences) == len(indices)\n", " n = len(coherences)\n", " x = np.arange(n)\n", " plt.bar(x, coherences, width=0.2, tick_label=indices, align='center')\n", " plt.xlabel('Models')\n", " plt.ylabel('Coherence Value')" ] }, { "cell_type": "code", "execution_count": 102, "metadata": { "collapsed": false, "nbpresent": { "id": "b86ba0c1-c7c4-43a5-a9f5-8dfe7967be6c" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "evaluate_bar_graph([lsi_coherence, hdp_coherence, lda_coherence, lm_coherence, lda_lsi_coherence],\n", " ['LSI', 'HDP', 'LDA', 'LDA_Mod', 'LDA_LSI'])" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "df6cc31a-0b01-4700-b210-836dd510007a" } }, "source": [ "### Customizing the topic coherence measure\n", "Till now we only used the `c_v` coherence measure. There are others such as `u_mass`, `c_uci`, `c_npmi`. All of these calculate coherence in a different way. `c_v` is found to be most in line with human ratings but can be much slower than `u_mass` since it uses a sliding window over the texts." ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "664fa23d-ba6e-4a30-9287-e4fef1cc093e" } }, "source": [ "### Making your own coherence measure\n", "Let's modify `c_uci` to use `s_one_pre` instead of `s_one_one` segmentation" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": true, "nbpresent": { "id": "b3652f43-da03-4027-9170-83e1679dfa2b" } }, "outputs": [], "source": [ "from gensim.topic_coherence import (segmentation, probability_estimation,\n", " direct_confirmation_measure, indirect_confirmation_measure,\n", " aggregation)\n", "from gensim.matutils import argsort\n", "from collections import namedtuple" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "collapsed": false, "nbpresent": { "id": "8ce2b802-f0c1-4ffc-9ce5-c2792856b5b4" } }, "outputs": [], "source": [ "make_pipeline = namedtuple('Coherence_Measure', 'seg, prob, conf, aggr')" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "collapsed": true, "nbpresent": { "id": "9994e7f0-f366-40da-9c14-76e8142ee46e" } }, "outputs": [], "source": [ "measure = make_pipeline(segmentation.s_one_one,\n", " probability_estimation.p_boolean_sliding_window,\n", " direct_confirmation_measure.log_ratio_measure,\n", " aggregation.arithmetic_mean)" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "416f5820-1538-4483-a77f-5211c8179891" } }, "source": [ "To get topics out of the topic model:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "collapsed": true, "nbpresent": { "id": "aa9d35ae-c458-49d2-bdbe-d93d5cb3ba9c" } }, "outputs": [], "source": [ "topics = []\n", "for topic in lm.state.get_lambda():\n", " bestn = argsort(topic, topn=10, reverse=True)\n", "topics.append(bestn)" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "13f246a0-918e-44c1-ae19-7af118d83585" } }, "source": [ "__Step 1__: Segmentation" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": true, "nbpresent": { "id": "821ab68b-c377-40b1-bdf3-b92d66414383" } }, "outputs": [], "source": [ "# Perform segmentation\n", "segmented_topics = measure.seg(topics)" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "e4b50714-b644-4213-b3cb-bdac9fe22476" } }, "source": [ "__Step 2__: Probability estimation" ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "collapsed": false, "nbpresent": { "id": "d8a8bcc6-8b37-4d4f-ad06-903804776078" } }, "outputs": [], "source": [ "# Since this is a window-based coherence measure we will perform window based prob estimation\n", "per_topic_postings, num_windows = measure.prob(texts=train_texts, segmented_topics=segmented_topics,\n", " dictionary=dictionary, window_size=2)" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "6f302dcb-787b-42b0-98f0-1df0a163a818" } }, "source": [ "__Step 3__: Confirmation Measure" ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "collapsed": true, "nbpresent": { "id": "ffb5aaa9-5fa1-4b28-ba2f-e23525caa392" } }, "outputs": [], "source": [ "confirmed_measures = measure.conf(segmented_topics, per_topic_postings, num_windows, normalize=False)" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "3544f061-6870-4630-bd54-79f75decf8b6" } }, "source": [ "__Step 4__: Aggregation" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": false, "nbpresent": { "id": "31c64f41-a499-4f80-8ccd-1364940f7383" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-11.2873225334\n" ] } ], "source": [ "print(measure.aggr(confirmed_measures))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# How this topic model can be used further\n", "The best topic model here can be used as a standalone for news article classification. However a topic model can also be used as a dimensionality reduction algorithm to feed into a classifier. A good topic model should be able to extract the signal from the noise efficiently, hence improving the performance of the classifier." ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.12" }, "nbpresent": { "slides": { "04abaf09-1754-419e-9cf8-3c4f0accfc5f": { "id": "04abaf09-1754-419e-9cf8-3c4f0accfc5f", "prev": "67c9421a-0e61-4346-873f-bf3769d00c97", "regions": { "48b5cd39-b89b-4e2f-be2a-47a0fccafd3b": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "862c087b-b918-47b9-b0cf-42b71996e061", "part": "whole" }, "id": "48b5cd39-b89b-4e2f-be2a-47a0fccafd3b" } } }, "0527f44a-39b6-4cf8-9802-d16b8cd34754": { "id": "0527f44a-39b6-4cf8-9802-d16b8cd34754", "prev": "103c32ed-02bc-4365-a431-5acd77fe6585", "regions": { "ed3805ae-4076-41ad-a578-69a0b2356f95": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "b3652f43-da03-4027-9170-83e1679dfa2b", "part": "whole" }, "id": "ed3805ae-4076-41ad-a578-69a0b2356f95" } } }, "05fa6235-ac93-41b7-9975-3fee534b0c94": { "id": "05fa6235-ac93-41b7-9975-3fee534b0c94", "prev": "e44d6d8f-7236-458f-a308-36142bc72ff4", "regions": { "3e316a57-509e-404e-a89b-bde56696b966": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "c39406c8-1e69-4249-91ac-894338d4053b", "part": "whole" }, "id": "3e316a57-509e-404e-a89b-bde56696b966" } } }, "0e2565e0-a21d-4dbb-a4b3-8698e797c45d": { "id": "0e2565e0-a21d-4dbb-a4b3-8698e797c45d", "prev": "11baa747-dc0e-430a-8f38-65331394d2fd", "regions": { "2e423579-bece-40ca-ba30-122f49d93655": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "e4b50714-b644-4213-b3cb-bdac9fe22476", "part": "whole" }, "id": "2e423579-bece-40ca-ba30-122f49d93655" } } }, "103c32ed-02bc-4365-a431-5acd77fe6585": { "id": "103c32ed-02bc-4365-a431-5acd77fe6585", "prev": "23b717ee-a57c-42c5-9959-c8a314a329c6", "regions": { "aa966e74-db8d-473a-9ee6-8cad8e7407f3": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "664fa23d-ba6e-4a30-9287-e4fef1cc093e", "part": "whole" }, "id": "aa966e74-db8d-473a-9ee6-8cad8e7407f3" } } }, "10763d44-d64e-46c7-a164-8b92d219e71d": { "id": "10763d44-d64e-46c7-a164-8b92d219e71d", "prev": "d84b78ed-e79f-4657-b62b-eeff30c4fe8d", "regions": { "a27ddbe9-cfa8-49fe-b284-3567ebbfb1c7": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "43870992-c2ff-47cf-8b6b-f62855673b42", "part": "whole" }, "id": "a27ddbe9-cfa8-49fe-b284-3567ebbfb1c7" } } }, "11baa747-dc0e-430a-8f38-65331394d2fd": { "id": "11baa747-dc0e-430a-8f38-65331394d2fd", "prev": "a2c51720-8844-4953-94a8-55d723ec2499", "regions": { "6d7e8f18-6703-4c31-8353-4a714df2d33f": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "821ab68b-c377-40b1-bdf3-b92d66414383", "part": "whole" }, "id": "6d7e8f18-6703-4c31-8353-4a714df2d33f" } } }, "12513a0d-3e80-464d-9285-3bdd87e0b9c0": { "id": "12513a0d-3e80-464d-9285-3bdd87e0b9c0", "prev": "e71a7d3a-c9bb-4db0-9597-95b9b3233d3b", "regions": { "5fb06a62-1d61-417a-9c02-3fa7fa00fee1": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "416f5820-1538-4483-a77f-5211c8179891", "part": "whole" }, "id": "5fb06a62-1d61-417a-9c02-3fa7fa00fee1" } } }, "13c7e576-8024-4b19-8874-d65c24a9ee0f": { "id": "13c7e576-8024-4b19-8874-d65c24a9ee0f", "prev": "b6050bf2-3f03-47ef-9510-80c01755a79e", "regions": { "45c58bb7-75a4-4434-b5fa-59f7ad56e7d6": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "2c5b03e0-ce0f-4999-8fe1-820a9fe06873", "part": "whole" }, "id": "45c58bb7-75a4-4434-b5fa-59f7ad56e7d6" } } }, "23b717ee-a57c-42c5-9959-c8a314a329c6": { "id": "23b717ee-a57c-42c5-9959-c8a314a329c6", "prev": "4033c3a0-0021-4cbc-a589-50c63550217b", "regions": { "ca7e045e-962d-47e3-a594-eafdf7424671": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "df6cc31a-0b01-4700-b210-836dd510007a", "part": "whole" }, "id": "ca7e045e-962d-47e3-a594-eafdf7424671" } } }, "257bf09e-bd55-4957-97ea-4d3c8b85016a": { "id": "257bf09e-bd55-4957-97ea-4d3c8b85016a", "prev": null, "regions": { "cf220469-7ef0-4fb9-80b4-cbdb55aa86db": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "e0085648-0300-4087-9b12-ee7d2392ce4f", "part": "whole" }, "id": "cf220469-7ef0-4fb9-80b4-cbdb55aa86db" } } }, "280f0473-61ec-4b88-b9d4-172e734fd0a5": { "id": "280f0473-61ec-4b88-b9d4-172e734fd0a5", "prev": "d7495fd8-cfb5-42ee-a0eb-86679c419bae", "regions": { "c58169da-ccea-4657-95a3-fc1e5fba3ac3": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "f4d505e5-5e90-4770-aaae-04ae05d697b5", "part": "whole" }, "id": "c58169da-ccea-4657-95a3-fc1e5fba3ac3" } } }, "2e4a9702-f7a2-48a5-bd13-2087e9216b38": { "id": "2e4a9702-f7a2-48a5-bd13-2087e9216b38", "prev": "04abaf09-1754-419e-9cf8-3c4f0accfc5f", "regions": { "b31a05d5-a8fe-40d2-a368-cc39f50ee938": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "1181e3a8-6803-4f41-9d55-397f3d700c28", "part": "whole" }, "id": "b31a05d5-a8fe-40d2-a368-cc39f50ee938" } } }, "4033c3a0-0021-4cbc-a589-50c63550217b": { "id": "4033c3a0-0021-4cbc-a589-50c63550217b", "prev": "c68aae9d-645c-4cbf-9dc1-92ed9aa0f5d3", "regions": { "55173d13-adca-4e7f-a760-92bd299e6c40": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "b86ba0c1-c7c4-43a5-a9f5-8dfe7967be6c", "part": "whole" }, "id": "55173d13-adca-4e7f-a760-92bd299e6c40" } } }, "479d81b5-3b8b-4ddf-bbfe-6ae6ff33c2fa": { "id": "479d81b5-3b8b-4ddf-bbfe-6ae6ff33c2fa", "prev": "280f0473-61ec-4b88-b9d4-172e734fd0a5", "regions": { "6c334c87-c8a0-4328-b310-6be0e9a89532": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "4dbde9d2-3a9d-4677-8dd4-90066c0cb7c4", "part": "whole" }, "id": "6c334c87-c8a0-4328-b310-6be0e9a89532" } } }, "488af944-ad92-49c5-9d1d-ccdb1e929dce": { "id": "488af944-ad92-49c5-9d1d-ccdb1e929dce", "prev": "13c7e576-8024-4b19-8874-d65c24a9ee0f", "regions": { "fb1eddce-8820-408b-8b73-3a1654b93816": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "7da56259-bbf2-4f63-93f6-033833ae4494", "part": "whole" }, "id": "fb1eddce-8820-408b-8b73-3a1654b93816" } } }, "4af127dc-0330-4f8e-b907-3e409ba31a06": { "id": "4af127dc-0330-4f8e-b907-3e409ba31a06", "prev": "fbd9f3b3-f9b0-4886-b987-3f9d0ca983bc", "regions": { "1f9e4115-c1c7-4e4c-a262-648adc28ad2a": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "3d784001-6875-4be5-b8e8-e6c490f5b7b4", "part": "whole" }, "id": "1f9e4115-c1c7-4e4c-a262-648adc28ad2a" } } }, "67c9421a-0e61-4346-873f-bf3769d00c97": { "id": "67c9421a-0e61-4346-873f-bf3769d00c97", "prev": "efc03832-2e6d-4250-8ac5-f4c13cfdb733", "regions": { "d9b839cd-46ac-451d-bb1b-3edd613c0ba3": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "3ca3d45b-a28b-41c7-b5de-4c124c50d13d", "part": "whole" }, "id": "d9b839cd-46ac-451d-bb1b-3edd613c0ba3" } } }, "78837f0a-d7b6-48ae-b64e-3a2af8286ccc": { "id": "78837f0a-d7b6-48ae-b64e-3a2af8286ccc", "prev": "bb7417b1-270b-4977-bbf3-606a574c38ec", "regions": { "37ced915-20bf-49cd-9691-82e9fdcfe211": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "b1a8c7b4-dc46-4bfe-b17b-d604f212b389", "part": "whole" }, "id": "37ced915-20bf-49cd-9691-82e9fdcfe211" } } }, "7f7b5da4-7345-442b-8cd5-662cfba97db9": { "id": "7f7b5da4-7345-442b-8cd5-662cfba97db9", "prev": "f6d5269c-54db-4887-b274-d00572aead72", "regions": { "5fcadbcf-4f67-4bd7-bc4c-0e9db215581c": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "a02b72fb-0049-4ec3-825f-179e396f3904", "part": "whole" }, "id": "5fcadbcf-4f67-4bd7-bc4c-0e9db215581c" } } }, "823091e1-74b1-44e3-af50-388881c30968": { "id": "823091e1-74b1-44e3-af50-388881c30968", "prev": "e24d4b0b-34e2-46de-a99d-a4be39ca2951", "regions": { "cd97517e-4f86-48bd-9496-92ebad8c97cf": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "ffb5aaa9-5fa1-4b28-ba2f-e23525caa392", "part": "whole" }, "id": "cd97517e-4f86-48bd-9496-92ebad8c97cf" } } }, "845fbe01-dd28-4ad8-9eb5-d13c49f6772c": { "id": "845fbe01-dd28-4ad8-9eb5-d13c49f6772c", "prev": "87040bd6-a3e9-4785-97e0-08d7e7c5b8ef", "regions": { "1b5a1350-c3d1-43d8-bbc3-90ac260b5a8b": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "bcbc3313-3a57-4923-b330-69691eaf7535", "part": "whole" }, "id": "1b5a1350-c3d1-43d8-bbc3-90ac260b5a8b" } } }, "8541226b-6ff1-4700-a399-71e3cf68d91b": { "id": "8541226b-6ff1-4700-a399-71e3cf68d91b", "prev": "10763d44-d64e-46c7-a164-8b92d219e71d", "regions": { "7c4c47d8-a698-4e96-a411-556d9ad6b15b": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "281d1434-ce22-46c6-ba53-71a24a476568", "part": "whole" }, "id": "7c4c47d8-a698-4e96-a411-556d9ad6b15b" } } }, "87040bd6-a3e9-4785-97e0-08d7e7c5b8ef": { "id": "87040bd6-a3e9-4785-97e0-08d7e7c5b8ef", "prev": "ad16016c-8a9e-49da-a3d2-5ab56ca11579", "regions": { "cc35a589-c8c7-459f-893d-102c0d77bee3": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "8778b874-a6d1-4f2f-ba02-35dc0fa10f0c", "part": "whole" }, "id": "cc35a589-c8c7-459f-893d-102c0d77bee3" } } }, "8aa83fc2-d106-4c85-8b7f-1116db7ee9d4": { "id": "8aa83fc2-d106-4c85-8b7f-1116db7ee9d4", "prev": "f870a325-581b-4d8e-a4c0-095972e4cc21", "regions": { "9f7afc1f-6e9d-47bf-98e0-7e0350e1f516": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "45b1a641-1152-4364-ad25-62d1f8187317", "part": "whole" }, "id": "9f7afc1f-6e9d-47bf-98e0-7e0350e1f516" } } }, "944a5639-4b22-4f7f-b836-5ac3bf1cb21e": { "id": "944a5639-4b22-4f7f-b836-5ac3bf1cb21e", "prev": "d30e098d-5b03-4087-bb2e-fe706d78fae9", "regions": { "c32c5800-6b61-4a15-b909-b1163c6ffe62": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "4329af31-21b4-4570-903a-6df3715244c7", "part": "whole" }, "id": "c32c5800-6b61-4a15-b909-b1163c6ffe62" } } }, "951ea1a1-a91e-41a8-827e-fc3624ae3250": { "id": "951ea1a1-a91e-41a8-827e-fc3624ae3250", "prev": "d46a6bb8-e8dc-42dd-ac78-33a9cc66fcaa", "regions": { "bc84fb60-e322-4e23-8b12-21f7fbfd11be": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "caa35df4-b625-4246-bc1f-42c561f31486", "part": "whole" }, "id": "bc84fb60-e322-4e23-8b12-21f7fbfd11be" } } }, "96f08da8-8b76-4bf1-829e-50dc77b96f23": { "id": "96f08da8-8b76-4bf1-829e-50dc77b96f23", "prev": "7f7b5da4-7345-442b-8cd5-662cfba97db9", "regions": { "ee8f45c8-aaa8-4c02-8067-bee120c4685d": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "672c009d-3dbc-4a1f-a789-2a0fe78729b9", "part": "whole" }, "id": "ee8f45c8-aaa8-4c02-8067-bee120c4685d" } } }, "9d28ba7f-c1e5-4ac3-ae0d-08721cddf897": { "id": "9d28ba7f-c1e5-4ac3-ae0d-08721cddf897", "prev": "b758d6c7-7c92-4aba-a50f-4ea841c3bbd5", "regions": { "f1d84675-1d92-48aa-b454-b5cfd4919f9c": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "85e46481-0245-448c-b4e2-e0c6e175357c", "part": "whole" }, "id": "f1d84675-1d92-48aa-b454-b5cfd4919f9c" } } }, "a2c51720-8844-4953-94a8-55d723ec2499": { "id": "a2c51720-8844-4953-94a8-55d723ec2499", "prev": "ec5e5d0b-4635-44cc-acc2-f4a52d49a309", "regions": { "8e52be0c-e63e-434c-b1ca-9c69b58557a6": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "13f246a0-918e-44c1-ae19-7af118d83585", "part": "whole" }, "id": "8e52be0c-e63e-434c-b1ca-9c69b58557a6" } } }, "ad16016c-8a9e-49da-a3d2-5ab56ca11579": { "id": "ad16016c-8a9e-49da-a3d2-5ab56ca11579", "prev": "257bf09e-bd55-4957-97ea-4d3c8b85016a", "regions": { "ba9b7c66-e2b9-4e94-a595-b6e1e9c8ba3a": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "25997dab-04e3-4abc-b22f-b36944b208c2", "part": "whole" }, "id": "ba9b7c66-e2b9-4e94-a595-b6e1e9c8ba3a" } } }, "aea4c7d8-d448-4c6e-b98a-aee48ab874f3": { "id": "aea4c7d8-d448-4c6e-b98a-aee48ab874f3", "prev": "823091e1-74b1-44e3-af50-388881c30968", "regions": { "c9f42ad3-4f13-490e-98af-ba7f90c04c7e": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "3544f061-6870-4630-bd54-79f75decf8b6", "part": "whole" }, "id": "c9f42ad3-4f13-490e-98af-ba7f90c04c7e" } } }, "aedf0537-c77a-45f0-9d07-af274cfcc254": { "id": "aedf0537-c77a-45f0-9d07-af274cfcc254", "prev": "e6ae4652-4831-456f-a99c-275d5a367c31", "regions": { "6b39b1f4-a8eb-48a7-abe6-34f074ddfffe": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "58e7dda6-0dd2-4e4f-b81a-0b530c66b20b", "part": "whole" }, "id": "6b39b1f4-a8eb-48a7-abe6-34f074ddfffe" } } }, "b225aeee-0655-46cd-b065-53ac161542e1": { "id": "b225aeee-0655-46cd-b065-53ac161542e1", "prev": "944a5639-4b22-4f7f-b836-5ac3bf1cb21e", "regions": { "3fb9131f-b513-4608-88e3-1829aab4af80": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "0924faf0-a957-4d12-b35c-b50ebb30f370", "part": "whole" }, "id": "3fb9131f-b513-4608-88e3-1829aab4af80" } } }, "b6050bf2-3f03-47ef-9510-80c01755a79e": { "id": "b6050bf2-3f03-47ef-9510-80c01755a79e", "prev": "96f08da8-8b76-4bf1-829e-50dc77b96f23", "regions": { "35a04fb6-5997-463a-b71f-8ad41ce5def6": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "f7724653-52ef-41e8-aa22-6232be216b08", "part": "whole" }, "id": "35a04fb6-5997-463a-b71f-8ad41ce5def6" } } }, "b758d6c7-7c92-4aba-a50f-4ea841c3bbd5": { "id": "b758d6c7-7c92-4aba-a50f-4ea841c3bbd5", "prev": "f2b5f77b-2cf3-4728-901e-453b1ee328e4", "regions": { "3907d293-429a-446b-aa7b-d48636df66de": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "92dbb672-adca-4535-8089-de23712828d8", "part": "whole" }, "id": "3907d293-429a-446b-aa7b-d48636df66de" } } }, "b78b6f6e-aa16-462e-8f65-fcb552b32c31": { "id": "b78b6f6e-aa16-462e-8f65-fcb552b32c31", "prev": "de9edf29-6b79-4254-9128-e8e5339d95b7", "regions": { "7907113d-9b89-4a1c-9b8e-9ccf0f800218": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "0e5ca1a8-9c78-412a-9ab4-a4d0be5afd34", "part": "whole" }, "id": "7907113d-9b89-4a1c-9b8e-9ccf0f800218" } } }, "bb7417b1-270b-4977-bbf3-606a574c38ec": { "id": "bb7417b1-270b-4977-bbf3-606a574c38ec", "prev": "aedf0537-c77a-45f0-9d07-af274cfcc254", "regions": { "4186cf60-3730-4fac-9b82-c178d043465c": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "6b5572c0-2ab0-4b13-a08f-3db21b4c4f21", "part": "whole" }, "id": "4186cf60-3730-4fac-9b82-c178d043465c" } } }, "bc583748-3efc-4990-a121-5c23ddd1cf76": { "id": "bc583748-3efc-4990-a121-5c23ddd1cf76", "prev": "b78b6f6e-aa16-462e-8f65-fcb552b32c31", "regions": { "1fe1815a-69fc-439e-9943-115c788d87de": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "161e8770-8bc2-41ae-98f4-08d1c9311e82", "part": "whole" }, "id": "1fe1815a-69fc-439e-9943-115c788d87de" } } }, "bebeb5ec-eea2-4353-b2e1-ba7cdb847132": { "id": "bebeb5ec-eea2-4353-b2e1-ba7cdb847132", "prev": "aea4c7d8-d448-4c6e-b98a-aee48ab874f3", "regions": { "acd4706d-0fa8-4d2c-93b1-e01bcddce185": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "31c64f41-a499-4f80-8ccd-1364940f7383", "part": "whole" }, "id": "acd4706d-0fa8-4d2c-93b1-e01bcddce185" } } }, "c68aae9d-645c-4cbf-9dc1-92ed9aa0f5d3": { "id": "c68aae9d-645c-4cbf-9dc1-92ed9aa0f5d3", "prev": "b225aeee-0655-46cd-b065-53ac161542e1", "regions": { "18e9a755-775e-407c-adec-19d9d2553aa3": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "59cc671f-041a-4d6f-a609-f1b9855aa05c", "part": "whole" }, "id": "18e9a755-775e-407c-adec-19d9d2553aa3" } } }, "c86c2c29-3931-4f32-b9b8-2927bd48a5d2": { "id": "c86c2c29-3931-4f32-b9b8-2927bd48a5d2", "prev": "8541226b-6ff1-4700-a399-71e3cf68d91b", "regions": { "98d1caf9-aaab-4a6a-8d39-875e61f4b508": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "ada914a2-bacb-4300-8ce3-f1332843d24c", "part": "whole" }, "id": "98d1caf9-aaab-4a6a-8d39-875e61f4b508" } } }, "ca688a20-d25d-4266-8f63-967e003c1f2f": { "id": "ca688a20-d25d-4266-8f63-967e003c1f2f", "prev": "78837f0a-d7b6-48ae-b64e-3a2af8286ccc", "regions": { "3b6c70c9-c6b9-4505-aefb-c64c0d183b96": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "943a5fcd-7c2e-4c16-9879-34882a7a74d4", "part": "whole" }, "id": "3b6c70c9-c6b9-4505-aefb-c64c0d183b96" } } }, "d30e098d-5b03-4087-bb2e-fe706d78fae9": { "id": "d30e098d-5b03-4087-bb2e-fe706d78fae9", "prev": "c86c2c29-3931-4f32-b9b8-2927bd48a5d2", "regions": { "ce2693da-705b-4afd-9284-d04c8e1b2ff4": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "4f313370-b5f0-4754-9744-157da0447fc4", "part": "whole" }, "id": "ce2693da-705b-4afd-9284-d04c8e1b2ff4" } } }, "d386ac9f-a3fc-4b7e-8171-72c5de5bcd6b": { "id": "d386ac9f-a3fc-4b7e-8171-72c5de5bcd6b", "prev": "488af944-ad92-49c5-9d1d-ccdb1e929dce", "regions": { "742b6acb-94bd-40bc-95c5-45686415a4d2": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "13f462fd-b0c3-4a29-90f3-050e2317b72c", "part": "whole" }, "id": "742b6acb-94bd-40bc-95c5-45686415a4d2" } } }, "d46a6bb8-e8dc-42dd-ac78-33a9cc66fcaa": { "id": "d46a6bb8-e8dc-42dd-ac78-33a9cc66fcaa", "prev": "e1b1494f-f764-4c7c-9b18-9c4117ac6b1a", "regions": { "46818eb4-db41-4ae4-ab4a-fb8aa8381df4": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "699e2ddb-add6-4134-a723-1bb37029f013", "part": "whole" }, "id": "46818eb4-db41-4ae4-ab4a-fb8aa8381df4" } } }, "d7495fd8-cfb5-42ee-a0eb-86679c419bae": { "id": "d7495fd8-cfb5-42ee-a0eb-86679c419bae", "prev": "845fbe01-dd28-4ad8-9eb5-d13c49f6772c", "regions": { "1b6fb9c6-e9e8-48d0-8879-43681a10b003": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "d447e236-b1b9-4cf7-bc39-8bfb499d4730", "part": "whole" }, "id": "1b6fb9c6-e9e8-48d0-8879-43681a10b003" } } }, "d84b78ed-e79f-4657-b62b-eeff30c4fe8d": { "id": "d84b78ed-e79f-4657-b62b-eeff30c4fe8d", "prev": "05fa6235-ac93-41b7-9975-3fee534b0c94", "regions": { "2dc757c4-cd6f-4663-b3ed-16873bd59e53": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "6b8eef4a-a87d-42bd-84dd-586610828698", "part": "whole" }, "id": "2dc757c4-cd6f-4663-b3ed-16873bd59e53" } } }, "de9edf29-6b79-4254-9128-e8e5339d95b7": { "id": "de9edf29-6b79-4254-9128-e8e5339d95b7", "prev": "4af127dc-0330-4f8e-b907-3e409ba31a06", "regions": { "ef8b9aae-46b3-45ae-8ddf-d951cecabb16": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "d8cfc39f-aa3b-469f-ae34-1ef99ef51a25", "part": "whole" }, "id": "ef8b9aae-46b3-45ae-8ddf-d951cecabb16" } } }, "deebcf04-3780-4222-bac9-4ec42c55e64e": { "id": "deebcf04-3780-4222-bac9-4ec42c55e64e", "prev": "479d81b5-3b8b-4ddf-bbfe-6ae6ff33c2fa", "regions": { "41284583-e45d-4b58-80b1-9aa982c35d62": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "e7995c4c-f483-4cb5-9f53-3b8c5fef39c3", "part": "whole" }, "id": "41284583-e45d-4b58-80b1-9aa982c35d62" } } }, "e1226821-9a12-4537-a8af-79cc88d3d16a": { "id": "e1226821-9a12-4537-a8af-79cc88d3d16a", "prev": "0e2565e0-a21d-4dbb-a4b3-8698e797c45d", "regions": { "a85036ed-bcf3-498f-bcbf-d29b7ba22e33": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "d8a8bcc6-8b37-4d4f-ad06-903804776078", "part": "whole" }, "id": "a85036ed-bcf3-498f-bcbf-d29b7ba22e33" } } }, "e1b1494f-f764-4c7c-9b18-9c4117ac6b1a": { "id": "e1b1494f-f764-4c7c-9b18-9c4117ac6b1a", "prev": "e975c742-3e8e-42fb-992f-68889dc8eacf", "regions": { "4481842a-f6a3-4783-8056-761d3ff7903c": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "c02b6f0a-801c-4a8f-aa8f-8c9d64df7a9a", "part": "whole" }, "id": "4481842a-f6a3-4783-8056-761d3ff7903c" } } }, "e24d4b0b-34e2-46de-a99d-a4be39ca2951": { "id": "e24d4b0b-34e2-46de-a99d-a4be39ca2951", "prev": "e1226821-9a12-4537-a8af-79cc88d3d16a", "regions": { "8a097e4f-9443-46a4-9b0f-84d5e12c50e7": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "6f302dcb-787b-42b0-98f0-1df0a163a818", "part": "whole" }, "id": "8a097e4f-9443-46a4-9b0f-84d5e12c50e7" } } }, "e44d6d8f-7236-458f-a308-36142bc72ff4": { "id": "e44d6d8f-7236-458f-a308-36142bc72ff4", "prev": "951ea1a1-a91e-41a8-827e-fc3624ae3250", "regions": { "cc091066-cdf1-4dd5-bf80-5c7c94722472": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "d2aa5aac-acc7-41c9-96d4-5410c0d8a14b", "part": "whole" }, "id": "cc091066-cdf1-4dd5-bf80-5c7c94722472" } } }, "e6ae4652-4831-456f-a99c-275d5a367c31": { "id": "e6ae4652-4831-456f-a99c-275d5a367c31", "prev": "bc583748-3efc-4990-a121-5c23ddd1cf76", "regions": { "fc109e55-75c1-42c7-a13b-68d9feb3aad7": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "fe809373-e88b-44eb-9cb9-08be3dc5949a", "part": "whole" }, "id": "fc109e55-75c1-42c7-a13b-68d9feb3aad7" } } }, "e71a7d3a-c9bb-4db0-9597-95b9b3233d3b": { "id": "e71a7d3a-c9bb-4db0-9597-95b9b3233d3b", "prev": "f6887642-4c01-4304-bedb-6e6bf5f5c45e", "regions": { "88ed165d-ed0c-4d77-a642-afc80f335c88": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "9994e7f0-f366-40da-9c14-76e8142ee46e", "part": "whole" }, "id": "88ed165d-ed0c-4d77-a642-afc80f335c88" } } }, "e975c742-3e8e-42fb-992f-68889dc8eacf": { "id": "e975c742-3e8e-42fb-992f-68889dc8eacf", "prev": "8aa83fc2-d106-4c85-8b7f-1116db7ee9d4", "regions": { "6f8253e7-9544-4503-84a2-5dd528b2b98c": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "e8936716-d06c-4cef-ae87-5c5da9a25a85", "part": "whole" }, "id": "6f8253e7-9544-4503-84a2-5dd528b2b98c" } } }, "ec5e5d0b-4635-44cc-acc2-f4a52d49a309": { "id": "ec5e5d0b-4635-44cc-acc2-f4a52d49a309", "prev": "12513a0d-3e80-464d-9285-3bdd87e0b9c0", "regions": { "007395dd-4907-4340-9391-024482d674f4": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "aa9d35ae-c458-49d2-bdbe-d93d5cb3ba9c", "part": "whole" }, "id": "007395dd-4907-4340-9391-024482d674f4" } } }, "efc03832-2e6d-4250-8ac5-f4c13cfdb733": { "id": "efc03832-2e6d-4250-8ac5-f4c13cfdb733", "prev": "deebcf04-3780-4222-bac9-4ec42c55e64e", "regions": { "ece43b16-b994-439a-a683-911e322998be": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "a6d40ad7-2abd-44e5-8839-62731fb5eab7", "part": "whole" }, "id": "ece43b16-b994-439a-a683-911e322998be" } } }, "f2b5f77b-2cf3-4728-901e-453b1ee328e4": { "id": "f2b5f77b-2cf3-4728-901e-453b1ee328e4", "prev": "ca688a20-d25d-4266-8f63-967e003c1f2f", "regions": { "fd2525a2-6271-4119-a693-9ebaa319233e": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "b492de13-0053-416c-b314-1bbae21ca828", "part": "whole" }, "id": "fd2525a2-6271-4119-a693-9ebaa319233e" } } }, "f6887642-4c01-4304-bedb-6e6bf5f5c45e": { "id": "f6887642-4c01-4304-bedb-6e6bf5f5c45e", "prev": "0527f44a-39b6-4cf8-9802-d16b8cd34754", "regions": { "22ac5030-534d-4372-b64f-11254caef474": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "8ce2b802-f0c1-4ffc-9ce5-c2792856b5b4", "part": "whole" }, "id": "22ac5030-534d-4372-b64f-11254caef474" } } }, "f6d5269c-54db-4887-b274-d00572aead72": { "id": "f6d5269c-54db-4887-b274-d00572aead72", "prev": "9d28ba7f-c1e5-4ac3-ae0d-08721cddf897", "regions": { "4adeafcb-a40e-4001-9cea-ced25a006c2a": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "380ef8b7-6de1-4822-ae30-7120e12b5955", "part": "whole" }, "id": "4adeafcb-a40e-4001-9cea-ced25a006c2a" } } }, "f870a325-581b-4d8e-a4c0-095972e4cc21": { "id": "f870a325-581b-4d8e-a4c0-095972e4cc21", "prev": "d386ac9f-a3fc-4b7e-8171-72c5de5bcd6b", "regions": { "6923b170-3e50-4538-a408-f2032324357e": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "68d38063-fb92-4d36-b3fb-f2d3cbff9eb5", "part": "whole" }, "id": "6923b170-3e50-4538-a408-f2032324357e" } } }, "fbd9f3b3-f9b0-4886-b987-3f9d0ca983bc": { "id": "fbd9f3b3-f9b0-4886-b987-3f9d0ca983bc", "prev": "2e4a9702-f7a2-48a5-bd13-2087e9216b38", "regions": { "b1150180-2e0b-444f-956f-2dd4cf1f3d4a": { "attrs": { "height": 0.8, "width": 0.8, "x": 0.1, "y": 0.1 }, "content": { "cell": "dbeeeabe-b6dd-477c-a798-fb7b39302ba9", "part": "whole" }, "id": "b1150180-2e0b-444f-956f-2dd4cf1f3d4a" } } } }, "themes": {} } }, "nbformat": 4, "nbformat_minor": 1 }