Ján Hric - slovenský stemmer Opis problému, motivácia Vyhľadávanie informácií v dokumentoch je samo osebe problém komplexný. Zatiaľ nemožno hovoriť o pokusoch naučiť počítač text,pochopiť', spracovanie textu je zvyčajne založené len na identifikácií slov a frekvencii ich výskytu. Ľudský jazyk predstavuje veľkú prekážku pri spracovaní, najmä pre množstvo výnimiek a rôzne spôsoby vyjadrenia tej istej myšlienky. Ani jednoduchá identifikácia toho istého slova nie je priamočiara. Slovo sa totiž môže v texte vyskytovať v rôznych tvaroch. V prípade jazykov so značným ohýbaním slov - akým je aj slovenčina - je tvarov jedného slova veľa a často sa od seba značne líšia. Cieľom projektu bolo vytvoriť systém schopný rozpoznať rôzne tvary toho istého slova v slovenskom texte. Presnejšie: systém by mal vedieť v texte identifikovať hľadané slovo bez ohľadu na jeho gramatický tvar. Nejde teda o určenie základného tvaru slova, ide len o identifikáciu rôznych tvarov ako tvary toho istého slova. Takto sa pri hľadaní slova v texte nájdu aj jeho iné tvary, než aký sa hľadá, hoci systém ani jeden tvar nebude považovať za základný. V angličtine sa koreň slova označuje pojmom stem, preto sa projekt volá stemmer - snaží sa nájsť akýsi koreň slova (nie nutne gramatický), vďaka ktorému dokáže zoskupiť rôzne tvary slova. Na ukážku funkčnosti algoritmu by mal systém poskytovať možnosť vpísať hľadané slovo a zobraziť jeho pozície v spracovanom texte. Príklad Vstupný text: Úplným nedopatrením sa dostal zo svojho koterca a zaútočil na stádo. Hľadané slovo: nedopatrenie Výstup: pozícia slova,nedopatrením' vo vstupnom texte Je jasné, že systém nebude schopný bezproblémovo identifikovať tvary všetkých slov (o to sa už snažia viacerí dlhé roky). Cieľom je navrhnúť rôzne algoritmy a odskúšať ich efektivitu. Existujúce riešenia Existujúce riešenia využívajú tieto spôsoby:
Tabuľka všetkých tvarov slov - tento spôsob nemám v pláne použiť (je to skôr databázový problém). Lematizácia, definované pravidlá prípon (alebo predpôn) Štatistické metódy (napr. string distance measure) Rôzna úprava slov, napr. vyhodenie samohlások Metóda tabuľky všetkých tvarov slov vyžaduje vopred určiť všetky tvary všetkých známych slov a uložiť ich do tabuľky, v ktorej sa slové spracúvaných dokumentov budú hľadať. V súčasnej dobe sa už vďaka veľkým kapacitám pevných diskov i operačných pamätí stáva takéto riešenie reálnym, no vyžaduje veľké ľudské úsilie. Z hľadiska algoritmu je to v podstate databázový problém. Definovanie pravidiel je asi najčastejší spôsob riešenia. V tomto prípade je nutná dobrá znalosť spracúvaného jazyka. Vo väčšine jazykov sa ohýbaním mení len posledná časť slov, preto sa definujú najmä prípony, podľa ktorých systém dokáže zaradiť tvar slova do nejakej skupiny. V rámci tejto skupiny môžu byť iné podskupiny, čím je vytvorený strom pravidiel. Často sa tak dá získať aj skutočný základný tvar slova, výhodnejšie je však - pre nejednoznačnosť tvarov - určiť len spoločný koreň potenciálnych slov. Štatistické metódy sa snažia zisťovať súvislosti medzi tvarmi slov podľa frekvencie ich výskytu v texte a zhlukovaním pomocou zhlukovacích algoritmov. Je tu potrebná nejáká funkcia na určenie podobnosti dvoch slov, podľa ktorej algoritmus dokáže zhluky tvoriť. Rôzne metódy a ich vyhodnotenie možno nájsť v [1], [2], [3]. Výhodou štatistických metód je prakticky nulová potreba znalosti spracúvaného jazyka (čo ukazujú autori najmä v [3]). Iné metódy predstavujú jednoduchú úpravu slov do inej podoby a porovnávanie len tejto podoby. Ide napríklad o vyhadzovanie samohlások. Myšlienka je založená na pozorovaní, že rôzne tvary slova sa často líšia len v samohláskach a po ich vyhodení budú rovnaké. Táto metóda v podstate tiež nevyžaduje znalosť spracúvaného jazyka, hoci znalosť nemôže byť na škodu - môžeme vopred odhadnúť, či a aká vhodná bude tá-ktorá úprava slov. Koncepcia riešenia V projekte som sa zameral na využitie metódy vzdialenosti reťazcov (angl. string distance measure) a vyhodenie samohlások zo slov. Stemmer však umožňuje aj použitie jednoduchých pravidiel, kde som zvýšil týmto jazykovo nezávislým algoritmom účinnosť na slovenských textoch. Vzdialenosť reťazcov
Štatistický stemmer funguje na základe porovnávania dvojíc reťazcov (slov) a ich následné zaraďovanie do skupín. Ak sa dva reťazce vyhodnotia ako veľmi podobné, zaradia sa do jednej skupiny. Táto skupina by mala predstavovať rôzne tvary toho istého slova. Ak sú reťazce príliš odlišné, zaradia sa do iných skupín. Každý reťazec vstupného textu sa postupne porovnáva so všetkými skupinami a zaradí sa do tej, ktorá mu je najbližšia. Postup pri tejto metóde je približne takýto: Získanie zoznamu reťazcov zo vstupného textu/textov. Opakovaný výskyt reťazca sa nezapisuje, no kvôli vyhľadávaniu sa ku každému reťazcu zapíšu jeho pozície v texte/textoch. Vytvorenie prvej skupiny - bude ju predstavovať jeden z reťazcov. Postupný prechod ostatnými reťazcami, ich porovnávanie s reťazcami v existujúcich skupinách a zaradenie do príslušnej skupiny, prípadne vytvorenie novej. Porovnávanie reťazca so skupinou kvôli rýchlosti nemusí prebiehať na všetkých reťazcoch v skupine. Skupina môže byť reprezentovaná spoločným koreňom. Ten sa vytvorí ako spoločná časť reťazcov doteraz patriacacich do danej skupiny. Zrýchli sa tým zaraďovanie do skupín, no následkom môže byť zníženie kvality porovnávania, lebo porovnávanie už neprebieha na celých slovách. Alterntívou k okamžitej tvorbe finálnych skupín je možnosť ich neskoršieho zlúčenia. Nebudú sa porovnávať slová so skupinami, lež skupiny so skupinami. Najprv sa každé slovo bude považovať za vlastnú skupinu. Potom sa porovnajú vytvorené skupiny medzi sebou a podobné sa zlúčia. Toto sa opakuje do splnenia podmienky zastavenia. Hlavným parametrom algoritmu je porovnávacia funkcia. Cieľom je, aby reťazce predstavujúce jedno slovo mali vzdialenosť vyššiu než reťazce slov rôznych. Využíva sa pri tom vlastnosť ohýbania slov: pri ohýbaní sa mení len posledná časť slova. Táto vlastnosť platí takmer bezvýnimočne aj v slovenčine. Preto funkcia musí považovať za dôležitú podobnosť prvej časti slova a penalizovať rozdiel podľa toho, ako skoro nastane. Problémy Kedy považujeme reťazce sa veľmi podobné? Stanovenie tejto hodnoty predstavuje základ úspešnej tvorby skupín. To isté platí o podmienke zastavenia pri porovnávaní skupín. Veľa slov algoritmus nedokáže správne analyzovať. Ide najmä o slová krátke, kde sa ohýbaním mení veľká časť (v pomere k dĺžke slova).
Vyhadzovanie samohlások Pri tejto metóde sa reťazce porovnávajú až po vyradení samohlások, napr.,preskripcia' sa zmení na,prskrpc'. Myšlienka je založená na skutočnosti, že väčšina tvarov podstatných mien pri skloňovaní mení len samohlásky, napr. cesta, cesty, ceste, cestu, cestou, ciest. Žiaľ, existujú mnohé výnimky, napr. tvary množného čísla: cestám (pridanie,m'), cestách (pridanie,ch'), cestami (pridanie,m')..., pri daktorých podstatným menách aj jednotného čísla: trenie - trením (pridanie,m'), dieťa - dieťaťa (pridanie,ť')... Tieto prípady by sa mohli špeciálne ošetriť. Tvorba skupín opísaná pri štatistickom stemmeri vyššie bude prebiehať aj tu. V tomto prípade sa do skupiny zapíše len tvar slova bez samohlások. Porovnávanie skupín medzi sebou význam nemá, lebo vyhodenie samohlások je akcia jednoznačná - už po prejdení všetkých reťazcov vstupného textu budú skupiny vytvorené. Problémy Na mnohé tvary prosté vyhodenie samohlások nestačí. Sú potrebné pravidlá alebo nejaká metóda na odstránenie prípon so spoluhláskami (-ami, -ach, -ovi a pod.). Slová sa môžu často líšiť len v samohláskach (napr. honba - hanba). Tieto slová algoritmus považuje za totožné. Diakritické znamienka Často sa pri slovách skloňovaním menia diakritické znaky, napr. baňa - bane, stôl - stoly. Táto zmena spravidla prebieha len v poslednej slabike slova. Pri oboch algoritmoch by bolo vhodné z poslednej slabiky odstrániť diakritické znamienka pred spracovaním reťazca. Iné slovné druhy Stemmer najlepšie funguje pre podstatné a prídavné mená. Tie majú totiž pravidelné ohýbanie. Tak isto príslovky nepredstavujú značný problém, lebo sa podobajú na prídavné mená (napr. jasný - jasno) a radové číslovky sa skloňujú ako prídavné mená (prvý, prvým, prvého...). Pri zámenách existuje mnoho neštruktúrovaných tvarov (ten - toho - tomu, oni - im - ich a pod.) a slovesá časovaním často menia aj základ (skákať - skáče, vedieť - vie...). Práve tieto slovné druhy predstavujú najťažšiu skupinu reťazcov pre stemmer. Projekt sa nimi nebude špeciálne zaoberať, no bude zaujímavé pozorovať, ako si s nimi stemmer poradí.
Implementácia Čítanie slov Program považuje za slovo každú súvislú postupnosť pismen. Kvôli neskoršiemu vyhľadávaniu si po prečítaní každého slova zapíše jeho pozíciu vo vstupnom texte. Podľa nastavených prepínačov sa slová po prečítaní ešte upravia: Prevod písmen na malé. Toto sa vykoná vždy, lebo veľkosť písmen zväčša nič o význame slova nevypovedá, napr. len pozícia slova vo vete ovplyvní veľkosť prvého písmena. Odstránenie mäkčeňov z písmen ď, ť, ň, ľ. Táto funkcia sa riadi vlastnosťou slovenčiny, že dané písmená strácajú mäkčene pred samohláskami e a i. Napr. v slove baňa sa pri skloňovaní mení ň na n (baňa - bane). Ostatné spoluhlásky nie sú takto ovplyvnené, preto ich netreba upraviť. Odstránenie dĺžňov zo samohlások á, í, ú a spoluhlások ĺ a ŕ, odstránenie vokáňa z dvojhlásky ô a zmena dvojhlásky ie na samohlásku e. Podnetom je predlžovanie samohlások a slabikotvorných spoluhlások pri skloňovaní, napr. banka - bánk, pošta - pôšt, cesta - ciest, vlna - vĺn. Opäť ide o vyčerpaný zoznam zmien, preto netreba upravovať iné písmená, resp. skupiny písmen. Odstránenie pádových prípon -ách, -ach, -ami, -och, -ovi, -ám, -am, -ím, -om, - mi. Tu už možno hovoriť o akýchsi pravidlách. Táto funkcia nie je štandardne zapnutá, pretože odstránenie prípony môže byť negatívne, ak daná časť slova nie je v skutočnosti pádová prípona, napr. v slove leňoch. Na druhej strane, stemmer založený na vyhadzovaní samohlások nedokáže správne tvary slov s týmito príponami rozpoznať (pre prítomnosť spolushlások v nich), čo činí túto funkciu užitočnou. V programe nie je možnosť odstránenia (resp. úpravy) všetkých diakritických znakov. Je to kvôli lepšej schopnosti rozlišovania slov, ktoré sa líšia len mäkčeňmi a dĺžňami. Vyhadzovanie samohlások Táto metóda je jednoduchšia než porovnávanie podobnosti reťazcov. Program po prečítaní a úprave slova zo vstupného textu odstráni zo slova samohlásky. Vzniknutý tvar slova považuje za koreň a pridá ho do zoznamu koreňov. Ak už taký koreň jestvuje, len pridá informácie o ďalšej pozícii vo vstupnom texte. Za samohlásky program považuje písmená a, á, i, í, e, é, ě, o, ó, ô, u, ú. Písmená ä, ö a ü sú dobrým rozlišovacím znakom a ohýbaním slova sa nemenia, preto sa v slovách nechávajú. Umožnené sú dva spôsoby vyhadzovania samohlások: Úplné vyhodenie samohlások. V tomto prípade sa odstánia všetky samohlásky zo slova. Ide o štandardný a jednoduchý postup, no pomerne nepresný.
Vyhodenie posledných samohlások. Tu sa využíva fakt, že len posledná časť slova sa ohýbaním mení. Bolo však potrebné nájsť spôsob, aby sa zo všetkých tvarov slova odstránili tie isté skupiny samohlások. Pri mnohých slovách stačí odstrániť samohlásky z konca slova, napr. brána - brán, bránou - brán, počítača - počítač, počítaču - počítač. Ale v iných slovách sa samohlásky skloňovaním aj dopĺňajú, napr. zátka - zátok, povodeň - povodne, karta - kariet. Odstránenie samohlások z konca slova nestačí, lebo rôzne tvary slov sa po úprave budú líšiť (zátk - zátok, povodeň - povodň, kart - kariet). Odstránenie aj predošlej skupiny samohlások (čiže tej, čo je pred koncom slova) problém nerieši (karta - krt, kariet - kart). Rozpisom rôznych tvarov slov som prišiel na tento spôsob: Odstráni sa skupina samohlások z konca slova (ak sa slovo končí samohláskami) a ak zostane slovo ukončené jednou spoluhláskou (teda nie skupinou spoluhlások), odstráni sa skupina samohlások pred touto spoluhláskou, napr. karta - kart, kariet - kart, povodeň - povodň, povodne - povodň (nerozlišovanie ď, ť, ň, ľ musí byť zapnuté), počítača - počítč. Využíva sa fakt, že samohlásky sa vkladajú, len ak je v základom tvare slova skupina spoluhlások, a vkladajú sa vždy pred poslednú spoluhlásku zo skupiny. Vyhadzovanie samohlások len z konca slova možno opäť považovať za akési definované pravidlo, ktoré vzniklo pozorovaním ohýbania v jazyku. Presnosť porovnávania slov sa však zvýši, lebo väčšina samohlások z koreňa slova zostane zachovaná. Vzdialenosť reťazcov Táto metóda je výpočtovo náročnejšia než vyhadzovanie samohlások, no má menšie problémy s gramatickými príponami. Základom je funkcia na porovnanie dvoch reťazcov slov. Čím sú slová podobnejšie, tým nižšia je hodnota funkcie, pre rovnaké slová je nulová. Podstatnou vlastnosťou funkcie je zohľadnenie dĺžky rovnakej časti slov vzhľadom na celkovú dĺžku slov (v prípade rovnakých dĺžok toho dlhšieho slova). Funkcia prebraná z [3] sa riadi pozíciou prvého rôzneho znaku, čiže prvou pozíciou, na ktorej sa reťazce líšia. Podobnosťou slov za touto pozíciou sa už nezaoberá - považuje to za prefix, resp. za rôznorodosť koreňov slov. Vzťah na výpočet vzdialenosti slov dĺžky n+1 (toho dlhšieho slova, ak sú rôzne dlhé), ktoré sa prvý raz líšia na pozícii m (indexované od 0), je: D = (n-m+1)/m * sum(i=m, n: 1/(2^(i-m))) ak m <> 0 D = nekonečno ak m = 0 Napr. pre slová konopa a konopný je n=6, m=5 a D = (6-5+1)/5 * (1/(2^0) + 1/(2^1)) = 0,4*1,5 = 0,6. Pre nekonečno sa používa maximálna hodnota desatinného typu (Double.MAX_VALUE). Po prečítaní slova zo vstupného textu (a jeho úprave podľa prepínačov) sa slovo porovná z dosiaľ uloženými koreňmi a nájde sa ten, ktorému je najbližší. Ak je táto vzdialenosť
nižšia než stanovená hodnota, zo slov sa vytvorí spoločný koreň, t. j. nechá sa len ich spoločná časť (prefix). Takto sa vytvoria korene, ktoré by mali reprezentovať rôzne tvary jedného slova. Náročnosť tohto algoritmu je O(n^2), spracovanie vstupného textu trvá dlho. Vyhľadávanie Cieľom určenia koreňov pri oboch spomenutých spôsoboch je schopnosť nájsť vo vstupnom texte rôzne tvary slova určením len jedného (napr. základného) tvaru. Po vpísaní hľadaného slova sa naň najprv aplikujú úpravy podľa prepínačov použitých pri tvorbe koreňov (prevod na malé písmená, odstránenie ď, ť, ň, ľ...). Potom sa slovo hľadá v zozname koreňov: Ak sa na tvorbu koreňov použilo vyhadzovanie samohlások, vyhodia sa tým istým spôsobom samohlásky aj z hľadaného slova a potom sa len nájde rovnaký tvar slova. Ak taký tvar v zozname je, vypíšu sa jeho uložené pozície vo vstupnom texte. Ak nie, vypíše sa oznam o neúspechu. Ak sa použila metóda vzdialenosti rerťazcov, slovo sa postupne porovnáva s koreňmi zo zoznamu a nájde sa najbližší koreň. Ak je vzdialenosť tohto koreňa od hľadaného slova nižšia než stanovená hodnota (použitá aj pri tvorbe koreňov), vypíšu sa pozície slov s týmto koreňom vo vstupnom texte. Ak nie, vypíše sa oznam o neúspechu. Testovanie Testovanie prebiehalo na slovenských kratších článkoch aj dlhých knihách v slovenskom preklade. Vyhodnotenie prebiehalo na trinástich slovách. Určil som všetky správne tvary daného slova a vyhodnotil presnosť a pokrytie algoritmov. Skúšal som všetky tri typy stemmera a každý z nich som skúsil bez a so zapnutou možnosťou odstránenia pádových prípon. Výsledky sú v nasledujúcej tabuľke. Označenie algoritmov: 1 - vyhodenie všetkých samohlások 2 - vyhodenie samohlások z konca slova 3 - vzdialenosť reťazcov Označenie prepínačov: a - vypnuté odstránenie pádových prípon b - zapnuté odstránenie pádových prípon Označenie funkcie:
pr -presnosť (pomer počtu správne vrátených tvarov slova k počtu všetkých vrátených tvarov slova) po - pokrytie (pomer počtu správne vrátených tvarov slova k počtu všetkých správnych tvarov slova v texte) slovo 1a pr 1a po 1b pr 1b po 2a pr 2a po 2b pr 2b po 3a pr 3a po 3b pr stena 64.38% 82.45% 66.66% 98.24% 85.45% 82.45% 84.84% 98.24% 97.91% 82.45% predstava 95.00% 95.00% 95.00% 95.00% 95.00% 95.00% 95.00% 95.00% 22.09% 95.00% 22.09% obraz 91.17% 76.22% 92.03% 85.24% 91.17% 76.22% 92.03% 85.24% 72.88% 70.49% 73.38% srdce 88.57% 81.57% 89.47% 89.47% 88.57% 81.57% 89.47% 89.47% 89.47% 89.47% 89.47% hlava 98.69% 96.17% 98.72% 98.72% 98.69% 96.17% 98.72% 98.72% 94.96% 96.17% 74.63% dlaň 61.53% 100% 53.33% 100% 100% 100% 100% 100% 100% 100% 100% chlap 75.00% 70.58% 77.77% 82.35% 75.00% 70.58% 77.77% 82.35% 29.54% 76.47% 29.78% účet 80.64% 78.12% 80.64% 78.12% 86.20% 78.12% 86.20% 78.12% 0% 0% 0% žena 79.85% 78.72% 79.43% 79.43% 79.85% 78.72% 79.43% 79.43% 64.91% 26.24% 75.86% auto 7.83% 83.51% 7.59% 95.21% 7.83% 83.51% 7.59% 95.21% 93.57% 54.25% 83.87% dom 66.66% 76.05% 0.37% 7.04% 76.05% 76.05% 0.37% 7.04% 87.50% 69.01% - noc 100% 100% 100% 100% 100% 100% 100% 100% 100% 77.20% 100% zbraň 91.66% 84.61% 92.59% 96.15% 95.65% 84.61% 96.15% 96.15% 95.65% 84.61% 96.15% Výsledky výrazne závisia od povahy slova. V mnohých prípadoch je presnosť/pokrytie pri rôznych algoritmoch rovnaká/-é, lebo identifikujú správne tie isté tvary slova. So slovami dlaň a noc si algoritmy poradili najlepšie. Sú to totiž slová bez zmeny koreňa pri skloňovaní a kombinácia ich spoluhlások je jedinečná. So slovom účet si lepšie poradili algoritmy vyhadzovania samohlások, pretože spoluhláskami je dobre identifikovateľné, no je to krátke slovo a mení sa mu koreň, preto vzdialenosť reťazcov neuspela. Slovo auto má, naopak, len jednu spoluhlásku, preto je presnosť algoritmu vyhodenia samohlások veľmi nízka. Algoritmus vzdialenosti reťazcov dosahuje vždy pomerne vysoké pokrytie, presnosť kolíše. Mnohé slová totiž vyhodnotí ako podobné, ak majú dostatočne dlhý spoločný prefix, čím sa dostanú do výsledkov. Odstránenie pádových prípon - podľa očakávania - vo väčšine prípadov čiastočne zlepšilo kvalitu výsledkov (hneď prvé slová stena, obraz, srdce, hlava). Pri slove dom má však katastrofálny následok, lebo po odstránení,prípony' -om ostane len,d'. Výsledky ukazujú, že aj vyhodenie samohlások, aj vzdialenosť reťazcov majú svoje chyby a každý algoritmus je výhodnejší pri iných typoch slov. Definovanie pravidiel (tu je ich jednoduchým reprezentantom odstránenie pádových prípon) ostáva stále tým najistejším spôsobom hľadania stemov. Pozitívne je zistenie, že úprava algoritmu
vyhadzovania samohlások na vyhodenie samohlások len z poslednej časti slova dosahuje vždy lepšie alebo aspoň rovnako dobré výsledky ako pôvodný algoritmus vyhadzujúci všetky samohlásky. Program Systém je naprogramovaný v jazyku Java, preto na jeho spustenie je nutné mať nainštalované JRE (Java Runtime Environment). Priložený súbor s príponou.jar možno spustiť príkazom: java -jar HricStemmer.jar Otvorí sa okno umožňujúce nastaviť parametre stemmera, určiť vstupný súbor a po jeho spracovaní vpísať slovo, ktoré chceme hľadať. Vstupných súborov možno nahrať viac - vždy po vpísaní názvu súboru stlačením tlačidla,nahraj súbor'. Podporované kódovanie súboru je UTF-8. Súbory sa spracujú akoby to bol jeden súvislý text, no program si zapamätá pozície slov pre každý súbor. Parametre stemmera možno meniť len pred nahratím prvého súboru. Vyberá sa typ stemmera a prepínače predspracovania slova. Po nahratí súboru je už objekt stemmera vytvorený a parametre ostávajú platné aj pre ďalšie nahrané súbory. Hľadanie je umožnené až po nahratí prvého súboru. Ďalšie súbory sa dajú nahrať aj neskôr, po odskúšaní hľadania na prvom. Vpísaním slova do hľadacieho políčka a stlačením tlačidla,nájsť' sa program pokúsi nájsť stem pre dané slovo. Ak sa mu to podarí, vypíše daný stem a aj pozície slova vo vstupných súboroch. Výpis má podobu krátkej časti textu, v ktorej sa slovo identifikované ako jeden z tvarov hľadaného slova nachádza.
Literatúra 1, Bacchin, M., Ferro, N., Melucchi, M.: Experiments to evaluate a statistical stemming algorithm. University of Padua at CLEF 2002. 2, Leusch, G., Ueffing, N., Ney, H.: A Novel String-to-String Distance Measure With Applications to Machine Translation Evaluation. RWTH Aachen University of Technology D-52056 Aachen, Germany. 3, Majumder, P., Mitra, M., Datta, K.: Statistical vs. Rule-Based Stemming for Monolingual French Retrieval. CVPR Unit, Indian Statistical Institute, Dept. of EE, Jadavpur University, Kolkata.