Wyrażenia języka mają odwoływać się do:
  1. tokenów i ich oznakowania morfo-syntaktycznego
  2. anotacji składniowych/semantycznych (realizowanych jako chunki)
  3. nieciągłych anotacji realizowanych jako kilka anotacji ciągłych powiązanych ze sobą,
  4. elementów nadrzędnych anotacji (heads),
  5. relacji między anotacjami
  6. dodatkowych własności przypisanych anotacjom.

Potrzebujemy formatu zapisu korpusu, który pozwoli na ujęcie tych rzeczy.

UWAGA: w ramach projektu musimy zdecydować się również na format zapisu korpusu znakowanego na wielu poziomach (potrzebny do zapisu „korpusu Infinity”). Nie jest to jednak oczywiste czy to powinien być ten sam format. Moim zdaniem (AR) nie. Argumenty:
  1. Format zapisu korpusu Infinity (odtąd KI) uwzględnia anotacje na wielu różnych poziomach i wszystko wskazuje na to, że anotacja jednego dokumentu będzie realizowana poprzez wiele osobnych plików (stand-off). Czytanie tego będzie siłą rzeczy mało wydajne, a testowanie języka (w tym utrzymanie testów automatycznych) będzie uciążliwe.
  2. Całe JOSKIPI/CCL opiera się na koncepcji tokenów. Przynajmniej pierwsze plany formatu KI zakładały znakowanie na poziomie znaków. Oznaczałoby to konieczność automatycznej konwersji w locie przy każdym użyciu języka.

UWAGA: sprawdziłem format TEI i jednak anotacje są tam znakowane na poziomie tokenów a nie znaków. Tak więc ten argument odpada jeśli zdecydujemy się na TEI. BB: wątpię, żebyśmy przyjęli w pełni TEI, ten format jest tak barokowy, że aż się dziwię, że ktoś z niego korzysta (zrozumienie TEI i napisanie odpowiednich narzędzi do jego czytania chyba pochłania więcej czasu niż opracowanie własnego formatu :P)

Argument na temat wydajności jest o tyle istotny, że spędziliśmy trochę czasu na przeprowadzanie optymalizacji bez sprawdzania czy była ona niezbędna (chodzi o bitowy zapis tagów i operacje bitowe jako zbiory). Byłoby głupio teraz zniszczyć ten potencjał szybkiego działania poprzez stały narzut na czytanie zawiłego, wieloplikowego formatu.

Proponuję opracować stosunkowo prosty format zapisu korpusu, gdzie wszystko będzie w jednym pliku. BB: "wszystko w jednym pliku" wg mnie to nie jest dobry pomysł.
Propozycje ogólne:
  • Tworzymy format możliwie zbliżony do XCES-a i rozszerzamy go o anotacje, relacje itp. Niektóre rzeczy będą musiałby być przypisane do zdania jako takiego.
  • Tworzymy prosty format możliwie zwięzły — co się da, to w czystym tekście, używamy wcięć i słów kluczowych na początku linijki.
  • Używamy jakiejś istniejącej techniki serializacji, np. JSON — i definiujemy struktury.

Jeśli opracujemy dwa formaty, potrzebny będzie konwerter. Jeśli format KI faktycznie będzie opierał się na poziomie znaków, daje to dodatkową korzyść: użytkownik będzie świadomie musiał uporać się z problemami z segmentacją (sytuacjami, gdy granica anotacji mija się z podziałem na tokeny). Gdyby JOSKIPI/CCL czytało jedynie format ze znakowaniem na poziomie znaków, to rozwiązywanie tych problemów staje się nieodłącznym elementem czytania korpusu.

UWAGA 2: alternatywnym rozwiązaniem jest przyjęcie prostszego formatu KI, gdzie
  • anotacje znakujemy na poziomie tokenów,
  • mamy możliwość zapisu anotacji w jednym pliku.

Moim zdaniem (AR) to lepsze wyjście, ale wydaje mi się, że większość jest za znakowaniem na poziomie znaków.

