Апертиум, как се създава нова езикова двойка

From Apertium
Revision as of 15:19, 27 November 2010 by Gradinarovo (talk | contribs)
Jump to navigation Jump to search

Апертиум, как се създава нова езикова двойка

Този документ има за цел да обясни как се създава нова езикова двойка в Апертиум системата за машинен превод от началото до края.

Не е необходимо никакво знание по лингвистика или по машинен превод над нивото на различаване на съществителни имена от глаголи (представки и други)

Въведение

Както може би вече сте се досетили, Апертиум е система за машинен превод. Всъщност, казано по-точно това е платформа за преводи. Разполага с машина и инструменти, които ви позволяват да създавате ваши собствени системи за превод. Единственото нещо, което трябва да направите е да запишете данните. Основно те се състоят от три речника и няколко правила за преподреждане на думите и други граматични трансформации.

За по конкретна информация как точно работи системата, има някои доста добри ръководства на уеб сайта на проекта apertium.sourceforge.net.

Какво ще ви е необходимо

  • lttoolbox (>= 3.0.0)
  • libxml utils (xmllint etc.)
  • apertium (>= 3.0.0)
  • текстов редактор (или ако предпочитате специализиран XML редактор)

Този документ няма да описва как да инсталирате тези пакети. За повече информация за това прочетете секцията с документацията на уеб сайта на Апертиум.

От какво се състои езиковата двойка?

Системата за машинен превод Апертиум е от повърхностно-трансферен тип, което ще рече, че работи с речници и повърхностни правила за позициониране на думите. Повърхностнното позициониране на думите се различава от "пълното позициониране" с това, че не прави цялостно синтактично парсиране. По принцип правилата са операции върху групи от лексически раздели, и не са операции върху дървовидни структури. Основно съществуват три основни речника:

  1. Морфологичния речник за език ХХ: той съдържа правилата за това как се спрягат думите в език ХХ. В нашия пример този речник ще се нарича: apertium-ru-bg.ru.dix
  2. Морфологичния речник за език УУ: той съдържа правилата за това как се спрягат думите в език УУ. В нашия пример този речник ще се нарича: apertium-ru-bg.bg.dix
  3. Двуезичен речник: съдържа съответстия между думи и символи на двата езика. В нашия пример този речник ще се нарича: apertium-ru-bg.ru-bg.dix

В двойката за превод и двата езика могат да бъдат или източник или приемник на превода, това са относителни тернини.

Също така има два файла за правила на трансфера. Това са правилата, които управляват как се пренареждат думите в изреченията, пр. chat noir (черна котка на френски.) -> котка черна -> черна котка. Управляват се и родовете, числата и т.н. Правилата могат да бъдат използвани и да се смъкват или изтриват лексически елементи, както ще бъде описано по-късно. Тези файлове са:

  • правила за трансфер на език ХХ към УУ: този файл съдържа правила относно промяната от език ХХ към УУ. В нашия пример това ще бъде: apertium-ru-bg.trules-ru-bg.xml
  • правила за трансфер на език УУ към ХХ: този файл съдържа правила относно промяната на език УУ към ХХ. В нашия пример това ще бъде: apertium-ru-bg.trules-bg-ru.xml

Много от езиковите двойки, които са налични в момента имат и друг файлове, но ние няма да ги разясняваме тук. Горните файлове са тези, които са необходими за изграждането на една функционална система.

Езикова двойка

Както може да се предположи от имената на файловете, това ръководство ще използва за обяснение на създаването на основната система примери от руски на български. Това е идеалната двойка, тъй като системата работи по-добре с по-близки езици.

Кратка бележка за термините

Преди да продължим има няколко термини, които трябва да бъдат разяснени.

Първият е лема. Лема е цитирането на дума. Това представлява думата, без никаква граматическа информация. На пример, лемата на думата котки е котка. За българските съществителни това обикновенно е единственото число на въпросната дума. За глаголи, лемата е основната форма. Лемата на глагола бях е съм.

Вторият е символа. В контекста на Апертиум системата, символа означава граматически етикет. Думата котки е множествено число, следователно тя има символа за съществително и символа за множествено число. На входа и изхода на модулите на Апертиум, горните обикновено се подават между ъглови скоби, както следва:

  • <n>; за съществителни
  • <pl>; за множествено число

