====== Nová reprezentace koordinací ====== ==== Předmluva ==== Tato stránka popisuje úvahy okolo budoucího řešení koordinací v Treexu, který by měl tou dobou nativně podporovat [[http://universaldependencies.github.io/docs/|Universal Dependencies]] (UD). Mým cílem bylo, aby to bylo intuitivní. Tedy aby člověk, který o tom moc neví, na první pokus napsal kód, který bude dělat tu správnou věc, a to zejména, pokud ten kód neřeší koordinace. (Teď totiž na koordinace člověk musí v Treexu myslet, ať už píše jakýkoli kód.) Samozřejmě takovýto cíl nejde nikdy zcela splnit, koordinace jsou prostě zapeklité ve všech stylech a svým způsobem se pletou do skoro všech ostatních jevů v jazyce. Názvy metod, parametrů a atributů nejsou definitivní, zatím mi jde spíš o celkovou koncepci. Samozřejmě uvítám návrhy na lepší názvy. ==== get_children a get_parent ==== * ''get_children'' bude vracet všechny efektivní děti (společná rozvití do toho ale nepočítám, to se vrátí jen u "primárního" rodiče, viz [[treex:coordinations#spolecna-rozviti|níže]]). * ''get_parent'' bude vracet efektivního rodiče (u společných rozvití opět jen toho primárního) * Tím pádem odpadne potřeba používat slovo "effective". * Koordinační spojky a čárky budou mít stejného rodiče jako conjuncts, tedy # John, Mary and Bob love bed and breakfast my ($john, $comma, $mary, $and1, $bob, $bed, $and2, $bf) = $love->get_children(); * Treex bude tedy interně vlastně používat maďarský/tesnierovský styl koordinací, stromové hrany se budou krýt s těmi lingvistickými (efektivními). Zároveň ale bude mít prostředky pro rozlišení jednotlivých koordinačních struktur, vnořených koordinací i společných rozvití, viz dále. ==== Treex API pro koordinace ==== * Místo ''is_member'' bude ''is_conjunct'' (malý rozdíl: v pražském stylu má spojka vnořené koordinace ''is_member=1'', ale teď bude mít ''is_conjunct=0''). Případně můžeme zavést další metody jako ''is_coord_conjunction'' a ''is_coord_delimiter'', pokud budou potřeba. * Metoda ''get_coord_children()'' vrátí objekty typu ''Treex::Core::Coord'' nebo prázdný seznam, např. # John, Mary and Bob love bed and breakfast my ($coord1, $coord2) = $love->get_coord_children(); my ($john, $mary, $bob) = $coord1->conjuncts(); my ($and) = $coord1->conjunctions(); # deprel=cc my ($comma) = $coord1->delimiters(); # deprel=punct * Metoda ''get_coordination'' vrátí objekt typu ''Treex::Core::Coord'' (nebo undef). Půjde takto také snadno zjistit, zda je uzel součástí nějaké koordinace jako conjunct, conjunction či delimiter (typicky čárka). U vnořených koordinací se vrátí nejvyšší koordinace, např. # Simon and Garfunkel or Dylan my $coord = $simon->get_coordination(); my ($simon, $garfunkel, $dylan) = $coord->conjuncts(transitive=>1); my ($coord_inner, $dylan) = $coord->conjuncts(transitive=>0); # otázka je, jaká bude defaultní hodonota parametru transitive my ($or) = $coord->conjunctions(); my ($and) = $coord_inner->conjunctions(); * Metoda get_children by mohla mít volitelný parametr ''no_coord'' $node->get_children({no_coord=>1}); # bude ekvivalentní grep {!$_->get_coordination} $node->get_children(); * Samozřejmě budeme potřebovat i metody na vytváření a měnění koordinací. To zatím nemám moc promyšlené. Jedna možnost: my ($simon, $and, $garfunkel, $or, $dylan) = map {$nodeA->create_child()} (1..5); my $coord_inner = $nodeA->create_coord_child(); my $coord_outer = $nodeA->create_coord_child(); $coord_inner->add_conjuncts($simon, $garfunkel); $coord_inner->add_conjunctions($and); $coord_outer->add_conjuncts($coord_inner, $dylan); $coord_outer->add_conjunctions($or); # ekvivalentní zkratka: my $coord_inner = $nodeA->create_coord_child({conjuncts=>[$simon, $garfunkel], conjunction=>$and}); my $coord_outer = $nodeA->create_coord_child({conjuncts=>[$coord_inner, $dylan], conjunction=>$or}); Uzly tvořící koordinaci musejí existovat (a tedy musejí mít nějakého závislostního rodiče, Treex nedovoluje uzly visící ve vzduchu) dřív, než se přidají do koordinace. Metody ''add_''* (a ''create_coord_child'' ve zkratce) by ale měly uzly převěsit tak, aby visely pod ''$nodeA'' (pokud původně visely někde jinde). ==== Společná rozvití ==== Společná rozvití (shared dependants) se budou zachycovat jen pomocí secondary dependencies definovaných v UD (viz dokumentace [[http://universaldependencies.github.io/docs/u/overview/specific-syntax.html#secondary-predicates|syntaxe]] a [[http://universaldependencies.github.io/docs/format.html#syntactic-annotation|CoNLL-U]]). # "big and cheap apples and oranges, which were sold yesterday" my $apples = $big->get_parent(); my ($oranges) = $big->get_secondary_parents(); ($oranges) = $cheap->get_secondary_parents(); $oranges = $sold->get_parent(); ($apples) = $sold->get_secondary_parents(); Secondary dependencies jde v UD využít i k dalším jevům (např. doplněk). Měli bychom možná nějak odlišit ty případy, kdy se jedná o společné rozvití. Secondary dependencies jsou v UD typované (mají svůj deprel), takže asi bude třeba ještě nějaká další metoda, která vrátí i typ, viz [[treex:coordinations#typovane-hrany]]. === Motivace pro zvolené řešení společných rozvití === Společné rozvití je většinou těžké odlišit od privátního (cf. "Jan a Marie, kteří"). Typicky jsme si jedním rodičem jisti a ten druhý (či třetí) je nejistý (jako v životě:-), mohli bychom jim tedy říkat mother a father, až na to, že pokud je možných otců víc (koordinovaných), tak v lingvistice se nestává, že by jen jeden byl rodičem a ostatní ne). Často nás rozdíl mezi společným a privátním rozvitím nezajímá a pražský styl nám to komplikuje, že takto jemná distinkce se odráží v celé topologii stromu. V tomto návrhu je snadné tu distinkci ignorovat. Zdeněk má taky případnou poznámku: > V tom, kolik ve větě najdeme společných rozvití, je určitá arbitrárnost. Nemyslím víceznačnost, ale např. reprezentaci vět typu "Kristus přišel a zvěstoval pokoj", ve kterých můžeme vidět buď společné rozvití, anebo rekonstruovaný perspron s koreferencí. Ano, pokud bychom chtěli doplňovat takovéto koreference, tak prostě smažeme secondary parent u "Kristus" a doplníme šipku z nově vytvořeného perspronu na "Kristus". Tedy nemusíme vůbec měnit topologii existujících uzlů, a to je myslím velká výhoda oproti současnému PDT stylu. ==== Vnitřní treexová reprezentace ==== Možná by se v Treexu hodil obecný prostředek na zachycení množiny uzlů (která nemusí tvořit podstrom). Pro klauze máme ''clause_number'' a metody get_clause_nodes, ''get_clause_root'' atd. Pro pojmenované entity máme n-strom, kde z n-uzlu vedou odkazy na množinu a-uzlů, ale Treex automaticky udržuje i odkazy v opačném směru, takže mám metodu ''$anode-''''>n_node()''. Aby fungovalo Treex API pro koordinace, tak potřebujeme nějaký takový mechanismus. Aby fungovalo rozlišení vnořených koordinací, tak potřebujeme spíš něco jako ty n-stromy, kde půjde zachytit, která koordinace je vnořena do které. ==== Detaily a diskuze ==== * Apozice budou řešeny hypotaktickým vztahem (druhý člen závisí na prvním), v UD deprel=appos. Takže se to nebude plést do koordinací. * V UD jsou předložky a spojky "dole", takže není třeba metod, které by hledaly efektivní děti/rodiče a ještě navíc přeskakovaly předložky (parametr dive=>AuxCP zmizí). * Lze zařídit, aby treexové API "předstíralo" nějakou jinou reprezentaci (třeba Prague/Stanford/Moscow family style), než jaká je ta skutečná treexová interní. Problém ale nastává, když pak chce někdo měnit strukturu, tedy přidávat či převěšovat uzly. Myslím, že pak musí přesně vědět, jaká je ta interní struktura, protože zde se jakékoli předstírání může dost vymstít. Ono by to předstírání asi bylo matoucí i při prohlížení v TrEdu (tedy kdyby API předstíralo a TrEd ne, opačně viz [[treex:coordinations#vizualizace-v-tredu]]) či XML treexových souborů a při debugování. Proto bych se radši takovémuto předstírání vyhnul. * Samozřejmě Read::CoNLLU bude umět načítat stanfordské koordinace a Write::CoNLLU je bude zapisovat. Budeme mít taky bloky, které budou převádět mezi naší treexovou (právě popsanou v tomto návrhu) reprezentací koordinací a různými jinými styly (Read/Write ::CoNLLU může tento transformační blok interně využívat). * Některé reprezentace koordinací mohou být výhodnější pro některé typy parserů. Bylo by jistě zajímavé to prozkoumat (jak plánujeme už několik let, a mezitím o tom vyšlo několik článků, ale žádný to ještě neprozkoumal tak důkladně, jak bych si představoval). Myslím si ale, že je chyba přizpůsobovat treexovou reprezentaci tomu, co umí současné parsery. Měli bychom se už konečně odpoutat od představy, že když je v treebanku nějaký jev reprezentován nějakým stylem, že to tak musíme dělat i při trénování parseru. * Výše popsaný návrh koordinací byl motivován hlavně tím, aby se to dobře používalo, když už to je naparsované (podobnou motivaci mají i UD). Nicméně si myslím, že by zrovna takovýto styl mohl být docela výhodný i pro parsery. Všechny hrany jsou ty efektivní, které parser zná i mimo koordinace. Po parseru se chce jen základní analýza (na které by se měli všichni shodnout). Podrobnější analýzu (vnořené koordinace, společná rozvití) už budou dělat jiné specializované klasifikátory, které dostanou parsing na vstupu, takže budou mít mnohem lepší podmínky pro správné rozhodnutí. * V pražském stylu (ale i ve stanfordském a moskevském, i když tam je to těžší poznat) je rozdíl mezi vícečetnou a vnořenou koordinací. Např. můj oblíbený (zkrácený) příklad z PDT: "Šetřete, netelefonujte, faxujte." Zde bych zrovna řekl, že nás pražský styl nutí rozlišovat (a přiřadit tomu úplně jinou topologii) úplně nepatrný sémantický rozdíl (pokud to vůbec jako vnímáme jako rozdíl a ne spurious ambiguity). Z tohoto hlediska se mi líbí nový návrh v tom, že i tento rozdíl je zakódován jen v atributech (a jde tedy snadno ignorovat) a topologie zůstává stejná. ==== Typované hrany ==== Občas v Treexu potřebujeme seznam uzlů, kam se z aktuálního uzlu dá dostat přes "šipku" daného typu. Občas potřebujeme ale pro každý vrácený uzel znát přesný typ (a podtyp) té šipky. Např. od metody ''get_aligned_nodes'' většinou chceme jen ten seznam uzlů, ale občas potřebujeme znát i typ alignmentu. Současné řešení vrací dvojici (''$nodes_array_ref, $types_array_ref''), ale to komplikuje to častější použití, kdy nás typy nezajímají. U normálních závislostí tento problém nenastává, protože každý uzel má jen jednoho rodiče (takže lze kdykoli na ten uzel zavolat ''deprel()'' či ''afun()'' a typ závislosti zjistit). Ale sekundárních závislostí může být víc než jedna. Možná by šlo využít perlovských anotací proměnných (viz ''perldoc attributes''), ale to moc lidí neumí používat. Jednodušší asi bude metoda ''$nodeA-''''>align_type_to($nodeB)'', respektive ''$nodeA-''''>deprel_to($nodeB)'' (''deprel_to'' by fungovalo pro sekundární rodiče i pro toho primárního, pro ostatní uzly by to vrátilo undef). ==== Vizualizace v TrEdu ==== Pokud se TrEd nepoužívá k editaci, ale jen k prohlížení, dovedu si představit i nějaké "předstírání" jiné struktury, než jaká je ta skutečná interní, a víc zobrazovacích módů. Jednalo by se jen o vizualizaci definovanou v stylesheetu. Přesto bych jako výchozí zobrazovací mód vybral takový, který nic nepředstírá, aby to uživatele nemátlo. Primární mód by zobrazoval všechny koordinované uzly jako sourozence (v jedné rovině). U vnořených koordinací by tedy toto zobrazení vedlo k o něco širším (plošším, tedy ne tak hlubokým) stromům než v současnosti (což na širokoúhlých monitorech může být spíš vítané). Uzly s ''is_conjunct'' by byly nějak zvýrazněné. Pokud to TrEd umí, tak bych koordinované uzly dal do společného rámečku, tedy nějak takto
       ------------------ love-----------
      /     /        /           \       \
  ---/-----/--------/--        ---\-------\---------
  | John Mary and Bob |        | bed and breakfast |
  ---------------------        ---------------------
Simon and Garfunkel or Dylan Alternativní zobrazovací mód by byl podobný tomu současnému, až na to že (stejně jako v primárním módu): * Společné rozvití by viselo na prvním (primárním) rodiči a ostatní by byly jako secondary dependencies značeny čárkovanou hranou. (V současném zobrazení visí společné rozvití na spojce a je tedy na stejné rovině jako jeho rodiče, což mi odjakživa přišlo velmi matoucí. Toho se teď zbavíme.) * Koordinační spojka by byla na stejné úrovni jako conjuncts. Takže conjuncts i koordinační spojka (čárka) by visely na umělém (přidaném) uzlu.
               love
             /     \
       #Coord       #Coord
      /  / | \         /| \
     /  /  |  \       / |  \
 John Mary and Bob  bed and breakfast


           #Coord
          /    |  \
     #Coord    or  Dylan
    /   | \  
 Simon and Garfunkel