MM Uwaga ogólna na temat znakowania na poziomie znaków. W moim rozumieniu nie oznacza to, że wszystkie anotacje są opisane od znaku do znaku. Oznacza to, że w jednym pliku mamy ciągły tekst, w drugim segmentację na tokeny po znakach, a w kolejnych anotacje semantyczne odwołujące się do poziomu słów. Korekta W tym rozumiemy wracamy do problemu co zrobić kiedy w segmentacji pojawi się błąd, który będziemy chcieli skorygować, aby możliwe było dodanie jakiejś anotacji. Podział lub połączenie istniejących tokenów będzie wymagało przenumerowania pozostałych tokenów. Można uznać, że nie będziemy ręcznie edytować korpusów i za to będzie odpowiedzialne narzędzie.

Znaki vs Tokeny

Za znakami:
  • prosty format
  • można znakować składiowo/nerowo korpus niepodzielony na tokeny
  • niezależny od segmentacji - a wciąż nie mamy ustalonego sposobu segmentacji
  • korpus Michała jest znakowany na poziomie znaków
  • gdy coś się rozjedzie ze względu na segmentację, to od razu widać błąd
  • mniej miejsc na pomyłki AR: nie zgadzam się, może być więcej pomyłek: lingwista może oznakować przez pomyłkę niecały token, token wraz ze spacją itp. BB lingwista znakuje używając narzędzia, które do tego może nie dopuścić
Wady znaków:
  • konieczność konwersji do tokenów dla JOSKIPI/CCL (ale konwerter znaki->tokeny przy braku niejednoznaczności segmentacji jest trywialna; i ja i Michał robimy to w locie; i do tej pory się jeszcze to nie rozjechał0) MM niekoniecznie, przyjmując format np. TEI jest warstwa tokenów, na której operując pozostałe warstwy anotacji
  • format pozwala na zapis niespójnych danych (granice anotacji i tokenów się mijają)
  • odkładanie problemów na później: gdy zmienimy podział na tokeny korpusu już oznakowanego składniowo, odpowiedzialność za obsłużenie niespójnych z tokenami anotacji zrzucamy na oprogramowanie do przetwarzania na wyższych poziomach
Za tokenami:
  • JOSKIPI/CCL
  • nasze dotychczasowe korpusy składniowe
  • konwersja na poziom znaków trywialna
Wady tokenów:
  • brak ustalonej segmentacji
  • może się rozjechać "po cichu", gdy coś się zmieni na poziomie segmentacji (np. w Morfeuszu) AR: moim zdaniem po każdej zmianie segmentacji trzeba i tak sprawdzić poprawność na wyższych poziomach (czy orthy się nie zmieniły) BB problem jest taki, że w takim Morfeuszu może się coś zmienić bardzo subtelnego i tego nie zauważymy (ale fakt jest faktem - jak zauważymy zmianę segmentacji to trzeba wszystko zweryfikować)

Propozycja formatu dla CCL

Założenie: rozszerzamy obecny format XCES-owy, staramy się uzyskać format, który jest możliwie podobny do wewnętrznej reprezentacji danych oraz nie odbiega bardz od XCES-a. Nie staramy się zachować zgodności ze standardem XCES, ponieważ wydaje się on już niewspierany1 oraz liczymy się z tym, że proponowany format będzie rozwiązaniem zastępczym (tj. oprócz niego powstanie format właściwy do zapisu wszystkich warstw oznakowania korpusu — teraz sprawą priorytetową jest mieć JAKIKOLWIEK format, by dało się testować reguły).

1 A. Przepiórkowski, P. Bański, Which XML standards for multilevel corpus annotation?

Definicje

Zdanie jest ciągiem tokenów oznakowanych morfo-syntaktycznie. Oprócz tego oznakowania mamy znakowania na poziomie anotacji/fraz z oddzielnych kanałach.

Kanał fiycznie jest ciągiem numerków (liczby całokowite nieujemne). Numerków jest tyle, ile tokenów w zdaniu. W zdaniu może być najwyżej jeden kanał o podanej nazwie.