Други примери за символи са <sg>; единствено число, <p1> първо лице, <pri> сегашно изявително наклонение и др. Когато са записани в квадратни скобки символите могат същото така да се приемат като тагове. Важно е да се отбележи, че в много от съществуващите езикови двойки дефинициите на символите са думи, образувани от началните букви на други думи на Каталонски език. На пример, vbhaver - от vb (глагол) и haver ("да имам" на каталонски). Символите са дефинирани в <sdef> тагове и се използват с <s> тагове.

Третата дума е парадигма. В контекста на Апертиум системата, парадигмата се отнася примерно как се спряга цяла група от думи. В морфологичния речник, лемите (виж по-горе) се свързват с парадигмите, което ни дава възможност да опишем как всяка лема може да бъде спрегната без да се налага да описваме всички наставки.

Примерно, ако искаме да съхраним две прилагателни работлив и мързелив, вместо да запазваме две еднакви наствки:

  • работлив, работли (в, по-, най-)
  • мързелив, мързели (в, по-, най-)

Можем просто да съхраним едната и после да кажем, че "мързелив, се спряга като работлив, или "горделив се спряга като работлив","похотлив се спряга като работлив", "красноречив се спряга като работлив" и така нататък. В този пример, работлив ще е парадигмата, модела за това как всички останали се спрягат. Точното описание на как точно се дефинира това ще бъде обяснено скоро. Парадигмите се дефинират в <pardef> тагове и се използват в <par> тагове.

Начало

Многоезини речници

Нека да започнем като направим нашия първи езиков речник. Речника представлява XML файл. Пуснете си вашия текстов редактор и напишете следното:

<?xml version="1.0" encoding="UTF-8"?>
<dictionary>

</dictionary>

Така, файла дефинира за сега, че искаме да направим речник. За да бъде полезен този файл трябва да добавим още няколко реда, първия от които е азбука. Тя дефинира поредицата от букви, които мога да се използват в речника за руски език. Ще изглежда по следния начин и ще съдържа всички букви от руската азбука:

<alphabet>АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя</alphabet>

Поставете азбуката под тага <dictionary>.

След това трябва да дефинираме някои символи. Да започнем с нещо по-елементарно, съществително (n) в единствено число (pl) и множествено число (pl).

<sdefs>
   <sdef n="n"/>
   <sdef n="sg"/>
   <sdef n="pl"/>
</sdefs>

Символните имена не трябва да бъдат толкова кратки, всъщност те биха могли дори да бъдат написани пълно, но тъй като ще се налага да ги пишем често, има логика да използваме съкращения.

За нещастие, не е толкова лесно, съществителните в руския се спрягат не само по число, а също така и по род и наклонение. Обаче, за този пример ще приемем, че съществителното е в мъжки род и в именителен падеж ( цялостен пример може да бъде намерен в края на този документ )

Следва да дефинираме секция за парадигмите,

<pardefs>

</pardefs>

и секция за речника:

<section id="main" type="standard">

</section>

Има два вида секции, първия е стандартна секция, която съдържа думи, енклитика и други. Втория вид е неусловна секция, която най-често съдържа препинателни знаци и други. Тук нямаме такава неусловна секция, но тя ще бъде описана по-късно.

Така, файла ни трябва да изглежда по следния начин:

<?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>

Сега имаме структурата, можем да започнем с добавянето на съществително. За пример ще използваме "граммофон", което означава "грамофон" или "устройство, което свири с плочи".

Първото нещо, което трябва да направим, тъй като нямаме предишни парадигми е да дефинираме парадигма.

Запомнете, че приемаме мъжки род и именителен падеж. Единственото число на съществителното е "граммофон", и множественото число е "граммофоны". Така:

<pardef n="граммофон__n">
   <e>
     <p>
       <l/>
       <r><s n="n"/><s n="sg"/></r>
     </p>
   </e>
   <e>
     <p>
       <l>ы</l>
       <r><s n="n"/><s n="pl"/></r>
     </p>
   </e>
</pardef>

Забележка: '<l/>' (еквивалент на <l></l>) означава, че няма допълнителен материал да бъде добавян в основата на думата в единствено число.

Това може да изглежда като доста подробен начин за описването му, но има причини за това и скоро се свиква с него. Вие сигурно се чудите какво означават <e>,

, <l> и <r>. Така,

  • e - запис.
  • p - двойка.
  • l - ляво.
  • r - дясно.

