Difference between revisions of "Jak zrobić nową parę języków"
(Created page with '{{TOCD}} Apertium, tworzenie nowej pary językowej. Ten artykuł opisuje, jak stworzyć od podstaw, nową parę językową dla maszynowego systemu tłumaczenia Apertium. Nie za…') |
|||
(25 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
{{TOCD}} |
{{TOCD}} |
||
Ten artykuł opisuje, jak stworzyć od początku, nową parę języków dla systemu tłumaczenia automatycznego Apertium. |
|||
Apertium, tworzenie nowej pary językowej. |
|||
Nie zawiera, żadnej wiedzy na temat językoznawstwa lub tłumaczenia automatycznego powyżej poziomu możliwości odróżniania rzeczowników od czasowników (i przyimków itp.) |
|||
Ten artykuł opisuje, jak stworzyć od podstaw, nową parę językową dla maszynowego systemu tłumaczenia Apertium. |
|||
Nie zawiera, żadnej wiedzy na temat językoznawstwa i automatycznego tłumaczenia powyżej poziomu możliwości odróżniania rzeczowników od czasowników (i przyimków itp.) |
|||
==Wprowadzenie== |
==Wprowadzenie== |
||
Apertium jest, jak |
Apertium jest, jak się zapewne domyślasz, systemem do automatycznego tłumaczenia komputerowego. Dokładniej mówiąc jest to platforma stworzona do tego celu. Zawiera silnik oraz zbiór narzędzi, które pozwalają na zbudowanie własnego systemu translacji. Jedyną rzeczą, którą użytkownik musi wykonać to wprowadzenie danych. Podstawowo są to trzy słowniki oraz kilka zasad (np. zmiany szyku zdania lub gramatyki). |
||
Bardziej szczegółowe wprowadzenie na temat jak to wszystko działa znajdziesz w dziale [[Publications]]. |
|||
==Wymagania== |
==Wymagania== |
||
Line 19: | Line 17: | ||
* edytor tekstu (lub specjalny edytor XML) |
* edytor tekstu (lub specjalny edytor XML) |
||
Ten poradnik nie obejmuje instalacji powyższych narzędzi. W celu zasięgnięcia dalszych porad zajrzyj do dokumentacji projektu na stronie Apertium. |
|||
==Na czym polega para |
==Na czym polega para języków?== |
||
Apertium jest |
Apertium jest komputerowym systemem tłumaczenia, który do pracy wykorzystuje słowniki oraz płytkie reguły transferowe (shallow transfer rules). Zasadniczą różnicą pomiędzy głębokimi i płytkimi zasadami jest to, że płytkie zasady nie analizują składni oraz działają na grupach jednostek leksykalnych zamiast używania struktury drzewa. Wyróżnia się trzy podstawowe słowniki: |
||
# |
# Słownik morfologiczny dla języka xx: zawierający zbiór zasad dot. odmieniania słowa w języku xx. W naszym przykładzie będzie to: <code>apertium-sh-en.sh.dix</code> |
||
# Słownik morfologiczny dla języka yy: zawierający zbiór zasad dot. odmieniania słowa w języku yy. W naszym przykładzie będzie to: <code>apertium-sh-en.en.dix</code> |
|||
<code>apertium-sh-en.sh.dix</code> |
|||
# |
# Słownik dwujęzyczny: zawierający zależności pomiędzy słowami i symbolami w tych dwóch językach. W naszym przykładzie będzie to: <code>apertium-sh-en.sh-en.dix</code> |
||
<code>apertium-sh-en.en.dix</code> |
|||
# Dwujęzyczny słownik: zawierający zaleznosci pomiędzy słowami i symbolami w tych dwóch językach. W naszym przykłedzie będzie to: |
|||
<code>apertium-sh-en.sh-en.dix</code> |
|||
W parze |
W parze tłumaczonych języków dany język może być zarówno źródłem jak i wynikiem translacji. |
||
Istnieją również dwa pliki |
Istnieją również dwa pliki zawierające zasady transferu. Zasady te opisują, w jaki sposób zarządzać szykiem zdań np. “kot czarny -> czarny kot”. Regulują one też powiązania pomiędzy płcią, liczbami itp. Zasady te mogą być też wykorzystywane do dodawania lub usuwania elementów leksykalnych, co będzie opisane później. Pliki, o których mowa to: |
||
* zasady transferu języka xx do |
* zasady transferu języka xx do yy: zawierający zasady translacji języka xx do języka yy. W naszym przypadku będzie to: <code>apertium-sh-en.sh-en.t1x</code> |
||
<code>apertium-sh-en. |
* zasady transferu języka yy do xx: zawierający zasady translacji języka yy do języka xx. W naszym przypadku będzie to: <code>apertium-sh-en.en-sh.t1x</code> |
||
* zasady transferu języka yy do języka xx: ten plik zawiera jak powinno się zamieniać język yy w xx. W naszym przyĸładzie będzie to: |
|||
<code>apertium-sh-en.en-sh.t1x</code> |
|||
Wiele par językowych posiada dodatkowe pliki, jednak nie będą |
Wiele dostępnych par językowych posiada dodatkowe pliki, jednak nie będą one tutaj opisywane. Powyższe pliki służą, jako podstawa do stworzenia funkcjonalnego systemu. |
||
==Przykładowa para== |
==Przykładowa para języków== |
||
Jak |
Jak zapewne zauważyłeś, ten artykuł opiera się o przykład translatora Serbsko-Chorwackiego na Angielski w celu opisania zasad tworzenia podstawowej wersji systemu. Jest to dość niefortunna para języków, zważywszy na fakt, że system działa lepiej w przypadku bardziej pokrewnych języków. Nie powinno to jednak przeszkadzać w przypadku użycia tak prostych przykładów, jakie będą tu zaprezentowane. |
||
==Wyjaśnienie używanych pojęć== |
==Wyjaśnienie używanych pojęć== |
||
Istnieje kilka pojęć, z którymi powinieneś się zapoznać zanim będziemy mogli kontynuować. |
|||
Pierwszym jest ''lemma''. Jest to forma |
Pierwszym określeniem jest ''[http://pl.wikipedia.org/wiki/Lemma lemma]''. Jest to forma podstawowa danego słowa. Ma ona najczęściej postać zbliżoną do najprostszej z możliwych (bezokoliczników itd.). Dla przykładu, lemma słowa ''cats'' to ''cat''. W języku angielskim lemmy rzeczowników są zazwyczaj w liczbie pojedynczej. Dla czasowników, lemma jest bezokolicznikiem, np. lemmą ''was'' będzie ''be''. |
||
Następnym jest ''symbol''. |
Następnym określeniem jest ''symbol''. W kontekście systemu Apertium, symbol oznacza etykietę gramatyczną danego słowa. Słowo ''cats'' jest rzeczownikiem w liczbie mnogiej, więc będzie miało zarówno przyporządkowany symbol rzeczownika jak i symbol liczby mnogiej. Na wejściu i wyjściu modułów programowych są one zazwyczaj pomiędzy ostrymi nawiasami, tak jak poniżej: |
||
* <code><n></code>; dla rzeczownika |
* <code><n></code>; dla rzeczownika |
||
* <code><pl></code>; dla liczby mnogiej. |
* <code><pl></code>; dla liczby mnogiej. |
||
Innymi przykładami symbolami są <sg> (liczba pojedyncza) <p1> (pierwsza osoba) itd. Pisane w ostrych nawiasach symbole mogą być też traktowane, jako tagi. Warto zauważyć, że w wielu obecnie dostępnych parach językowych definicje symboli są akronimami lub skrótami zaczerpniętymi z języka katalońskiego. Symbole są definiowane w tagu <sdef> i używane w <nowiki> <s> </nowiki> |
|||
Trzecie |
Trzecie określenie to ''paradygmat''. W ramach systemu Apertium, paradygmat odnosi się do sposobu, w jaki powinno się odmieniać daną grupę słów. W słownikach morfologicznych, lemmy (patrz wyżej) są przypisane do paradygmatów, które pozwalają nam opisać, w jaki sposób dana lemmy odmienia się, bez konieczności zapisywania wszystkich końcówek. |
||
W słownikach jednojęzykowych, lemmy (patrz wyżej) są przypisane do paradygmatów, które pozwalają w jaki sposób dana lemma odmienia się, bez koniecznosci zapisywania wszystkich końcówek. |
|||
Poniższy przykład pokazuje użyteczność tego |
Poniższy przykład pokazuje użyteczność tego podejścia, w przypadku, gdy chcemy zapisać przymiotniki ‘‘happy'' i ''lazy'': |
||
* happy, happ (y, ier, iest) |
* happy, happ (y, ier, iest) |
||
* lazy, laz (y, ier, iest) |
* lazy, laz (y, ier, iest) |
||
Możemy |
Możemy po prostu zapisać jedno, a następnie powiedzieć, “lazy odmienia się jak happy" lub równoznacznie, “shy odmienia się jak happy", "naughty odmienia się jak happy", "friendly odmienia się jak happy" itd. W tym przykładzie ''happy'' jest paradygmatem pokazującym jak powinno się odmieniać inne słowa. Paradygmaty definiuje się w tagu <paradef> a używa w tagu <par>. |
||
==Na początek== |
==Na początek== |
||
Line 74: | Line 66: | ||
===Słowniki jednojęzyczne=== |
===Słowniki jednojęzyczne=== |
||
{{see-also|List of dictionaries|Incubator}} |
{{see-also|List of dictionaries|Incubator}} |
||
Zacznijmy od stworzenia pierwszego słownika. |
Zacznijmy od stworzenia naszego pierwszego źródłowego słownika. Będzie to dokument XML. Otwórz swój edytor i wpisz: |
||
<pre> |
<pre> |
||
<?xml version="1.0" encoding="UTF-8"?> |
<?xml version="1.0" encoding="UTF-8"?> |
||
Line 81: | Line 73: | ||
</dictionary> |
</dictionary> |
||
</pre> |
</pre> |
||
Na razie definiujemy, że to, co zaraz stworzymy będzie słownikiem. Aby był przydatny musimy dodać kilka innych wpisów, pierwszym będzie alfabet. Definiuje on zbiór liter, które mogą być użyte. Dla słownika Serbsko-Chorwackiego będzie wyglądał tak: |
|||
<pre> |
<pre> |
||
<alphabet>ABCČĆDDžĐEFGHIJKLLjMNNjOPRSŠTUVZŽabcčćddžđefghijklljmnnjoprsštuvzž</alphabet> |
<alphabet>ABCČĆDDžĐEFGHIJKLLjMNNjOPRSŠTUVZŽabcčćddžđefghijklljmnnjoprsštuvzž</alphabet> |
||
</pre> |
</pre> |
||
Alfabet umieść poniżej tagu <dictionary>. |
|||
Następnie |
Następnie zdefiniujemy kilka symboli. Zacznijmy od prostych rzeczy jak: rzeczownik (n) w liczbie pojedynczej (sg) i mnogiej (pl). |
||
<pre> |
<pre> |
||
<sdefs> |
<sdefs> |
||
Line 96: | Line 88: | ||
</sdefs> |
</sdefs> |
||
</pre> |
</pre> |
||
Nazwy symboli nie muszą być |
Nazwy symboli nie muszą być krótkie, w rzeczywistości mogą być napisane w całości, lecz częste używanie długich nazw byłoby na dłuższą metę męczące. |
||
Niestety, |
Niestety, sprawa jest nieco bardziej skomplikowana. Rzeczowniki w języku Sarbsko-Chorwackim odmieniają się także od płci i przypadku. Jednak założymy na potrzeby tego przykładu, że rzeczownik jest rodzaju męskiego w mianowniku (pełny przykład można znaleźć na końcu tego dokumentu). |
||
Następnym krokiem jest |
Następnym krokiem jest zdefiniowanie sekcji dla paradygmatów, |
||
<pre> |
<pre> |
||
<pardefs> |
<pardefs> |
||
Line 106: | Line 98: | ||
</pardefs> |
</pardefs> |
||
</pre> |
</pre> |
||
Oraz sekcji słownika: |
|||
<pre> |
<pre> |
||
<section id="main" type="standard"> |
<section id="main" type="standard"> |
||
Line 112: | Line 104: | ||
</section> |
</section> |
||
</pre> |
</pre> |
||
Istnieją dwa typy sekcji |
Istnieją dwa typy sekcji - pierwszy jest sekcją standardową, która zawiera słowa, enklityki itd. Drugim typem sekcji jest [[inconditional section]] zawierająca znaki interpunkcyjne itd. Opisywany przykład nie zawiera drugiego typu. |
||
Plik na obecną chwilę powinien wyglądać tak: |
Plik na obecną chwilę powinien wyglądać tak: |
||
Line 131: | Line 123: | ||
</dictionary> |
</dictionary> |
||
</pre> |
</pre> |
||
Mamy więc szkielet, możemy rozpocząć pracę od dodania rzeczownika. Rzecznikiem tym będzie 'gramofon'. |
|||
Pierwszą rzeczą, jaką musimy zrobić |
Pierwszą rzeczą, jaką musimy zrobić jest określenie paradygmatu. |
||
Pamiętaj, że |
Pamiętaj, że zakładamy, iż jest to rodzaj męski w mianowniku. Liczba pojedyncza tego rzeczownika to 'gramofon', a mnoga 'gramofoni'. Tak, więc: |
||
<pre> |
<pre> |
||
<pardef n="gramofon__n"> |
<pardef n="gramofon__n"> |
||
Line 142: | Line 134: | ||
</pardef> |
</pardef> |
||
</pre> |
</pre> |
||
Uwaga: '<l/>' ( |
Uwaga: '<l/>' (równoznaczne z <l></l>) oznacza, że nie ma żadnych dodatkowych znaków dołączanych do rdzenia rzeczownika w 1-szej liczbie pojedynczej. |
||
Może to wyglądać na dość |
Może to wyglądać na dość zawiłą drogą opisywania tak prostych rzeczy, lecz zaowocuje to w przyszłości. |
||
Prawdopodobnie zastanawiasz się, co oznaczają tagi <e>, <p>, <l> i <r>. A więc: |
|||
* e, jest |
* e, jest słowem początkowym. |
||
* p, jest dla |
* p, jest dla pary. |
||
* l, jest z lewej strony. |
* l, jest z lewej strony. |
||
* r, jest z prawej strony. |
* r, jest z prawej strony. |
||
Dlaczego z lewej i prawej? |
Dlaczego z lewej i prawej? Cóż, słowniki morfologiczne zostaną później skompilowane do finalnej postaci. Kompilowanie ich od lewej do prawej powoduje analizę słów, a kompilowanie od prawej do lewej - słowa analizy. Na przykład: |
||
<pre> |
<pre> |
||
* gramofoni (od lewej do prawej) gramofon<n><pl> (analiza) |
* gramofoni (od lewej do prawej) gramofon<n><pl> (analiza) |
||
* gramofon<n><pl> (od prawej do lewej) gramofoni (generowanie) |
* gramofon<n><pl> (od prawej do lewej) gramofoni (generowanie) |
||
</pre> |
</pre> |
||
Zdefiniowaliśmy, zatem paradygmat, teraz musimy połączyć go z odpowiadającą lemmą, czyli w tym przypadku "gramofon". Umieścimy to w sekcji, którą przed chwilą zdefiniowaliśmy. |
|||
Słowo początkowe, które umieścimy w <section>, powinno wyglądać tak: |
|||
<pre> |
<pre> |
||
<e lm="gramofon"><i>gramofon</i><par n="gramofon__n"/></e> |
<e lm="gramofon"><i>gramofon</i><par n="gramofon__n"/></e> |
||
</pre> |
</pre> |
||
Krótkie objaśnienie: |
Krótkie objaśnienie: |
||
* lm oznacza lemmy. |
|||
* i odnosi się do tożsamości (lewa i prawa strona taka sama). |
|||
* par oznacza paradygmat. |
|||
Ten wpis stanowi lemma słowa gramofon, korzeń (root) słowa gramofon i paradygmat, który odmienia się za pomocą gramofon_n. Różnica pomiędzy lemmą a korzeniem, jest taka, że lemma jest formą podstawową słowa, podczas gdy korzeń jest fragmentem lemmy. Wyjaśni się to później, gdy wejścia będą różne. |
|||
* lm, jest dla lemmy. |
|||
* i, jest dla toższamości (lewa i prawa strona taka sama). |
|||
* par, jest dla parygmatu. |
|||
Jesteśmy już gotowi do przetestowania słownika. Zapisz plik a następnie powróć do powłoki (shell). Najpierw musimy skompilować nasz plik (za pomocą lt-comp) a następnie przetestować (używając, lt-proc) |
|||
Ten wpis stanowi lemma słowa, gramofon, korzeń (root), gramofon i paradygmat który odmienia się za pomocą gramofon_n. Różnica pomiędzy lemmą a korzeniem, jest to że lemma jest podstawową formą słowa, podczas gdy korzeń jest fragmentem lemmy. Stanie się to jaśniejsze później, gdy wejscia będą różne. |
|||
Teraz jesteśmy gotowi do przetestowania słownika. Zapisz plik a następnie powróć do powłoki (shell). Pierw musimy skompilować naszą prace (za pomocą lt-comp), następnie przetestujemy (dzięki lt-proc) |
|||
<pre> |
<pre> |
||
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin |
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin |
||
</pre> |
</pre> |
||
Powinno |
Powinno zwrócić: |
||
<pre> |
<pre> |
||
main@standard 12 12 |
main@standard 12 12 |
||
</pre> |
</pre> |
||
Kompilując kod od lewej do prawej, produkujemy analizer. Spróbujmy stworzyć też generator: |
|||
<pre> |
<pre> |
||
$ lt-comp rl apertium-sh-en.sh.dix sh-en.autogen.bin |
$ lt-comp rl apertium-sh-en.sh.dix sh-en.autogen.bin |
||
</pre> |
</pre> |
||
Na tym |
Na tym etapie komenda powinna zwrócić ten sam rezultat. |
||
Teraz możemy |
Teraz możemy je przetestować. Uruchom lt-proc na analizatorze. |
||
<pre> |
<pre> |
||
$ lt-proc sh-en.automorf.bin |
$ lt-proc sh-en.automorf.bin |
||
</pre> |
</pre> |
||
Wpisz gramofoni (gramofony), a na wyjściu |
Wpisz gramofoni (gramofony), a na wyjściu powinien ukazać się: |
||
<pre> |
<pre> |
||
^gramofoni/gramofon<n><pl>$ |
^gramofoni/gramofon<n><pl>$ |
||
</pre> |
</pre> |
||
Teraz, dla słownika Angielskiego, wykonaj te same kroki, lecz zamień słowo gramofon na jego angielski |
Teraz, dla słownika Angielskiego, wykonaj te same kroki, lecz zamień słowo gramofon na jego angielski odpowiednik (gramophone) pamiętając o prawidłowej odmianę. |
||
Co w |
Co w przypadku gdybyś chciał użyć słowa 'record player'? To wyjaśnimy sobie później. |
||
Powinneś mieć juz dwa pliki w katalogu: |
|||
Powinniśmy na tym etapie dysponować dwoma plikami w katalogu: |
|||
* apertium-sh-en.sh.dix który zawiera (bardzo) prosty słownik Serbsko-Chorwacki, i |
|||
* apertium-sh-en. |
* apertium-sh-en.sh.dix który zawiera prosty słownik Serbsko-Chorwacki, oraz |
||
* apertium-sh-en.en.dix który zawiera prosty słownik Angielski. |
|||
===Słownik dwujęzyczny=== |
===Słownik dwujęzyczny=== |
||
A więc mamy dwa |
A więc mamy dwa morfologiczne słowniki, następnym krokiem jest stworzenie dwujęzycznego słownika. Będzie on opisywać zależności pomiędzy słowami. Wszystkie słowniki mają ten sam format, (który określony jest w DTD, dix.dtd). |
||
Stwórz nowy plik, apertium-sh-en.sh-en.dix i |
Stwórz nowy plik, apertium-sh-en.sh-en.dix i dodaj podstawowy szkielet, na którym będziemy się opierać: |
||
<pre> |
<pre> |
||
<?xml version="1.0" encoding="UTF-8"?> |
<?xml version="1.0" encoding="UTF-8"?> |
||
Line 219: | Line 213: | ||
</dictionary> |
</dictionary> |
||
</pre> |
</pre> |
||
Teraz musimy dodać wpis do translacji pomiędzy dwoma słowami. Wygląda to tak: |
Teraz musimy dodać wpis służący do translacji pomiędzy dwoma słowami. Wygląda to tak: |
||
<pre> |
<pre> |
||
<e><p><l>gramofon<s n="n"/></l><r>gramophone<s n="n"/></r></p></e> |
<e><p><l>gramofon<s n="n"/></l><r>gramophone<s n="n"/></r></p></e> |
||
</pre> |
</pre> |
||
Ponieważ często zdarza się, że takich wpisów jest bardzo dużo, są one najczęściej pisane w jednej linii, w celu polepszenia czytelności kodu. Pamiętając o 'l' oraz 'r' oczywiście. Tym razem kompilujemy plik od lewej do prawej by utworzyć translator Serbsko-chorwacko → Angielski, a kompilowanie od prawej do lewej spowodowałoby utworzenie Angielsko → Serbsko-chorwackiego słownika. |
|||
Because there are a lot of these entries, they're typically written on one line to facilitate easier reading of the file. Again with the 'l' and 'r' right? Well, we compile it left to right to produce the Serbo-Croatian → English dictionary, and right to left to produce the English → Serbo-Croatian dictionary. |
|||
Następnym krokiem jest uruchomienie poniższych komend: |
|||
Gdy to skończysz, uruchom poniższe komendy: |
|||
<pre> |
<pre> |
||
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin |
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin |
||
Line 236: | Line 230: | ||
$ lt-comp rl apertium-sh-en.sh-en.dix en-sh.autobil.bin |
$ lt-comp rl apertium-sh-en.sh-en.dix en-sh.autobil.bin |
||
</pre> |
</pre> |
||
Na potrzeby generowania analizatorów morfologicznych (automorf), generatorów (autogen) oraz tłumaczeń słów (autobil), bil będzie oznaczać "dwujęzyczny". |
|||
=== |
===Zasady Transferu=== |
||
Więc, mamy dwa jednojęzyczne słowniki, oraz jeden dwujęzyczny. |
Więc, mamy dwa jednojęzyczne słowniki, oraz jeden dwujęzyczny. Jedyne, czego teraz potrzebujemy to zaimplementowanie zasad dla rzeczowników. Pliki tego typu posiadają własne DTD (transfer.dtd) znajdującym się w pakiecie Apertium. Gdy zaistnieje potrzeba zaimplementowania jakiejś zasady pomocnym krokiem jest spojrzenie na sposób, w jaki zostało to zaimplementowane w innych plikach językowych. Wiele z nich ma to do siebie, że mogą być użyte ponownie w translacji różnych języków. Przykład opisany poniżej może być używany dla wszystkich języków z domyślnym podmiotem. |
||
Zacznijmy podobnie jak w poprzednich przykładach, |
Zacznijmy podobnie jak w poprzednich przykładach, wykonując szkielet: |
||
<pre> |
<pre> |
||
<?xml version="1.0" encoding="UTF-8"?> |
<?xml version="1.0" encoding="UTF-8"?> |
||
Line 249: | Line 243: | ||
</transfer> |
</transfer> |
||
</pre> |
</pre> |
||
At the moment, because we're ignoring case, we just need to make a rule that takes the grammatical symbols input and outputs them again. |
|||
W tym momencie musimy jedynie stworzyć zasadę, która będzie brała symbole gramatyczne i przesyłała je z powrotem. |
|||
Pierw musimy zdefinować kategorie oraz atrybuty. Obydwie będą używane do grupowania symboli gramatycznych. Kategorie pozwalają nam do grupowania symboli które pasują do pewnego wzorca (dla przykładu 'n.*' dla wszystkich rzeczowników). Atrybuty z koleji zbiór grup symboli z którch możemy wybierać. |
|||
Najpierw musimy zdefiniować kategorie oraz atrybuty. Obydwa fragmenty będą używane do grupowania symboli gramatycznych. Kategorie pozwalają nam na grupowanie symboli, które pasują do pewnego wzorca (dla przykładu 'n.*' dla wszystkich rzeczowników). Atrybuty z kolei utworzą grupę symboli, z których będziemy mogli w przyszłości korzystać. |
|||
Dodajmy |
Dodajmy wiec niezbędne sekcje: |
||
<pre> |
<pre> |
||
<section-def-cats> |
<section-def-cats> |
||
Line 262: | Line 257: | ||
</section-def-attrs> |
</section-def-attrs> |
||
</pre> |
</pre> |
||
Ponieważ odmieniamy jedynie rzeczowniki w liczbie pojedynczej i mnogiej to potrzebujemy dodać osobną kategorię dla rzeczowników, razem z atrybutem liczby. Coś takiego powinno wystarczyć: |
|||
W section-def-cats dodaj: |
W section-def-cats dodaj: |
||
Line 270: | Line 265: | ||
</def-cat> |
</def-cat> |
||
</pre> |
</pre> |
||
Ten fragment kodu wyłapuje wszystkie rzeczowniki (lemmy i następujące po nich <n>), i odnosi się do nich, jako "nom"y (później zobaczymy jak tego używać). |
|||
W sekcji section-def-attrs, dodaj: |
W sekcji section-def-attrs, dodaj: |
||
Line 285: | Line 280: | ||
</def-attr> |
</def-attr> |
||
</pre> |
</pre> |
||
Pierwsza |
Pierwsza dodaje atrybut "nbr" (liczbę), która może być liczbą pojedynczą (sg) lub mnogą pl). |
||
Druga definiuje atrybut a_nom (atrybut rzeczownika). |
Druga definiuje atrybut a_nom (atrybut rzeczownika). |
||
Line 295: | Line 290: | ||
</section-def-vars> |
</section-def-vars> |
||
</pre> |
</pre> |
||
Te zmienne będą używane do przechowywania lub przenoszenia |
Te zmienne będą używane do przechowywania lub przenoszenia atrybutów pomiędzy zasadami. Na razie wystarczy nam tylko jedna zmienna |
||
<pre> |
<pre> |
||
<def-var n="number"/> |
<def-var n="number"/> |
||
</pre> |
</pre> |
||
Na koniec musimy dodać zasadę, która pobierze rzeczownik i zwróci go w odpowiedniej formie. Musimy zatem dodać sekcję zasad... |
|||
<pre> |
<pre> |
||
<section-rules> |
<section-rules> |
||
Line 305: | Line 300: | ||
</section-rules> |
</section-rules> |
||
</pre> |
</pre> |
||
Zwiększymy trochę tempo, najpierw wklejając poniższy kod a dopiero potem go omawiając. |
|||
Przyśpieszmy trochę. Po prostu dodaj poniższą zasadę, a następnie przejdź dalej. |
|||
<pre> |
<pre> |
||
<rule> |
<rule> |
||
Line 323: | Line 318: | ||
</pre> |
</pre> |
||
Pierwszy tag jest oczywisty, definiuje zasadę. Drugi mówi: "zastosują tą zasadę, |
Pierwszy tag jest oczywisty, po prostu definiuje zasadę. Drugi mówi: "zastosują tą zasadę, jeżeli pasuje do wzorca". W tym przykładzie wzorzec składa się z pojedynczego rzeczownika (zdefiniowany przez kategorię "nom"). Zwróć uwagę, że wzorce są dostosowywane w kolejności od najdłuższego pasującego. Więc jeśli masz trzy zasady: pierwszą łapiącą "<prn><vblex><n>", drugą łapiącą "<prn><vblex>" i trzecią łapiącą "<n>", pierwszą zastosowaną regułą będzie właśnie reguła pierwsza. |
||
Dla każdego wzorca |
Dla każdego wzorca jest odpowiadająca jej akcja, która tworzy odpowiadający wynik na wyjściu będący jednostką leksykalną (lu). |
||
Zaciskające tagi (clip tags) pozwalają użytkownikowi na wybranie i manipulowanie na atrybutach i elementach języka źródłowego (side="sl") lub docelowego (side="tl") elementu leksykalnego. |
|||
Spróbujmy więc to skompilować i przetestować. Zasady transferu kompilujemy za pomocą: |
|||
Pominięte tagi pozwalają użytkownikowi do wybrania i manipulowania na atrybutach i elementach języka źródłowego (side="sl") lub docelowego (side="tl") elementu leksykalnego. |
|||
Skompilujmy i przetestujmy więc to. Zasady transferu kompilujemy za pomocą: |
|||
<pre> |
<pre> |
||
$ apertium-preprocess-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin |
$ apertium-preprocess-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin |
||
Line 335: | Line 329: | ||
Które powinno wygenerować plik <code>sh-en.t1x.bin</code>. |
Które powinno wygenerować plik <code>sh-en.t1x.bin</code>. |
||
Jesteśmy już gotowi do przystąpienia to fazy testowania. Pominęliśmy jednak bardzo ważną część kodu, a mianowicie tagger part-of-speech (PoS), jednak omówimy to później. Na razie możemy przetestować to, co mamy. |
|||
Najpierw zanalizujmy słowo gramofoni: |
|||
<pre> |
<pre> |
||
$ echo "gramofoni" | lt-proc sh-en.automorf.bin |
$ echo "gramofoni" | lt-proc sh-en.automorf.bin |
||
^gramofon/gramofon<n><pl>$ |
^gramofon/gramofon<n><pl>$ |
||
</pre> |
</pre> |
||
W normalnych warunkach tagger PoS powinien wybrać prawidłową wersję analizując część mowy, jednak ponieważ go nie zaimplementowaliśmy, użyjemy tego skryptu (podziękowania dla Sergio), który powinien zwrócić tylko odpowiednią wersje. |
|||
<pre> |
<pre> |
||
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \ |
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \ |
||
Line 348: | Line 342: | ||
^gramofon<n><pl>$ |
^gramofon<n><pl>$ |
||
</pre> |
</pre> |
||
Wykorzystamy to razem z zasadami transferu: |
|||
<pre> |
<pre> |
||
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \ |
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \ |
||
Line 362: | Line 356: | ||
* '<pl>' jest atrybutem numeru (nbr) na pozycji pierwszej w języku docelowym. |
* '<pl>' jest atrybutem numeru (nbr) na pozycji pierwszej w języku docelowym. |
||
Spróbuj |
Spróbuj zamienić jedną z zasad na komentarz, skompilować i zobaczyć co się stanie. |
||
Mamy teraz rezultat z wyjścia, ostatnią rzeczą jaką musimy się zająć jest wygenerowanie odmienionych form języka docelowego. Do wykonania tej czynności użyjemy lt-proc, w rybie generacji (-g), a nie w trybie analizy (-a). |
|||
So, now we have the output from the transfer, the only thing that remains is to generate the target-language inflected forms. For this, we use lt-proc, but in generation (-g), not analysis mode. |
|||
<pre> |
<pre> |
||
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \ |
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \ |
||
Line 373: | Line 367: | ||
gramophones\@ |
gramophones\@ |
||
</pre> |
</pre> |
||
And c'est ca. You now have a machine translation system that translates a Serbo-Croatian noun into an English noun. Obviously this isn't very useful, but we'll get onto the more complex stuff soon. Oh, and don't worry about the '@' symbol, I'll explain that soon too. |
|||
Masz teraz przed sobą system tłumaczenia maszynowego, który tłumaczy rzeczownik w języku serbsko-chorwackim na rzeczownik angielski. Oczywiście nie jest to szczególnie przydatne, ale niedługo przejdziemy do bardziej skomplikowanych rzeczy. Nie przejmuj się symbolem '@', później wyjaśnimy sobie do czego służy i jak go używać. |
|||
Think of a few other words that inflect the same as gramofon. How about adding those. We don't need to add any paradigms, just the entries in the main section of the monolingual and bilingual dictionaries. |
|||
Pomyśl o kilku innych przykładach rzeczowników, odmieniających się w ten sam sposób co rzeczownik gramofon. Spróbuj dodać je do słownika. Nie musimy dodawać żadnych paradygmatów, wystarczy tylko dodać wpisy w głównych sekcjach słownika jednojęzycznego i dwujęzycznego. |
|||
==Bring on the verbs== |
|||
==Pora na czasowniki== |
|||
Ok, so we have a system that translates nouns, but thats pretty useless, we want to translate verbs too, and even whole sentences! How about we start with the verb to see. In Serbo-Croatian this is videti. Serbo-Croatian is a null-subject language, this means that it doesn't typically use personal pronouns before the conjugated form of the verb. English is not. So for example: I see in English would be translated as vidim in Serbo-Croatian. |
|||
Ok, mamy system, który tłumaczy nam rzeczowniki, ale jest to trochę bezużyteczne, chcemy też przecież tłumaczyć czasowniki, a nawet całe zdania! Może na początek zacznijmy od tłumaczenia czasowników. W języku serbsko-chorwackim czasownik nazywa się videti. |
|||
Język serbsko-chorwacki jest językiem nie-tematycznym, co oznacza, iż zwykle nie stosuje zaimków poprzedzających odmienioną formę czasownika. Angielski taki nie jest. Na ten przykład: "I see" (ja widzę) w języku angielskim zostałoby przetłumaczone na "vidim" w języku Serbsko-Chorwackim. |
|||
* Vidim |
* Vidim |
||
Line 385: | Line 382: | ||
* I see |
* I see |
||
Uwaga: <code><p1></code> oznacza pierwszą osobę |
|||
Okaże się to ważne, w momencie, gdy zaczniemy pisać zasady transferu dla czasowników. Inne przykłady języków nie-tematycznych obejmują: Hiszpański, Rumuński i Polski. Wynika to także z tego, że, gdy w serbsko-chorwackim słowniku morfologicznym musimy dodać tylko czasownik, w angielskim słowniku morfologicznym musimy dodać czasownik i zaimek osobowy. Przeanalizujemy oba sposoby. |
|||
This will be important when we come to write the transfer rule for verbs. Other examples of null-subject languages include: Spanish, Romanian and Polish. This also has the effect that while we only need to add the verb in the Serbo-Croatian morphological dictionary, we need to add both the verb, and the personal pronouns in the English morphological dictionary. We'll go through both of these. |
|||
Inne formy czasownika "videti" to: vidiš, vidi, vidimo, vidite, and vide; które odpowiadają: you see (singular), he sees, we see, you see (plural), oraz they see. |
|||
Istnieją dwie formy "you see", jedna jest w liczbie mnogiej oraz formalnej pojedynczej (vidite) oraz druga tylko w nieformalnej pojedynczej (vidiš). |
|||
Spróbujemy przetłumaczyć następujące zdanie: "Vidim gramofoni" na "I see gramophones". W poszanowaniu miejsca, dodamy po prostu wystarczającą ilość informacji do tłumaczenia i pozostawimy wypełnianie paradygmatów (dodanie spójników do czasownika), jako ćwiczenia. |
|||
We're going to try and translate the sentence: "Vidim gramofoni" into "I see gramophones". In the interests of space, we'll just add enough information to do the translation and will leave filling out the paradigms (adding the other conjugations of the verb) as an exercise to the reader. |
|||
Bystry czytelnik najprawdopodobniej już zauważył, że nie możemy po prostu przetłumaczyć "vidim gramofoni”, ponieważ nie jest to zdanie poprawne gramatycznie w języku Serbsko-Chorwackim. Poprawnie brzmiałoby ono vidim gramofone, jako, iż rzeczownik jest w bierniku. Będziemy musieli dodać również i tą formę, aczkolwiek nie ma potrzeby dodawania informacji o przypadku, po prostu dodamy dodatkową opcję dla liczby mnogiej. Przepisz zatem fragment zawierający 'e' dla 'i' oraz zamień 'i' na 'e'. |
|||
The astute reader will have realised by this point that we can't just translate vidim gramofoni because it is not a grammatically correct sentence in Serbo-Croatian. The correct sentence would be vidim gramofone, as the noun takes the accusative case. We'll have to add that form too, no need to add the case information for now though, we just add it as another option for plural. So, just copy the 'e' block for 'i' and change the 'i' to 'e' there. |
|||
Pierwszą rzeczą którą musimy zrobić jest dodanie symboli. Najpierw musimy dodać symbol dla 'verb', który będziemy od tej pory nazywać "vblex" (co znaczy czasownik leksykalny, przeciwnie do czasowników modalnych czy innych typów). Czasowniki mają 'person' (osobę), oraz 'tense' (czas) jak również liczbę, więc dodajmy kilka z nich. Musimy przetłumaczyć "I see", więc dla osoby powinniśmy dodać "p1", lub 'first person', a dla czasu "pri", albo 'present indicative'. |
|||
<pre> |
<pre> |
||
<sdef n="vblex"/> |
<sdef n="vblex"/> |
||
Line 403: | Line 401: | ||
<sdef n="pri"/> |
<sdef n="pri"/> |
||
</pre> |
</pre> |
||
Gdy to zrobimy, również z rzeczownikami, dodamy paradygmat lub koniugację czasownika. Pierwsza linijka powinna wyglądać następująco: |
|||
After we've done this, the same with the nouns, we add a paradigm for the verb conjugation. The first line will be: |
|||
<pre> |
<pre> |
||
<pardef n="vid/eti__vblex"> |
<pardef n="vid/eti__vblex"> |
||
</pre> |
</pre> |
||
Symbol '/' jest użyty w celu wytyczenia granicy gdzie łodygi (fragmenty pomiędzy tagami <l> i </l>) są również pododawane. |
|||
Następnie odmiana pierwszej osoby liczby pojedyńczej: |
|||
Then the inflection for first person singular: |
|||
<pre> |
<pre> |
||
Line 415: | Line 413: | ||
</pre> |
</pre> |
||
'im' oznacza koniec (jak w 'vidim'), jest on potrzebny w celu dodania 'eti' do sekcji <r>, jako że zostanie odcięty z definicji. Reszta jest stosunkowo prosta: 'vblex' jest czasownikiem leksykalnym, 'pri' jest czasem orientacyjnym, 'p1' to pierwsza osoba a 'sg' jest liczbą pojedyńczą. Możemy również dodać liczbę mnogą która byłaby taka sama, za wyjątkiem 'imo' zamiast 'im' i 'pl' zamiast 'sg'. |
|||
Następnie musimy dodać lemmę, oraz paradygmat do głównej sekcji: |
|||
After this we need to add a lemma, paradigm mapping to the main section: |
|||
<pre> |
<pre> |
||
<e lm="videti"><i>vid</i><par n="vid/eti__vblex"/></e> |
<e lm="videti"><i>vid</i><par n="vid/eti__vblex"/></e> |
||
</pre> |
</pre> |
||
Uwaga: zawartość <nowiki><i> </i></nowiki> jest korzeniem (rootem), a nie lemmą. |
|||
To część pracy jaką wykona dla nas translator Serbsko-Chorwacki. Skompilujmy oraz przetestujmy kod. |
|||
Thats the work on the Serbo-Croatian dictionary done for now. Lets compile it then test it. |
|||
<pre> |
<pre> |
||
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin |
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin |
||
Line 432: | Line 430: | ||
^vidimo/videti<vblex><pri><p1><pl>$ |
^vidimo/videti<vblex><pri><p1><pl>$ |
||
</pre> |
</pre> |
||
Teraz musimy zrobić to samo dla angielskiego słownika (pamiętaj o dodaniu tego samego symbolu definicji, tak samo jak dodaliśmy do Serbsko-Chorwackiego). |
|||
Ok, so now we do the same for the English dictionary (remember to add the same symbol definitions here as you added to the Serbo-Croatian one). |
|||
Paradygmatem w tym przypadku będzie: |
|||
The paradigm is: |
|||
<pre> |
<pre> |
||
<pardef n="s/ee__vblex"> |
<pardef n="s/ee__vblex"> |
||
</pre> |
</pre> |
||
ponieważ czas przeszły to 'saw'. Teraz możemy wykonać jedną z dwóch rzeczy - możemy dodać pierwszą i drugą osobę, ale w tej samej formie. Tak na prawdę, wszystkie formy (za wyjątkiem trzeciej osoby liczby pojedyńczej) czasownika 'to see' są równoznaczne 'see'. Więc zamiast tego dodamy tylko jedną linię kodu dla 'see' i dodamy jedynie symbol 'pri'. |
|||
<pre> |
<pre> |
||
Line 444: | Line 442: | ||
</pre> |
</pre> |
||
oraz, jak zwykle, wpis w głównej sekcji: |
|||
and as always, an entry in the main section: |
|||
<pre> |
<pre> |
||
<e lm="see"><i>s</i><par n="s/ee__vblex"/></e> |
<e lm="see"><i>s</i><par n="s/ee__vblex"/></e> |
||
</pre> |
</pre> |
||
Potem skompilujmy i przetestujmy kod: |
|||
Then lets save, recompile and test: |
|||
<pre> |
<pre> |
||
$ lt-comp lr apertium-sh-en.en.dix en-sh.automorf.bin |
$ lt-comp lr apertium-sh-en.en.dix en-sh.automorf.bin |
||
Line 456: | Line 454: | ||
^see/see<vblex><pri>$ |
^see/see<vblex><pri>$ |
||
</pre> |
</pre> |
||
Teraz kolej na obowiązkowy wpis w dwujęzycznym słowniku: |
|||
Now for the obligatory entry in the bilingual dictionary: |
|||
<pre> |
<pre> |
||
<e><p><l>videti<s n="vblex"/></l><r>see<s n="vblex"/></r></p></e> |
<e><p><l>videti<s n="vblex"/></l><r>see<s n="vblex"/></r></p></e> |
||
</pre> |
</pre> |
||
(nie zapomnij o dodaniu sdef'ów do wpisów) |
|||
(again, don't forget to add the sdefs from earlier) |
|||
Oraz re-kompilacja: |
|||
And recompile: |
|||
<pre> |
<pre> |
||
$ lt-comp lr apertium-sh-en.sh-en.dix sh-en.autobil.bin |
$ lt-comp lr apertium-sh-en.sh-en.dix sh-en.autobil.bin |
||
Line 469: | Line 467: | ||
main@standard 18 18 |
main@standard 18 18 |
||
</pre> |
</pre> |
||
Teraz pora na test: |
|||
<pre> |
<pre> |
||
$ echo "vidim" | lt-proc sh-en.automorf.bin | \ |
$ echo "vidim" | lt-proc sh-en.automorf.bin | \ |
||
Line 477: | Line 475: | ||
^see<vblex><pri><p1><sg>$^@ |
^see<vblex><pri><p1><sg>$^@ |
||
</pre> |
</pre> |
||
Widzimy że analiza wypadła pomyślnie, ale kiedy próbujemy wygenerować z tego "powierzchnię", otrzymujemy '#', jak poniżej: |
|||
We get the analysis passed through correctly, but when we try and generate a surface form from this, we get a '#', like below: |
|||
<pre> |
<pre> |
||
$ echo "vidim" | lt-proc sh-en.automorf.bin | \ |
$ echo "vidim" | lt-proc sh-en.automorf.bin | \ |
||
Line 485: | Line 483: | ||
#see\@ |
#see\@ |
||
</pre> |
</pre> |
||
Symbol '#' oznacza, że generato nie może utworzyć poprawnej formy leksykalnej czasownika ponieważ jej nie posiada. Dlaczego? |
|||
This '#' means that the generator cannot generate the correct lexical form because it does not contain it. Why is this? |
|||
Krótko mówiąc, analizy nie są ze sobą zgodne, 'see' w słowniku oznacza see<vblex><pri>, a to dostarczone przez transfer oznacza see<vblex><pri><p1><sg>. Serbsko-Chorwacka strona posiada więcej informacji niż tego wymaga strona angielska. Możesz to sprawdzić, dodając brakujące symbole do angielskiego słownika, rekompilując, i testując ponownie. |
|||
Jednakże, bardziej paradygmatycznym wyjściem z tej sytuacji jest napisanie zasady. Otwieramy więc plik zasad: (<code>apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin</code> gdybyś zapomniał) |
|||
Musimy dodać nową kategorię dla czasowników ('verb'). |
|||
<pre> |
<pre> |
||
<def-cat n="vrb"> |
<def-cat n="vrb"> |
||
Line 497: | Line 495: | ||
</def-cat> |
</def-cat> |
||
</pre> |
</pre> |
||
usimy również dodać atrybuty dla czasu i osoby. Zrobimy to w bardzo prosty sposób, możesz dodać p2 i p3, ale w tym przypadku to pominiemy by zaoszczędzić miejsce: |
|||
We also need to add attributes for tense and for person. We'll make it really simple for now, you can add p2 and p3, but I won't in order to save space. |
|||
<pre> |
<pre> |
||
<def-attr n="temps"> |
<def-attr n="temps"> |
||
Line 507: | Line 505: | ||
</def-attr> |
</def-attr> |
||
</pre> |
</pre> |
||
Powinniśmy również dodać atrybut dla czasowników: |
|||
We should also add an attribute for verbs. |
|||
<pre> |
<pre> |
||
<def-attr n="a_verb"> |
<def-attr n="a_verb"> |
||
Line 513: | Line 511: | ||
</def-attr> |
</def-attr> |
||
</pre> |
</pre> |
||
Teraz sama zasada: |
|||
Now onto the rule: |
|||
<pre> |
<pre> |
||
<rule> |
<rule> |
||
Line 530: | Line 528: | ||
</rule> |
</rule> |
||
</pre> |
</pre> |
||
Pamiętasz, gdy ująłeś fragment zawierający zaciskające (clip) tagi w komentarz w poprzednim przykładzie zasad i gdy znikły one z transferu? Cóż, to praktycznie to samo co próbujemy zaimplementować teraz. Poddajemy czasownik pełnej analizie ale zwracamy tylko część analizy (lemme + tag czasownika + tag czasu). |
|||
Remember when you tried commenting out the 'clip' tags in the previous rule example and they disappeared from the transfer, well, thats pretty much what we're doing here. We take in a verb with a full analysis, but only output a partial analysis (lemma + verb tag + tense tag). |
|||
Gdy zrekompilujemy kod, otrzymamy: |
|||
So now, if we recompile that, we get: |
|||
<pre> |
<pre> |
||
$ echo "vidim" | lt-proc sh-en.automorf.bin | \ |
$ echo "vidim" | lt-proc sh-en.automorf.bin | \ |
||
Line 539: | Line 537: | ||
^see<vblex><pri>$^@ |
^see<vblex><pri>$^@ |
||
</pre> |
</pre> |
||
oraz: |
|||
and: |
|||
<pre> |
<pre> |
||
$ echo "vidim" | lt-proc sh-en.automorf.bin | \ |
$ echo "vidim" | lt-proc sh-en.automorf.bin | \ |
||
Line 547: | Line 545: | ||
see\@ |
see\@ |
||
</pre> |
</pre> |
||
Wypróbuj to używając 'vidimo' (we see) by zobaczyć czy otrzymujemy poprawny wynik. |
|||
Teraz spróbuj tego samego z użyciem "vidim gramofone": |
|||
<pre> |
<pre> |
||
$ echo "vidim gramofoni" | lt-proc sh-en.automorf.bin | \ |
$ echo "vidim gramofoni" | lt-proc sh-en.automorf.bin | \ |
||
Line 558: | Line 556: | ||
</pre> |
</pre> |
||
== |
==A co z zaimkami?== |
||
Jest fajnie, ale ciągle nie mamy osobowych zaimków, które są potrzebne w języku angielskim. W celu ich dodaniu, najpierw potrzebujemy wyedytować angielski słownik morfologiczny. |
|||
Well, thats great, but we're still missing the personal pronoun that is necessary in English. In order to add it in, we first need to edit the English morphological dictionary. |
|||
Jak przedtem, pierwszym krokiem jest dodanie symboli: |
|||
As before, the first thing to do is add the necessary symbols: |
|||
<pre> |
<pre> |
||
<sdef n="prn"/> |
<sdef n="prn"/> |
||
<sdef n="subj"/> |
<sdef n="subj"/> |
||
</pre> |
</pre> |
||
W tym przypadku, prn jest zaimkiem, a subj jest podmiotem (tak jak podmiot w zdaniu). |
|||
Ponieważ nie ma tutaj rdzenia (roota), ani 'lemmy' dla osobowego podmiotu zaimka, po prostu dodajemy pardef tak jak poniżej: |
|||
<pre> |
<pre> |
||
<pardef n="prsubj__prn"> |
<pardef n="prsubj__prn"> |
||
Line 575: | Line 573: | ||
</pardef> |
</pardef> |
||
</pre> |
</pre> |
||
gdzie 'prsubj' jest 'podmiotem osobowym' (personal subject). Reszta (You, We itd.) zostaje, jako ćwiczenie dla czytelnika. |
|||
Możemy dodać wpis do głównej sekcji, tak jak poniżej: |
|||
We can add an entry to the main section as follows: |
|||
<pre> |
<pre> |
||
<e lm="personal subject pronouns"><i/><par n="prsubj__prn"/></e> |
<e lm="personal subject pronouns"><i/><par n="prsubj__prn"/></e> |
||
</pre> |
</pre> |
||
Zapiszmy, skompilujmy i przetestujmy kod. Powinniśmy otrzymać coś takiego: |
|||
So, save, recompile and test, and we should get something like: |
|||
<pre> |
<pre> |
||
$ echo "I" | lt-proc en-sh.automorf.bin |
$ echo "I" | lt-proc en-sh.automorf.bin |
||
Line 587: | Line 585: | ||
</pre> |
</pre> |
||
(Uwaga: wynik jest wypisany drukowanymi literami, ponieważ 'I' jest drukowane). |
|||
(Note: it's in capitals because 'I' is in capitals). |
|||
Teraz musimy poprawić regułę dla czasownika ('verb') by otrzymać osobowy podmiot zaimka razem z poprawną formą czasownika. |
|||
Now we need to amend the 'verb' rule to output the subject personal pronoun along with the correct verb form. |
|||
Najpierw, dodajmy kategorię: |
|||
First, add a category (this must be getting pretty pedestrian by now): |
|||
<pre> |
<pre> |
||
<def-cat n="prpers"> |
<def-cat n="prpers"> |
||
Line 597: | Line 595: | ||
</def-cat> |
</def-cat> |
||
</pre> |
</pre> |
||
Teraz, dodajmy typy zaimków, jako atrybuty, możemy też dodać typ 'obj’, jako, że przy nim jesteśmy, aczkolwiek nie będziemy go teraz potrzebować: |
|||
Now add the types of pronoun as attributes, we might as well add the 'obj' type as we're at it, although we won't need to use it for now: |
|||
<pre> |
<pre> |
||
<def-attr n="tipus_prn"> |
<def-attr n="tipus_prn"> |
||
Line 604: | Line 602: | ||
</def-attr> |
</def-attr> |
||
</pre> |
</pre> |
||
A teraz, by wczytać regułę: |
|||
And now to input the rule: |
|||
<pre> |
<pre> |
||
<rule> |
<rule> |
||
Line 629: | Line 627: | ||
</rule> |
</rule> |
||
</pre> |
</pre> |
||
Jest to praktycznie ta sama reguła co wcześniej, dodaliśmy tylko kilka niewielkich poprawek. |
|||
This is pretty much the same rule as before, only we made a couple of small changes. |
|||
Potrzebowaliśmy wyniku: |
|||
We needed to output: |
|||
<pre> |
<pre> |
||
^prpers<prn><subj><p1><sg>$ ^see<vblex><pri>$ |
^prpers<prn><subj><p1><sg>$ ^see<vblex><pri>$ |
||
</pre> |
</pre> |
||
by generator mógł wybrać prawidłowy zaimek i prawidłową formę czasownika. |
|||
so that the generator could choose the right pronoun and the right form of the verb. |
|||
Więc, krótkie podsumowanie: |
|||
So, a quick rundown: |
|||
* <code><lit></code>, |
* <code><lit></code>, wypisuje ciąg literowy, w tym przypadku "prpers" |
||
* <code><lit-tag></code>, |
* <code><lit-tag></code>, wypisuje tag literowy, ponieważ nie możemy otrzymać tagu z czasownika dodamy go ręcznie, "prn" dla zaimka, a "subj" dla podmiotu. |
||
* <code><b/></code> |
* <code><b/></code> wypisuje spację (pusty znak). |
||
Zwróć uwagę, że otrzymaliśmy liczbę oraz czas wprost z czasownika. |
|||
Note that we retrieved the information for number and tense directly from the verb. |
|||
Więc teraz, jeśli skompilujemy i przetestujemy znowu, otrzymujemy: |
|||
So, now if we recompile and test that again: |
|||
<pre> |
<pre> |
||
$ echo "vidim gramofone" | lt-proc sh-en.automorf.bin | \ |
$ echo "vidim gramofone" | lt-proc sh-en.automorf.bin | \ |
||
Line 653: | Line 650: | ||
I see gramophones |
I see gramophones |
||
</pre> |
</pre> |
||
które (pomijając długo oczekiwany, końcowy rezultat), jest stosunkowo dokładnym i precyzyjnym tłumaczeniem. |
|||
Which, while it isn't exactly prize-winning prose (much like this HOWTO), is a fairly accurate translation. |
|||
==Więc co z tym gramofonem? (Wielowyrazy)== |
|||
==So tell me about the record player (Multiwords)== |
|||
Jakby na to nie spojrzeć, nasze tłumaczenie dla słowa "gramophone" nie wydaje się być najlepszym z możliwych. Lepszym tłumaczeniem byłoby coś w stylu 'record player'. Co prawda jest to więcej niż jedno słowo, możemy jednak potraktować to tłumaczenie jakoby było ono jednym słowem, a konkretnie wielowyrazem (multiword/multipalabra). |
|||
While gramophone is an English word, it isn't the best translation. Gramophone is typically used for the very old kind, you know with the needle instead of the stylus, and no powered amplification. A better translation would be 'record player'. Although this is more than one word, we can treat it as if it is one word by using multiword (multipalabra) constructions. |
|||
Nie ma potrzeby zaglądać do słownika Serbsko-Chorwackiego, użyjemy jedynie angielskiego i dwujęzycznego, więc czym prędzej je otwórzmy. |
|||
We don't need to touch the Serbo-Croatian dictionary, just the English one and the bilingual one, so open it up. |
|||
Liczba mnoga od 'record player' to 'record players', więc korzysta ona z tego samego paradygmatu, co gramophone (gramophone__n) — dodajemy tylko na końcu 's'. Jedyne, co musimy zrobić to dodać nowy element do głównej sekcji. |
|||
<pre> |
<pre> |
||
<e lm="record player"><i>record<b/>player</i><par n="gramophone__n"/></e> |
<e lm="record player"><i>record<b/>player</i><par n="gramophone__n"/></e> |
||
</pre> |
</pre> |
||
Jedyną różnicę stanowi użycie tagu <b/>, aczkolwiek nie jest to kompletna nowość, jako że widzieliśmy ją już w pliku z regułami. |
|||
The only thing different about this is the use of the <b/> tag, although this isn't entirely new as we saw it in use in the rules file. |
|||
A więc, ponownie kompilujemy i testujemy nasz kod: |
|||
So, recompile and test in the orthodox fashion: |
|||
<pre> |
<pre> |
||
$ echo "vidim gramofone" | lt-proc sh-en.automorf.bin | \ |
$ echo "vidim gramofone" | lt-proc sh-en.automorf.bin | \ |
||
Line 675: | Line 672: | ||
I see record players |
I see record players |
||
</pre> |
</pre> |
||
Idealnie. Dużym plusem korzystania z wielowyrazów jest fakt, że możemy dosłownie tłumaczyć związki frazeologiczne, bez potrzeby tłumaczenia słowa po słowie. Na przykład, angielska fraza "at the moment" byłaby przetłumaczona na język Serbsko-Chorwacki, jako "trenutno" (trenutak = ''moment'', trenutno będący czasownikiem) — Tłumaczenie tego słowo po słowie na język Serbsko-Chorwacki nie byłoby w tym przypadku możliwe. |
|||
==Radzenie sobie z dialektami== |
==Radzenie sobie z dialektami== |
||
Serbko-Chorwacki |
Serbko-Chorwacki zwykle pozwala na kilka sposóbów zapisania tego samego słowa, z powodu różnych dialektów. Posiada fajny system zapisywania fonetycznego więc można pisać tak jak się dane słowo wymawia. Na przykład, ludność mówiąca po Ijekaviańsku powiedziałaby "rječnik", w czasie gdy ktoś mówiący po Ekaviańsku powiedziałby "rečnik", co z kolei podkreśla różnice w wymowie słowiańskich samogłosek. |
||
===Analizer=== |
===Analizer=== |
||
Nie |
Nie wydaje się to znacząco trudne do zaimplementowania, prawda? I faktycznie nie jest, można to w łatwy sposób wykonać za pomocą parydgmatów. Nie są one używane jedynie w celu dodawania gramatycznych symboli, ale również w celu zamiany znaków/symboli nawzajem między sobą. Dla przykładu, poniżej znajduje się paradygmat który akceptuje zarówno "e" i "je" w analizie. Powinien on trafić razem z innymi paradygmatami do jednojęzycznego słownika Serbsko-Chorwackiego. |
||
<pre> |
<pre> |
||
Line 708: | Line 705: | ||
</pre> |
</pre> |
||
To pozwala |
To pozwala na analizę tych dwóch form, aczkolwiek wymagało by to więcej pracy w przypadku gdyby zainstniała potrzeba wyświetlenia obu form. |
||
===Generator=== |
===Generator=== |
||
Line 715: | Line 712: | ||
*[[Building dictionaries]] |
*[[Building dictionaries]] |
||
*[[Finding_errors_in_dictionaries]] |
|||
*[[Cookbook]] |
*[[Cookbook]] |
||
*[[Chunking]] |
*[[Chunking]] |
||
Line 722: | Line 720: | ||
[[Category:HOWTO]] |
[[Category:HOWTO]] |
||
[[Category:Writing dictionaries]] |
[[Category:Writing dictionaries]] |
||
[[Category:Quickstart]] |
Latest revision as of 07:04, 16 February 2015
Ten artykuł opisuje, jak stworzyć od początku, nową parę języków dla systemu tłumaczenia automatycznego Apertium.
Nie zawiera, żadnej wiedzy na temat językoznawstwa lub tłumaczenia automatycznego powyżej poziomu możliwości odróżniania rzeczowników od czasowników (i przyimków itp.)
Wprowadzenie[edit]
Apertium jest, jak się zapewne domyślasz, systemem do automatycznego tłumaczenia komputerowego. Dokładniej mówiąc jest to platforma stworzona do tego celu. Zawiera silnik oraz zbiór narzędzi, które pozwalają na zbudowanie własnego systemu translacji. Jedyną rzeczą, którą użytkownik musi wykonać to wprowadzenie danych. Podstawowo są to trzy słowniki oraz kilka zasad (np. zmiany szyku zdania lub gramatyki).
Bardziej szczegółowe wprowadzenie na temat jak to wszystko działa znajdziesz w dziale Publications.
Wymagania[edit]
- lttoolbox (>= 3.0.0)
- libxml utils (xmllint itp.)
- apertium (>= 3.0.0)
- edytor tekstu (lub specjalny edytor XML)
Ten poradnik nie obejmuje instalacji powyższych narzędzi. W celu zasięgnięcia dalszych porad zajrzyj do dokumentacji projektu na stronie Apertium.
Na czym polega para języków?[edit]
Apertium jest komputerowym systemem tłumaczenia, który do pracy wykorzystuje słowniki oraz płytkie reguły transferowe (shallow transfer rules). Zasadniczą różnicą pomiędzy głębokimi i płytkimi zasadami jest to, że płytkie zasady nie analizują składni oraz działają na grupach jednostek leksykalnych zamiast używania struktury drzewa. Wyróżnia się trzy podstawowe słowniki:
- Słownik morfologiczny dla języka xx: zawierający zbiór zasad dot. odmieniania słowa w języku xx. W naszym przykładzie będzie to:
apertium-sh-en.sh.dix
- Słownik morfologiczny dla języka yy: zawierający zbiór zasad dot. odmieniania słowa w języku yy. W naszym przykładzie będzie to:
apertium-sh-en.en.dix
- Słownik dwujęzyczny: zawierający zależności pomiędzy słowami i symbolami w tych dwóch językach. W naszym przykładzie będzie to:
apertium-sh-en.sh-en.dix
W parze tłumaczonych języków dany język może być zarówno źródłem jak i wynikiem translacji.
Istnieją również dwa pliki zawierające zasady transferu. Zasady te opisują, w jaki sposób zarządzać szykiem zdań np. “kot czarny -> czarny kot”. Regulują one też powiązania pomiędzy płcią, liczbami itp. Zasady te mogą być też wykorzystywane do dodawania lub usuwania elementów leksykalnych, co będzie opisane później. Pliki, o których mowa to:
- zasady transferu języka xx do yy: zawierający zasady translacji języka xx do języka yy. W naszym przypadku będzie to:
apertium-sh-en.sh-en.t1x
- zasady transferu języka yy do xx: zawierający zasady translacji języka yy do języka xx. W naszym przypadku będzie to:
apertium-sh-en.en-sh.t1x
Wiele dostępnych par językowych posiada dodatkowe pliki, jednak nie będą one tutaj opisywane. Powyższe pliki służą, jako podstawa do stworzenia funkcjonalnego systemu.
Przykładowa para języków[edit]
Jak zapewne zauważyłeś, ten artykuł opiera się o przykład translatora Serbsko-Chorwackiego na Angielski w celu opisania zasad tworzenia podstawowej wersji systemu. Jest to dość niefortunna para języków, zważywszy na fakt, że system działa lepiej w przypadku bardziej pokrewnych języków. Nie powinno to jednak przeszkadzać w przypadku użycia tak prostych przykładów, jakie będą tu zaprezentowane.
Wyjaśnienie używanych pojęć[edit]
Istnieje kilka pojęć, z którymi powinieneś się zapoznać zanim będziemy mogli kontynuować.
Pierwszym określeniem jest lemma. Jest to forma podstawowa danego słowa. Ma ona najczęściej postać zbliżoną do najprostszej z możliwych (bezokoliczników itd.). Dla przykładu, lemma słowa cats to cat. W języku angielskim lemmy rzeczowników są zazwyczaj w liczbie pojedynczej. Dla czasowników, lemma jest bezokolicznikiem, np. lemmą was będzie be.
Następnym określeniem jest symbol. W kontekście systemu Apertium, symbol oznacza etykietę gramatyczną danego słowa. Słowo cats jest rzeczownikiem w liczbie mnogiej, więc będzie miało zarówno przyporządkowany symbol rzeczownika jak i symbol liczby mnogiej. Na wejściu i wyjściu modułów programowych są one zazwyczaj pomiędzy ostrymi nawiasami, tak jak poniżej:
<n>
; dla rzeczownika<pl>
; dla liczby mnogiej.
Innymi przykładami symbolami są <sg> (liczba pojedyncza) <p1> (pierwsza osoba) itd. Pisane w ostrych nawiasach symbole mogą być też traktowane, jako tagi. Warto zauważyć, że w wielu obecnie dostępnych parach językowych definicje symboli są akronimami lub skrótami zaczerpniętymi z języka katalońskiego. Symbole są definiowane w tagu <sdef> i używane w <s>
Trzecie określenie to paradygmat. W ramach systemu Apertium, paradygmat odnosi się do sposobu, w jaki powinno się odmieniać daną grupę słów. W słownikach morfologicznych, lemmy (patrz wyżej) są przypisane do paradygmatów, które pozwalają nam opisać, w jaki sposób dana lemmy odmienia się, bez konieczności zapisywania wszystkich końcówek.
Poniższy przykład pokazuje użyteczność tego podejścia, w przypadku, gdy chcemy zapisać przymiotniki ‘‘happy i lazy:
- happy, happ (y, ier, iest)
- lazy, laz (y, ier, iest)
Możemy po prostu zapisać jedno, a następnie powiedzieć, “lazy odmienia się jak happy" lub równoznacznie, “shy odmienia się jak happy", "naughty odmienia się jak happy", "friendly odmienia się jak happy" itd. W tym przykładzie happy jest paradygmatem pokazującym jak powinno się odmieniać inne słowa. Paradygmaty definiuje się w tagu <paradef> a używa w tagu <par>.
Na początek[edit]
Słowniki jednojęzyczne[edit]
- See also: List of dictionaries and Incubator
Zacznijmy od stworzenia naszego pierwszego źródłowego słownika. Będzie to dokument XML. Otwórz swój edytor i wpisz:
<?xml version="1.0" encoding="UTF-8"?> <dictionary> </dictionary>
Na razie definiujemy, że to, co zaraz stworzymy będzie słownikiem. Aby był przydatny musimy dodać kilka innych wpisów, pierwszym będzie alfabet. Definiuje on zbiór liter, które mogą być użyte. Dla słownika Serbsko-Chorwackiego będzie wyglądał tak:
<alphabet>ABCČĆDDžĐEFGHIJKLLjMNNjOPRSŠTUVZŽabcčćddžđefghijklljmnnjoprsštuvzž</alphabet>
Alfabet umieść poniżej tagu <dictionary>.
Następnie zdefiniujemy kilka symboli. Zacznijmy od prostych rzeczy jak: rzeczownik (n) w liczbie pojedynczej (sg) i mnogiej (pl).
<sdefs> <sdef n="n"/> <sdef n="sg"/> <sdef n="pl"/> </sdefs>
Nazwy symboli nie muszą być krótkie, w rzeczywistości mogą być napisane w całości, lecz częste używanie długich nazw byłoby na dłuższą metę męczące.
Niestety, sprawa jest nieco bardziej skomplikowana. Rzeczowniki w języku Sarbsko-Chorwackim odmieniają się także od płci i przypadku. Jednak założymy na potrzeby tego przykładu, że rzeczownik jest rodzaju męskiego w mianowniku (pełny przykład można znaleźć na końcu tego dokumentu).
Następnym krokiem jest zdefiniowanie sekcji dla paradygmatów,
<pardefs> </pardefs>
Oraz sekcji słownika:
<section id="main" type="standard"> </section>
Istnieją dwa typy sekcji - pierwszy jest sekcją standardową, która zawiera słowa, enklityki itd. Drugim typem sekcji jest inconditional section zawierająca znaki interpunkcyjne itd. Opisywany przykład nie zawiera drugiego typu.
Plik na obecną chwilę powinien wyglądać tak:
<?xml version="1.0" encoding="UTF-8"?> <dictionary> <sdefs> <sdef n="n"/> <sdef n="sg"/> <sdef n="pl"/> </sdefs> <pardefs> </pardefs> <section id="main" type="standard"> </section> </dictionary>
Mamy więc szkielet, możemy rozpocząć pracę od dodania rzeczownika. Rzecznikiem tym będzie 'gramofon'.
Pierwszą rzeczą, jaką musimy zrobić jest określenie paradygmatu.
Pamiętaj, że zakładamy, iż jest to rodzaj męski w mianowniku. Liczba pojedyncza tego rzeczownika to 'gramofon', a mnoga 'gramofoni'. Tak, więc:
<pardef n="gramofon__n"> <e><p><l/><r><s n="n"/><s n="sg"/></r></p></e> <e><p><l>i</l><r><s n="n"/><s n="pl"/></r></p></e> </pardef>
Uwaga: '<l/>' (równoznaczne z <l></l>) oznacza, że nie ma żadnych dodatkowych znaków dołączanych do rdzenia rzeczownika w 1-szej liczbie pojedynczej.
Może to wyglądać na dość zawiłą drogą opisywania tak prostych rzeczy, lecz zaowocuje to w przyszłości.
Prawdopodobnie zastanawiasz się, co oznaczają tagi <e>,
, <l> i <r>. A więc:
- e, jest słowem początkowym.
- p, jest dla pary.
- l, jest z lewej strony.
- r, jest z prawej strony.
Dlaczego z lewej i prawej? Cóż, słowniki morfologiczne zostaną później skompilowane do finalnej postaci. Kompilowanie ich od lewej do prawej powoduje analizę słów, a kompilowanie od prawej do lewej - słowa analizy. Na przykład:
* gramofoni (od lewej do prawej) gramofon<n><pl> (analiza) * gramofon<n><pl> (od prawej do lewej) gramofoni (generowanie)
Zdefiniowaliśmy, zatem paradygmat, teraz musimy połączyć go z odpowiadającą lemmą, czyli w tym przypadku "gramofon". Umieścimy to w sekcji, którą przed chwilą zdefiniowaliśmy.
Słowo początkowe, które umieścimy w </dictionary>
Teraz musimy dodać wpis służący do translacji pomiędzy dwoma słowami. Wygląda to tak:
<e><p><l>gramofon<s n="n"/></l><r>gramophone<s n="n"/></r></p></e>
Ponieważ często zdarza się, że takich wpisów jest bardzo dużo, są one najczęściej pisane w jednej linii, w celu polepszenia czytelności kodu. Pamiętając o 'l' oraz 'r' oczywiście. Tym razem kompilujemy plik od lewej do prawej by utworzyć translator Serbsko-chorwacko → Angielski, a kompilowanie od prawej do lewej spowodowałoby utworzenie Angielsko → Serbsko-chorwackiego słownika.
Następnym krokiem jest uruchomienie poniższych komend:
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin $ lt-comp rl apertium-sh-en.en.dix sh-en.autogen.bin $ lt-comp lr apertium-sh-en.en.dix en-sh.automorf.bin $ lt-comp rl apertium-sh-en.sh.dix en-sh.autogen.bin $ lt-comp lr apertium-sh-en.sh-en.dix sh-en.autobil.bin $ lt-comp rl apertium-sh-en.sh-en.dix en-sh.autobil.bin
Na potrzeby generowania analizatorów morfologicznych (automorf), generatorów (autogen) oraz tłumaczeń słów (autobil), bil będzie oznaczać "dwujęzyczny".
Zasady Transferu[edit]
Więc, mamy dwa jednojęzyczne słowniki, oraz jeden dwujęzyczny. Jedyne, czego teraz potrzebujemy to zaimplementowanie zasad dla rzeczowników. Pliki tego typu posiadają własne DTD (transfer.dtd) znajdującym się w pakiecie Apertium. Gdy zaistnieje potrzeba zaimplementowania jakiejś zasady pomocnym krokiem jest spojrzenie na sposób, w jaki zostało to zaimplementowane w innych plikach językowych. Wiele z nich ma to do siebie, że mogą być użyte ponownie w translacji różnych języków. Przykład opisany poniżej może być używany dla wszystkich języków z domyślnym podmiotem.
Zacznijmy podobnie jak w poprzednich przykładach, wykonując szkielet:
<?xml version="1.0" encoding="UTF-8"?> <transfer> </transfer>
W tym momencie musimy jedynie stworzyć zasadę, która będzie brała symbole gramatyczne i przesyłała je z powrotem.
Najpierw musimy zdefiniować kategorie oraz atrybuty. Obydwa fragmenty będą używane do grupowania symboli gramatycznych. Kategorie pozwalają nam na grupowanie symboli, które pasują do pewnego wzorca (dla przykładu 'n.*' dla wszystkich rzeczowników). Atrybuty z kolei utworzą grupę symboli, z których będziemy mogli w przyszłości korzystać.
Dodajmy wiec niezbędne sekcje:
<section-def-cats> </section-def-cats> <section-def-attrs> </section-def-attrs>
Ponieważ odmieniamy jedynie rzeczowniki w liczbie pojedynczej i mnogiej to potrzebujemy dodać osobną kategorię dla rzeczowników, razem z atrybutem liczby. Coś takiego powinno wystarczyć:
W section-def-cats dodaj:
<def-cat n="nom"> <cat-item tags="n.*"/> </def-cat>
Ten fragment kodu wyłapuje wszystkie rzeczowniki (lemmy i następujące po nich <n>), i odnosi się do nich, jako "nom"y (później zobaczymy jak tego używać).
W sekcji section-def-attrs, dodaj:
<def-attr n="nbr"> <attr-item tags="sg"/> <attr-item tags="pl"/> </def-attr>
a następnie
<def-attr n="a_nom"> <attr-item tags="n"/> </def-attr>
Pierwsza dodaje atrybut "nbr" (liczbę), która może być liczbą pojedynczą (sg) lub mnogą pl).
Druga definiuje atrybut a_nom (atrybut rzeczownika).
Następnie musimy dodać sekcje dla globalnych zmiennych:
<section-def-vars> </section-def-vars>
Te zmienne będą używane do przechowywania lub przenoszenia atrybutów pomiędzy zasadami. Na razie wystarczy nam tylko jedna zmienna
<def-var n="number"/>
Na koniec musimy dodać zasadę, która pobierze rzeczownik i zwróci go w odpowiedniej formie. Musimy zatem dodać sekcję zasad...
<section-rules> </section-rules>
Zwiększymy trochę tempo, najpierw wklejając poniższy kod a dopiero potem go omawiając.
<rule> <pattern> <pattern-item n="nom"/> </pattern> <action> <out> <lu> <clip pos="1" side="tl" part="lem"/> <clip pos="1" side="tl" part="a_nom"/> <clip pos="1" side="tl" part="nbr"/> </lu> </out> </action> </rule>
Pierwszy tag jest oczywisty, po prostu definiuje zasadę. Drugi mówi: "zastosują tą zasadę, jeżeli pasuje do wzorca". W tym przykładzie wzorzec składa się z pojedynczego rzeczownika (zdefiniowany przez kategorię "nom"). Zwróć uwagę, że wzorce są dostosowywane w kolejności od najdłuższego pasującego. Więc jeśli masz trzy zasady: pierwszą łapiącą "<prn><vblex><n>", drugą łapiącą "<prn><vblex>" i trzecią łapiącą "<n>", pierwszą zastosowaną regułą będzie właśnie reguła pierwsza.
Dla każdego wzorca jest odpowiadająca jej akcja, która tworzy odpowiadający wynik na wyjściu będący jednostką leksykalną (lu). Zaciskające tagi (clip tags) pozwalają użytkownikowi na wybranie i manipulowanie na atrybutach i elementach języka źródłowego (side="sl") lub docelowego (side="tl") elementu leksykalnego.
Spróbujmy więc to skompilować i przetestować. Zasady transferu kompilujemy za pomocą:
$ apertium-preprocess-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin
Które powinno wygenerować plik sh-en.t1x.bin
.
Jesteśmy już gotowi do przystąpienia to fazy testowania. Pominęliśmy jednak bardzo ważną część kodu, a mianowicie tagger part-of-speech (PoS), jednak omówimy to później. Na razie możemy przetestować to, co mamy.
Najpierw zanalizujmy słowo gramofoni:
$ echo "gramofoni" | lt-proc sh-en.automorf.bin ^gramofon/gramofon<n><pl>$
W normalnych warunkach tagger PoS powinien wybrać prawidłową wersję analizując część mowy, jednak ponieważ go nie zaimplementowaliśmy, użyjemy tego skryptu (podziękowania dla Sergio), który powinien zwrócić tylko odpowiednią wersje.
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \ gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' ^gramofon<n><pl>$
Wykorzystamy to razem z zasadami transferu:
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \ gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \ apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin
Powinniśmy otrzymać:
^gramophone<n><pl>$^@
- 'gramophone' jest w języku docelowym (side="tl") lemma (lem) na pozycji pierwszej (pos="1").
- '<n>' jest a_nom na pozycji pierwszej w języku docelowym.
- '<pl>' jest atrybutem numeru (nbr) na pozycji pierwszej w języku docelowym.
Spróbuj zamienić jedną z zasad na komentarz, skompilować i zobaczyć co się stanie.
Mamy teraz rezultat z wyjścia, ostatnią rzeczą jaką musimy się zająć jest wygenerowanie odmienionych form języka docelowego. Do wykonania tej czynności użyjemy lt-proc, w rybie generacji (-g), a nie w trybie analizy (-a).
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \ gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \ apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin | \ lt-proc -g sh-en.autogen.bin gramophones\@
Masz teraz przed sobą system tłumaczenia maszynowego, który tłumaczy rzeczownik w języku serbsko-chorwackim na rzeczownik angielski. Oczywiście nie jest to szczególnie przydatne, ale niedługo przejdziemy do bardziej skomplikowanych rzeczy. Nie przejmuj się symbolem '@', później wyjaśnimy sobie do czego służy i jak go używać.
Pomyśl o kilku innych przykładach rzeczowników, odmieniających się w ten sam sposób co rzeczownik gramofon. Spróbuj dodać je do słownika. Nie musimy dodawać żadnych paradygmatów, wystarczy tylko dodać wpisy w głównych sekcjach słownika jednojęzycznego i dwujęzycznego.
Pora na czasowniki[edit]
Ok, mamy system, który tłumaczy nam rzeczowniki, ale jest to trochę bezużyteczne, chcemy też przecież tłumaczyć czasowniki, a nawet całe zdania! Może na początek zacznijmy od tłumaczenia czasowników. W języku serbsko-chorwackim czasownik nazywa się videti.
Język serbsko-chorwacki jest językiem nie-tematycznym, co oznacza, iż zwykle nie stosuje zaimków poprzedzających odmienioną formę czasownika. Angielski taki nie jest. Na ten przykład: "I see" (ja widzę) w języku angielskim zostałoby przetłumaczone na "vidim" w języku Serbsko-Chorwackim.
- Vidim
- see<p1><sg>
- I see
Uwaga: <p1>
oznacza pierwszą osobę
Okaże się to ważne, w momencie, gdy zaczniemy pisać zasady transferu dla czasowników. Inne przykłady języków nie-tematycznych obejmują: Hiszpański, Rumuński i Polski. Wynika to także z tego, że, gdy w serbsko-chorwackim słowniku morfologicznym musimy dodać tylko czasownik, w angielskim słowniku morfologicznym musimy dodać czasownik i zaimek osobowy. Przeanalizujemy oba sposoby.
Inne formy czasownika "videti" to: vidiš, vidi, vidimo, vidite, and vide; które odpowiadają: you see (singular), he sees, we see, you see (plural), oraz they see.
Istnieją dwie formy "you see", jedna jest w liczbie mnogiej oraz formalnej pojedynczej (vidite) oraz druga tylko w nieformalnej pojedynczej (vidiš).
Spróbujemy przetłumaczyć następujące zdanie: "Vidim gramofoni" na "I see gramophones". W poszanowaniu miejsca, dodamy po prostu wystarczającą ilość informacji do tłumaczenia i pozostawimy wypełnianie paradygmatów (dodanie spójników do czasownika), jako ćwiczenia.
Bystry czytelnik najprawdopodobniej już zauważył, że nie możemy po prostu przetłumaczyć "vidim gramofoni”, ponieważ nie jest to zdanie poprawne gramatycznie w języku Serbsko-Chorwackim. Poprawnie brzmiałoby ono vidim gramofone, jako, iż rzeczownik jest w bierniku. Będziemy musieli dodać również i tą formę, aczkolwiek nie ma potrzeby dodawania informacji o przypadku, po prostu dodamy dodatkową opcję dla liczby mnogiej. Przepisz zatem fragment zawierający 'e' dla 'i' oraz zamień 'i' na 'e'.
Pierwszą rzeczą którą musimy zrobić jest dodanie symboli. Najpierw musimy dodać symbol dla 'verb', który będziemy od tej pory nazywać "vblex" (co znaczy czasownik leksykalny, przeciwnie do czasowników modalnych czy innych typów). Czasowniki mają 'person' (osobę), oraz 'tense' (czas) jak również liczbę, więc dodajmy kilka z nich. Musimy przetłumaczyć "I see", więc dla osoby powinniśmy dodać "p1", lub 'first person', a dla czasu "pri", albo 'present indicative'.
<sdef n="vblex"/> <sdef n="p1"/> <sdef n="pri"/>
Gdy to zrobimy, również z rzeczownikami, dodamy paradygmat lub koniugację czasownika. Pierwsza linijka powinna wyglądać następująco:
<pardef n="vid/eti__vblex">
Symbol '/' jest użyty w celu wytyczenia granicy gdzie łodygi (fragmenty pomiędzy tagami <l> i </l>) są również pododawane.
Następnie odmiana pierwszej osoby liczby pojedyńczej:
<e><p><l>im</l><r>eti<s n="vblex"/><s n="pri"/><s n="p1"/><s n="sg"/></r></p></e>
'im' oznacza koniec (jak w 'vidim'), jest on potrzebny w celu dodania 'eti' do sekcji <r>, jako że zostanie odcięty z definicji. Reszta jest stosunkowo prosta: 'vblex' jest czasownikiem leksykalnym, 'pri' jest czasem orientacyjnym, 'p1' to pierwsza osoba a 'sg' jest liczbą pojedyńczą. Możemy również dodać liczbę mnogą która byłaby taka sama, za wyjątkiem 'imo' zamiast 'im' i 'pl' zamiast 'sg'.
Następnie musimy dodać lemmę, oraz paradygmat do głównej sekcji:
<e lm="videti"><i>vid</i><par n="vid/eti__vblex"/></e>
Uwaga: zawartość <i> </i> jest korzeniem (rootem), a nie lemmą.
To część pracy jaką wykona dla nas translator Serbsko-Chorwacki. Skompilujmy oraz przetestujmy kod.
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin main@standard 23 25 $ echo "vidim" | lt-proc sh-en.automorf.bin ^vidim/videti<vblex><pri><p1><sg>$ $ echo "vidimo" | lt-proc sh-en.automorf.bin ^vidimo/videti<vblex><pri><p1><pl>$
Teraz musimy zrobić to samo dla angielskiego słownika (pamiętaj o dodaniu tego samego symbolu definicji, tak samo jak dodaliśmy do Serbsko-Chorwackiego).
Paradygmatem w tym przypadku będzie:
<pardef n="s/ee__vblex">
ponieważ czas przeszły to 'saw'. Teraz możemy wykonać jedną z dwóch rzeczy - możemy dodać pierwszą i drugą osobę, ale w tej samej formie. Tak na prawdę, wszystkie formy (za wyjątkiem trzeciej osoby liczby pojedyńczej) czasownika 'to see' są równoznaczne 'see'. Więc zamiast tego dodamy tylko jedną linię kodu dla 'see' i dodamy jedynie symbol 'pri'.
<e><p><l>ee</l><r>ee<s n="vblex"/><s n="pri"/></r></p></e>
oraz, jak zwykle, wpis w głównej sekcji:
<e lm="see"><i>s</i><par n="s/ee__vblex"/></e>
Potem skompilujmy i przetestujmy kod:
$ lt-comp lr apertium-sh-en.en.dix en-sh.automorf.bin main@standard 18 19 $ echo "see" | lt-proc en-sh.automorf.bin ^see/see<vblex><pri>$
Teraz kolej na obowiązkowy wpis w dwujęzycznym słowniku:
<e><p><l>videti<s n="vblex"/></l><r>see<s n="vblex"/></r></p></e>
(nie zapomnij o dodaniu sdef'ów do wpisów)
Oraz re-kompilacja:
$ lt-comp lr apertium-sh-en.sh-en.dix sh-en.autobil.bin main@standard 18 18 $ lt-comp rl apertium-sh-en.sh-en.dix en-sh.autobil.bin main@standard 18 18
Teraz pora na test:
$ echo "vidim" | lt-proc sh-en.automorf.bin | \ gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \ apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin ^see<vblex><pri><p1><sg>$^@
Widzimy że analiza wypadła pomyślnie, ale kiedy próbujemy wygenerować z tego "powierzchnię", otrzymujemy '#', jak poniżej:
$ echo "vidim" | lt-proc sh-en.automorf.bin | \ gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \ apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin | \ lt-proc -g sh-en.autogen.bin #see\@
Symbol '#' oznacza, że generato nie może utworzyć poprawnej formy leksykalnej czasownika ponieważ jej nie posiada. Dlaczego?
Krótko mówiąc, analizy nie są ze sobą zgodne, 'see' w słowniku oznacza see<vblex><pri>, a to dostarczone przez transfer oznacza see<vblex><pri><p1><sg>. Serbsko-Chorwacka strona posiada więcej informacji niż tego wymaga strona angielska. Możesz to sprawdzić, dodając brakujące symbole do angielskiego słownika, rekompilując, i testując ponownie.
Jednakże, bardziej paradygmatycznym wyjściem z tej sytuacji jest napisanie zasady. Otwieramy więc plik zasad: (apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin
gdybyś zapomniał)
Musimy dodać nową kategorię dla czasowników ('verb').
<def-cat n="vrb"> <cat-item tags="vblex.*"/> </def-cat>
usimy również dodać atrybuty dla czasu i osoby. Zrobimy to w bardzo prosty sposób, możesz dodać p2 i p3, ale w tym przypadku to pominiemy by zaoszczędzić miejsce:
<def-attr n="temps"> <attr-item tags="pri"/> </def-attr> <def-attr n="pers"> <attr-item tags="p1"/> </def-attr>
Powinniśmy również dodać atrybut dla czasowników:
<def-attr n="a_verb"> <attr-item tags="vblex"/> </def-attr>
Teraz sama zasada:
<rule> <pattern> <pattern-item n="vrb"/> </pattern> <action> <out> <lu> <clip pos="1" side="tl" part="lem"/> <clip pos="1" side="tl" part="a_verb"/> <clip pos="1" side="tl" part="temps"/> </lu> </out> </action> </rule>
Pamiętasz, gdy ująłeś fragment zawierający zaciskające (clip) tagi w komentarz w poprzednim przykładzie zasad i gdy znikły one z transferu? Cóż, to praktycznie to samo co próbujemy zaimplementować teraz. Poddajemy czasownik pełnej analizie ale zwracamy tylko część analizy (lemme + tag czasownika + tag czasu).
Gdy zrekompilujemy kod, otrzymamy:
$ echo "vidim" | lt-proc sh-en.automorf.bin | \ gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \ apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin ^see<vblex><pri>$^@
oraz:
$ echo "vidim" | lt-proc sh-en.automorf.bin | \ gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \ apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin | \ lt-proc -g sh-en.autogen.bin see\@
Wypróbuj to używając 'vidimo' (we see) by zobaczyć czy otrzymujemy poprawny wynik.
Teraz spróbuj tego samego z użyciem "vidim gramofone":
$ echo "vidim gramofoni" | lt-proc sh-en.automorf.bin | \ gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \ apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin | \ lt-proc -g sh-en.autogen.bin see gramophones\@
A co z zaimkami?[edit]
Jest fajnie, ale ciągle nie mamy osobowych zaimków, które są potrzebne w języku angielskim. W celu ich dodaniu, najpierw potrzebujemy wyedytować angielski słownik morfologiczny.
Jak przedtem, pierwszym krokiem jest dodanie symboli:
<sdef n="prn"/> <sdef n="subj"/>
W tym przypadku, prn jest zaimkiem, a subj jest podmiotem (tak jak podmiot w zdaniu).
Ponieważ nie ma tutaj rdzenia (roota), ani 'lemmy' dla osobowego podmiotu zaimka, po prostu dodajemy pardef tak jak poniżej:
<pardef n="prsubj__prn"> <e><p><l>I</l><r>prpers<s n="prn"/><s n="subj"/><s n="p1"/><s n="sg"/></r></p></e> </pardef>
gdzie 'prsubj' jest 'podmiotem osobowym' (personal subject). Reszta (You, We itd.) zostaje, jako ćwiczenie dla czytelnika.
Możemy dodać wpis do głównej sekcji, tak jak poniżej:
<e lm="personal subject pronouns"><i/><par n="prsubj__prn"/></e>
Zapiszmy, skompilujmy i przetestujmy kod. Powinniśmy otrzymać coś takiego:
$ echo "I" | lt-proc en-sh.automorf.bin ^I/PRPERS<prn><subj><p1><sg>$
(Uwaga: wynik jest wypisany drukowanymi literami, ponieważ 'I' jest drukowane).
Teraz musimy poprawić regułę dla czasownika ('verb') by otrzymać osobowy podmiot zaimka razem z poprawną formą czasownika.
Najpierw, dodajmy kategorię:
<def-cat n="prpers"> <cat-item lemma="prpers" tags="prn.*"/> </def-cat>
Teraz, dodajmy typy zaimków, jako atrybuty, możemy też dodać typ 'obj’, jako, że przy nim jesteśmy, aczkolwiek nie będziemy go teraz potrzebować:
<def-attr n="tipus_prn"> <attr-item tags="prn.subj"/> <attr-item tags="prn.obj"/> </def-attr>
A teraz, by wczytać regułę:
<rule> <pattern> <pattern-item n="vrb"/> </pattern> <action> <out> <lu> <lit v="prpers"/> <lit-tag v="prn"/> <lit-tag v="subj"/> <clip pos="1" side="tl" part="pers"/> <clip pos="1" side="tl" part="nbr"/> </lu> <b/> <lu> <clip pos="1" side="tl" part="lem"/> <clip pos="1" side="tl" part="a_verb"/> <clip pos="1" side="tl" part="temps"/> </lu> </out> </action> </rule>
Jest to praktycznie ta sama reguła co wcześniej, dodaliśmy tylko kilka niewielkich poprawek. Potrzebowaliśmy wyniku:
^prpers<prn><subj><p1><sg>$ ^see<vblex><pri>$
by generator mógł wybrać prawidłowy zaimek i prawidłową formę czasownika.
Więc, krótkie podsumowanie:
<lit>
, wypisuje ciąg literowy, w tym przypadku "prpers"<lit-tag>
, wypisuje tag literowy, ponieważ nie możemy otrzymać tagu z czasownika dodamy go ręcznie, "prn" dla zaimka, a "subj" dla podmiotu.wypisuje spację (pusty znak).
Zwróć uwagę, że otrzymaliśmy liczbę oraz czas wprost z czasownika.
Więc teraz, jeśli skompilujemy i przetestujemy znowu, otrzymujemy:
$ echo "vidim gramofone" | lt-proc sh-en.automorf.bin | \ gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \ apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin | \ lt-proc -g sh-en.autogen.bin I see gramophones
które (pomijając długo oczekiwany, końcowy rezultat), jest stosunkowo dokładnym i precyzyjnym tłumaczeniem.
Więc co z tym gramofonem? (Wielowyrazy)[edit]
Jakby na to nie spojrzeć, nasze tłumaczenie dla słowa "gramophone" nie wydaje się być najlepszym z możliwych. Lepszym tłumaczeniem byłoby coś w stylu 'record player'. Co prawda jest to więcej niż jedno słowo, możemy jednak potraktować to tłumaczenie jakoby było ono jednym słowem, a konkretnie wielowyrazem (multiword/multipalabra).
Nie ma potrzeby zaglądać do słownika Serbsko-Chorwackiego, użyjemy jedynie angielskiego i dwujęzycznego, więc czym prędzej je otwórzmy.
Liczba mnoga od 'record player' to 'record players', więc korzysta ona z tego samego paradygmatu, co gramophone (gramophone__n) — dodajemy tylko na końcu 's'. Jedyne, co musimy zrobić to dodać nowy element do głównej sekcji.
<e lm="record player"><i>record<b/>player</i><par n="gramophone__n"/></e>
Jedyną różnicę stanowi użycie tagu , aczkolwiek nie jest to kompletna nowość, jako że widzieliśmy ją już w pliku z regułami.
A więc, ponownie kompilujemy i testujemy nasz kod:
$ echo "vidim gramofone" | lt-proc sh-en.automorf.bin | \ gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \ apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin | \ lt-proc -g sh-en.autogen.bin I see record players
Idealnie. Dużym plusem korzystania z wielowyrazów jest fakt, że możemy dosłownie tłumaczyć związki frazeologiczne, bez potrzeby tłumaczenia słowa po słowie. Na przykład, angielska fraza "at the moment" byłaby przetłumaczona na język Serbsko-Chorwacki, jako "trenutno" (trenutak = moment, trenutno będący czasownikiem) — Tłumaczenie tego słowo po słowie na język Serbsko-Chorwacki nie byłoby w tym przypadku możliwe.
Radzenie sobie z dialektami[edit]
Serbko-Chorwacki zwykle pozwala na kilka sposóbów zapisania tego samego słowa, z powodu różnych dialektów. Posiada fajny system zapisywania fonetycznego więc można pisać tak jak się dane słowo wymawia. Na przykład, ludność mówiąca po Ijekaviańsku powiedziałaby "rječnik", w czasie gdy ktoś mówiący po Ekaviańsku powiedziałby "rečnik", co z kolei podkreśla różnice w wymowie słowiańskich samogłosek.
Analizer[edit]
Nie wydaje się to znacząco trudne do zaimplementowania, prawda? I faktycznie nie jest, można to w łatwy sposób wykonać za pomocą parydgmatów. Nie są one używane jedynie w celu dodawania gramatycznych symboli, ale również w celu zamiany znaków/symboli nawzajem między sobą. Dla przykładu, poniżej znajduje się paradygmat który akceptuje zarówno "e" i "je" w analizie. Powinien on trafić razem z innymi paradygmatami do jednojęzycznego słownika Serbsko-Chorwackiego.
<pardef n="e_je__yat"> <e> <p> <l>e</l> <r>e</r> </p> </e> <e> <p> <l>je</l> <r>e</r> </p> </e> </pardef>
Następnie w głównej sekcji:
<e lm="rečnik"><i>r</i><par n="e_je__yat"/><i>čni</i><par n="rečni/k__n"/></e>
To pozwala na analizę tych dwóch form, aczkolwiek wymagało by to więcej pracy w przypadku gdyby zainstniała potrzeba wyświetlenia obu form.