{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<script>\n",
       "  function code_toggle() {\n",
       "    if (code_shown){\n",
       "      $('div.input').hide('500');\n",
       "      $('#toggleButton').val('Show Code')\n",
       "    } else {\n",
       "      $('div.input').show('500');\n",
       "      $('#toggleButton').val('Hide Code')\n",
       "    }\n",
       "    code_shown = !code_shown\n",
       "  }\n",
       "\n",
       "  $( document ).ready(function(){\n",
       "    code_shown=false;\n",
       "    $('div.input').hide()\n",
       "  });\n",
       "</script>\n",
       "<form action=\"javascript:code_toggle()\"><input type=\"submit\" id=\"toggleButton\" value=\"Show Code\"></form>\n",
       "<style>\n",
       ".rendered_html td {\n",
       "    font-size: xx-large;\n",
       "    text-align: left; !important\n",
       "}\n",
       ".rendered_html th {\n",
       "    font-size: xx-large;\n",
       "    text-align: left; !important\n",
       "}\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%html\n",
    "<script>\n",
    "  function code_toggle() {\n",
    "    if (code_shown){\n",
    "      $('div.input').hide('500');\n",
    "      $('#toggleButton').val('Show Code')\n",
    "    } else {\n",
    "      $('div.input').show('500');\n",
    "      $('#toggleButton').val('Hide Code')\n",
    "    }\n",
    "    code_shown = !code_shown\n",
    "  }\n",
    "\n",
    "  $( document ).ready(function(){\n",
    "    code_shown=false;\n",
    "    $('div.input').hide()\n",
    "  });\n",
    "</script>\n",
    "<form action=\"javascript:code_toggle()\"><input type=\"submit\" id=\"toggleButton\" value=\"Show Code\"></form>\n",
    "<style>\n",
    ".rendered_html td {\n",
    "    font-size: xx-large;\n",
    "    text-align: left; !important\n",
    "}\n",
    ".rendered_html th {\n",
    "    font-size: xx-large;\n",
    "    text-align: left; !important\n",
    "}\n",
    "</style>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "%%capture\n",
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "import sys\n",
    "sys.path.append(\"..\")\n",
    "from statnlpbook.util import execute_notebook\n",
    "import statnlpbook.parsing as parsing\n",
    "from statnlpbook.transition import *\n",
    "from statnlpbook.dep import *\n",
    "import pandas as pd\n",
    "from io import StringIO\n",
    "from IPython.display import display, HTML\n",
    "\n",
    "execute_notebook('transition-based_dependency_parsing.ipynb')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "is_executing": false,
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "<!---\n",
    "Latex Macros\n",
    "-->\n",
    "$$\n",
    "\\newcommand{\\Xs}{\\mathcal{X}}\n",
    "\\newcommand{\\Ys}{\\mathcal{Y}}\n",
    "\\newcommand{\\y}{\\mathbf{y}}\n",
    "\\newcommand{\\balpha}{\\boldsymbol{\\alpha}}\n",
    "\\newcommand{\\bbeta}{\\boldsymbol{\\beta}}\n",
    "\\newcommand{\\aligns}{\\mathbf{a}}\n",
    "\\newcommand{\\align}{a}\n",
    "\\newcommand{\\source}{\\mathbf{s}}\n",
    "\\newcommand{\\target}{\\mathbf{t}}\n",
    "\\newcommand{\\ssource}{s}\n",
    "\\newcommand{\\starget}{t}\n",
    "\\newcommand{\\repr}{\\mathbf{f}}\n",
    "\\newcommand{\\repry}{\\mathbf{g}}\n",
    "\\newcommand{\\x}{\\mathbf{x}}\n",
    "\\newcommand{\\prob}{p}\n",
    "\\newcommand{\\a}{\\alpha}\n",
    "\\newcommand{\\b}{\\beta}\n",
    "\\newcommand{\\vocab}{V}\n",
    "\\newcommand{\\params}{\\boldsymbol{\\theta}}\n",
    "\\newcommand{\\param}{\\theta}\n",
    "\\DeclareMathOperator{\\perplexity}{PP}\n",
    "\\DeclareMathOperator{\\argmax}{argmax}\n",
    "\\DeclareMathOperator{\\argmin}{argmin}\n",
    "\\newcommand{\\train}{\\mathcal{D}}\n",
    "\\newcommand{\\counts}[2]{\\#_{#1}(#2) }\n",
    "\\newcommand{\\length}[1]{\\text{length}(#1) }\n",
    "\\newcommand{\\indi}{\\mathbb{I}}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "%load_ext tikzmagic"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Parsing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "+ Syntactic constituency\n",
    "+ Syntactic dependencies\n",
    "+ Parsing algorithms\n",
    "+ Evaluation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Syntactic constituency"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Reminder: parts of speech (POS)\n",
    "\n",
    "[Parts of speech](sequence_labeling_slides.ipynb) categorise the syntactic function of words.\n",
    "\n",
    "[Penn Treebank POS tagset](https://www.ling.upenn.edu/courses/Fall_2003/ling001/penn_treebank_pos.html):\n",
    "\n",
    "Tag || Example\n",
    ":--- | :--- | :---\n",
    "CC | Coordinating conjunction | *and*\n",
    "CD | Cardinal number | *1*\n",
    "DT | Determiner | *the*\n",
    "EX | Existential there | *there*\n",
    "FW | Foreign word | *שלום*\n",
    "IN | Preposition or subordinating conjunction | *in*\n",
    "JJ | Adjective | *high*\n",
    "JJR | Adjective, comparative | *higher*\n",
    "JJS | Adjective, superlative | *highest*\n",
    "LS | List item marker | *,*\n",
    "MD | Modal | *can*\n",
    "NN | Noun, singular or mass | *desk*\n",
    "NNS | Noun, plural | *desks*\n",
    "NNP | Proper noun, singular | *Denmark*\n",
    "NNPS | Proper noun, plural | *Danes*\n",
    "PDT | Predeterminer | *both*\n",
    "POS | Possessive ending | *'s*\n",
    "PRP | Personal pronoun | *you*\n",
    "PRP$ | Possessive pronoun | *your*\n",
    "RB | Adverb | *well*\n",
    "RBR | Adverb, comparative | *better*\n",
    "RBS | Adverb, superlative | *best*\n",
    "RP | Particle |\n",
    "SYM | Symbol |\n",
    "TO | to |\n",
    "UH | Interjection |\n",
    "VB | Verb, base form | *see*\n",
    "VBD | Verb, past tense | *saw*\n",
    "VBG | Verb, gerund or present participle | *seeing*\n",
    "VBN | Verb, past participle | *seen*\n",
    "VBP | Verb, non-3rd person singular present | *see*\n",
    "VBZ | Verb, 3rd person singular present | *sees*\n",
    "WDT | Wh-determiner |\n",
    "WP | Wh-pronoun |\n",
    "WP\\$ | Possessive wh-pronoun |\n",
    "WRB | Wh-adverb |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Syntactic constituents\n",
    "\n",
    "**Phrases** also have a grammatical function when they are syntactic constituents.\n",
    "\n",
    "[Penn Treebank constituent tagset](https://www.ldc.upenn.edu/sites/www.ldc.upenn.edu/files/penn-etb-2-style-guidelines.pdf):\n",
    "\n",
    "Phrase Level || Example\n",
    ":--- | :--- | :---\n",
    "ADJP | Adjective Phrase | *really high*\n",
    "ADVP | Adverb Phrase | *very well*\n",
    "CONJP | Conjunction Phrase | *as well as*\n",
    "FRAG | Fragment |\n",
    "INTJ | Interjection |\n",
    "LST | List marker |\n",
    "NP | Noun Phrase | *high desk*\n",
    "PP | Prepositional Phrase | *at home*\n",
    "PRN | Parenthetical |\n",
    "PRT | Particle. Category for words that should be tagged RP |\n",
    "QP | Quantifier Phrase (i.e. complex measure/amount phrase); used within NP |\n",
    "RRC | Reduced Relative Clause |\n",
    "VP | Verb Phrase | *see the desk*\n",
    "WHADJP | Wh-adjective Phrase. Adjectival phrase containing a wh-adverb | *how hot*\n",
    "WHAVP | Wh-adverb Phrase, containing a wh-adverb | *how well*\n",
    "WHNP | Wh-noun Phrase, containing some wh-word | *which book*\n",
    "WHPP | Wh-prepositional Phrase, containing a wh-noun phrase | *of which*\n",
    "X | Unknown, uncertain, or unbracketable. |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Clause Level ||\n",
    ":--- | :---\n",
    "S | simple declarative clause, i.e. one that is not introduced by a (possible empty) subordinating conjunction or a wh-word and that does not exhibit subject-verb inversion.\n",
    "SBAR | Clause introduced by a (possibly empty) subordinating conjunction.\n",
    "SBARQ | Direct question introduced by a wh-word or a wh-phrase. Indirect questions and relative clauses should be bracketed as SBAR, not SBARQ.\n",
    "SINV | Inverted declarative sentence, i.e. one in which the subject follows the tensed verb or modal.\n",
    "SQ | Inverted yes/no question, or main clause of a wh-question, following the wh-phrase in SBARQ."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Trees\n",
    "\n",
    "A **tree** is a connected acyclic undirected graph.\n",
    "\n",
    "Graphs consist of **nodes** and **edges** between them.\n",
    "\n",
    "<center><img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/2/24/Tree_graph.svg/1920px-Tree_graph.svg.png\" width=40%/></center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Syntactic constituency trees (phrase structure trees)\n",
    "\n",
    "* **Nodes**: syntactic constituents, labeled by type (including individual words, labeled by POS).\n",
    "* **Edges**: connecting phrases to their constituents, unlabeled.\n",
    "\n",
    "<center>\n",
    "    <img src=\"../img/spaghetti1.png\" width=80%>\n",
    "</center>\n",
    "\n",
    "<div style=\"text-align: right;\">\n",
    "    (from <a href=\"https://aclanthology.org/P13-1045/\">Socher et al., 2013</a>)\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "<center>\n",
    "    <table><tr>\n",
    "    <td><img src=\"https://d3i71xaburhd42.cloudfront.net/0fea9208b2e18dd679a0e913a918bbb949eb8589/2-Figure2-1.png\" width=80%></td>\n",
    "    <td><img src=\"https://d3i71xaburhd42.cloudfront.net/0fea9208b2e18dd679a0e913a918bbb949eb8589/3-Figure5-1.png\" width=80%></td>\n",
    "        </tr></table>\n",
    "</center>\n",
    "\n",
    "<div style=\"text-align: right;\">\n",
    "    (from <a href=\"https://aclanthology.org/N18-5011\">Gokcen et al., 2018</a>)\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Another example of a *PP attachment* problem: does the **PP** (prepositional phrase) attach to the **VP** (verbal phrase) or the **NP** (noun phrase)?\n",
    "<center>\n",
    "    <img src=\"../img/proposal.png\" width=60%>\n",
    "</center>\n",
    "\n",
    "<div style=\"text-align: right;\">\n",
    "    (from <a href=\"https://aclanthology.org/2022.acl-long.220\">Kitaev et al., 2022</a>)\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Treebanks\n",
    "\n",
    "A dataset that consists of a text corpus with annotated (syntactic) trees.\n",
    "\n",
    "Some commonly used treebanks:\n",
    "\n",
    "* English: *Penn Treebank* (4.8 million words)\n",
    "* Mandarin Chinese: *Chinese Treebank* (1.5 million words)\n",
    "* German: *TIGER* (0.9 million words), *TüBa-D/Z* (1.6 million words)\n",
    "* Czech: *Prague Dependency Treebank* (2 million words)\n",
    "* Danish: *Arboretum* (0.2 million words)\n",
    "* ...\n",
    "* Multilingual: *Universal Dependencies* (more in a few slides)\n",
    "\n",
    "<center><img src=\"https://production-media.paperswithcode.com/datasets/treebank.png\" width=30%/></center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Constituency parsers\n",
    "\n",
    "Structured prediction: trained on treebanks to build constituency trees from text.\n",
    "\n",
    "See more in the [chapter from this book about constituency parsing](parsing.ipynb) ([slides](parsing_slides.ipynb)).\n",
    "\n",
    "<center>\n",
    "    <img src=\"https://d3i71xaburhd42.cloudfront.net/30a4754062a5f8c99e665db0b702a4da060af340/5-Figure2-1.png\" width=30%>\n",
    "</center>\n",
    "\n",
    "<div style=\"text-align: right;\">\n",
    "    (from <a href=\"https://aclanthology.org/2022.acl-long.220\">Kitaev et al., 2022</a>)\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Syntactic dependencies"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Motivation: information extraction\n",
    "\n",
    "In [relation extraction](information_extraction_slides.ipynb), it helps to define **linguistic** patterns such as `<subject> <verb> <object>` instead of purely text-based patterns.\n",
    "\n",
    "> <font color=\"blue\">Dechra Pharmaceuticals</font>, which has just made its second acquisition, had previously purchased <font color=\"green\">Genitrix</font>.\n",
    "\n",
    "> <font color=\"blue\">Trinity Mirror plc</font>, the largest British newspaper, purchased <font color=\"green\">Local World</font>, its rival.\n",
    "\n",
    "> <font color=\"blue\">Kraft</font>, owner of <font color=\"blue\">Milka</font>, purchased <font color=\"green\">Cadbury Dairy Milk</font> and is now gearing up for a roll-out of its new brand.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "**Syntactic dependencies** are a useful representation for this purpose.\n",
    "\n",
    "<center>\n",
    "    <img src=\"parsing_figures/dep4re.png\" width=\"60%\">\n",
    "</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "## Motivation: question answering by reading comprehension\n",
    "\n",
    "<center>\n",
    "    <img src=\"https://d3i71xaburhd42.cloudfront.net/05dd7254b632376973f3a1b4d39485da17814df5/6-Figure4-1.png\" width=100%>\n",
    "</center>\n",
    "\n",
    "<div style=\"text-align: right;\">\n",
    "    (from <a href=\"https://aclanthology.org/D16-1264\">Rajpurkar et al., 2016</a>)\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "## Motivation: question answering from knowledge bases\n",
    "\n",
    "<center>\n",
    "    <img src=\"https://d3i71xaburhd42.cloudfront.net/faee0c81a1170402b149500f1b91c51ccaf24027/2-Figure1-1.png\" width=50%>\n",
    "</center>\n",
    "\n",
    "<div style=\"text-align: right;\">\n",
    "    (from <a href=\"https://aclanthology.org/D17-1009\">Reddy et al., 2017</a>)\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Motivation: machine translation\n",
    "\n",
    "Reordering rules can be stated in terms of syntactic dependencies:\n",
    "\n",
    "<center>\n",
    "    <img src=\"https://d3i71xaburhd42.cloudfront.net/f4c750cdf8f557eea3a4b76be16e99ec15f0c92b/3-Figure2-1.png\" width=100%>\n",
    "</center>\n",
    "\n",
    "<div style=\"text-align: right;\">\n",
    "    (from <a href=\"https://arxiv.org/abs/2104.08384\">Rasooli et al., 2021</a>)\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Syntactic dependency trees\n",
    "\n",
    "* **Nodes**: individual words, and a special `ROOT` node.\n",
    "* Edges (**arcs**): labeled syntactic relations between words: from **head** to **dependent**.\n",
    "\n",
    "Must be a tree: **every word has exactly one head, and `ROOT` has no head**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "scrolled": true,
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div id='displacy3' style=\"width: 2400px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy3',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [{\"start\": 6, \"end\": 7, \"label\": \"det\", \"dir\": \"left\"}, {\"start\": 2, \"end\": 4, \"label\": \"dobj\", \"dir\": \"right\"}, {\"start\": 0, \"end\": 2, \"label\": \"root\", \"dir\": \"right\"}, {\"start\": 3, \"end\": 4, \"label\": \"det\", \"dir\": \"left\"}, {\"start\": 5, \"end\": 7, \"label\": \"case\", \"dir\": \"left\"}, {\"start\": 2, \"end\": 7, \"label\": \"obl\", \"dir\": \"right\"}, {\"start\": 1, \"end\": 2, \"label\": \"nsubj\", \"dir\": \"left\"}],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"I\"}, {\"text\": \"saw\"}, {\"text\": \"the\"}, {\"text\": \"star\"}, {\"text\": \"with\"}, {\"text\": \"the\"}, {\"text\": \"telescope\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy3'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conllu = \"\"\"\n",
    "# ID\tFORM\tLEMMA\tUPOS\tXPOS\tFEATS\tHEAD\tDEPREL\tDEPS\tMISC\n",
    "1\tI\t_\t_\t_\t_\t2\tnsubj\t_\t_\n",
    "2\tsaw\t_\t_\t_\t_\t0\troot\t_\t_\n",
    "3\tthe\t_\t_\t_\t_\t4\tdet\t_\t_\n",
    "4\tstar\t_\t_\t_\t_\t2\tdobj\t_\t_\n",
    "5\twith\t_\t_\t_\t_\t7\tcase\t_\t_\n",
    "6\tthe\t_\t_\t_\t_\t7\tdet\t_\t_\n",
    "7\ttelescope\t_\t_\t_\t_\t2\tobl\t_\t_\n",
    "\"\"\"\n",
    "arcs, tokens = to_displacy_graph(*load_arcs_tokens(conllu))\n",
    "render_displacy(arcs, tokens,\"2400px\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Syntactic ambiguity"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "scrolled": true,
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div id='displacy4' style=\"width: 2400px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy4',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [{\"start\": 6, \"end\": 7, \"label\": \"det\", \"dir\": \"left\"}, {\"start\": 2, \"end\": 4, \"label\": \"dobj\", \"dir\": \"right\"}, {\"start\": 0, \"end\": 2, \"label\": \"root\", \"dir\": \"right\"}, {\"start\": 3, \"end\": 4, \"label\": \"det\", \"dir\": \"left\"}, {\"start\": 5, \"end\": 7, \"label\": \"case\", \"dir\": \"left\"}, {\"start\": 2, \"end\": 7, \"label\": \"obl\", \"dir\": \"right\"}, {\"start\": 1, \"end\": 2, \"label\": \"nsubj\", \"dir\": \"left\"}],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"I\"}, {\"text\": \"saw\"}, {\"text\": \"the\"}, {\"text\": \"star\"}, {\"text\": \"with\"}, {\"text\": \"the\"}, {\"text\": \"telescope\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy4'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conllu = \"\"\"\n",
    "# ID\tFORM\tLEMMA\tUPOS\tXPOS\tFEATS\tHEAD\tDEPREL\tDEPS\tMISC\n",
    "1\tI\t_\t_\t_\t_\t2\tnsubj\t_\t_\n",
    "2\tsaw\t_\t_\t_\t_\t0\troot\t_\t_\n",
    "3\tthe\t_\t_\t_\t_\t4\tdet\t_\t_\n",
    "4\tstar\t_\t_\t_\t_\t2\tdobj\t_\t_\n",
    "5\twith\t_\t_\t_\t_\t7\tcase\t_\t_\n",
    "6\tthe\t_\t_\t_\t_\t7\tdet\t_\t_\n",
    "7\ttelescope\t_\t_\t_\t_\t2\tobl\t_\t_\n",
    "\"\"\"\n",
    "arcs, tokens = to_displacy_graph(*load_arcs_tokens(conllu))\n",
    "render_displacy(arcs, tokens,\"2400px\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div id='displacy5' style=\"width: 2400px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy5',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [{\"start\": 6, \"end\": 7, \"label\": \"det\", \"dir\": \"left\"}, {\"start\": 2, \"end\": 4, \"label\": \"dobj\", \"dir\": \"right\"}, {\"start\": 4, \"end\": 7, \"label\": \"nmod\", \"dir\": \"right\"}, {\"start\": 0, \"end\": 2, \"label\": \"root\", \"dir\": \"right\"}, {\"start\": 3, \"end\": 4, \"label\": \"det\", \"dir\": \"left\"}, {\"start\": 5, \"end\": 7, \"label\": \"case\", \"dir\": \"left\"}, {\"start\": 1, \"end\": 2, \"label\": \"nsubj\", \"dir\": \"left\"}],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"I\"}, {\"text\": \"saw\"}, {\"text\": \"the\"}, {\"text\": \"star\"}, {\"text\": \"with\"}, {\"text\": \"the\"}, {\"text\": \"telescope\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy5'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conllu = \"\"\"\n",
    "# ID\tFORM\tLEMMA\tUPOS\tXPOS\tFEATS\tHEAD\tDEPREL\tDEPS\tMISC\n",
    "1\tI\t_\t_\t_\t_\t2\tnsubj\t_\t_\n",
    "2\tsaw\t_\t_\t_\t_\t0\troot\t_\t_\n",
    "3\tthe\t_\t_\t_\t_\t4\tdet\t_\t_\n",
    "4\tstar\t_\t_\t_\t_\t2\tdobj\t_\t_\n",
    "5\twith\t_\t_\t_\t_\t7\tcase\t_\t_\n",
    "6\tthe\t_\t_\t_\t_\t7\tdet\t_\t_\n",
    "7\ttelescope\t_\t_\t_\t_\t4\tnmod\t_\t_\n",
    "\"\"\"\n",
    "arcs, tokens = to_displacy_graph(*load_arcs_tokens(conllu))\n",
    "render_displacy(arcs, tokens,\"2400px\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "<center>\n",
    "    <table>\n",
    "        <tr>\n",
    "            <td><img src=\"parsing_figures/telescope1.jpeg\" width=50%/></td>\n",
    "            <td><img src=\"parsing_figures/telescope2.jpg\" width=50%/></td>\n",
    "        </tr>\n",
    "    </table>\n",
    "</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### CoNLL-U format\n",
    "\n",
    "Tabular format with 10 columns indicating various morphosyntactic attributes.\n",
    "\n",
    "Shown here: ID, surface form, dependency head and dependency relation.\n",
    "\n",
    "(The others are shown as `_` but normally they would be filled in too.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th># ID</th>\n",
       "      <th>FORM</th>\n",
       "      <th>LEMMA</th>\n",
       "      <th>UPOS</th>\n",
       "      <th>XPOS</th>\n",
       "      <th>FEATS</th>\n",
       "      <th>HEAD</th>\n",
       "      <th>DEPREL</th>\n",
       "      <th>DEPS</th>\n",
       "      <th>MISC</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>I</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>2</td>\n",
       "      <td>nsubj</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>2</td>\n",
       "      <td>saw</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>0</td>\n",
       "      <td>root</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>3</td>\n",
       "      <td>the</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>4</td>\n",
       "      <td>det</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>4</td>\n",
       "      <td>star</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>2</td>\n",
       "      <td>dobj</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>5</td>\n",
       "      <td>with</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>7</td>\n",
       "      <td>case</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>6</td>\n",
       "      <td>the</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>7</td>\n",
       "      <td>det</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>7</td>\n",
       "      <td>telescope</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>4</td>\n",
       "      <td>nmod</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div id='displacy6' style=\"width: 2400px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy6',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [{\"start\": 6, \"end\": 7, \"label\": \"det\", \"dir\": \"left\"}, {\"start\": 2, \"end\": 4, \"label\": \"dobj\", \"dir\": \"right\"}, {\"start\": 4, \"end\": 7, \"label\": \"nmod\", \"dir\": \"right\"}, {\"start\": 0, \"end\": 2, \"label\": \"root\", \"dir\": \"right\"}, {\"start\": 3, \"end\": 4, \"label\": \"det\", \"dir\": \"left\"}, {\"start\": 5, \"end\": 7, \"label\": \"case\", \"dir\": \"left\"}, {\"start\": 1, \"end\": 2, \"label\": \"nsubj\", \"dir\": \"left\"}],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"I\"}, {\"text\": \"saw\"}, {\"text\": \"the\"}, {\"text\": \"star\"}, {\"text\": \"with\"}, {\"text\": \"the\"}, {\"text\": \"telescope\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy6'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "display(HTML(pd.read_csv(StringIO(conllu), sep=\"\\t\").to_html(index=False)))\n",
    "render_displacy(arcs, tokens,\"2400px\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Need for universal syntactic annotation\n",
    "\n",
    "How to define the relation labels? There are different linguistic traditions in different languages...\n",
    "<center>\n",
    "    <img src=\"../img/ud.png\" width=60%>\n",
    "</center>\n",
    "\n",
    "<div style=\"text-align: right;\">\n",
    "    (from <a href=\"https://cl.lingfil.uu.se/~miryam/assets/pdf/thesis.pdf\">de Lhoneux, 2019</a>)\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Universal Dependencies\n",
    "\n",
    "* Annotation framework featuring [37 syntactic relations](https://universaldependencies.org/u/dep/all.html)\n",
    "* [Treebanks](http://universaldependencies.org/) in over 130 languages\n",
    "* Large project with [over 500 contributors](https://lindat.mff.cuni.cz/repository/xmlui/handle/11234/1-4758)\n",
    "* Cross-linguistically consistent annotation of typologically diverse languages ([de Marneffe et al., 2021](https://aclanthology.org/2021.cl-2.11/))\n",
    "\n",
    "<center><img src=\"../img/ud_treebanks.png\" width=70%/></center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### UD dependency relations\n",
    "\n",
    "<table border=\"1\">\n",
    "  <tr style=\"background-color:cornflowerblue; font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\"> </td>\n",
    "      <td style=\"text-align: left;\"> Nominals </td>\n",
    "      <td style=\"text-align: left;\"> Clauses </td>\n",
    "      <td style=\"text-align: left;\"> Modifier words </td>\n",
    "      <td style=\"text-align: left;\"> Function Words </td>\n",
    "  </tr>\n",
    "  <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"background-color:darkseagreen\">\n",
    "\tCore arguments\n",
    "      </td>\n",
    "      <td style=\"text-align: left;\">\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/nsubj.html\" title=\"u-dep nsubj\">nsubj</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/obj.html\" title=\"u-dep obj\">obj</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/iobj.html\" title=\"u-dep iobj\">iobj</a>\n",
    "      </td>\n",
    "      <td style=\"text-align: left;\">\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/csubj.html\" title=\"u-dep csubj\">csubj</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/ccomp.html\" title=\"u-dep ccomp\">ccomp</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/xcomp.html\" title=\"u-dep xcomp\">xcomp</a>\n",
    "      </td>\n",
    "\t  <td style=\"text-align: left;\"></td><td style=\"text-align: left;\"></td>\n",
    "  </tr>\n",
    "  <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"background-color:darkseagreen;\">\n",
    "\tNon-core dependents\n",
    "      </td>\n",
    "      <td style=\"text-align: left;\">\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/obl.html\" title=\"u-dep obl\">obl</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/vocative.html\" title=\"u-dep vocative\">vocative</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/expl.html\" title=\"u-dep expl\">expl</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/dislocated.html\" title=\"u-dep dislocated\">dislocated</a>\n",
    "      </td>\n",
    "      <td style=\"text-align: left;\">\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/advcl.html\" title=\"u-dep advcl\">advcl</a>\n",
    "      </td>\n",
    "      <td style=\"text-align: left;\">\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/advmod.html\" title=\"u-dep advmod\">advmod</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/discourse.html\" title=\"u-dep discourse\">discourse</a>\n",
    "      </td>\n",
    "      <td style=\"text-align: left;\">\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/aux_.html\" title=\"u-dep aux\">aux</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/cop.html\" title=\"u-dep cop\">cop</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/mark.html\" title=\"u-dep mark\">mark</a>\n",
    "      </td>\n",
    "  </tr>\n",
    "  <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"background-color:darkseagreen\">\n",
    "\tNominal dependents\n",
    "      </td>\n",
    "      <td style=\"text-align: left;\">\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/nmod.html\" title=\"u-dep nmod\">nmod</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/appos.html\" title=\"u-dep appos\">appos</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/nummod.html\" title=\"u-dep nummod\">nummod</a>\n",
    "      </td>\n",
    "      <td style=\"text-align: left;\">\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/acl.html\" title=\"u-dep acl\">acl</a>\n",
    "      </td>\n",
    "      <td style=\"text-align: left;\">\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/amod.html\" title=\"u-dep amod\">amod</a>\n",
    "      </td>\n",
    "      <td style=\"text-align: left;\">\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/det.html\" title=\"u-dep det\">det</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/clf.html\" title=\"u-dep clf\">clf</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/case.html\" title=\"u-dep case\">case</a>\n",
    "      </td>\n",
    "  </tr style=\"font-size: x-large; text-align: left;\">\n",
    "  <tr style=\"background-color:cornflowerblue; font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\"> Coordination </td>\n",
    "      <td style=\"text-align: left;\"> MWE </td>\n",
    "      <td style=\"text-align: left;\"> Loose </td>\n",
    "      <td style=\"text-align: left;\"> Special </td>\n",
    "      <td style=\"text-align: left;\"> Other </td>\n",
    "  </tr>\n",
    "  <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\">\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/conj.html\" title=\"u-dep conj\">conj</a><br>\n",
    "\t    <a href=\"https://universaldependencies.org/u/dep/cc.html\" title=\"u-dep cc\">cc</a>\n",
    "      </td>\n",
    "      <td style=\"text-align: left;\">\n",
    "\t  <a href=\"https://universaldependencies.org/u/dep/fixed.html\" title=\"u-dep fixed\">fixed</a><br>\n",
    "\t  <a href=\"https://universaldependencies.org/u/dep/flat.html\" title=\"u-dep flat\">flat</a><br>\n",
    "\t  <a href=\"https://universaldependencies.org/u/dep/compound.html\" title=\"u-dep compound\">compound</a>\n",
    "    </td>\n",
    "    <td style=\"text-align: left;\">\n",
    "\t  <a href=\"https://universaldependencies.org/u/dep/list.html\" title=\"u-dep list\">list</a><br>\n",
    "\t  <a href=\"https://universaldependencies.org/u/dep/parataxis.html\" title=\"u-dep parataxis\">parataxis</a>\n",
    "    </td>\n",
    "    <td style=\"text-align: left;\">\n",
    "\t  <a href=\"https://universaldependencies.org/u/dep/orphan.html\" title=\"u-dep orphan\">orphan</a><br>\n",
    "\t  <a href=\"https://universaldependencies.org/u/dep/goeswith.html\" title=\"u-dep goeswith\">goeswith</a><br>\n",
    "\t  <a href=\"https://universaldependencies.org/u/dep/reparandum.html\" title=\"u-dep reparandum\">reparandum</a>\n",
    "    </td>\n",
    "    <td style=\"text-align: left;\">\n",
    "\t  <a href=\"https://universaldependencies.org/u/dep/punct.html\" title=\"u-dep punct\">punct</a><br>\n",
    "\t  <a href=\"https://universaldependencies.org/u/dep/root.html\" title=\"u-dep root\">root</a><br>\n",
    "\t  <a href=\"https://universaldependencies.org/u/dep/dep.html\" title=\"u-dep dep\">dep</a>\n",
    "    </td>\n",
    "  </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Beyond dependency trees\n",
    "\n",
    "UD also includes other morphosyntactic annotation:\n",
    "\n",
    "* Tokenisation and word segmentation\n",
    "* Morphological features (e.g., lemmas, case, gender)\n",
    "* **Universal part of speech tags (UPOS)**: coarse abstraction over language-specific POS tags (XPOS).\n",
    "\n",
    "<table class=\"typeindex\">\n",
    "  <thead>\n",
    "    <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <th>Open class words</th>\n",
    "      <th>Closed class words</th>\n",
    "      <th>Other</th>\n",
    "    </tr>\n",
    "  </thead>\n",
    "  <tbody>\n",
    "    <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/ADJ.html\" class=\"doclink doclabel\" title=\"u-pos ADJ\">ADJ</a></td>\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/ADP.html\" class=\"doclink doclabel\" title=\"u-pos ADP\">ADP</a></td>\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/PUNCT.html\" class=\"doclink doclabel\" title=\"u-pos PUNCT\">PUNCT</a></td>\n",
    "    </tr>\n",
    "    <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/ADV.html\" class=\"doclink doclabel\" title=\"u-pos ADV\">ADV</a></td>\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/AUX_.html\" class=\"doclink doclabel\" title=\"u-pos AUX\">AUX</a></td>\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/SYM.html\" class=\"doclink doclabel\" title=\"u-pos SYM\">SYM</a></td>\n",
    "    </tr>\n",
    "    <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/INTJ.html\" class=\"doclink doclabel\" title=\"u-pos INTJ\">INTJ</a></td>\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/CCONJ.html\" class=\"doclink doclabel\" title=\"u-pos CCONJ\">CCONJ</a></td>\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/X.html\" class=\"doclink doclabel\" title=\"u-pos X\">X</a></td>\n",
    "    </tr>\n",
    "    <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/NOUN.html\" class=\"doclink doclabel\" title=\"u-pos NOUN\">NOUN</a></td>\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/DET.html\" class=\"doclink doclabel\" title=\"u-pos DET\">DET</a></td>\n",
    "      <td style=\"text-align: left;\">&nbsp;</td>\n",
    "    </tr>\n",
    "    <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/PROPN.html\" class=\"doclink doclabel\" title=\"u-pos PROPN\">PROPN</a></td>\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/NUM.html\" class=\"doclink doclabel\" title=\"u-pos NUM\">NUM</a></td>\n",
    "      <td style=\"text-align: left;\">&nbsp;</td>\n",
    "    </tr>\n",
    "    <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/VERB.html\" class=\"doclink doclabel\" title=\"u-pos VERB\">VERB</a></td>\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/PART.html\" class=\"doclink doclabel\" title=\"u-pos PART\">PART</a></td>\n",
    "      <td style=\"text-align: left;\">&nbsp;</td>\n",
    "    </tr>\n",
    "    <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\">&nbsp;</td>\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/PRON.html\" class=\"doclink doclabel\" title=\"u-pos PRON\">PRON</a></td>\n",
    "      <td style=\"text-align: left;\">&nbsp;</td>\n",
    "    </tr>\n",
    "    <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\">&nbsp;</td>\n",
    "      <td style=\"text-align: left;\"><a href=\"https://universaldependencies.org/u/pos/SCONJ.html\" class=\"doclink doclabel\" title=\"u-pos SCONJ\">SCONJ</a></td>\n",
    "      <td style=\"text-align: left;\">&nbsp;</td>\n",
    "    </tr>\n",
    "  </tbody>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Danish UD example\n",
    "*the big fish ate the small fish*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div id='displacy9' style=\"width: 1400px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy9',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [{\"start\": 3, \"end\": 4, \"label\": \"nsubj\", \"dir\": \"left\"}, {\"start\": 4, \"end\": 7, \"label\": \"obj\", \"dir\": \"right\"}, {\"start\": 2, \"end\": 3, \"label\": \"amod\", \"dir\": \"left\"}, {\"start\": 0, \"end\": 4, \"label\": \"root\", \"dir\": \"right\"}, {\"start\": 1, \"end\": 3, \"label\": \"det\", \"dir\": \"left\"}, {\"start\": 6, \"end\": 7, \"label\": \"amod\", \"dir\": \"left\"}, {\"start\": 5, \"end\": 7, \"label\": \"det\", \"dir\": \"left\"}],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"Den\"}, {\"text\": \"store\"}, {\"text\": \"fisk\"}, {\"text\": \"spiste\"}, {\"text\": \"den\"}, {\"text\": \"lille\"}, {\"text\": \"fisk\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy9'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conllu = \"\"\"\n",
    "# ID\tFORM\tLEMMA\tUPOS\tXPOS\tFEATS\tHEAD\tDEPREL\tDEPS\tMISC\n",
    "1\tDen\t_\t_\t_\t_\t3\tdet\t_\t_\n",
    "2\tstore\t_\t_\t_\t_\t3\tamod\t_\t_\n",
    "3\tfisk\t_\t_\t_\t_\t4\tnsubj\t_\t_\n",
    "4\tspiste\t_\t_\t_\t_\t0\troot\t_\t_\n",
    "5\tden\t_\t_\t_\t_\t7\tdet\t_\t_\n",
    "6\tlille\t_\t_\t_\t_\t7\tamod\t_\t_\n",
    "7\tfisk\t_\t_\t_\t_\t4\tobj\t_\t_\n",
    "\"\"\"\n",
    "arcs, tokens = to_displacy_graph(*load_arcs_tokens(conllu))\n",
    "render_displacy(arcs, tokens,\"1400px\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "### Korean UD example\n",
    "*big fish small fish ate*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div id='displacy10' style=\"width: 1400px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy10',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [{\"start\": 0, \"end\": 5, \"label\": \"root\", \"dir\": \"right\"}, {\"start\": 3, \"end\": 4, \"label\": \"amod\", \"dir\": \"left\"}, {\"start\": 2, \"end\": 5, \"label\": \"nsubj\", \"dir\": \"left\"}, {\"start\": 4, \"end\": 5, \"label\": \"obj\", \"dir\": \"left\"}, {\"start\": 1, \"end\": 2, \"label\": \"amod\", \"dir\": \"left\"}],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"\\ud070\"}, {\"text\": \"\\ubb3c\\uace0\\uae30\\uac00\"}, {\"text\": \"\\uc791\\uc740\"}, {\"text\": \"\\ubb3c\\uace0\\uae30\\ub97c\"}, {\"text\": \"\\uba39\\uc5c8\\ub2e4\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy10'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conllu = \"\"\"\n",
    "# ID\tFORM\tLEMMA\tUPOS\tXPOS\tFEATS\tHEAD\tDEPREL\tDEPS\tMISC\n",
    "1\t큰\t_\t_\t_\t_\t2\tamod\t_\t_\n",
    "2\t물고기가\t_\t_\t_\t_\t5\tnsubj\t_\t_\n",
    "3\t작은\t_\t_\t_\t_\t4\tamod\t_\t_\n",
    "4\t물고기를\t_\t_\t_\t_\t5\tobj\t_\t_\n",
    "5\t먹었다\t_\t_\t_\t_\t0\troot\t_\t_\n",
    "\"\"\"\n",
    "arcs, tokens = to_displacy_graph(*load_arcs_tokens(conllu))\n",
    "render_displacy(arcs, tokens,\"1400px\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "<center><img src=\"../img/quiz_time.png\"></center>\n",
    "\n",
    "### [ucph.page.link/dep](https://ucph.page.link/dep)\n",
    "\n",
    "([Responses](https://docs.google.com/forms/d/1s94JgjTizC8d4JUUPxV4T46pB2SH4sYp40b9aHZeVvE/edit#responses))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "### Solution\n",
    "\n",
    "There are 6 nodes (including the root) and 5 arcs.\n",
    "<img src=\"parsing_figures/weparsedashortsentence-1.png\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Dependency parsing\n",
    "\n",
    "Task:\n",
    "* Predict **head** and **relation** for each word.\n",
    "* Classification? Sequence tagging? Sequence-to-sequence? Span selection? Or something else?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th># ID</th>\n",
       "      <th>FORM</th>\n",
       "      <th>LEMMA</th>\n",
       "      <th>UPOS</th>\n",
       "      <th>XPOS</th>\n",
       "      <th>FEATS</th>\n",
       "      <th>HEAD</th>\n",
       "      <th>DEPREL</th>\n",
       "      <th>DEPS</th>\n",
       "      <th>MISC</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>Alice</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>2</td>\n",
       "      <td>nsubj</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>2</td>\n",
       "      <td>saw</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>0</td>\n",
       "      <td>root</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>3</td>\n",
       "      <td>Bob</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "      <td>2</td>\n",
       "      <td>dobj</td>\n",
       "      <td>_</td>\n",
       "      <td>_</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "conllu = \"\"\"\n",
    "# ID\tFORM\tLEMMA\tUPOS\tXPOS\tFEATS\tHEAD\tDEPREL\tDEPS\tMISC\n",
    "1\tAlice\t_\t_\t_\t_\t2\tnsubj\t_\t_\n",
    "2\tsaw\t_\t_\t_\t_\t0\troot\t_\t_\n",
    "3\tBob\t_\t_\t_\t_\t2\tdobj\t_\t_\n",
    "\"\"\"\n",
    "display(HTML(pd.read_csv(StringIO(conllu), sep=\"\\t\").to_html(index=False)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Dependency parsing approaches\n",
    "\n",
    "* **Graph-based**: score all possible word pairs, find best combination (often a maximum spanning tree). Examples:\n",
    "  * [UDPipe](https://lindat.mff.cuni.cz/services/udpipe/run.php?model=english-ewt-ud-2.10-220711&data=Kraft,%20owner%20of%20Milka,%20purchased%20Cadbury%20Dairy%20Milk%20and%20is%20now%20gearing%20up%20for%20a%20roll-out%20of%20its%20new%20brand.)\n",
    "  * [Stanza](http://stanza.run/)\n",
    "* **Transition-based**: incrementally build the tree, one arc at a time, by applying a sequence of actions. Examples:\n",
    "  * [spaCy](https://demos.explosion.ai/displacy?text=Kraft%2C%20owner%20of%20Milka%2C%20purchased%20Cadbury%20Dairy%20Milk%20and%20is%20now%20gearing%20up%20for%20a%20roll-out%20of%20its%20new%20brand.&model=en_core_web_sm&cpu=0&cph=0)\n",
    "  * [UUParser](https://github.com/UppsalaNLP/uuparser)\n",
    "  * [TUPA](https://github.com/huji-nlp/tupa/)\n",
    "  \n",
    "<center>\n",
    "    <img src=\"https://d3i71xaburhd42.cloudfront.net/c267b4a64066b56c8eef053de391c3cbe58c9eb3/3-Figure2-1.png\" width=60%>\n",
    "</center>\n",
    "\n",
    "<div style=\"text-align: right;\">\n",
    "    (from <a href=\"https://aclanthology.org/P18-2077/\">Dozat & Manning, 2018</a>)\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Dependency parsing evaluation\n",
    "\n",
    "* Unlabeled Attachment Score (**UAS**): % of words with correct head\n",
    "* Labeled Attachment Score (**LAS**): % of words with correct head and label\n",
    "\n",
    "Always 0 $\\leq$ LAS $\\leq$ UAS $\\leq$ 100%."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Example: LAS and UAS\n",
    "\n",
    "<center>\n",
    "    <img src=\"parsing_figures/as.png\" width=70%/>\n",
    "</center>\n",
    "\n",
    "<center>\n",
    "    $\\mathrm{UAS}=\\frac{8}{12}=67\\%$\n",
    "</center>\n",
    "\n",
    "<center>\n",
    "    $\\mathrm{LAS}=\\frac{7}{12}=58\\%$\n",
    "</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Transition-based parsers\n",
    "\n",
    "Consist of a **<span style=\"color:blue\">buffer</span>** and **<span style=\"color:red\">stack</span>**, incrementally build the **parse** by applying **actions** (transitions).\n",
    "\n",
    "<center>\n",
    "    <img src=\"parsing_figures/tb_example.png\" width=97%/>\n",
    "</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "is_executing": false,
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Configuration\n",
    "\n",
    "- Stack \\\\(S\\\\): a last-in, first-out memory to keep track of words to process\n",
    "- Buffer \\\\(B\\\\): words remaining to be processed\n",
    "- Arcs \\\\(A\\\\): the dependency arcs created so far in the parse tree"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "What are the possible actions? Depends which **transition system** we are using!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "Common transition systems:\n",
    "+ arc-standard ([Nivre, 2003](https://aclanthology.org/W03-3017/))\n",
    "+ arc-eager ([Nivre, 2004](https://www.aclweb.org/anthology/W04-0308))\n",
    "+ arc-hybrid ([Kuhlmann et al., 2011](https://aclanthology.org/P11-1068/))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## arc-standard\n",
    "\n",
    "Possible actions at each step:\n",
    "- **SHIFT**: move the buffer top item to the stack.\n",
    "- For each relation $r$,\n",
    "  - **RIGHT-ARC-$r$**: create $r$ arc from second stack item to stack top. Then pop stack top.\n",
    "  - **LEFT-ARC-$r$**: create $r$ arc from stack top to second stack item. Then pop second stack item."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "Two special configurations:\n",
    "- **initial**: buffer contains the words, stack contains root, and arcs are empty.\n",
    "- **terminal**: buffer is empty, stack contains only root."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### arc-standard example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table><tr><td style='font-size: x-large;'>stack</td><td style='font-size: x-large;'>buffer</td><td style='font-size: x-large;'>parse</td><td style='font-size: x-large;'>action</td></tr>\n",
       "<tr><td style='font-size: x-large;'>ROOT</td><td style='font-size: x-large;'>Alice saw Bob</td><td style='font-size: x-large;'>\n",
       "    <div id='displacy75' style=\"width: 500px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy75',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"Alice\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy75'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script></td><td style='font-size: x-large;'></td></tr>\n",
       "<tr><td style='font-size: x-large;'>ROOT Alice</td><td style='font-size: x-large;'>saw Bob</td><td style='font-size: x-large;'>\n",
       "    <div id='displacy76' style=\"width: 500px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy76',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"Alice\"}, {\"text\": \"saw\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy76'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script></td><td style='font-size: x-large;'>shift</td></tr>\n",
       "<tr><td style='font-size: x-large;'>ROOT Alice saw</td><td style='font-size: x-large;'>Bob</td><td style='font-size: x-large;'>\n",
       "    <div id='displacy77' style=\"width: 500px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy77',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"Alice\"}, {\"text\": \"saw\"}, {\"text\": \"Bob\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy77'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script></td><td style='font-size: x-large;'>shift</td></tr>\n",
       "<tr><td style='font-size: x-large;'>ROOT saw</td><td style='font-size: x-large;'>Bob</td><td style='font-size: x-large;'>\n",
       "    <div id='displacy78' style=\"width: 500px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy78',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [{\"start\": 1, \"end\": 2, \"label\": \"nsubj\", \"dir\": \"left\"}],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"Alice\"}, {\"text\": \"saw\"}, {\"text\": \"Bob\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy78'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script></td><td style='font-size: x-large;'>leftArc-nsubj</td></tr>\n",
       "<tr><td style='font-size: x-large;'>ROOT saw Bob</td><td style='font-size: x-large;'></td><td style='font-size: x-large;'>\n",
       "    <div id='displacy79' style=\"width: 500px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy79',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [{\"start\": 1, \"end\": 2, \"label\": \"nsubj\", \"dir\": \"left\"}],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"Alice\"}, {\"text\": \"saw\"}, {\"text\": \"Bob\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy79'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script></td><td style='font-size: x-large;'>shift</td></tr>\n",
       "<tr><td style='font-size: x-large;'>ROOT saw</td><td style='font-size: x-large;'></td><td style='font-size: x-large;'>\n",
       "    <div id='displacy80' style=\"width: 500px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy80',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [{\"start\": 1, \"end\": 2, \"label\": \"nsubj\", \"dir\": \"left\"}, {\"start\": 2, \"end\": 3, \"label\": \"dobj\", \"dir\": \"right\"}],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"Alice\"}, {\"text\": \"saw\"}, {\"text\": \"Bob\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy80'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script></td><td style='font-size: x-large;'>rightArc-dobj</td></tr>\n",
       "<tr><td style='font-size: x-large;'>ROOT</td><td style='font-size: x-large;'></td><td style='font-size: x-large;'>\n",
       "    <div id='displacy81' style=\"width: 500px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy81',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [{\"start\": 1, \"end\": 2, \"label\": \"nsubj\", \"dir\": \"left\"}, {\"start\": 2, \"end\": 3, \"label\": \"dobj\", \"dir\": \"right\"}, {\"start\": 0, \"end\": 2, \"label\": \"root\", \"dir\": \"right\"}],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"Alice\"}, {\"text\": \"saw\"}, {\"text\": \"Bob\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy81'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script></td><td style='font-size: x-large;'>rightArc-root</td></tr>\n",
       "<tr><td style='font-size: x-large;'>ROOT</td><td style='font-size: x-large;'></td><td style='font-size: x-large;'>\n",
       "    <div id='displacy82' style=\"width: 500px;\"></div>\n",
       "    <script>\n",
       "    $(function() {\n",
       "    requirejs.config({\n",
       "        paths: {\n",
       "            'displaCy': ['/files/node_modules/displacy/displacy'],\n",
       "                                                  // strip .js ^, require adds it back\n",
       "        },\n",
       "    });\n",
       "    require(['displaCy'], function() {\n",
       "        console.log(\"Loaded :)\");\n",
       "        const displacy = new displaCy('http://localhost:8000', {\n",
       "            container: '#displacy82',\n",
       "            format: 'spacy',\n",
       "            distance: 150,\n",
       "            offsetX: 0,\n",
       "            wordSpacing: 20,\n",
       "            arrowSpacing: 3,\n",
       "\n",
       "        });\n",
       "        const parse = {\n",
       "            arcs: [{\"start\": 1, \"end\": 2, \"label\": \"nsubj\", \"dir\": \"left\"}, {\"start\": 2, \"end\": 3, \"label\": \"dobj\", \"dir\": \"right\"}, {\"start\": 0, \"end\": 2, \"label\": \"root\", \"dir\": \"right\"}],\n",
       "            words: [{\"text\": \"ROOT\"}, {\"text\": \"Alice\"}, {\"text\": \"saw\"}, {\"text\": \"Bob\"}]\n",
       "        };\n",
       "\n",
       "        displacy.render(parse, {\n",
       "            uniqueId: 'render_displacy82'\n",
       "            //color: '#ff0000'\n",
       "        });\n",
       "        return {};\n",
       "    });\n",
       "    });\n",
       "    </script></td><td style='font-size: x-large;'></td></tr></table>"
      ],
      "text/plain": [
       "<statnlpbook.transition.render_transitions_displacy.<locals>.Output at 0x7f57ed2ec460>"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "render_transitions_displacy(transitions, tokenized_sentence)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Transition-based parsing as structured prediction\n",
    "\n",
    "**Model** $p(a|c)$: how likely is action $a$ to be next, given that the current configuration is $c$?\n",
    "$$p(a|c) \\approx s_\\params(a,c)$$\n",
    "\n",
    "**Training**: learn $\\params$ with an annotated training set\n",
    "$$\n",
    "\\argmax_\\params \\prod_{x \\in \\train} \\prod_{i=1}^{|x|} s_\\params(a_i,c_i)\n",
    "$$\n",
    "\n",
    "**Decoding**: try to find the most likely action sequence\n",
    "$$\\argmax_{a_1,\\ldots,a_{|x|}}  \\prod_{i=1}^{|x|} s_\\params(a_i,c_i)$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Neural transition classifiers\n",
    "\n",
    "Sequence-to-sequence?\n",
    "<center>\n",
    "    <img src=\"parsing_figures/tb1.png\" width=60%/>\n",
    "</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Sequence-to-sequence, but with control structure:\n",
    "<center>\n",
    "    <img src=\"parsing_figures/tb2.png\" width=30%/>\n",
    "</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Example neural transition classifiers\n",
    "* Each step is a new classification instance, with word embedding features ([Chen and Manning, 2014](https://aclanthology.org/D14-1082/))\n",
    "* Stack-LSTM: recurrent state updated across steps ([Dyer et al., 2015](https://aclanthology.org/P15-1033/))\n",
    "* Each step is a new classification instance, with **BiLSTM** features ([Kiperwasser and Goldberg, 2016](https://aclanthology.org/Q16-1023/))\n",
    "* Stack-pointer: global attention to select attachment ([Ma et al., 2018](https://aclanthology.org/P18-1130/))\n",
    "* Stack-transformer: self-attention for state representation ([Fernandez Astudillo et al., 2020](https://aclanthology.org/2020.findings-emnlp.89/))\n",
    "\n",
    "<center>\n",
    "    <img src=\"https://d3i71xaburhd42.cloudfront.net/8292a74aba4eab2ca864b457c17b02634fef4ddd/5-Figure7-1.png\" width=30%/>\n",
    "</center>\n",
    "\n",
    "<div style=\"text-align: right;\">\n",
    "    (from <a href=\"https://aclanthology.org/K18-2010/\">Hershcovich et al., 2018</a>)\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Training\n",
    "\n",
    "+ Loss function: often negative log-likelihood or max-margin\n",
    "+ **Teacher forcing:**  always choose the ground truth action.\n",
    "\n",
    "*Alternative:* (see also [MT slides](nmt_slides_active.ipynb))\n",
    "\n",
    "+ **Scheduled sampling:** with a certain probability, use model predictions instead.\n",
    "\n",
    "But what is the **ground truth**? Treebanks contain **trees**, not action sequences!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "**Oracle**: rules to select the right action given the configuration **and the correct tree**.\n",
    "\n",
    "<center><img src=\"../img/oracle.png\" width=50%/></center>\n",
    "\n",
    "<div style=\"text-align: right;\">\n",
    "    (from <a href=\"https://aclanthology.org/P17-1104/\">Hershcovich et al., 2017</a>)\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Decoding\n",
    "\n",
    "+ Greedy decoding:\n",
    "    + Always pick the **most likely action** (according to the classifier)\n",
    "    + Continue applying more actions **until a terminal configuration is reached**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "+ Beam search:\n",
    "    * Maintains a list of top-$k$ action+configuration sequences in a **beam**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## arc-hybrid\n",
    "\n",
    "- **SHIFT**: move the buffer top item to the stack.\n",
    "- **RIGHT-ARC-$r$**: create $r$ arc from second stack item to stack top. Then pop stack top.\n",
    "- **LEFT-ARC-$r$**: create $r$ arc from **buffer top** to stack top. Then pop **stack top**.\n",
    "\n",
    "<center><img src=\"../img/archybrid.png\" width=20%/></center>\n",
    "\n",
    "- **initial**: buffer contains the words **followed by root**, stack is **empty**, and arcs are empty.\n",
    "- **terminal**: buffer **contains only root**, stack **is empty**."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### arc-hybrid example\n",
    "\n",
    "**Unlabeled parsing** (without relation labels), just for simplicity.\n",
    "\n",
    "https://danielhers.github.io/archybrid.pdf"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "<center><img src=\"../img/quiz_time.png\"></center>\n",
    "\n",
    "### [ucph.page.link/tb](https://ucph.page.link/tb)\n",
    "\n",
    "([Responses](https://app.quizalize.com/dash/R3JvdXA6YTUzMGNkZjItYTRiYS00NGM2LTk3ZGEtZDc4YjlkMjkyODg4/activity/QWN0aXZpdHk6OWYxNzM2NTUtMjJhYi00YzVkLTgzOTUtODA3ZWYyNjczY2Fh/what))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## Summary: arc-hybrid vs arc-standard\n",
    "<table class=\"typeindex\">\n",
    "  <thead>\n",
    "    <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <th></th>\n",
    "      <th>LEFT-ARC</th>\n",
    "      <th>initial configuration</th>\n",
    "      <th>terminal configuration</th>\n",
    "    </tr>\n",
    "  </thead>\n",
    "  <tbody>\n",
    "    <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\">arc-standard</td>\n",
    "        <td style=\"text-align: left;\">create arc from <b>stack</b> top to <b>second</b> stack item,<br>pop <b>second</b> stack item</td>\n",
    "        <td style=\"text-align: left;\">stack contains <b>root</b>,<br>buffer contains words</td>\n",
    "        <td style=\"text-align: left;\">stack contains <b>root</b>,<br>buffer is <b>empty</b></td>\n",
    "    </tr>\n",
    "    <tr style=\"font-size: x-large; text-align: left;\">\n",
    "      <td style=\"text-align: left;\">arc-hybrid</td>\n",
    "        <td style=\"text-align: left;\">create arc from <b>buffer</b> top to stack <b>top</b>,<br>pop stack <b>top</b></td>\n",
    "        <td style=\"text-align: left;\">stack is <b>empty</b>,<br>buffer contains words <b>and root</b></td>\n",
    "        <td style=\"text-align: left;\">stack is <b>empty</b>,<br>buffer contains <b>root</b></td>\n",
    "    </tr>\n",
    "  </tbody>\n",
    "</table>\n",
    "\n",
    "<center><img src=\"../img/archybrid.png\" width=20%/>(arc-hybrid)</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Summary\n",
    "\n",
    "* **Dependency parsing** predicts word-to-word dependencies\n",
    "* Treebanks in many languages, thanks to **UD**\n",
    "* Fast and accurate parsing, e.g. **transition-based**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Further reading\n",
    "\n",
    "* [EACL 2014 tutorial on dependency parsing](http://stp.lingfil.uu.se/~nivre/eacl14.html)\n",
    "* [Slides about semantic parsing](https://danielhers.github.io/mr.pdf)\n",
    "* [Chapter from this book about transition-based dependency parsing](http://localhost:8888/notebooks/chapters/transition-based_dependency_parsing.ipynb)\n",
    "* [Chapter from this book about constituency parsing](parsing.ipynb) ([slides](parsing_slides.ipynb))\n",
    "* [Jurafsky & Martin, Chapter 14](https://web.stanford.edu/~jurafsky/slp3/14.pdf)"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}