Защо ляво и дясно? Ами морфологичните речници по-късно ще бъдат компилирани в крайни автомати. Компилирането им отляво надясно създава анализ от думи и от дясно наляво думи от анализи. Например:

* граммофоны (отляво надясно) граммофон<n><pl> (анализ)
* граммофон<n><pl> (отдясно наляво) граммофоны (генерация)

Сега дефинирахме парадигма, трябва да я свържем с нейната лема, граммофон. Поставяме я в секцията, която дефинирахме.ed.

Записа, който ще сложим в </dictionary>

Сега е необходимо да добавим запис за превод между двете думи. Нещо като:

<e><p><l>граммофон<s n="n"/></l><r>грамофон<s n="n"/></r></p></e>

Тъй като има много такива записи, те се пишат обикновено на един и същи ред за да се улесни четенето на файла. Отново с 'l' и 'r'? Компилираме го от ляво надясно за да се създаде руско > български речник, и отдясно наляво за създаването на българо > руски речник.

И така, когато сме готови стартираме следните команди:

$ lt-comp lr apertium-ru-bg.ru.dix ru-bg.automorf.bin
$ lt-comp rl apertium-ru-bg.bg.dix ru-bg.autogen.bin

$ lt-comp lr apertium-ru-bg.bg.dix bg-ru.automorf.bin
$ lt-comp rl apertium-ru-bg.ru.dix bg-ru.autogen.bin

$ lt-comp lr apertium-ru-bg.ru-bg.dix ru-bg.autobil.bin
$ lt-comp rl apertium-ru-bg.ru-bg.dix bg-ru.autobil.bin

Така се генерират морфологичните анализатори (automorf), морфологичните генератори (autogen) и се проверяват думите (autobil), думата bil означава двуезичен.

Правила за трансфер

Така, имаме два морфологични речника и двуезичен речник. Това от което се нуждаем сега е правило за трансфер за съществителни. Правилата за трансфер имат собствени DTD фаилове(transfer.dtd), които могат да бъдат открити в пакета Apertium. Ако трябва да създадете ново правило е желателно да погледнете във файловете с правила на други езикови двойки първо. Много правила могат да бъдат използвани многократно от различните езици. Например правилото описано по-долу ще е полезно за всеки език, който използва падежи за определяне на личните местоимения(аз, ти, той, ние, вие, те) и те могат да се изпускат.

Започнете като всички други с основна структура:

<?xml version="1.0" encoding="UTF-8"?>
<transfer>

</transfer>

Тъй като в момента игнорираме падежа трябва само да направим правило, което да взема граматичните символи на входа и да ги извежда отново.

Първо трябва да се дефинират категории и атрибути. Категориите и атрибутите позволяват да групираме граматични символи. Категориите позволяват да групираме символи за съвпадение, например 'n.*' за всички съществителни(nouns). Атрибутите позволяват да се групират символи, от които може да се избира. Например 'sg' и 'pl' могат да се групират в атрибута число (number).

Нека да добавим необходимите раздели:

<section-def-cats>

</section-def-cats>
<section-def-attrs>

</section-def-attrs>

Тъй като само спрягаме съществителните в единствено и множествено число трябва да добавим категория за съществителни и атрибут за число. Нещо като следващото ще бъде достатъчно:

В section-def-cats се добавя:

<def-cat n="nom">
   <cat-item tags="n.*"/>
</def-cat>

Това прихваща всички съществителни (леми след които има <n> и след това каквото и да е друг) и се отнася към тях като с "nom"(ще демонстрираме използването му по-късно).

В секцията section section-def-attrs се добавя:

<def-attr n="nbr">
   <attr-item tags="sg"/>
   <attr-item tags="pl"/>
</def-attr>

и след това

<def-attr n="a_nom">
   <attr-item tags="n"/>
</def-attr>

Първото дефинира атрибута nbr(номер), който може да бъде и в единствено(sg) и в множествено число(pl).

Второто дефинира атрибута a_nom (атрибут съществително).

Следва да добавим секция за глобални променливи:

<section-def-vars>

</section-def-vars>

Тези променливи се използват за съхранение или трансфер на атрибути между правила. Необходимо ни е само едно за сега:

<def-var n="number"/>

Накрая добавяме правило, което да приеме съществителното и да го генерира в правилната форма. Ще ни трябва секция с правила...