Kanał to sposób znakowania fraz jednego typu. Nazwa kanału określa typ frazy, np. kanał NP (frazy rzeczownikowe). Fraza to para (kanał, zbiór tokenów) — reprezentuje ona frazę danego typu. Fraza jest reprezentowana w kanale jako te pozycje w ciągu, które mają ten sam, niezerowy numerek. Np. jeśli kanał to 11002200, to mamy dwie frazy: frazę 11 (tokeny 3. i 4. od początku) oraz frazę 2 (tokeny 5. i 6.). Zerowe numerki odpowiadają brakowi frazy w tym momencie. Numeracja w każdym kanale jest liczona niezależnie.

Fraza może być nieciągła (np. 0011002211 — mamy tu nieciągłą frazę o numerku 1). Najdłuższe ciągłe fragmenty nieciągłej frazy nazywamy anotacjami (chunks).

Nadrzędnik frazy (head) to jeden z jej tokenów, który jest wyznaczony. Każda fraza musi mieć dokładnie jeden nadrzędnik.

Relacja to nazwane skierowane połączenie między parą (nazwa kanału, nr anotacji) a drugą taką parą.

Własność tokenu to para stringów klucz–wartość przypisana do tokenu. Każdy token może mieć dowolną liczbę takich własności, nie są one uporządkowane. Klucz ani wartość nie może zawierać znaków pustych na początku ani na końcu.

Nagłówek i końcówka

<?xml version="1.0" encoding="UTF-8"?>
<chunkList>
…
</chunkList>

Rezygnujemy z DOCTYPE, bo i tak nie mamy DTD, rezygnujemy z cesAna, bo to już nie CES/XCES.

Struktura

W oryginalnym XCES-ie zarówno podział na akapity, jak i na zdania realizowany jest przez elementy <chunk>. Używane przez nas struktury danych zakładają, że tekst podzielony jest najpierw na akapity, a potem na zdania. Dlatego proponuję opisać to wprost. Zmianę można wprowadzić, bo i tak zdaniom chcemy przypisać rzeczy, których wcześniej nie było.

chunkList -> chunk
chunk -> sentence

Zdania (sentence) zawierają tokeny opisane jak w XCES-ie — z wyjątkiem dodatkowych informacji, które opisano w następnym punkcie.

Element sentence odpowiada dotychczasowemu chunk type="s". Pozostałe elementy chunk zostawiamy, lecz zakładamy, że nie ma wielu poziomów zagnieżdżenia chunków (prawdopodobnie takie założenie i tak było w poprzednim formacie — nie spotkaliśmy korpusu, gdzie by to wystąpiło). Elementy chunk mogą mieć atrybuty (np. id, type) — po staremu (czytnik może ewentualnie zawierać asercję, by nie przyjmować type="s" — gdyby przyszło to zapisać do zwykłego XCES-a).

<chunk …>
<sentence>
</sentence>
…
<sentence …>
</sentence>

Własności tokenu

Pozwalamy do XML-owego tagu tok dodać dowolną liczbę własności opisanych w następujący sposób:

<tok>
…
<prop key="nazwa1">wartość1</prop>
<prop key="nazwa2">wartość2</prop>
</tok>

Własności te będą też używane do opisu całej anotacji — w takiej sytuacji podpinamy je pod token będący nadrzędnikiem anotacji, a nazwa powinna zaczynać się od nazwy kanału i dwukropka. Z tego względu nie należy stosować znaku dwukropka w nazwie klucza w innych sytuacjach.

Opis anotacji

Do każdego tokenu dodajemy informację na temat kanałów anotacji:

<tok>
<orth>sektą</orth>
<lex disamb="1"><base>sekta</base><ctag>subst:sg:inst:f</ctag></lex>
<ann chan="NP" head="1">1</ann>
<ann chan="AdjP">0</ann>
</tok>
<tok>
<orth>wynaturzoną</orth>
<lex><base>wynaturzyć</base><ctag>ppas:sg:acc:f:perf:aff</ctag></lex>
<lex disamb="1"><base>wynaturzyć</base><ctag>ppas:sg:inst:f:perf:aff</ctag></lex>
<ann chan="NP">1</ann>
<ann chan="AdjP">0</ann>
</tok>
<tok>
<lex disamb="1"><base>seksualnie</base><ctag>adv:pos</ctag></lex>
<ann chan="NP">1</ann>
<ann chan="AdjP">0</ann>
</tok>

