Sistem de Adnotare cu Parti de Vorbire a Unui Text In Limbaj Natural Utilizand Metode Statistice
Sistem de adnotare cu părți de vorbire a unui text în limbaj natural utilizând metode statistice
Introducere
Dionysius Thrax din Alexandris a creat o schiță gramaticală pentru limba greacă(“technē”) care conținea informații lingvistice pentru acea perioadă. Această lucrare este sursa directă a unei proporții uimitoare a vocabularului nostru lingvistic modern, incluzând printre multe alte cuvinte, sintaxă, diftongi și analogii. De asemenea sunt incluse și descrierile a opt părți de vorbire: substantiv, verb, pronume, prepoziție, adverb, conjuncție, participiu, și articol. Deși au mai fost și alții (ca Aristotle sau Stoics) care aveau listele lor cu părți de vorbire, setul de opt a lui Thrax a devenit practic, baza, pentru următorii 200 de ani, a tuturor descrierilor subsecvențelor părților de vorbire grecești, latine și majorității limbajelor europene.
Schoolhouse Rock a fost un serial reușit de 3 minute de clipuri muzicale animate, difuzat pentru prima dată la televizor în 1973. Serialul a fost realizat pentru a inspira copii să învețe tabla înmulțirii, gramatică, știința de bază și istoria. Secvența Grammar Rock, de exemplu, includea cântece despre părți de vorbire. De fapt, Grammar Rock a fost remarcabil de tradițional în scrierea gramaticală, cuprinzând exact opt cântece despre părți de vorbire (deși lista a fost ușor modificată din originalul Thrax, substituind adjectivul și interjecția la originalul participiu și articol).
Listele de părți de vorbire mai recente (denumite și POS (part of speach), clase de cuvinte, clase morfologice, sau părți lexicale) au un număr mai mare de clase de cuvinte (45 pentru Penn Treebank (autor Marcus, 1993), 87 pentru corpus-ul Brown (autor Francis, 1979; autori Francis and Kučera, 1982), și 146 pentru setul de adnotări C7 (autor Garside, 1997)).
Importanța părților de vorbire pentru procesarea limbajului este aceea de a da o semnificativă cantitate de informație despre cuvânt și vecinii acestuia. Acest lucru este adevărat pentru majoritatea categoriilor (verb versus substantiv), dar este adevărat și pentru multe distincții subtile. De exemplu, aceste adnotări fac diferența dintre pronumele posesiv (my, your, his, her, its) și pronumele personal (I, you, he, me). Cunoscând faptul că pronumele este personal sau posesiv, putem afla ce cuvânt se află în vecinătatea acestuia (pronumele posesive sunt de obicei urmate de un substantiv, iar pronumele personale de un verb).
O parte de vorbire a unui cuvânt ne arată cum poate fi pronunțat un cuvânt. Cuvântul content, se exemplu, poate fi un substantiv sau un adjectiv. Sunt pronunțate diferit (substantivul este pronunțat CONtent și adjectivul conTENT). Partea de vorbire poate produce o pronunție mai naturală într-un sistem de sinteză a vorbirii și mai precisă într-un sistem de recunoaștere a limbajului. (Alte astfel de perechi include Object (substantiv) și obJECT (verb), DIScount (substantiv) și disCOUNT (verb)).
Părțile de vorbire sunt folosite foarte des în texte “de analiză parțială”, de exemplu pentru aflarea rapidă a unor nume sau alte expresii, pentru aplicații de extracție a informației. În concluzie, un corpus ce a fost marcat ca parte de vorbire este foarte folositor în cercetarea lingvistică, de exemplu în ajutarea găsirii unor exemple sau frecvențe de construcții particulare în corpus-uri mari.
În cele ce urmează, se va face un rezumat a claselor de cuvinte în engleză, urmat de o descriere de diferite seturi de adnotări pentru o codare formală a acestor clase, iar în următoarele secțiuni se vor aborda trei algoritmi de adnotare: adnotare rule-based, adnotare stochastică, și adnotare transformation-based.
1. Părți de vorbire, notații folosite în diferite corpus-uri
1.1. Clase de cuvinte în engleză
Până acum s-au folosit termeni de părți de vorbire ca substantive și verbe mai mult general. În această secțiune, vom da o definiție mai completă a acestora și a altor clase. Tradițional, definiția părții de vorbire a fost bazată pe funcții morfologice și sintactice; cuvinte ce funcționează similar în funcție de ce poate apărea în apropiere (“proprietățile lor distributive”), sunt grupate în clase. În timp ce clasele de cuvinte au tendințe spre coerență semantică (substantivele descriu deseori “oameni, locuri, sau lucruri”, și adjectivele deseori descriu proprietăți (însușiri), acesta nu este neapărat adevărat în toate cazurile, și în general nu folosim coerență semantică ca un criteriu de definire pentru părțile de vorbire.
Părțile de vorbire pot fi împărțite în două super-categorii: tipuri de clase închise și tipuri de clase deschise. Clasele închise sunt cele care au legături relativ fixe. De exemplu, prepozițiile sunt o clasă închisă pentru că ele, în engleză, sunt un set fix; prepoziții noi sunt inventate rar. Prin contrast substantivele și verbele sunt clase deschise pentru că substantive și verbe noi sunt descoperite în continuu sau sunt împrumutate din alte limbi (de exemplu, noul verb to fax sau substantivul împrumutat futon). Este posibil ca orice vorbitor sau corpus să aibă diferite cuvinte din clase deschise, dar toți vorbitorii unei limbi, și grupări, ce sunt destul de mari, partajează cuvintele clasei închise. Cuvintele claselor închise sunt, în general, și cuvinte funcționale; acestea (cuvintele funcționale) sunt cuvinte gramaticale ca of, it, and sau you, care tind să fie foarte scurte, apar frecvent, și joacă un rol important în gramatică.
Sunt patru clase deschise majore întâlnite în limbile vorbite în ziua azi în lume: substantive, verbe, adjective și adverbe. Se pare că în engleză le găsim pe toate patru, deși nu toate limbile vorbite le au. Multe dintre ele nu au adjective. În limba nativă americană Lakhota, de exemplu, și de asemenea posibil în chineză, cuvinte care în engleză corespund adjectivelor, au rol de subclase a verbelor.
Orice limbă vorbită până acum are cel puțin cele două categorii de substantiv și verb (deși în unele limbi, de exemplu în Nootka, distincția este subtilă). Substantivul este numele dat clasei lexicale în care există cuvinte pentru oameni, locuri, sau lucruri. Dar, cum clasele lexicale, ca substantivul, sunt definite mai mult din punct de vedere funcțional (morfologic sau sintactic), decât semantic, unele cuvinte pentru oameni, locuri și lucruri s-ar putea să nu fie cuvinte pentru oameni, locuri sau lucruri. Astfel substantivele includ termeni concreți ca ship și chair,abstracți ca band-width și relationship, și termeni ca verbe, cum este pacing în His pacing to and fro became quite annoying. Ceea ce definește un substantiv în engleză așadar, sunt lucruri cum ar fi abilitatea lui de a exista cu determinanți (a goat, its bandwidth, Plato`s Republic), de a trece la forme posesive (IBM`s annual revenue), și pentru majoritatea substantivelor, de a exista în forme de plural (goats, abaci).
Tradițional, substantivele sunt grupate în substantive proprii și substantive comune. Substantivele proprii, ca Regina, Colorado și IBM, reprezintă numele unei persoane sau a unei entități. În engleză, ele nu sunt, în general, precedate de articole (de exemplu, the book is upstairs, dar Regina is upstairs). In engleza scrisă, substantivele proprii sunt capitalizate de obicei.
În multe limbi vorbite, inclusiv în engleză, substantivele comune sunt împărțite în substantive numărabile și substantive nenumărabile. Substantivele numărabile sunt cele care se pot număra gramatical; deci, ele pot apărea atât în formă de singular, cât și în formă de plural (goat/goats, relationship/relationships) și pot fi și numărate (one goat, two goats). Substantivele nenumărabile sunt folosite atunci când ceva este văzut ca un întreg. Cuvintele ca snow, slat și communism nu se pot număra (contraexemplu *two snows sau *two communisms). Substantivele nenumărabile pot apărea, de asemenea, și fără articol, spre deosebire de substantivele numărabile la singular (Snow is white dar nu și *Goat is white).
Clasa verbelor include majoritatea cuvintelor ce se refera la acțiuni și procese, inclusiv verbe principale cum ar fi draw, provide, differ și go. Verbele în engleză au un număr de forme morfologice (persoana 1 și a 2-a singular (eat), persoana a 3-a singular (eats), progresiv (eating), participiu trecut eaten).
A treia formă a claselor deschise în engleză sunt adjectivele; semantic, această clasă include mulți termeni ce descriu proprietăți sau calități. Majoritatea limbilor vorbite au adjective pentru conceptul de culoare (white, black), vârstă (old, young), și valoare (bun, rău), dar sunt limbaje care nu au adjective.
Ultima formă a claselor deschise în limba engleză, adverbele, este atât semantică, cât și formală (câte puțin din amândouă). De exemplu, Schachter (1985) demonstrează că într-o propoziție, ca cea care urmează, toate cuvintele italice sunt adverbe:
Unfortunately, John walked home extremely slowly yesterday.
Din punct de vedere semantic, cuvintele acestei clase au însușirea de a modifica: adverbe direcționale sau adverbe locative (home, here, downhill) care specifică direcția sau locația unei acțiuni; adverbe degree (ce ajută la formarea gradului comparativ) (extremely, very, somewhat) ele specificând extinderea unei acțiuni, a unui proces sau a unei proprietăți; adverbe de mod (slowly, slinkily, delicately) descriu modul unor acțiuni sau procese; adverbe de timp descriu timpul când are loc o acțiune sau întâmplare(yesterday, Monday). Datorită naturii eterogene a acestei clase, unele adverbe (de exemplu adverbele de timp ca Monday) sunt adnotate în scheme de adnotare ca și substantive.
Clasele închise diferă mai mult de la o limbă la alta, spre deosebire de clasele deschise. Iată o scurtă trecere în revistă a câtorva clase închise în engleză dintre cele mai importante și câteva exemple pentru fiecare:
prepoziții: on, under, over, near, by, at, from, to, with
determinanți: a, an, the
pronume: she, who, I, others
conjuncții: and, but, or, as, if, when
verbe auxiliare: can, may, should, are
participii: up, down, on, off, in, out, at, by
numerale: one, two, three, first, second, third
Prepozițiile apar înaintea unei părți substantivale a frazei (noun phrase); semantic, ele sunt relaționale, indicând adesea relații spațiale sau temporale, literal (on it, before then, by the house) sau metaforic (on time, with gusto, beside herself). Dar deseori indică și alte legături (Hamlet was written by Shakespeare). Tabelul de mai jos conține prepoziții în engleză culese din dicționarul on-line CELEX (Celex, 1993), sortate în funcție de frecvența lor în corpus-ul COBUILD (http://www.fact-index.com/c/co/cobuild.html) cu 16 milioane de cuvinte în engleză. Deci aceasta nu se poate considera o listă definitivă. În alte dicționare clasele de cuvinte s-ar putea să fie etichetate diferit. Această listă combină prepoziții și particule.
Prepoziții (și particule) în engleză din dicționarul on-line CELEX.
Numărarea frecvenței este din corpus-ul COBUILD cu 16 milioane de cuvinte
O “particulă” (particle) este un cuvânt care se aseamănă cu prepoziția sau adverbul, și care adesea se combină cu verbe pentru a forma partea verbală a frazei (verb phrase), ca în exemplul următor:
So I went on for some days cutting and hewing timber…
Moral reform is the effort to throw off sleep…
Putem observa că acestea sunt mai curând particule decât prepoziții , pentru că în primul exemplu, on este urmat de o adevărată expresie prepozițională și nu de o parte substantivală a frazei (noun phrase). Cu ajutorul părților verbale a frazei (verb phrase) tranzitive, ca în al doilea exemplu, putem afirma că off este o particulă și nu o prepoziție pentru că particulele pot apărea după obiectele lor (throw sleep off precum și throw off sleep). Acest lucru nu este posibil și pentru prepoziții (The horse went off its track, dar nu și *The horse went its track off).
În [1] sunt puse la dit its track off).
În [1] sunt puse la dispoziție lista de particule, ce urmează, formate dintr-un singur cuvânt. Din moment ce este foarte greu de a diferenția automat particulele de prepoziții, unele liste de adnotări (ca cea folosită pentru CELEX) nu le pot diferenția, și chiar și pentru corpus-uri care pot face diferența (ca Penn Treebank, http://bulba.sdsu.edu/jeanette/thesis/PenTags.html) este foarte greu de a face distincția sigură într-un proces automat.
Listă de particule, în engleză, formate dintr-un singur cuvânt din Quirk et al.(1985). [1]
O clasă închisă particulară mică este articolul: în engleză sunt trei: a, an, și the (deși this (ca în this chapter) și that (ca în that page) sunt, de asemenea, incluse deseori). Articolele le găsim de obicei la începutul unei noun phrase. A și an marchează propoziția ca fiind nehotărâtă, în timp ce the o poate marca ca formă hotărâtă. Articolele sunt foarte frecvente în engleză; într-adevăr the este cel mai des întâlnit cuvânt în majoritatea corpus-urilor în engleză.
Iată statistica COBUILD, din nou dintre 16 milioane de cuvinte:
the 1,071,676
a 413,887
an 59,359
Conjuncțiile sunt folosite pentru a unii două expresii, clauze, sau propoziții. Conjuncțiile coordonatoare ca and, or, sau but, unesc două elemente de același fel. Conjuncțiile subordonatoare sunt folosite atunci când elemente nu sunt de același fel. De exemplu that în “I thought that you might like some milk” este o conjuncție subordonatoare care leagă clauza principală I thought cu clauza subordonată you might like some milk. Această clauză se numește subordonată pentru că ea reprezintă întregul “conținut” al verbului principal thought. Conjuncțiile subordonatoare ca that, care leagă un verb de argumentul său în acest fel , mai sunt numite și completive.
Conjuncții coordonatoare si subordonatoare în engleză din dicționarul on-line CELEX.
Numărarea frecvenței este din COBUILD (16 milioane de cuvinte).[1]
Pronumele sunt forme care se comportă ca și un fel de prescurtare când ne referim la o parte substantivală a frazei sau entitate sau eveniment. Pronumele personale se referă la persoane sau entități (you, she, I, it, me, etc.). Pronumele posesive sunt forme ale pronumelor personale care indică fie posesia în sine sau, de cele mai multe ori, indică o relație abstractă între o persoană și un obiect (my, your, his, her, its, one’s, their). Pronumele Wh- (what, who, whom, whoever) sunt folosite în anumite forme de întrebare, sau pot, de asemenea, să fie completive. (Frieda, who I met five years ago…).
Pronume în engleză din dicționarul on-line CELEX. Numărarea frecvențelor este din
COBUILD (16 milioane de cuvinte). [1]
O clasă închisă de subtipuri a verbelor în engleză sunt verbele auxiliare. Din punct de vedere lingvistic, auxiliarele sunt cuvinte (de obicei verbe) ce marchează o anumită trăsătură semantică a unui verb principal, inclusiv dacă o acțiune are loc în prezent, trecut sau viitor (referindu-ne la timp), și indiferent dacă o acțiune este necesară, posibilă, sugerată, dorită, etc. (referindu-ne la mod).
Auxiliarele în engleză includ verbul copulativ be, cele două verbe do și have, împreună cu formele lor derivate, și de asemenea o clasă de verbe modale. Be este denumit copulativ pentru că el leagă subiecte cu anumite tipuri de predicate nominale și adjective (He is a duck). Verbul have este folosit, de exemplu, pentru a marca timpul perfect (I have gone, I had gone), în timp ce be este folosit ca parte a construcțiilor pasive (We were robbed ), sau progresive (We are leaving). Modalele sunt folosite pentru a marca modul asociat cu evenimentul sau acțiunea înfățișate de verbul principal. Astfel can indică abilitatea sau posibilitatea, may indică permisiunea sau posibilitatea, must indică necesitatea și așa mai departe. În plus față de verbul copulativ have menționat mai sus, este un verb modal have ( I have to go), care este foarte comun în vorbirea engleză. Nici el, nici verbul modal dare, care este foate rar, nu au numărare de frecvență pentru că dicționarul CELEX nu distinge sensul verbului principal (I have three oranges, He dared me to eat them), de verbul modal (There has to be some mistake, Dare I confront him?) de sensul verbului auxiliar (I have never seen that).
Verbe modale în engleză din dicționarul on-line CELEX.
Numărarea frecvențelor este din COBUILD (16 milioane de cuvinte). [1]
Engleza are, de asemenea, și cuvinte cu funcții mai mult sau mai puțin unice, inclusiv interjecții (oh, ah, hey, man, alas), negații (no, not), expresii de politețe (please, thank you), expresii de salut (hello, goodbye), si existențialul there (there are two on the table) alături de altele. Faptul că aceste clase au desemnate nume particulare sau sunt luate împreună (ca interjecții sau chiar adverbe) depinde de scopul etichetării.
1.2. Adnotări pentru limba engleză
În secțiunea precedentă s-a făcut o descriere generală a varietății claselor lexicale în care se pot întâlni cuvintele limbii engleze. Această secțiune descrie notațiile existente, folosite în adnotarea părților de vorbire, pentru pregătirea algoritmilor variați ce vor fi descriși în secțiunile ce urmează.
Există un număr restrâns de adnotări populare pentru limba engleză, dintre care multe s-au dezvoltat din cele 87 de adnotări folosite pentru corpusul Brown (autori Francis and Kučena, 1982). Trei dintre cele mai des folosite sunt setul mic de 45 de adnotări Penn Treebank (autor Marcus, 1993), setul de mărime medie de 61 de adnotări C5 folosit de proiectele Lancaster UCREL-ului CLAWS (the Constituent Likelihood Automatic Word-tagging System) pentru a adnota corpusul britanic național (the British National Corpus – BNC) (autor Garside, 1997), și setul cel mai mare de 146 de adnotări C7 (autor Leech, 1994). În această secțiune se va prezenta cea mai mică dintre ele, setul Penn Treebank, și apoi se va discuta despre adnotări specifice suplimentare din celelalte seturi.
Adnotări de părți de vorbire Penn Treebank (inclusiv punctuație).
Setul Penn Treebank, din tabelul de mai sus, a fost aplicat corpus-ului Brown și alte câteva corpus-uri. Iată un exemplu de propoziție adnotată din versiunea Penn Treebank al corpus-ului Brown (într-un fișier ASCII, adnotările sunt de obicei reprezentate după fiecare cuvânt, precedate de “/”, dar adnotările pot fi reprezentate în diferite alte moduri):
The/DT grand/JJ jury/NN commented/VBD on/IN a/DT number/NN of/IN
other/JJ topics/NNS ./.
Setul Penn Treebank a fost adaptat după setul original de 87 de adnotări pentru corpus-ul Brown. Acest set redus omite informații care pot fi recuperate din identitatea punctului lexical. De exemplu setul original Brown de adnotări și alte seturi mai mari ca C5 includ câte o adnotare separată pentru fiecare formă diferită a verbelor do (C5 adnotarea “VDD” pentru did și “VDG” pentru doing), be, și have. Acestea au fost omise din setul Penn.
Anumite distincții sintactice nu au fost marcate în setul Penn Treebank pentru că propozițiile Treebank au fost analizate, nu numai adnotate, și așa unele informații sintactice sunt reprezentate în structura frazei. De exemplu, prepozițiile și conjuncțiile subordonatoare au fost combinate în simpla adnotare IN, din moment ce structura tree a propoziției le-a dezambiguat (conjuncțiile subordonatoare preced întotdeauna clauze, prepozițiile preced părți substantivale a frazei sau expresii prepoziționale).
Cu toate acestea, majoritatea situațiilor de adnotare, nu implică corpus-uri analizate; din acest motiv setul Penn Treebank nu este de ajuns pentru mulți dintre utilizatori. Setul de adnotări C7, de exemplu, face distincția dintre prepoziții (II) și conjuncții subordonatoare (CS), și distinge prepoziția to (II) de cuvântul ce marchează infinitivul to (TO).
Care dintre adnotările date se va folosi într-o aplicație particulară depinde, bineînțeles, de câtă informație are nevoie aplicația.
1.3. Procesul de adnotare a părților de vorbire
Adnotarea părților de vorbire (sau doar adnotare pe scurt) este procesul de desemnare a părților de vorbire sau a altor notații a claselor lexicale pentru fiecare cuvânt din corpus. Adnotările sunt atribuite de obicei și semnelor de punctuație; astfel adnotarea pentru limbajul natural este același proces ca tokenization pentru limbajele de programare, deși adnotările pentru limbajele naturale sunt mult mai neclare. Așa cum s-a sugerat la început, adnotările joacă un rol important în creștere în recunoașterea vorbirii, analiza limbajului natural și regăsirea informației.
Datele de intrare într-un algoritm de adnotare este un șir de cuvinte și un anumit set de adnotare dintre cele descrise in secțiunea precedentă. Datele de ieșire sunt, de fapt, o singură, și cea mai bună, adnotare pentru fiecare cuvânt. De exemplu, iată câteva propoziții din corpus-ul ATIS de dialoguri despre rezervări pentru călătoriile cu avionul. Pentru fiecare este realizată o potențială adnotare folosind setul Penn Treebank a cărui tabel este dat în secțiunea precedentă:
VB DT NN .
Book that flight .
VBZ DT NN VB NN ?
Does that flight serve dinner ?
Chiar și în aceste exemple simple, desemnarea automată a unei adnotări pentru fiecare cuvânt nu este banală. De exemplu, book este ambiguu. Aceasta însemnând că are mai mult de o singură folosință și parte de vorbire. Poate fi verb (ca în book that flight sau to book the suspect) sau un substantiv (ca în hand me that book, sau a book of matches). Similar, that poate fi un determinant (ca în Does that flight serve dinner), sau părți de vorbire complementive (ca în I thought that your flight was earlier). Problema adnotării părților de vorbire este de a rezolva aceste ambiguități, alegând adnotarea potrivită în acel context.
Cât de grea este problema adnotării? Majoritatea cuvintelor în engleză sunt concrete; adică au doar o singură adnotare. Dar multe dintre cele mai comune cuvinte în engleză sunt neclare (de exemplu can poate fi un auxiliar (‘to be able’), un substantiv (‘a metal container’), sau un verb (‘to put something in such a metal container’)). De fapt în reporturile lui DeRose (1988) în care doar 11.5% dintre tipurile cuvintelor în engleză din Brown Corpus sunt neclare, peste 40% dintre aparițiile din corpus-ul Brown sunt ambigue. Un tabel al ambiguității adnotării este următorul [1]:
Numărul tipurilor de cuvinte în corpus-ul Brown după gradul de ambiguitate
(după DeRose (1988)).
Din fericire, se pare că multe dintre cele 40% de apariții de cuvinte ambigue sunt ușor de clarificat. Aceasta este posibilă pentru că variatele adnotări asociate unui cuvânt nu sunt chiar la fel. De exemplu, a poate fi un determinant, sau litera a (probabil ca parte a acronimului sau a unei inițiale), dar sensul determinantului este mult mai probabil.
Majoritatea algoritmilor de adnotare se află în una dintre cele două clase: adnotări rule-base (bazată pe reguli) și adnotări shochastice. Adnotările rule-based implică în general o bază de date mare cu reguli de dezambiguare scrise de mână, ce specifică, de exemplu, că un cuvânt ambiguu este mai degrabă un substantiv decât un verb dacă urmează după un determinant. În următoare secțiune se va descrie un exemplu de adnotare rule-based, ENGTWOL, bazată pe arhitectura gramaticilor de constrângeri [1].
Adnotările stochastice în general rezolvă ambiguitățile adnotării folosind un corpus de antrenament pentru a calcula probabilitatea unui cuvânt dat de a avea o adnotare dată într-un anumit context. Într-una dintre secțiunile ce urmează se va descrie o adnotare stochastică numită adnotare HMM, numită de asemenea și Maximum Likelihood Tagger, sau adnotare Hidden Markov model.
În altă secțiune se va descrie o metodă apropiată adnotării numită adnotare transformation-based (bazată pe transformare) sau adnotarea Brill, denumită astfel după Brill (1995). Adnotarea Brill conține trăsături ale ambelor arhitecturi de adnotare. La fel ca și adnotarea rule-based, este bazată pe reguli care determină când un cuvânt ambiguu trebuie să aibă o adnotare dată. La fel ca și adnotarea stochastică, are un component de interpretare a mașinii: regulile sunt induse automat dintr-un corpus de adnotare realizat anterior.
2. Algoritmi de adnotare
2.1. Adnotarea pe baza unor reguli (Ruled-Based) a părților de vorbire
Primii algoritmi de desemnare automată a părților de vorbire se bazau pe o arhitectură cu două stagii (Harris, 1962; Klein and Simmons, 1963; Greene and Rubin, 1971)[5]. În primul stagiu se folosea un dicționar pentru a desemna fiecărui cuvânt o listă de potențiale părți de vorbire. Al doilea stagiu folosea liste mari de reguli de dezambiguare scrise de mână pentru a reduce această listă la o singură parte de vorbire pentru fiecare cuvânt.
Adnotarea ENGTWOL (Voutilainen, 1995)[4] se bazează pe aceleiași arhitectură pe două stagii, deși atât lexicul, cât și regulile de dezambiguare sunt mult mai sofisticate decât primii algoritmi apăruți. Lexicul ENGTWOL se bazează pe o morfologie pe două nivele, și are aproximativ 56,000 de intrări pentru cuvintele în engleză (Heikkilä, 1995), numărând un cuvânt cu părți de vorbire multiple (sensul nominal si verbal pentru hit) ca intrări separate, și desigur fără a număra formele derivate. Fiecare intrare este setată cu un set de trăsături morfologice și sintactice. În tabelul ce urmează sunt selectate câteva cuvinte, împreună cu o listă ușor simplificată a trăsăturilor acestora:
Exemple de intrări lexicale din lexicul ENGTWOL descris în
Voutilainen (1995) și Heikkilä (1995)
Majoritatea trăsăturilor din tabelul de mai sus sunt relativ de sine explicative; SG pentru singular, -SG3 pentru orice în afară de persoana a 3-a singular. ABSOLUT înseamnă necomparative și nesuperlative pentru un adjectiv, NOMINATIV înseamnă doar negenetiv, și PCP2 înseamnă participiu trecut. PRE, CENTRAL, și POST fante de ordine pentru determinanți (predeterminanții (all) apar înaintea determinanților (the): all the president`s men). NOINDEFDETERMINANT înseamnă că, cuvinte ca furniture nu apar cu determinantul nedefinit(indefinit) a. SV, SVO, și SVOO specifică structura de subcategorizare sau complementizare a verbului. SV înseamnă că verbul apare doar cu un subiect (nothing occured); SVO cu un subiect și un obiect (I showed the film); SVOO cu un subiect și două complemente: She showed her the ball.
În primul stagiu al adnotării, fiecare cuvânt este prelucrat prin traducerea pe două nivele a lexicului și sunt returnate intrările pentru toate părțile de vorbire posibile. De exemplu expresia Pavlov had shown that salivation… va returna următoarea listă (o linie pentru o adnotare posibilă, cu scrierea adnotării corecte îngroșat):
Pavlov PAVLOV N NOM SG PROPRIU
had HAVE V VFIN SVO TRECUT
HAVE PCP2 SVO
shown SHOW PCP2 SVOO SVO SV
that ADV
PRON DEM SG
DET CENTRAL DEM SG
CS
salivation N NOM SG
…
Un set de aproximativ 1,100 de constrângeri sunt aplicate propoziției introdusă ca dată de intrare pentru a descoperi părți de vorbire incorecte; intrările scrise îngroșat din tabelul de mai sus arată rezultatele dorite, în care adnotarea timpului trecut (nu participiul) este aplicată lui had, și adnotarea completivă (CS) este aplicată lui that. Constrângerile sunt folosite în mod negativ, pentru a elimina adnotările ce nu sunt potrivite în acest context. De exemplu o constrângere elimină toate citirile lui that cu excepția lui sensului de ADV (intensificator adverbial) (acesta fiind sensul din propoziție it isn`t that odd). Iată un exemplu simplificat de constrângere:
REGULA ADVERBIALĂ – THAT
Data de intrare: “that”
dacă
(+1 A/ADV/QUANT); /* dacă următorul cuvânt este adj, adverb, sau cuantificator */
(+2 PROP-LIM); / * și următorul este sfârșitul propoziției, * /
(NU –1 SVOC/A); / * și cuvântul precedent nu este verb */
/ * ‘consider’ ce îngăduie adj să fie complemente * /
atunci elimină adnotările ne-ADV
altfel elimină adnotările ADV
Primele două clauze ale acestei reguli verifică dacă that precede direct un final de propoziție constând în adjectiv, adverb, sau cuantificator. În toate celelalte cazuri citirea adverbului este eliminată. Ultima clauză elimină cazurile în care este precedat de verbe ca consider sau believe care pot lua un substantiv sau un adjectiv; aceasta este pentru a evita următoare frază a lui that ca și adverb:
I consider that odd.
O altă regulă este folosită pentru a exprima constrângerea că sensul completiv a lui that este probabil să fie folosit în cuvântul precedent, este un verb ce așteaptă un complement (ca believe, think, sau show), și dacă that este urmat de începutul unei noun phrase, și un verb finit.
Această descriere simplifică foarte mult arhitectura ENGTWOL; sistemul include, de asemenea, și constrângeri probabilistice, și se folosește și de celelalte informații sintactice discutate.
2.2. Gramatici de dezambiguare
În această secțiune se pune accentul doar pe formatul acestor gramatici. Și anume, în primul rând de ce ar alege cineva să scrie gramatici de mână. Conceperea unei bune descrieri bazată pe reguli necesită multă muncă și anumite aptitudini care nu sunt ușor de dobândit. În continuare, s-a lucrat puțin dar cu o documentație vastă, astfel încât o cercetare propriu-zisă de păreri ‚pro’ și ‚contra’ din această perspectivă rămâne să fie făcută. În contrast, mulți au folosit metode data-driven cu rezultate publicate în lucrări: garantând că există grupări de adnotare adecvate, un sistem de adnotare data-driven corect poate fi creat cu efort minim. În continuare, mai multe sisteme de adnotare sunt disponibile pe WWW ca și surse de cod, și deci nu este necesară implementarea programului cod de unul singur.
Există două păreri ‚contra’ majore cu sisteme de adnotare data-driven. În primul rând, în ciuda numeroaselor eforturi pare a fi foarte greu ca erorile sistemului de adnotare să coboare cu câteva procente (ceea ce la nivelul propoziției înseamnă că majoritatea propozițiilor care formează textul nu vor fi analizate). În al doilea rând, sistemele de adnotare data-driven par a fi mult mai potrivite pentru analiza cuvintelor cu o ordine fixă cu o morfologie săracă cum este limba engleză; limbile cu o morfologie mai bogată și care nu au o ordine fixă a cuvintelor ridică mai multe probleme pentru că abordările ei se bazează pe prezența claselor de cuvinte cu ordine fixă. Cu metoda clasică pare fi posibil să se obțină o rată de eroare mai mică decât în metoda data-driven, dar cantitatea de muncă implicată și gradul de expertiză cerut nu au fost încă reportate foarte bine.
Abordarea lingvistică a folosit două reguli formaliste înrudite: reguli care stabilesc limite și câteva reguli care au la bază un model de procesare, acestea fiind mai puțin expresive. Mai multe rezultate au fost obținute folosind tiparul de procesare; astfel atenția noastră se va îndrepta asupra lor.
Regulile cu model de procesare conțin două operațiuni de bază: de eliminare a citirii alternative și selectarea citirii (prin mutarea tuturor alternativelor sale). Aceste operațiuni sunt condiționate de context (sunt specificate alte cuvinte sau adnotări în propoziție, de obicei în contextul cel mai apropiat) și trebuie să fie convingătoare, altfel regula lasă cuvântul ambiguu intact. Este considerată o simplă regulă (în documentul formalist CG2 de Tapanainen 1996):
ȘTERGE (ART)
DACẶ (1C(V));
Această regulă șterge articolul (ART) dacă primul cuvânt din dreapta este în mod cert (1C) un verb (V). O gramatică generală conține multe reguli de acest fel. Regulile pot (și chiar) interacționează; de exemplu: o regulă poate dezambigua un cuvânt, rezultat pe care o altă regulă îl poate dezambigua la rândul ei.
Iată un exemplu de propoziție ambiguă:
“<The>”
“the” <*> <Def> DET CENTRAL ART SG/PL
“<table>”
“table” <Count> N NOM SG
"table" <SVO> V PRES -SG3 VFIN
"table" <SVO> V INF
"table" <SVO> V IMP VFIN
"table" <SVO> V SUBJONCTIVE VFIN
"<collapsed>"
"collapse" <SVO> EN
"collapse" <SVO> V PAST VFIN
"<.>"
"." <.> Pun
"<<p>>"
"<p>" Lim
Gramatica poate conține o regulă care cere prezența unui verb la mod personal pentru fiecare propoziție prin selectarea, ca fiind corectă, a adnotării VFIN oriunde în partea stângă (NOT *-1) sau dreaptă (NOT *1):
SELECTEAZẶ (VFIN)
DACẶ (NOT *-1 (VFIN))
(NOT *1 (VFIN)) ;
Această regulă nu va afecta cu nimic exemplul dat pentru că sunt două cuvinte care conțin verbe la mod personal. Totuși, în gramatică putem întâlni și următoarea regulă:
ȘTERGE (V)
DACĂ (-1C (ART));
Această regulă șterge verbele dacă primul cuvânt din stânga este concret un articol. Această regulă șterge toate formele de verb ale cuvântului table, astfel încât doar collapsed rămâne ambiguu într-o citire în limba engleză și un verb la mod personal (timp trecut, mai precis):
"<The>"
"the" <*> <Def> DET CENTRAL ART SG/PL
"<table>"
"table" <Count> N NOM SG
"<collapsed>"
"collapse" <SVO> EN
"collapse" <SVO> V PAST VFIN
"<.>"
"." <.> Pun
"<<p>>"
"<p>" Lim
Acum, regula SELECTEAZĂ își poate face treaba, astfel încât collapsed devine corect dezambiguat ca și verb la timp trecut.
O altă trăsătură a gramaticilor scrise de mână este lexicografia lor: multe reguli se referă nu doar la adnotări, dar și la cuvinte (leme sau chiar și formele cuvintelor). De exemplu, peste 50% dintre regulile din gramatica cu constrângeri a cuvintelor în engleză conține referiri la o lemă (sau la un set de leme), tipice cuvintelor claselor închise. Forma cuvântului that luat singur, cu cele cinci forme ambigue,
"<that>"
"that" <NonMod> <**CLB> <Rel> PRON SG/PL
"that" DET CENTRAL DEM SG
"that" PRON DEM SG
"that" ADV AD-A>
"that" <**CLB> CS
este dezambiguat cu peste 100 de constrângeri specifice cuvintelor. Se pare că formalizarea generalizării parțiale este o metodă ușoară, și totuși, neeconomă, de a descrie limbajul în scopuri de analiză.
A treia caracteristică a gramaticii de constrângeri este folosirea ordinii regulilor în forma subgramaticilor ordonate. O metodă de a folosi subgramatici ordonate este de a se baza pe constrângeri: constrângerile pe care se poate baza mai puțin sunt grupate în subgramatici separate; astfel încât: cu cât cele pe care se poate baza, pot face o analiză cât mai completă, cu atât regulile pe care se poate baza mai puțin, să fie folosite doar în cazuri extreme pentru a putea ajunge la un nivel acceptabil de dezambiguare a datelor de ieșire din sistemele de adnotare.
În încheierea acestei secțiuni putem menționa faptul că indiferent de metoda selectată, corpus-urile de antrenare bine adnotate sunt o resursă valoroasă pentru testarea și îmbunătățirea limbajelor.
2.3. Adnotarea Stochastică a părților de vorbire
Folosirea probabilităților în adnotare este o metodă destul de veche; probabilitățile au fost folosite pentru prima dată de (Stolz, 1965), o adnotare probabilistică folosind algoritmul Viterbi a fost schițată de Bahl și Mercer (1976), și numeroase adnotări stochastice au fost construite în 1980 [4]. Această secțiune descrie un algoritm particular de adnotare stochastică denumită în general Hidden Markov Model sau adnotare HMM [2]. Intuiția din spatele tuturor adnotărilor stochatice este o simplă generalizare a modului “alege cea mai probabilă adnotare pentru acest cuvânt”, bazată pe modelul Bayesian.
Pentru o propoziție dată sau o secvență de cuvinte, adnotările HMM aleg secvența de adnotare care maximizează următoarea formulă:
P(cuvânt|adnotare)*P(adnotare|n adnotări anterioare) (1)
În restul acestei secțiuni se va explica și motiva această ecuație particulară. Adnotările HMM în general aleg o secvență de adnotări pentru o propoziție întreagă, decât să aleagă pentru un singur cuvânt, dar pentru motive pedagogice, mai întâi vom vedea cum adnotarea HMM desemnează o adnotare unui singur cuvânt. Mai întâi dăm ecuația de bază, apoi lucrăm folosindu-ne de un exemplu, și în final vom da motivația pentru ecuație.
O adnotare bigram-HMM de acest gen alege adnotarea ti pentru cuvântul wi care este dat cel mai probabil de adnotarea anterioară ti-1 și cuvântul curent wi :
ti = P(tj|ti-1,wi) (2)
Prin câteva presupuneri simplificatoare Markov ce le vom da în cele ce urmează, rescriem ecuația (2) pentru a da ecuația de bază HMM pentru o singură adnotare după cum urmează:
ti = P (ti|ti-1)P(wi|tj) (3)
2.3.1. Exemplu de motivare
Vom da un exemplu, folosind adnotarea HMM pentru a desemna adnotarea potrivită pentru un singur cuvânt race în următoarele exemple [1]:
Secretariat/NNP is/VBZ expected/VBN to/TO race/VB tomorrow/NN
(Uneori adverbele ca “tomorrow” și “Monday” sunt adnotate cu NN în unele corpus-uri, inclusiv în Penn Treebank)
(5) People/NNS continue/VBP to/TO inquire/VB the/DT reason/NN for/IN the/DT
race/NN for/IN outer/JJ space/NN
În primul exemplu race este verb (VB); în al doilea este un substantiv (NN).
Pentru a demonstra scopul acestui exemplu, vom presupune că un alt mecanism a făcut deja cea mai bună adnotare posibilă pentru cuvintele vecine, lăsând doar cuvântul race neadnotat. O versiune bigram a adnotării HMM face o prezumție de simplificare că problema de adnotare poate fi rezolvată căutând printre cuvintele și adnotările din vecinătate. Considerăm problema de a desemna o adnotare a lui race dând doar aceste subsecvențe:
to/TO race/???
the/DT race/???
Vom vedea acum cum se aplică această ecuație în exemplul nostru cu race; Ecuația (3) spune că dacă încercăm să alegem între NN și VB pentru secvența to race, vom alege adnotarea cu probabilitatea mai mare între cele două ce urmează:
P(VB|TO)P(race|VB) (6)
și
P(NN|TO)P(race|NN) (7)
Ecuația (3) și instanțierile sale (6) și (7) fiecare conțin două probabilități: o probabilitate a unei secvențe de adnotare P(ti|ti-1) și o probabilitate a cuvântului P(wi|tj). Pentru race probabilitățile secvenței de adnotare P(NN|TO) și P(VB|TO) ne dau răspunsurile la întrebarea “Cât de probabil este să ne așteptăm la un verb(substantiv) având adnotarea precedentă?” Ele pot fi doar calculate dintr-un corpus prin numărare și normalizare. Putem să ne așteptăm că este mult mai probabil ca după TO să urmeze un verb decât un substantiv, din moment ce infinitivele (to race, to run, to eat) sunt mult mai comune în engleză. Este posibil ca un substantiv să urmeze după TO (walk to school, related to hunting), dar este mai puțin probabil.
Din corpus-ul combinat Brown și Switchboard se calculează probabilitățile ce urmează, arătându-ne că este de 15 ori mai probabil să găsim un verb după TO în loc de substantiv:
P(NN|TO) = .021
P(VB|TO) = .34
A doua parte a ecuației (3) și instanțierile sale, ecuațiile (6) și (7), este probabilitatea lexicală: probabilitatea substantivului race condiționată de fiecare adnotare, P(race|VB) și P(race|NN). Se observă că acest termen de probabilitate nu întreabă “care este cea mai probabilă adnotare pentru acest cuvânt”. Acesta pentru că, termenul de probabilitate nu este P(VB|race). În loc de acesta vom calcula P(race|VB). Probabilitatea răspunde la întrebarea “Dacă am fi așteptat un verb, cât de probabil este ca acest verb să fie race?”.
Probabilitățile lexicale din corpus-ul combinat Brown și Switchboard sunt:
P(race|NN) = .00041
P(race|VB) = .00003
Dacă înmulțim probabilitățile lexicale cu probabilitățile de adnotare a secvențelor, vom vedea că până și simpla versiune bigram a adnotării HMM, adnotează corect race ca și VB în ciuda faptului că este sensul mai puțin probabil a lui race. Aceasta deoarece:
P(VB|TO)P(race|VB) = .00001
P(NN|TO)P(race|NN) = .000007
2.3.2. Algoritmul existent pentru adnotarea HMM
Să ne amintim că o adnotare prin metoda HMM nu alege doar cea mai bună adnotare pentru un simplu cuvânt, ci și cea mai bună secvență de adnotări pentru o întreagă propoziție. Acum, după ce am văzut cazul unui singur cuvânt pentru adnotarea HMM, vom da ecuațiile complete. Se utilizează algoritmul Viterbi și se alege cea mai probabilă secvență de adnotare pentru fiecare propoziție. Astfel, această metodă presupune că încercăm să calculăm pentru fiecare propoziție cea mai probabilă secvență de adnotări T = t1,t2,…,tn dată în secvența de cuvinte din propoziția W = w1, … , wn.
= P(T|W)
După legea lui Bayes, P(T|W) poate fi exprimat astfel:
P(T|W) =
Astfel suntem conduși să alegem secvența de adnotări care maximizează :
=
Din moment ce căutăm cea mai probabilă secvență de adnotări pentru o propoziție ca secvență de cuvinte particulară, probabilitatea pentru secvența de cuvinte P(W) va fi la fel pentru fiecare secvență și o putem ignora. Ecuația de mai sus devine:
= P(T)P(W|T)
Produsul de probabilități din membrul drept poate fi calculat astfel:
Folosim ipoteza N-gram : apariția unui cuvânt depinde de aparițiile a N-1 cuvinte anterioare. Modelul trigram (N = 3) este folosit mai des,așa că îl vom defini pe acesta. Mai întâi, vom face prezumția de simplificare cum că probabilitatea unui cuvânt este dependent doar de adnotarea sa:
. Pentru modelul trigram
Astfel, alegem secvența de adnotare ce maximizează:
Ca de obicei, putem folosi estimarea maximă de probabilitate din frecvențe relative pentru a estima aceste probabilități.
Acest model poate fi netezit pentru a evita probabilitățile zero. Găsirea celei mai probabile secvențe de adnotări poate fi făcută cu algoritmul lui Viterbi [2].
Weishedel (1993) și DeRose (1988) [7] au garantat exactitatea de peste 96% pentru acest algoritm.
Adnotarea HMM pe care am văzut-o până acum este antrenată de informații adnotate de mână. Se demonstrează că este posibilă antrenarea adnotării HMM și cu informații neetichetate, folosind algoritmul EM. Aceste adnotări vor începe cu un dicționar care listează, a cărei adnotări pot fi desemnate cuvintelor; algoritmul EM învață atunci funcția de probabilitate a fiecărui cuvânt pentru fiecare adnotare, și probabilitățile tranzițiilor de adnotare. Totuși, o adnotare antrenată cu informații adnotate de mână funcționează mai bine decât una antrenată via EM. Astfel, adnotarea antrenată-EM “HMM pură” este probabil mai potrivită în cazurile unde nu este disponibilă nici o informație antrenată, de exemplu, pentru limbajele de adnotare pentru care nu există alte date adnotate de mână.
2.3.3. Adnotare pe bază de trasformare (Transformation-Based)
Adnotarea pe bază de transformare, numită uneori adnotare Brill, este un exemplu de Transformation-Based Learning (TBL), o abordare de tip “machine learning” (învățare automată). Metoda se inspiră atât din adnotările pe bază de reguli, cât și din cele stochastice. La fel ca adnotările pe bază de reguli, TBL se bazează pe reguli ce specifică ce adnotări ar trebui desemnate , la ce cuvinte. Dar, la fel ca adnotările stochastice, TBL este o tehnică de învățare automată, în care regulile sunt automat induse din informații. La fel ca unele adnotări HMM, TBL este o tehnică de învățare supervizată; presupune un corpus antrenat de pre-adnotări.
În [1] se oferă o analogie folositoare în înțelegerea paradigmei TBL. Să ne imaginăm un artist pictând un tablou cu o casă albă cu ornamente verzi și cerul albastru. Să presupunem că o mare parte din tablou era cerul, și deci cea mai mare parte a tabloului era albastră. Artistul ar putea începe folosind o pensulă mare și să picteze întreaga pânză albastră. Apoi ar putea schimba pensula cu alta albă mai mică, și să picteze întreaga casă albă. Va colora întreaga casă fără să se gândească că acoperișul este maro, geamurile albastre sau că grinda este verde. Apoi ia o pensulă mai mică maro și pictează acoperișul. Folosind apoi albastru, vopsește geamurile. Și în final, va vopsi cu verde grinda.
Pictorul începe cu o pensulă mare cu care va acoperi o mare parte din pânză, dar va colora multe zone care vor trebui pictate din nou. Următorul strat colorează mai puțin din pânză, dar de asemenea face și mai puține “greșeli”. Pentru fiecare strat nou se folosește câte o pensulă tot mai bună care corectează câte puțin din tablou, dar face doar câteva greșeli. TBL folosește cam aceeași metodă ca și pictorul. Algoritmul TBL are un set de reguli de adnotare. Un corpus este adnotat folosind regula generală, care este cea care se folosește la cele mai multe cazuri. Apoi, este aleasă o regulă puțin mai specifică, care schimbă câteva dintre adnotările originale. În următorul pas, se ia o regulă și mai strictă care va schimba un număr mai mic de adnotări (unele dintre ele pot fi chiar adnotări care au fost schimbate anterior).
2.3.3.1. Cum sunt aplicate regulile TBL
Să luăm una dintre regulile folosite de adnotarea lui Brill (1995). Înainte de a aplica regulile, sistemul de adnotare etichetează fiecare cuvânt cu adnotarea lui cea mai probabilă. Acestea le vom lua dintr-un corpus de adnotări. De exemplu, în corpus-ul Brown, race este cel mai probabil să fie substantiv:
P(NN|race) = .98
P(NN|race) = .02
Înseamnă că ambele exemple date mai sus pentru race vor fi codate cu NN. În primul caz acest lucru este greșit pentru că NN este adnotarea incorectă:
(8) is/VBZ expected/VBN to/TO rece/NN tomorrow/NN
În al doilea caz race este adnotat corect cu NN:
(9) the/DT race/NN for/IN outer/JJ space/NN
După ce s-a selectat cea mai probabilă adnotare, adnotarea Brill își va aplica regulile sale de transformare. Există o regulă care se aplică exact pentru acest fel de greșeală în cazul lui race:
Schimbă NN în VB când adnotarea anterioară este TO
Această regulă va schimba race/NN în race/VB chiar în această situație, din moment ce este precedat de to/TO:
(10) expected/VBN to/TO race/NN → expected.VBN to/TO race/VB
2.3.3.2. Cum se învață regulile TBL
Algoritmul Brill TBL are trei etape majore. Mai întâi etichetează fiecare cuvânt cu adnotarea cea mai probabilă. Apoi examinează fiecare transformare posibilă , și o selectează pe cea care rezultă în cea mai îmbunătățită adnotare. În final, re-adnotează informațiile în funcție de aceste reguli. Aceste trei etape se repetă până când se ajunge la un criteriu de oprire, cum ar fi atunci când nu mai sunt alte posibilități de îmbunătățire în pasul anterior. Trebuie știut faptul că stagiul al doilea solicită ca TBL să cunoască adnotarea corectă pentru fiecare cuvânt; acesta înseamnă că TBL este un algoritm de învățare supravegheat.
Datele de ieșire pentru procesul TBL este o listă ordonată de transformări; acestea constituie atunci o “procedură de adnotare” care poate fi aplicată unui corpus nou. În principiu setul de posibile transformări este infinit, din moment ce ne putem imagina transformări cum ar fi “transformă NN în VB dacă cuvântul anterior a fost “IBM” și cuvântul “the” se găsește între 17 și 158 de cuvinte înainte de acesta”. Dar TBL trebuie să ia în considerare toate transformările posibile, pentru a putea să aleagă pe cea corectă la fiecare pas din algoritm. Astfel, algoritmul are nevoie de o metodă pentru a limita setul de transformări. Fiecare transformare permisă este o instanțiere a uneia dintre cazuri. Setul de cazuri a lui Brill este listat în tabelul de mai jos, numit “lista Brill”.
Lista Brill: Fiecare începe cu “Schimbă adnotarea a în
adnotarea b când:…”. Variabilele a, b, z, și w se extind peste părțile de vorbire.
În practică, există un număr de metode pentru a face un algoritm mai eficient. Căutarea poate deveni mai eficientă prin pre-indexarea cuvintelor din corpus-uri de antrenare prin transformări potențiale.
În tabelul de mai jos sunt câteva dintre regulile învățate de sistemul de adnotare original a lui Brill.
Primele 20 transformări non-lexicale din sistemul de adnotare Brill (Brill, 1995)
2.4. Alte probleme de discuție
2.4.1. Adnotări multiple și cuvinte multiple
Două probleme care se ridică în adnotare sunt indeterminarea adnotării și cuvinte din mai multe părți. Problema indeterminării adnotării se pune atunci când un cuvânt este ambiguu între adnotări multiple și este imposibil sau foarte greu de dezambiguat. În acest caz, unele sisteme de adnotare permit folosirea de adnotări multiple. Acest caz este întâlnit în Penn Treebank și în British National Corpus. Adnotări indeterminabile comune include adjective versus timpul trecut versus participiu trecut (JJ/VBD/VBN), și adjective versus substantive ca modificator prenominal (JJ/NN).
A doua problemă se referă la cuvinte formate din mai multe părți. Seturile de adnotări C5 și C7, de exemplu, permit ca prepozițiile ca “in terms of” să fie tratate ca și un singur cuvânt prin adăugare de numere pentru fiecare cuvânt:
in/II31 terms/II32 of/II33
În final, unele corpus-uri de adnotări împart anumite cuvinte; de exemplu Penn Treebank și British National Corpus despică constrângeri și genitivul `s de tulpina lor:
would/MD n`t/RB
children/NNS `s/POS
2.4.2. Cuvinte necunoscute
Toți algoritmii de adnotare discutate până acum aveau nevoie de un dicționar care lista partea de vorbire posibilă a fiecărui cuvânt. Dar cel mai mare dicționar încă nu conține toate cuvintele. Nume proprii și acronime sunt create foarte des, și chiar și substantive noi și verbe apar în limbile vorbite cu o rată surprinzătoare. Așadar, pentru a construi un sistem de adnotare complet avem nevoie de o metodă pentru a ghici adnotarea unui cuvânt necunoscut.
Cel mai simplu algoritm posibil pentru un cuvânt necunoscut este să pretindem că fiecare cuvânt necunoscut este ambiguu printre toate adnotările posibile, cu egală probabilitate. Atunci sistemul de adnotare va trebui să se bazeze doar pe contextual-ul părților de vorbire trigram pentru a sugera adnotarea potrivită. Un algoritm ușor mai complex se bazează pe ideea că probabilitatea distribuției adnotărilor peste cuvintele necunoscute este foarte similară cu distribuția adnotărilor peste cuvintele care au apărut doar o dată într-un set de antrenare. Aceste cuvinte ce apar doar o singură dată se numesc hapax legomena (singularul pentru hapax legomenon). De exemplu, cuvintele necunoscute și hapax legomena se aseamănă prin faptul că ambele sunt cel mai probabil să fie substantive, urmate de verbe, dar sunt foarte puțin probabil ca ele să fie determinanți sau interjecții. Astfel probabilitatea P(|) pentru un cuvânt necunoscut este determinat de media distribuțiilor peste toate cuvintele găsite o singură dată într-un set de antrenare.
Cei mai puternici algoritmi pentru cuvinte necunoscute se folosesc de informații despre cum este pronunțat un cuvânt. De exemplu, cuvintele ce se termină în litera –s este probabil să fie substantivele plurale (NNS), în timp ce cuvintele ce se termină în –ed tind să fie participii trecute (VBN). Cuvintele care încep cu litere mari este probabil să fie substantive. Weischedel (1993) a folosit diferite moduri specifice de trăsături ortografice: 3 sfârșit-uri de inflecție (-ed, -s, -ing), 32 de sfârșit-uri de derivare (cum ar fi –ion, -al, -ive, și -ly), 4 valori pentru cuvintele scrise cu literă mare (inițială cu majusculă, etc.), și cuvinte cu cratimă (hyphenation). Pentru a calcula probabilitatea cuvintelor necunoscute s-a folosit următoarea ecuație:
P(wi|ti) = p(cuv-necun|ti) * p(majusculă|ti) * p(sf|cr|ti)
Alți cercetători, au preferat să folosească mașini de învățare pentru a induce trăsături folositoare, în loc să se sprijine pe aceste trăsături create de mână. Brill (1995) a folosit algoritmul TBL, unde cazurile care erau permise, erau definite ortografic (primele N litere din cuvinte, ultimele N litere din cuvânt, etc.). Algoritmul său a indus toate trăsăturile de inflecție, hyphenation, și multe trăsături de derivare cum ar fi –ly; Franz (1996) folosește un model care include mai multe trăsături, cum ar fi lungimea unui cuvânt și numeroase prefixe, și mai mult, include termeni de interacțiune între variate trăsături.
3. Aplicația Visual C++
3.1. Generalități
Evoluția în ultimii ani atât a tehnologiei hardware cât și a tehnologiei software permite programatorului folosirea unor programe utilitare performante cu ajutorul cărora pot fi realizate, la rândul lor, aplicații performante. Odată cu acceptarea mediilor informatice vizuale, programarea în și pentru aceste medii a devenit o necesitate.
O aplicație care să realizeze analiza gramaticală a unei fraze trebuie să fie compusă din:
interfață principală prin care utilizatorul comunică cu programul cu ajutorul câmpurilor de editare, butoanelor, etc;
bază de date conținând cuvintele și codul asociat fiecărei forme ce ar putea-o lua într-o frază;
bază de date conținând reguli din care să rezulte codul corect asociat fiecărui cuvânt analizat.
Pentru realizarea acestei aplicații se putea opta pentru mai multe medii de programare:
Web Site+PHP+SQL. Aplicația se putea realiza sub forma unui site web care să comunice cu bazele de date conținând cuvintele respectiv regulile cu ajutorului limbajului PHP. Bazele de date se puteau realiza în SQL, mySQL sau orice alt mediu care poate fi accesat cu ajutorul limbajului PHP.
Visual FoxPro. FoxPro este considerat unul din cele mai puternice utilitare pentru manipularea bazelor de date. Acesta înglobează toate facilitățile oferite de PHP+SQL iar noile versiuni vizuale permit de altfel realizarea unor interfețe performante.
Visual C++, Visual Basic sau Visual J++. Oricare din aceste trei medii de programare permit manipularea complexă a datelor oferind și posibilitatea realizării interfețelor grafice performante.
Desigur, fiecare dintre variantele propuse mai sus are, în cazul acestei aplicații, avantajele și dezavantajele ei. Spre exemplu, în cazul primei opțiuni, realizarea unui site web poate deveni simplă dacă se utilizează unui utilitar specializat însă programarea în PHP poate deveni foarte complexă. În plus, programatorul necesită cunoștințe temeinice în trei medii de programare, ceea ce poate fi un dezavantaj în cazul în care se dorește îmbunătățirea aplicației.
FoxPro excelează în crearea și manipularea bazelor de date însă este limitat în programarea orientată pe obiecte.
În cazul celei de-a treia opțiuni oricare din cele trei medii de programare permit realizarea cu ușurință a acestei aplicații. Toate cele trei medii de programare fac parte din pachetul de utilitare "Microsoft Visual Studio" iar dintre ele Visual C++ este considerat cel mai complex atât din punct de vedere al posibilităților de realizare a programelor cât și din punct de vedere al sintaxei.
Aplicația a fost concepută folosind adnotarea rule-based bazându-se pe cele două stagii amintite în subcapitolul 2.1.
Visual C++ nu este un simplu limbaj de programare ci include mai multe componente care, împreuna, permit realizarea interfețelor Windows. Dintre acestea cele mai importante sunt:
Microsoft Foundation Classes (MFC) – o bibliotecă de clase care permite realizarea cu ușurință a aplicațiilor Windows datorită posibilității folosirii mai multor modele de aplicații predefinite.
App Wizard – un generator de cod care realizează scheletul oricărei aplicații MFC incluzând clase, funcții și fișiere sursă.
Class Wizard – un utilitar ce generează codul de bază pentru o nouă clasă sau funcție. Cu ajutorul acestei componente se generează prototipul clasei sau funcției.
App Studio – un editor atât de cod sursă cât și de ferestre care permite folosirea tuturor componentelor necesare realizării unei aplicații profesionale.
3.2. Realizarea aplicațiilor Visual C++
Cea mai simplă și accesibilă variantă de a realiza o aplicație Visual C++ este folosirea componentei Microsoft Foundation Classes (MFC). Realizarea unei aplicații Visual C++ cu ajutorul MFC presupune 7 pași:
Alegerea numelui și tipului proiectului (figura 4.1)
Alegerea tipului aplicației
Tipul aplicației MFC Visual C++ poate fi:
Dialog based – în care aplicația constă într-o fereastră simplă
Single Document Interface (SDI) – aplicația permite deschiderea și manipularea unui singur fișier odată.
Multiple Document Interface (MDI) – aplicația permite deschiderea și manipularea mai multor fișiere în același timp.
Alegerea tipului de bază de date (în cazul în care este necesară)
Alegerea suportului pentru fișiere (Container, mini server, full server, etc.)
Alegerea opțiunilor suplimentare
tipul controalelor;
socluri;
numărul și tipul fișierelor ce pot fi accesate
Alegerea stilului proiectului
MFC standard
Windows Explorer
Definirea clasei de bază și a numelui acesteia (figura 4.3)
În cazul acestei aplicații s-a folosit ca și clasă de bază CFormView, clasă care oferă facilitățile unei aplicații de tip Dialog Based. Aceasta permite introducerea oricărui tip de control (buton, câmp de editare, meniu derulant, etc.) în cadrul interfeței principale, spre deosebire de clasa CView care permite doar afișarea și editarea textelor în cadrul ferestrei principale (tip Notepad).
Alegerea acestui tip de aplicații predefinite are ca și rezultat realizarea unei structuri de directoare și fișiere conținând codul prototip al unui program de tip MFC SDI. De asemenea, în cadrul aplicației este inclusă o fereastră predefinită și un meniu predefinit, ușor de modificat de către programator.
3.3. Interfața principală
O aplicație Windows trebuie realizată cât mai simplu pentru a furniza utilizatorului doar informațiile necesare. Pentru informațiile auxiliare este recomandată realizarea unor sub-ferestre pe care utilizatorul să le poate accesa cu ajutorul unui meniu sau a unor butoane.
Această aplicație are ca scop analiza unei fraze în limba engleză. Ca să se poată realiza acest lucru, pe lângă aplicația principală trebuie să existe un dicționar și unul sau mai multe seturi de reguli.
Interfața principală este structurată simplu, utilizatorul trebuind doar să introducă fraza de analizat, să aleagă dicționarul după care se va face analiza și să apeleze butonul „Analyze”. Fraza se poate introduce într-un câmp de tip „EditBox” multi-linie iar rezultatul este afișat tot într-un câmp „EditBox” multi-linie însă doar cu drept de citire (read-only).
Pe lângă rezultatul analizei programul mai oferă și date referitoare la numărul de cuvinte existente în fraza de analizat, numărul de apariții a cuvântului în dicționar și numărul de reguli găsite și aplicate în fraza.
Analiza frazelor se poate face după trei tipuri de dicționare, fiecare fiind diferit față de celelalte prin codificarea rolului fiecărui cuvânt în frază. Numărul de apariții a unui cuvânt în dicționar este funcție de numărul de roluri pe care le poate avea într-o frază. Spre exemplu, „to” poate fi găsit în infinitivul verbelor dar poate avea și rol de articol.
Interfața principală este prezentată în figura 4.4.
Utilizatorul poate introduce fraza de analizat în câmpul „Input”, apoi poate alege unul din dicționarele din câmpul „Tagset” iar la apelarea butonului „Analyze”, programul va afișa rezultatul în câmpul „Result” și statisticile în câmpurile „Statistics”.
Programul permite analiza frazelor cu fiecare dintre cele trei dicționare existente. Astfel utilizatorul poate șterge rezultatul oferit de program cu ajutorul butonului „Clear result”, poate alege un alt tip de dicționar existent și reanaliza fraza dorită.
Interfața principală mai conține și un meniu, fiecare din sub-meniurile acestuia având una sau mai multe funcții.
File – Conține funcția „Exit” care poate fi accesată de către utilizator pentru ieșirea din program
View- conține funcția „Status Bar” care permite activarea sau dezactivarea barei de status
Tools – conține funcția „Insert” care permite utilizatorului adăugarea de noi cuvinte în cele trei dicționare existente.
Help- conține funcțiile „About” și „Help” cu ajutorul cărora utilizatorul poate afla date referitoare la versiunea programului cât și date referitoare la utilizarea programului.
Pe lângă fereastra principală programul mai conține alte patru ferestre secundare: Insert, About, Help și Help-Insert.
Cu ajutorul ferestrei „Insert”, utilizatorul poate introduce cuvinte noi în dicționarele existente.
Această fereastră conține patru câmpuri de editare și trei butoane. Unul din câmpurile de editare este cel în care utilizatorul introduce cuvântul nou iar celelalte trei sunt pentru introducerea codului (adnotărilor) pentru cuvântul introdus.
Fereastra „Insert” este prezentată în figura 4.5.
Utilizatorul are posibilitatea de a accesa oricând fereastra „Tagsets Help” în care este sunt prezentate în detaliu adnotările pentru rolurile ce le poate avea un cuvânt într-o frază.
Programul este astfel conceput încât dacă unul din fișierele necesare aplicației nu există se va afișa o fereastră de avertisment asupra inexistenței fișierului respectiv. Spre exemplu, daca fișierul „tagsets.help” nu există se va afișa fereastra din figura 4.6, iar câmpurile ferestrei „Tagsets Help” vor fi goale, aceasta preluând datele din acel fișier.
După afișarea acestei ferestre de avertizare fereastra „Tagsets Help” va apare ca în figura 4.7.
Fereastra „Help” a aplicației este asemănătoare cu cea „Tagsets Help” doar că în cadrul acesteia se oferă informații despre utilizarea programului, la rândul lor luate dintr-un fișier „.help” ce poate fi modificat de către orice utilizator.
Aplicația oferă posibilitatea de a adăuga cuvinte și adnotări noi în fișierele dicționar. Dacă utilizatorul dorește să verifice existența acestor cuvinte în dicționar el poate vizualiza oricare din fișierele conținând cuvintele și adnotările corespunzătoare lor prin apelarea butonului „Show dictionary”.
La apelarea acestui buton se va deschide o fereastră în care vor fi afișate cuvintele din dicționar sortate alfabetic. Nu se vor afișa cuvintele din toate cele trei dicționare ci doar cele din dicționarul activ, și anume cel selectat în zona „Tagset”. Spre exemplu, daca dicționarul „C7” este cel activ, în fereasta „Dictionary” se vor afișa cuvintele din acest dicționar.
Fereastra „Dictionary” este de forma celei din figura 4.8.
3.4. Funcțiile aplicației
Scopul principal al aplicației este să realizeze o analiză cât mai corectă a frazelor. Pentru atingerea acestui scop programul trebuie să poată aplica un număr cât mai mare de reguli.
Visual C++ structurează fișierele unei aplicații SDI după cum urmează:
<nume proiect>.cpp – conține funcțiile de bază necesare rulării aplicației Windows
<nume proiect>Doc.cpp – conține funcțiile cu care utilizatorul poate manipula fișierele aplicației
<nume proiect>View.cpp – conține funcțiile ce țin de interfața principală. Tot aici se regăsesc funcțiile declarate de utilizator (programator).
Pe lângă fișierele sursă „.cpp”, aplicația conține fișierele header „.h” in care sunt declarate toate clasele, funcțiile și variabilele programului, fișierele resursă „.rc” unde sunt înregistrate date referitoare la ferestrele aplicației.
Clasa în care s-au declarat funcțiile utilizator este declarată în wordsView.h și este de forma:
class CWordsView : public CFormView
{
protected: // create from serialization only
CWordsView();
DECLARE_DYNCREATE(CWordsView)
public:
//{{AFX_DATA(CWordsView)
enum { IDD = IDD_WORDS_FORM };
CString sentence;
int radio_option;
CString result_edit;
CString words_c;
CString tags_c;
CString rules_c;
//}}AFX_DATA
// Attributes
public:
CWordsDoc* GetDocument();
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CWordsView)
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual void OnInitialUpdate(); // called first time after construct
//}}AFX_VIRTUAL
// Implementation
public:
CInsertDlg insert_dialog;
db dbase[150];
int match(char *pattern, char *str);
char *tags[256];
int check_both(int j, char *prev_taglist, char *taglist, char *next_taglist);
int check_right(int j, char *taglist, char *next_taglist);
int check_left(int j, char *prev_taglist, char *taglist);
int tag_i,word_i,rules_i;
char tagfile[80],lrulefile[80],rrulefile[80],brulefile[80];
char buf[16000];
char* get_tag(char filename[80], char *word);
char ret_str[16000];
char* c(CString str);
virtual ~CWordsView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CWordsView)
afx_msg void OnAnalyze();
afx_msg void OnClearfields();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
Dintre funcțiile și variabilele declarate în această clasă doar cele ce se regăsesc în zona „Implementation” sunt funcții și variabile utilizator, restul fiind funcții create implicit de către Visual C++ la crearea aplicației.
La apelarea butonului „Analyze” din fereastra principală programul accesează funcția „OnAnalyze” care este de forma:
void CWordsView::OnAnalyze()
{
UpdateData(TRUE);
char *tmpbuf,*tmp,*t;
CString text, aux;
int i=0, j;
word_i=0;
tag_i=0;
rules_i=0;
switch(radio_option)
{
case 0:{
strcpy(tagfile,"tags2");
strcpy(lrulefile,"left_rules2");
strcpy(rrulefile,"right_rules2");
strcpy(brulefile,"both_rules2");
} break;
case 1:{
strcpy(tagfile,"tags5");
strcpy(lrulefile,"left_rules5");
strcpy(rrulefile,"right_rules5");
strcpy(brulefile,"both_rules5");
} break;
case 2:{
strcpy(tagfile,"tags7");
strcpy(lrulefile,"left_rules7");
strcpy(rrulefile,"right_rules7");
strcpy(brulefile,"both_rules7");
} break;
}
t = c(sentence);
tmpbuf = strtok(t," ");
while ( tmpbuf != NULL )
{
strcpy(dbase[i].word,tmpbuf);
i++;
tmpbuf = strtok(NULL," ");
}
word_i=i;
text=" ";
for(j=0;j<i;j++)
{
tmp=get_tag(tagfile,dbase[j].word);
strcpy(dbase[j].tags,tmp);
if (j>0)
{
check_left (j,dbase[j-1].tags,dbase[j].tags);
check_right(j,dbase[j-1].tags,dbase[j].tags);
}
if ( j > 1 )
{
check_both(j,dbase[j-2].tags, dbase[j-1].tags,dbase[j].tags);
}
}
for(j=0;j<i;j++)
{
if( dbase[j].tags != NULL )
{
aux.Format("%s %s/[%s]",text,dbase[j].word,dbase[j].tags);
text = aux;
}
}
result_edit=aux;
words_c.Format("%d",word_i);
tags_c.Format("%d",tag_i);
rules_c.Format("%d",rules_i);
UpdateData(FALSE);
}
Cu ajutorul acestei funcții se apelează funcțiile care verifică fișierele cu reguli definite de utilizator. Astfel, în blocul switch se verifică tipul dicționarului după care se va face analiza, dicționar ales de către utilizator în interfața principală din câmpul „Tagset”. Odată găsit tipul dicționarului se atribuie variabilelor tagfile, lrulefile, rrulefile, brulefile numele fișierelor corespunzătoare. După atribuire se pornește la analizarea frazei introduse de utilizator. Această frază este despărțită în cuvinte și fiecare cuvânt este înregistrat în structura dbase. Structura dbase este definită într-un fișier header separat „structs.h” și are ca și componente două variabile de tip caracter: word – folosită pentru stocarea fiecărui cuvânt, tags – folosită pentru stocarea adnotărilor fiecărui cuvânt. Structura dbase are forma:
typedef struct
{
char word[35];
char tags[256];
} db;
„dbase” este o variabilă șir de tipul db și este declarată în cadrul clasei CwordsView.
După stocarea fiecărui cuvânt din frază în structura dbase se apelează funcția get_tag. Această funcție are rolul de a verifica dacă cuvântul analizat există în dicționar. Funcția get_tag are ca și parametrii de intrare variabila ce conține numele fișierului dicționar și variabila ce conține cuvântul pentru care se dorește căutarea adnotării.
Funcția get_tag este de forma:
char* CWordsView::get_tag(char filename[80], char *word)
{
char wf[50], tf[50];
int i;
FILE *f;
char buffer[16000];
buffer[0] = ' ';
buffer[1] = 0;
if( ( f=fopen(filename,"r") ) == NULL )
{
return NULL;
}
fseek( f, 0L, SEEK_SET );
while ( !feof(f) )
{
fscanf(f,"%s",wf);
fscanf(f,"%s",tf);
if( _stricmp(word,wf) == 0 )
{
strcat(buffer,tf);
strcat(buffer," ");
tag_i++;
}
}
fclose(f);
i=strlen(buffer);
if ( i > 0)
strcpy(buf,buffer);
else
strcpy(buf," ");
return buf;
}
Deoarece funcția returnează chiar șirul de adnotări găsit în fișierul dicționar, în cadrul funcției „OnAnalyze” este nevoie de atribuirea funcției get_tag variabilei tags din structura dbase.
Partea cea mai importantă a programului, și anume analiza cât mai corectă a frazei, se realizează cu ajutorul funcțiilor care verifică regulile impuse de utilizator. Aceste reguli se bazează pe adnotări și sunt introduse de utilizator în trei fișiere diferite pentru fiecare dintre cele trei dicționare existente. Regulile sunt aplicate doar în cazul în care un cuvânt are asociat mai mult de o adnotare. În cazul în care succesiunea de adnotări din fraza analizată se regăsește într-unul din fișierele cu reguli, acea succesiunea de adnotări din frază va fi înlocuită cu succesiunea de adnotări din fișierul cu reguli.
Spre exemplu dacă se analizează propoziția „I have to go” iar „go” nu se regăsește în dicționar, pentru „to” se vor returna două adnotări, unul ca articol (II) și unul ca însoțind un verb la infinitiv (TO):
I/[ PPIS1 ] have/[ VH0 ] to/[ II TO ] go/[ ]
Dacă „go” se află în dicționar ca verb la infinitiv, în cazul folosirii dicționarului C7, acesta va avea adnotarea „VVI”. Rezultatul analizei propoziției de mai sus va fi următorul:
I/[ PPIS1 ] have/[ VH0 ] to/[ TO ] go/[ VVI ]
După cum se poate observa, adnotarea „II” pentru „to” a fost eliminat deoarece într-unul din fișierele cu reguli (right_rules) s-a impus regula ca dacă lui „to” îi urmează un verb la infinitiv acesta va avea adnotarea „TO”. Pentru un cuvânt analizat, regulile sunt definite în funcție de adnotările cuvântului următor (fișier right_rules), cuvântului precedent (fișier left_rules), atât cuvântului precedent cât și celui următor (fișier both_rules).
Funcțiile care verifică și aplică regulile stabilite de utilizator sunt: check_left, check_right, check_both. Diferențele dintre aceste funcții sunt minore și apar doar la parametrii de intrare și atribuirea de valori variabilelor.
Spre exemplu, funcția check_right are forma:
int CWordsView::check_right(int j, char *taglist, char *next_taglist)
{
FILE *rules_file;
char one[10], two[10];
CString t;
if( ( rules_file=fopen(rrulefile,"r") ) == NULL )
{
return 0;
}
fseek( rules_file, 0L, SEEK_SET );
while ( !feof(rules_file) )
{
fscanf(rules_file,"%s",one);
fscanf(rules_file,"%s",two);
if (next_taglist && match(two,next_taglist) == 1)
{
if (taglist && match(one,taglist) == 1 )
{
strcpy(dbase[j-1].tags," ");
strcat(dbase[j-1].tags,one);
strcat(dbase[j-1].tags," ");
rules_i++;
return 1;
}
}
}
fclose(rules_file);
return 0;
}
Deoarece Visual C++ folosește implicit pentru câmpurile de editare variabile de tip CString, a fost nevoie de o nouă funcție care să transforme aceste variabile din CString în char[]. Funcția cu care se realizează acest lucru este funcția „c” (convert).
char* CWordsView::c(CString str)
{
char *xx;
xx = str.GetBuffer(0);
strcpy(ret_str,xx);
ASSERT( str.GetLength() == (int)strlen(xx) );
str.ReleaseBuffer();
return( ret_str );
}
O altă funcție auxiliară definită este match, cu ajutorul căreia se realizează căutarea unui șir de caractere în alt șir de caractere. Această funcție este folosită pentru căutarea unei adnotări anume în lista de adnotări a fiecărui cuvânt în vederea aplicării regulilor.
int CWordsView::match(char *pattern, char *str)
{
char pat[35], src[256];
char *t;
strcpy(pat,pattern);
strcpy(src,str);
t = strtok(src," ");
while ( t != NULL )
{
if ( _stricmp(pat,t) == 0 )
return 1;
t=strtok(NULL," ");
}
return 0;
}
După ce în funcția OnAnalyze sunt parcurse toate funcțiile de analiză și aplicare a regulilor, sunt actualizate toate variabilele necesare pentru afișarea rezultatelor, respectiv:
result_edit – fraza rezultat
words_c – variabila contor care conține numărul cuvintelor din frază
tags_c – variabila contor care conține numărul de adnotări găsite în frază
rules_c – variabila contor care conține numărul de reguli aplicate în frază
Pe lângă funcțiile definite în clasa CwordsView mai există și funcțiile definite în clasa CInsertDlg. Acestea aparțin ferestrei „Insert” cu ajutorul căreia utilizatorul poate introduce cuvinte noi în cele trei dicționare.
Cea mai importantă funcție din această clasă este funcția accesată la apelarea butonului „Insert”, si anume „OnInsert()”. Această funcție are forma:
void CInsertDlg::OnInsert()
{
UpdateData(TRUE);
char file_treebank[] = "tags2";
char file_c5[] = "tags5";
char file_c7[] = "tags7";
FILE *f1,*f2,*f3;
if ( (f1 = fopen(file_treebank,"a+")) == NULL )
{
MessageBox("Cannot open Treebank dictionary file",MB_OK);
}
if ( (f2 = fopen(file_c5,"a+")) == NULL )
{
MessageBox("Cannot open C5 dictionary file",MB_OK);
}
if ( (f3 = fopen(file_c7,"a+")) == NULL )
{
MessageBox("Cannot open C7 dictionary file",MB_OK);
}
UpdateData(FALSE);
if( i_word !=""&& i_treebank_tag !="" && i_c5_tag !="" && i_c7_tag !="" )
{
fprintf(f1,"%s %s\n",i_word,i_treebank_tag);
fprintf(f2,"%s %s\n",i_word,i_c5_tag);
fprintf(f3,"%s %s\n",i_word,i_c7_tag);
}
else
{
MessageBox("Empty field!",MB_OK);
}
UpdateData(TRUE);
i_word ="" ;
i_treebank_tag ="" ;
i_c5_tag ="" ;
i_c7_tag ="" ;
UpdateData(FALSE);
fclose(f1);
fclose(f2);
fclose(f3);
}
Pe lângă introducerea cuvintelor și adnotările corespunzătoare lor, funcția mai are rolul de a verifica corectitudinea datelor introduse. Funcția nu va adăuga nici un cuvânt în fișiere dacă unul din cele patru câmpuri de editare este gol ci va afișa o fereastră de avertizare (figura 4.8).
O altă funcție folosită în cadrul aplicației este funcția read_help cu ajutorul căreia se citesc fișierele conținând date informative despre program și datele despre adnotări. Spre exemplu, pentru citirea informațiilor despre adnotări funcția are forma:
int thelp::read_help()
{
FILE *f;
int i=0;
CString aux;
char s[100];
if ( (f=fopen("tagsets.help","r")) == NULL)
{
AfxMessageBox("Cannot open \"tagsets.help\" file!",MB_ICONSTOP, MB_OK);
return 0;
}
while ( !feof(f) )
{
fgets( s, 100, f );
if(s != NULL)
{
aux.Format("%s",s);
list_box.AddString(aux);
}
}
return 1;
}
În cadrul acestei funcții s-a folosit pentru afișarea mesajelor de avertizare funcția predefinită AfxMessageBox, care, spre deosebire de MessageBox, mai acceptă un parametru în plus, acesta fiind tipul icoanei ce v-a fi afișată împreună cu mesajul de avertizare. În figura 4.9 sunt prezentate trei variante de ferestre de avertizare, fiecare diferind prin timpul icoanei.
La apelarea butonului „Show dictionary” programul va deschide o nouă fereastră în care vor fi afișate cuvintele existente în dicționarul curent. Ca și pentru celelalte ferestre, deschiderea unei ferestre noi se realizează cu funcția predefinită „DoModal()”. Această funcție este apelată în cadrul funcției corespunzătoare butonului „Show dictionary”, „OnShowDictionary()”. Această funcție este de forma:
void CWordsView::OnShowDictionary()
{
UpdateData(TRUE);
switch(radio_option)
{
case 0:{
strcpy(tagfile,"tags2");
} break;
case 1:{
strcpy(tagfile,"tags5");
} break;
case 2:{
strcpy(tagfile,"tags7");
} break;
}
UpdateData(FALSE);
strcpy(dictDlg.dictfile,tagfile);
dictDlg.DoModal();
}
Această funcție verifică în blocul switch care dintre dicționare este cel activ și atribuie variabilei dictfile numele fișierului dicționar corespunzător. Variabila dictfile face parte din clasa corespunzătoare ferestrei „Dictionary” și este folosită în cadrul fișierului DictionaryDlg.cpp în funcția ce deschide fișierul dicționar și afișează datele în fereastra „Dictionary”.
Această funcție are forma:
void CDictionaryDlg::show_dictionary()
{
FILE *f;
int i=0;
CString aux;
char s[100],ss[100];
if ( (f=fopen(dictfile,"r")) == NULL)
{
AfxMessageBox("Cannot open dictionary file!",MB_ICONSTOP,MB_OK);
}
while ( !feof(f) )
{
fscanf(f,"%s",s);
fscanf(f,"%s",ss);
if(s != NULL)
{
aux.Format("%s",s);
dict_list.AddString(aux);
}
}
}
Apelarea funcției de mai sus se face, de fapt, la deschiderea ferestrei. Orice fereastră, la deschidere, apelează funcția predefinită „OnInitDialog()”, funcție in care sunt inițializate toate variabilele necesare rulării. Astfel, funcția show_dictionary() se apelează in interiorul funcției OnInitDialog(). Pentru fereastra „Dictionary”, funcția OnInitDialog() are forma:
BOOL CDictionaryDlg::OnInitDialog()
{
CDialog::OnInitDialog();
show_dictionary();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
Comentariile sunt adăugate implicit de Visual C++ la crearea funcției.
4. Concluzii
Limbile vorbite în ziua de azi au, în general, un set de cuvinte de clase închise relativ mic, care sunt adesea foarte frecvente, joacă în general rolul de cuvinte funcționale, și pot fi foarte ambiguu în adnotarea lor. Cuvintele de clase deschise include în general diferite feluri de substantive, verbe, adjective. Există un număr de scheme de codare a părților de vorbire, bazate pe seturi de adnotări având între 40 și 200 de adnotări.
Adnotarea părților de vorbire este un proces care constă în desemnarea, cu câte o etichetă, a fiecărui cuvânt dintr-o secvență de cuvinte. Sistemele de adnotare sunt împărțite în rule-based și stochastice. Adnotările bazate pe reguli, folosesc reguli scrise de mână pentru a distinge ambiguitatea adnotării. Adnotările Stochastic sunt fie HMM-based, când se alege secvența de adnotare care maximizează produsul probabilității unui cuvânt și probabilitatea secvenței de adnotare, fie cue-based, când se folosesc arbori de decizie sau modele de entropie maximă pentru a combina trăsăturile probabilistice.
Sistemele de adnotare sunt evaluate adesea prin compararea datelor de ieșire dintr-un set de teste cu etichetele date de om pentru acel test. Analizarea erorii ajută în indicarea zonei unde sistemul de adnotare nu a funcționat corect.
Aplicația elaborată în cadrul proiectului realizează analiza gramaticală a propozițiilor. Astfel ea poate fi folosită și în scop didactic. Ca și metodă de abordare s-a folosit adnotarea rule-based. Prin folosirea unor seturi de adnotări programul încearcă să realizeze o analiză cât mai corectă a propozițiilor.
Aplicația poate fi îmbunătățită prin adăugarea de cuvinte noi în dicționare și prin adăugarea de reguli noi pentru fiecare din cele trei seturi de adnotări folosite.
Bibliografie:
[1] Daniel Jurafski, James H. Martin: “Speech and Language Processing”, Ed. Prentice
Hall, 2000.
[2] Doina Tătar: “Inteligență artificială, demonstrarea automată a teoremelor, prelucrarea
limbajului natural”, Editura Albastră, Cluj-Napoca, 2001.
[3] Eric Brill: „A simple rule-based part-of-speech tagger”, 1992, pp. 152-155.
[4] Christer Samuelsson and Atro Voutilainen: „Comparing a Linguistic and a Stochastic
Tagger”, Ed. Association for Computational Linguistics, Madrid, 1997, pp. 246-253.
[5] Eric Brill: „Unsupevised Learning of Disambiguation Rules for Part of Speech Tagging”,
Ed. Association for Computational Linguistics, 1995, pp. 1-13.
[6] Atro Voutilainen: „A syntax-based part of speech analyser”, 1995.
[7] Eric Brill: „Some Advances in Transformation-Based Part of Speech Tagging”, 1994, pp.
722-727.
[8] K. Church: „A stochastic parts program and noun phrase parser for unrestricted text”, Ed.
Proceedings of the Second Conference on Applied Natural Language Processing}, Austin,
Texas, 1988, pp. 136-143.
[9] S. DeRose: „Grammatical category disambiguation by statistical optimization”, Ed.
Association for Computational Linguistics, 1988.
[10] M. Marcus, B. Santorini and M. A. Marcinkiewicz: ”Building a Large Annotated Corpus of
English: The Penn Treebank”. Ed. Association for Computational Linguistics, Vol.19,
1993, pp. 313-330.
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Sistem de Adnotare cu Parti de Vorbire a Unui Text In Limbaj Natural Utilizand Metode Statistice (ID: 149188)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