<section-rules>

</section-rules>

Като сменяме стъпката от предишния пример ще покажем правилото, след това ще го разгледаме, отколкото наобратно.

<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>

Първия таг е очевиден, той дефинира правило. Втория таг основно казва: "приложи правилото, ако примера е намерен". В този случай примера се състои от едно съществително (дефинирано от категорията nom). Забележете, че примерите се съпоставят по правилото на по-дългото съвпадение е първо. Така че ако имате три правила, пърото прихваща "<prn><vblex><n>", второто прихваща "<prn><vblex>", третото прихваща "<n>", примера който ще съвпадне и правилото, което ще се изпулни е първото.

За всеки пример има свързано действие, което генерира определен изход. Изхода е лексическа мярка (lu).

Клип тага позволява на потребителя да избира и манипулира атрибути и части на лексическия параграф на входния език (side="sl"), или изходния език (side="tl").

Нека да го компилираме и да го тестваме. Правилата за трансфер се компилират с:

$ apertium-preprocess-transfer apertium-ru-bg.trules-ru-bg.xml trules-ru-bg.bin

Файла trules-ru-bg.bin ще бъде създаден.

Сега вече сме готови да тестваме нашата система за машинен превод. Липсва една важна част, част на говора (PoS) тагер, но той ще бъде описан скоро. Междувременно можем да тестваме по следния начин:

Първо да анализираме думата граммофоны:

$ echo "граммофоны" | lt-proc ru-bg.automorf.bin 
^граммофон/граммофон<n><pl>$

Обикновенно тук тагера PoS ще избере правилната версия на базата на част от речта, но тъй като нямаме PoS тагер все още можем да използваме следния елементарен gawk скрипт (благодарение на Segio), който просто ще ни даде първия елемент, който е получен.

$ echo "граммофоны" | lt-proc ru-bg.automorf.bin | \
  gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \
^граммофон<n><pl>$

Сега нека да обработим резултата с правило за трансфер:

$ echo "граммофоны" | lt-proc ru-bg.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-ru-bg.trules-ru-bg.xml trules-ru-bg.bin ru-bg.autobil.bin

Това ще ни даде:

^грамофон<n><pl>$^@
  • 'грамофон' е изходният език (side="tl") лема (lem) на позиция 1 (pos="1").
  • '<n>' е a_nom на изходния език на позиция 1.
  • '<pl>' е атрибута за число (nbr) на изходния език на позиция 1.

Опитайте се да коментирате едно от тези клипови твърдения, да компилирате отново и да видите какво се случва.

Така, сега имаме изхода от прехвърлянето, единственото което остава е да се генерират спрегнатите форми на изходния език. За тази цел ние използваме lt-proc, но в режим на генериране (-g), не на анализ.

$ echo "граммофоны" | lt-proc ru-bg.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-ru-bg.trules-ru-bg.xml trules-ru-bg.bin ru-bg.autobil.bin | \
  lt-proc -g ru-bg.autogen.bin

грамофони\@

И c'est ca. Сега имате система за машинен превод, която превежда съществително от руски в съществително на български. Очевидно това не е много полезно, но скоро ще се спрем на по-сложните неща. А, и не се тревожете за символа '@', ще обясня това скоро.

Помислете за няколко други думи, които се спрягат по същия начин като грамофон. Какво ще кажете за добавянето на тези. Не трябва да добавяме никакви парадигми, само записите в главната секция на едноезичните и двуезичните речници.

Да вкараме глаголите в играта

Добре, имаме система, която превежда съществителни, но това е доста безполезно, ние искаме също така да превеждаме глаголи и дори цели изречения! Какво ще кажете да започнем с глагола "да видя". В руския това е "увидеть". Руският е език с нулев подлог, това означава, че в някои случаи не се използват лични местоимения преди спрегнатата форма на глагола. Например: Виждам на български би било преведено като вижу на руски.

  • Вижу
  • виждам<p1><sg>
  • Аз виждам

Забележка: <p1> обозначава първо лице

Това ще бъде важно когато трябва да напишем правилото за прехвърляне на глаголи. Други примери за нулев подлог включват: испански, румънски и полски. Също така има и последицата, че докато ние само се нуждаем да добавим глагола в руския морфологичен речник, трябва да добавим както глагола, така и личните местоимения в българския морфологичен речник. Ще минем и през двете.