Token może mieć dowolną liczbę elementów <ann>. W jednym tokenie może nie może być wielu tagów ann z tą samą nazwą anotacji. Zapis ann określa stan anotacji w kanale o podanej nazwie. Stan opisany jest numerkiem. Numerek 0 oznacza, że anotacja o podanej nazwie w tym miejscu nie występuje. Numerek dodatni oznacza, że token należy do anotacji o podanym numerze. Jeśli nastąpią po sobie dwa tokeny, jeden oznaczony jako <ann chan="NP">1</ann>, a drugi — <ann chan="NP">2</ann>, oznacza to, że pierszy należy do frazy NP o numerze 1, a drugi — do frazy nr 2 (są to oddzielne frazy, w zapisie IOB2 drugi token miałby tag B, jako że zaczyna nową frazę).

W ten sposób można określać też frazy nieciągłe. Przykładowo, jeśli wystąpi najpierw token oznaczony jako <ann chan="NP">1</ann>, po nim <ann chan="NP">0</ann>, potem <ann chan="NP">1</ann>, oznacza to, że pierwszy i trzeci token należą do nieciągłej frazy NP o numerze 1, natomiast token między nimi nie należy do frazy NP.

Uwaga: format ten zakłada, że numerowanie w każdym kanale jest niezależne, tzn. jeśli mamy np. frazę NP o numerze 1 i frazę VP o numerze jeden, to frazy te nie mają ze sobą nic wspólnego.

Podczas parsowania tego formatu można najpierw podzielić ciąg na podciągi o tych samych numerach. Jest to pierwsze przybliżenie fraz. W dalszym etapie można wyróżnić podciągi niebędące frazami (z numerkiem 0). W kolejnym etapie można rozpoznać które z anotacji są samodzielne (mają unikalny numerek), a które są częścią większej, nieciągłej frazy (numerki się powtarzają).

Frazy nieciągłe można rozpoznać po tym, że występuje więcej anotacji o tym samym numerze (anotacji rozumianych jako ciągów sąsiadujących tokenów o tym samym numerku).

Frazy mogą mieć określone elementy nadrzędne (ang. heads). Jeśli pojawi się head="1", oznacza to, że dany token jest nadrzędnikiem anotacji/frazy.

Dodatkowym wymaganiem jest przypisywanie każdemu tokenowi w ramach zdania tego samego ciągu nazw anotacji (tj. wartości będą różne, ale te same kanały powinny być widoczne w opisie każdego tokenu). Interpretacją liczby w środku ann jest numerek nadany frazie/anotacji (wartość 0 oznacza, że nie ma w tym kanale żadnej anotacji).

Opis relacji (wewnątrzzdaniowych i międzyzdaniowych)

Wymaga wprowadzenia identyfikatorów zdań, np.

<sentence id="s1">
...
</sentence>

Z założenia relacje międzyzdaniowe mogą wymagać wczytania całego dokumentu, więc czytanie strumieniowe (zdanie po zdaniu) będzie raczej niemożliwe. Dlatego proponuję, aby wszystkie relacje, które mogą być międzyzdaniowe były opisane w jednym miejscu (w pliku z tokenami na początku lub na końcu, lub w osobnym pliku). Przykład zapisu:

<relations>
  <rel name="REF:AgP-NP">
    <from sent="s2" chan="AgP">2</from>
    <from sent="s1" chan="PERSON_NAM">1</from>
  </rel>
  <rel name="REF:NP-NP">
  ...
  </rel>
</relations>

Własności przypisane frazie (nieaktualne)

TODO czy na pewno to doklejać też do zdania?

Podobnie jak relacje, informację tę zawieramy w elemencie sentence. Jedna fraza może zawierać wiele tokenów — dlatego trudno przypisać tę informację do jednego tokenu.

Opis frazy jest opcjonalny. Nadmiarowy opis powinien być natomiast wykrywany (więcej opisów tej samej frazy bądź opis frazy o nieistniejącym numerku/kanale).

<phrase id="1" chan="NP">
  <prop key="WNSense">kot-1</prep>
  <prop key="annotator">A.A.</prep>
</phrase>

TODO: czy potrzebujemy możliwość opisu lematu i tagu, lub też wielu lematów i tagów, jak token?