Другите форми на глагола увидеть са: видиш, видит, видим, видите и видут; които съответстват на: ти виждаш (единствено), той вижда, ние виждаме, вие виждате (множествено число) и те виждат.

Има две форми на вие виждате, едната е в множествено число (виждате) и другата е в единствено формално число (Виждате).

Ще се опитаме да преведем изречението: "Видим граммофоны" във "Виждам грамофони". Всъщност, само ще добавим достатъчно информация да направим превода и ще оставим попълването на парадигмите (добавянето на другото спрежение на глагола) като задача на читателя.

Първото нещо, което трябва да направим е да добавим повече символи. Първо трябва да добавим символ за 'глагол', което ще наречем "vblex" (това означава лексикален глагол, обратно на модални глаголи и други типове). Глаголите имат 'лице' и 'време' заедно с число, така че нека да добавим също така няколко от тези. Трябва да преведем "Аз виждам", така че за лице трябва да добавим "p1" или 'първо лице' и за време "pri" или 'сегашно изявително'.

<sdef n="vblex"/>
<sdef n="p1"/>
<sdef n="pri"/>

След като сме приключили с това, същото със съществителните, добавяме парадигма за спрягането на глагола. Първият ред ще бъде:

<pardef n="вид/ите__vblex">

'/' се използва да разграничава къде се добавят stems-ите (частите между таговете <l> </l>).

След това окончанието за първо лице, единствено число:

<e>
   <p>
     <l>им</l>
     <r>ите<s n="vblex"/><s n="pri"/><s n="p1"/><s n="sg"/></r>
   </p>
</e>

'им' обозначава края (като при 'видим'), необходимо е да се добави 'ите' към секцията <r>, тъй като това ще бъде отрязано от дефиницията. Останалото е сравнително лесно, 'vblex' е лексикален глагол, 'pri' е сегашно изявително наклонение, 'p1' е първо лице и 'sg' е единствено число. Можем също да добавим множественото число, което ще бъде същото, освен 'име' вместо 'им' и 'pl' вместо 'sg'.

След това трябва да добавим лема, парадигмично картографиране към главния раздел:

<e lm="видите"><i>вид</i><par n="вид/ите__vblex"/></e>

Забележка: съдържанието на <i> </i> е коренът, не лемата.

Това е работата по руския речник, която сме свършили за сега. Нека да го компилираме и изпробваме.

$ lt-comp lr apertium-ru-bg.ru.dix ru-bg.automorf.bin
main@standard 23 25
$ echo "видим" | lt-proc ru-bg.automorf.bin
^видим/видите<vblex><pri><p1><sg>$
$ echo "видим" | lt-proc ru-bg.automorf.bin
^видим/видите<vblex><pri><p1><pl>$

Добре, сега правим същото и за българския речник (не забравяйте да добавите същите символни дефиниции, каквито добавихте за руския речник).

Парадигмата е:

<pardef n="s/ee__vblex">

защото миналото време е 'видях'. Сега можем да направим едно от двете неща, можем да добавим и първо, и второ лице, но те са в една и съща форма. Фактически, всички форми (освен трето лице, единствено число) на глагола 'да видя' са 'виждам'. Така че вместо това ние правим само един запис за 'виждам' и му задаваме само символа 'pri'.

<e>
   <p>
     <l>м</l>
     <r>м<s n="vblex"/><s n="pri"/></r>
   </p>
</e>

и както винаги, запис в главния раздел:

<e lm="виждам"><i>е</i><par n="вижда/м__vblex"/></e>

Тогава нека да запишем, да прекомпилираме и изпробваме:

$ lt-comp lr apertium-ru-bg.bg.dix bg-ru.automorf.bin
main@standard 18 19

$ echo "виждам" | lt-proc bg-ru.automorf.bin
^виждам/виждам<vblex><pri>$

Сега за задължителния запис в двуезичния речник:

<e><p><l>видите<s n="vblex"/></l><r>виждате<s n="vblex"/></r></p></e>

(отново, не забравяйте да добавите sdefs от по-рано)

И прекомпилираме:

$ lt-comp lr apertium-ru-bg.ru-bg.dix ru-bg.autobil.bin
main@standard 18 18
$ lt-comp rl apertium-ru-bg.ru-bg.dix bg-ru.autobil.bin
main@standard 18 18

Сега изпробваме:

$ echo "видим" | lt-proc ru-bg.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-ru-bg.trules-ru-bg.xml trules-ru-bg.bin ru-bg.autobil.bin 

^виждаме<vblex><pri><p1><sg>$^@

Анализът преминава правилно, но когато се опитаме да генерираме повърхностна форма, получаваме '#' като по-долу:

$ echo "видим" | lt-proc ru-bg.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-ru-bg.trules-ru-bg.xml trules-ru-bg.bin ru-bg.autobil.bin | \
  lt-proc -g ru-bg.autogen.bin
#виждам\@

Като '#' означава, че генераторът не може да генерира правилната лексикална форма, защото не я съдържа. Защо се получава така?

Принципно, анализите не съвпадат, 'виждам' в речника е виждам<vblex><pri>, но виждам получено от трансфера е видим<vblex><pri><p1><sg>. В руската страна има повече информация отколкото българската страна се нуждае. Можете да изпробвате това като добавите липсващите символи към българския речник, и след това прекомпилирате и тествате отново.

Все пак, по-парадигматичен начин да се погрижим за това е като напишем правило. Така, отваряме файлът с правилата (apertium-ru-bg.trules-ru-bg.xml в случай, че сте забравили).

Трябва да добавим нова категория за 'глагол'.

<def-cat n="vrb">
   <cat-item tags="vblex.*"/>
</def-cat>

Също така трябва да добавим атрибути за глаголно време и лице. Ще го направим много просто за сега, можете да добавите p2 и p3, но аз няма да го направя, за да спестя място.

<def-attr n="temps">
   <attr-item tags="pri"/>
</def-attr>

<def-attr n="pers">
   <attr-item tags="p1"/>
</def-attr>

Трябва също да добавим атрибут за глаголи.

<def-attr n="a_verb">
   <attr-item tags="vblex"/>
</def-attr>

Сега върху правилото:

<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>

Спомнете си когато се опитахте да махнете коментара на 'clip' таговете в предишния пример с правило и те изчезнаха от трансфера, ами, това е доста от което правим тук. Въвеждаме глагол с пълен анализ, но извеждаме само частичен анализ (лема + таг на глагола + таг на глаголното време).

Така че сега ако го прекомпилираме, получаваме:

$ echo "видим" | lt-proc ru-bg.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-ru-bg.trules-ru-bg.xml trules-ru-bg.bin ru-bg.autobil.bin
^виждам<vblex><pri>$^@

и:

$ echo "видим" | lt-proc ru-bg.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-ru-bg.trules-ru-bg.xml trules-ru-bg.bin ru-bg.autobil.bin | \
  lt-proc -g ru-bg.autogen.bin
виждаме\@

Опитайте с 'видиме' (ние виждаме) да видите дали получавате правилния изход.

Сега опитайте с "видим граммофоны":

$ echo "видим граммофоны" | lt-proc ru-bg.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-ru-bg.trules-ru-bg.xml trules-ru-bg.bin ru-bg.autobil.bin | \
  lt-proc -g ru-bg.autogen.bin
виждаме грамофони\@

Но какво да кажем за личните местоимения?

Ами, това е страхотно, но все още ни липсва личното местоимение, което е необходимо за българския. За да го добавим, трябва първо да редактираме българския морфологичен речник.

Както преди, първото нещо да направим е да добавим необходимите символи:

<sdef n="prn"/>
<sdef n="subj"/>

От двата символа, prn е местоимение и subj е подлог (като в подлога на изречение).

Защото няма корен или 'лема' за подлози лични местоимения, просто добавяме pardef както следва:

<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>

Като 'prsubj' е 'личен подлог'. Останалите от тях (Вие, Ние и др.) са оставени като упражнение за читателя.

Можем да добавим запис към основния раздел както следва:

<e lm="подлози за лично местоимение"><i/><par n="prsubj__prn"/></e>

Така, записваме, прекомпилираме и тестваме, и трябва да получим нещо като:

$ echo "I" | lt-proc bg-ru.automorf.bin
^аз/prpers<prn><subj><p1><sg>$

Сега трябва да коригираме правилото за 'глагол' да изкара подлог лично местоимение заедно с правилната форма на глагола.

Първо, добавяме категория (това трябва да бъде доста прозаично за сега):

<def-cat n="prpers">
   <cat-item lemma="prpers" tags="prn.*"/>
</def-cat>

Сега добавяме типовете местоимение като атрибути, можем да добавим и типа 'obj' като сме на него, въпреки че няма да ни трябва за сега:

<def-attr n="tipus_prn">
   <attr-item tags="prn.subj"/>
   <attr-item tags="prn.obj"/>
</def-attr>

И сега да въведем правилото:

<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>

Това е почти същото правило като преди, само ще направим няколко малки промени.

Трябваше да изкараме:

^prpers<prn><subj><p1><sg>$ ^виждам<vblex><pri>$

така че генераторът да може да избере правилното местоимение и правилната форма на глагола.

Така че накратко:

  • <lit>, отпечатва буквен низ, в този случай "prpers"
  • <lit-tag>, отпечатва буквен таг, защото не можем да вземем таговете от глагола ги добавяме сами, "prn" за местоимение и "subj" за подлог.
  • , отпечатва празно пространство.

Забележете, че получихме информацията за номер и време директно от глагола.

Така, сега ако го прекомпилираме и тестваме отново:

$ echo "вижу граммофоны" | lt-proc ru-bg.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-ru-bg.trules-ru-bg.xml trules-ru-bg.bin ru-bg.autobil.bin | \
  lt-proc -g ru-bg.autogen.bin
Аз виждам грамофони

Което, макар и да не е точно проза на лауреат (много харесвам това HOWTO), е относително точен превод.

Кажи ми за грамофона (Мултидуми)

Докато грамофон е английска дума, това не е най-добрият превод. Грамофон обикновено се използва за много стар вид, който вие познавате с игла вместо с щифт без усилване. По-добър превод би бил 'възпороизвеждащ запис'. Въпреки че това е повече от една дума, може да го разглеждаме като, че е една дума като използваме конструкции на мултидуми (multipalabra).

Не трябва да пипаме руския речник, само българския и двуезичния, така че го отворете.

Множественото число на 'възпороизвеждащ запис' е 'възпороизвеждащи записи', така че да приема същата парадигма като грамофон (грамофон__n) — при това ние просто добавихме 'и'. Всичко, което е необходимо да направим е да добавим нов елемент към главния раздел.

<e lm="възпороизвеждащ запис"><i>запис<b/>възпроизвеждащ</i><par n="грамофон__n"/></e>

Единственото различно тук е използването на тага , въпреки че това не е изцяло ново както го видяхме в употреба във файлът с правила.

Така, прекомпилираме и тестваме в старата последователност:

$ echo "вижу граммофоны" | lt-proc ru-bg.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-ru-bg.trules-ru-bg.xml trules-ru-bg.bin ru-bg.autobil.bin  | \
  lt-proc -g ru-bg.autogen.bin
Аз виждам възпороизвеждащи записи

Перфектно. Голяма полза от използването на мултидуми е, че можете да превеждате идиоматични изрази дословно, без да се налага да превеждате дума-по-дума. Например българската фраза "в момента" би била преведена на руски като "в данный момент" — преводът на тази българска фраза в руски не би бил възможен дума по дума.

Справяне с незначително изменение

Българският обикновено има няколко начина за изговаряне на всяка дума заради диалектните варианти. Има яка фонетична писмена система, така че се пише както се изговаря. Например, хората говорещи в Западна България биха казали "млеко", докато някой говорещ в Източна България би казал "мляко", което отразява разликите в произношението на прото-славянската гласна ят.

Анализ

Трябва да има относително лесен начин за справяне с това, и има, отново чрез използване на парадигми. Парадигми не се използват само за добавяне на граматични символи, но те също така могат да бъдат използвани да заменят всеки знак/символ с друг. Например, ето парадигма за приемане на "e" и "я" в анализа. Парадигмата трябва, както другите, да отиде в едноезичния българския речник.

  <pardef n="е_я__ят">
    <e>
      <p>
        <l>e</l>
        <r>e</r>
      </p>
    </e>
    <e>
      <p>
        <l>я</l>
        <r>e</r>
      </p>
    </e>
  </pardef>

Тогава в "основния раздел":

    <e lm="млеко"><i>r</i><par n="e_я__ят"/><i>е</i><par n="млек/о__n"/></e>

Но това само ни позволява да анализираме двете форми... необходима е повече работа, ако искаме да генерираме и двете форми.

Възпроизвеждане

Виж също