User:Peter.Michalec 65: Query Categorization: Objavovanie Wikipedia entít pomocou Gazeteer-u Gazetteer je druh slovníka, ktorý obsahuje rôzne údaje o nejakej entite. Slovo pôvodne pocháza z geografie, ale toto pomenovanie slúži pre ľuboľný slovník. Zadanie úlohy Cieľom úlohy je identifikovať entity v zadanom texte. Pomocou existujúceho slovníka sa bude v texte vyhľadávať entita, ktorá bude identifikovaná ako entita n Wikipédii. Podstatné sú tu rôzne pomenovania jednej entity, kde chceme mať pod jednou Wiki entitou zahrnutých viacero názvou tej istej entity. Príklad je wiki entita Mobile phone. Má viaceré alternatívne názvy: mobile phone, cell phone, hand phone. Identifikovaná wiki entita je však stále jedna. Data.JPG Návrh riešenia Riešenie tejto úlohy bude tvorené z dvoch častí: vytvorenie slovníka na hľadanie a následné samotné vyhľadávanie. Vytvorenie slovníka Slovníka sa bude vytvárať z dumpu anglickej wikipédie. Všetky požadované entity sú uložené v jednom XML dokumente, ktorého veľkosť je 42,7 GB. Na obrázku je príklad jednej entity z tohto súboru.
Wiki_Sample_Page_text.JPG Táto entita obsahuje aj text, ktorý vidíme na stránke wikipédie. Avšak niektoré entity sú len redirektmi na iné entity, ktoré nemajú text, ale len odkaz na inú entitu. Príklad aj s vyznačím, ktorý redirect sa parsuje, je na nasledujúcom obrázku.
Wiki_Sample_Page_redirect.JPG Jednotlivé entity sú oddelené elementmi <page>. Po zozbieraní mena entity, testu a prípadného redirektu sa na konci každej entity vyhodnotia tieto údaje. Nakoľko som pri prvých pokusoch zistil, že vytvorenie stromovej mapovej štruktúry (popísanej nižšie) zabralo príliš veľa pamäte, rozhodol som sa, že budem vyberať len tie entity, ktoré sú ľudia. Toto sa robí v texte entity sledovaním kategórie. Wikipédia síce má kategóriu "Peoople," avšak v tejto kategórii sa nachádzajú len podkategórie a nie osoby (viď ). Preto pre ľudí hľadám výrazy v kategóriách: [Category:Living people] [Category:Dead people] deaths] births] Pri posledných dvoch nehľadám aj slovo "Category" nakoľko sa tu nachádza aj číslo roku narodenia, ktoré je samozrejme premenlivé. Dôsledkom čiastočného parsovanie wikipédie je nutnosť ošteriť redirekty na entity. Ak prídem k nejakému redirektu, tak neviem jednoznačne povedať, či entita, na ktorú sa odkazuje je, alebo nie je človek. Preto sa všetky redirekty najskôr zozbierajú do zonamu a až po dokončení parsovania sa spracujú. Ich spracovanie je jednoduché: ak entita, na ktorú sa daný redirekt odkazuje je v zozname nájdených ľudí, tak ju pridaj do zoznamu nájdených entít. Postupne sa prejdu všetky entity, pričom sa pozerá na nemo enity a či je to redirekt, alebo nie. Všetky nájdené entity sa zapíšu do súboru, ktorý slúži ako medzivýstup parsovania entít a ich vyhľadávania. Do tohto súboru sa zapíšu tri informácie pre každú entitu:
identifikátor entity - vyrábaný počas prechádzania XML súborom. Bude to číslo, ktoré identifikuje entitu, ktoré sa ďalej použije. Meno entity - konkrétny reťazec, ktorý sa nachádza v XML súbore v tagu <title> Identifikátor redirektu - toto je nepovinný parameter, ktorý sa nachádza, ak je daná entita odkazom na inú entitu Tieto tri zložky budú oddelené dvoma znakmi "," ktoré budú slúžiť ako jednoznačné oddeľovače. Identifikácia každej entity bude zapísaná na samostatný riadok v súbore. Dva príklady pre entity zapísané do súboru: 173629 Jim Higgs 1389062 Alioune Kebe 403118 - príklad bez redirektu - príklad s redirektom Vyhľadávanie pomocou slovníka Pre vyhľadávanie použijem stromovú štruktúru máp pre rýchle vyhľadávanie. Všetky mapy budú obsahovať dvojice kľúč-hodnota, pričom kľúč bude vždy jeden znak ("character"). Hodnota bude vlastná štruktúra, ktorá uchováva identifikátory entít (indexy v slovníku), ktoré končia na danom mieste a ďalšiu mapu, ktorá sa využije na pokračovanie v hľadaní. Táto štruktúra sa bude vytvárať postupným načítavaním jednotlivých entít zo zadaného súboru a rozoberaním mena entity na znaky a ich postupné vkladanie do máp. Jeden príklad, ako môže táto mapa vyzerať je na obrázku. Search_map_sample.jpg
Keďže na jednu entitu môže ukazovať viacero iných entít, rozhodol som sa, že pri nájdení nejakej entity sa zapíše len jej identifikátor. Po skončení prehľadávania sa nájdené identifikátory premenia na konkrétne meno entity. K tomuto budem využívať pomocoú mapu, v ktorej budú kľúče identifikátory entít (číselné hodnoty) a ich hodnota bude buď ďalší identifikátor (ak sa jedná o redirekt), alebo konkrétny názov entity. Keď už máme vytvorenú mapu hľadania, môžeme vykonávať samotné hľadanie. Vyhľadávať sa bude v reťazci znakov, pričom sa nerozlišuje jeho dĺžka ani štruktúra. Nakoľko som chcel dodržať lineány čas vyhľadávania, rozhodol som sa prechádzať celý test po jednotlivých znakoch vstupného reťazca. Kvôli tomuto je aj strom máp vytvorený zo slovníka so znakmi ako kľúčmi. Samotné vyhľadávanie entít prebieha nasledovne: 1. Nastav prvotnú pracovnú mapu na koreňovú mapu stromu 2. Načítaj ďalší znak zo vstupu, pokiaľ ešte môžeš 3. Pozri sa, či sa znak nachádza v danej mape Ak nie, tak prejdi na koniec slova - najbližší ne-alfanumerický znak - a nastav pracovnú mapu na koreňovú mapu a pokračuj v bode 2. Ak áno tak sa pozri, aké je hodnota mapy Ak je to index do sovníka Over, či ďalší znak je biely znak (medzera, nový riadok, tabulátor) Ak je (našli sme entitu), tak si zaznač miesto nájdenia entity v texte, nastav pracovnú mapu na koreňovú mapu a pokračuj v bode 2. Ak nie je (entita s daným názvom tam nie je), tak nastav pracovnú mapu na koreňovú mapu a pokračuj v bode 2. Ak je to ďalšia mapa (sme v nelistovom uzle) tak ju nastav na pracovnú mapu, prejdi na koniec slova a pokračuj v bode 2. 4. Po skončení prehľadávania vypíš všetky nájdené entity Príklad vyhľadávanie v texte "I love my automobile." pre vyhľadávaciu mapu so slovami "automobile" a "lord": Načíta sa znak 'I' a zistí sa, že nie je v mape, tak sa preskočí až na medzeru. Načíta sa znak 'l' a zistí sa, že je v mape, tak sa pokračuje v hľadaní s ďalšou mapou. Načíta sa znak 'o' a zistí sa, že je v mape, tak sa pokračuje v hľadaní s ďalšou mapou.
Načíta sa znak 'v' a zistí sa, že nie je v pracovnej mape, tak sa preskočí na ďalší niealfanumerický znak (v tomto prípade na najbližšiu medzeru) a pracovná mapa sa nastaví na koreňovú. Načíta sa znak 'm' a zistí sa, že nie je v mape, tak sa preskočí až na medzeru. Načíta sa znak 'a' a zistí sa, že je v mape, tak sa pokračuje v hľadaní s ďalšou mapou. Potom sa postunpe prejdú všetky znaky až do konca a nájde sa entita "automobile." Jej výskyt sa vypíše. Implementácia Pre implementáciu som si zvolil programovací Jazyk Java. Parsovanie som vykonal pomocou štandardného SAX parsera, ktorý je dostupný v JDK. Keďže SAX parser je udalosťami riadený, nie je pamäťovo náročný. Udalosti, ktoré som zachytával sú: začiatočný element koncový element znaky vo vnútri tela elementu Tieto udalosti som využil na zozbieranie informácii o hľadaných enitách. Po zozbieraní všetkých entít a redirektov som spracoval redirekty, z ktorých som vybral len tie, ktoré sa odkazovali na niektoú nájdenú entitu. Tieto som potom zapísal do súboru. Následne som tento súbor mohol využiť na hľadanie. Postupne som z neho čítal riadky a vytvoril som reprezentáciu slovníka na hľadanie. Používanie programu Program som urobil ako konzolovú aplikáciu. Spúťaný je s dvoma prepínačmi: P - parsovanie wikipédie S - hľadanie v texte Obidva parametre môžu mať zadaný nepovinný názov súboru. Je to buď XML súbor, z ktorého sa parsuje (pre parameter P), alebo súbor. z ktorého sa bude čítať vstupný text (parameter S). Ak sa tieto súbory nezadajú, tak sa zoberie preddefinovná cesta k súboru a preddefinovaný text na hľadanie. Zapisovanie aj čítanie slovníka vždy prebieha z/do súboru s názvom gazetter_wiki_dump_articles_people.txt. Na výstupe konzoly potom vydíme výsledky. Výstupy programu aj z parsovanie Wikipédie aj z jedného hľadania sú priložené v prislúchajúcich súboroch.
Upozornenie: keďže spracovanie všetkých mien do stromovej štruktúry zaberá veľa pamäte, je nutné buď zväčšiť maximálny Java Heap size (argumentom pre JVM, napíklad: -Xmx4608m) alebo vytvoriť slovník na hľadanie z menšieho vstupného súbora. Výsledky Navrhovaný prístup našiel spolu 2 103 349 enít, ktoré vyhovovali hľadaným kritériám. Z tohto počtu bolo 999 833 redirektov a 1 103 516 konkrétnych entít (priložený súbor). Testoval rýchlosti a pamäťovej náročnosti som vykonal na nasledovnej konfigurácii: Procesor Intel Core i7 @2400MHz, 8 GB RAM, Windows 7 64-bit. Priemerné časy spracovávania sú nasledované: Parsovanie - precházanie XML súboru Spracovanie nájdených entít a redirektov Zápis nájdených entít do súboru Prečítanie slovníka zo súboru a vytvorenie mapy 8 minút a 2 sekundy 1,3 sekundy 7,5 sekúnd 55,7 sekúnd Samotné hľadanie entít je vďaka stromovej štruktúre so znakmi, ako aj s preskakovaním pri nenájdení znaku vo vyhľadávacej mape naozaj rýchle. Vstupný súbor, ktorý mal približne jeden milón znakov sa podarilo prehľadať za 71 milisekúnd. Pamäťové nároky som získal pomocou programu na monitorovanie Java procesov JVisualVM, ktorý je dodávaný spolu s JDK. Pamäťová naročnosť bola nasledovná: Pri parsovaní sa použilo 2420 MB RAM (z celkového Java Heap Size 3435) Pri vyhľadávaní bolo zabratých 3166 MB pamäte (tu sa dosiahol maximálny nastavený Heap size - 4608 MB) Testovanie presnosti a pokrytia som vykonal na troch článkoch z CNN. Všetky tri články, ako aj výstupy programu pre ne sú priložené. Hodnoty presnosti a pokrytia sú pre tieto tri články nasledovné: Článok 1: Presnosť = 3/3 = 1 -> 100% Všetky nájdené entity boli správne Pokrytie = 3/(3+10) = 0,23 -> 23% V tomto článku sa často spomínalo meno jedného autora, avšak toto aj keď patrí človeku nie je na wikipédii a preto ho program v článku nenašiel
Článok 2: Presnosť = 13/18 = 0,722 -> 72,2% Entity prezidentov našiel iba podľa priezviska a nie celého uvedeného mena. Taktiež našlo entitu "St. Peter" pričom v texte je námestie "St. Peter's Square" Pokrytie = 13/(13+18) = 0,419 -> 41,9% "Francis" namiesto celého "Pope Francis" Častý výskyt skráteného Článok 3: Presnosť = 11/13 = 0,846 -> 84,6% Podobne ako článok 2. Pokrytie = 11/(11+4) = 0,733 -> 73,3% sú na wiki. Pomerne málo mien, niektoré nie Nedotatky Vzhľadávanie pomocou mapovej stromovej štruktúry je síce vskutku rýchle, ale spracovať všetky entity z Wikipédie je pamäťovo veľmi náročné práve kvôli rozdeľovanie na znaky. Ak by sme chceli sparsovať všetky entity, museli by sme vztvoriť iný prístup. Druhým nedostatkom riešenia sú práve spracovania osôb. Napríklad, ak by som chcel vyhľadať osobu s meno "Abe Lincoln", ktorý bol hudobníkom v minulom storočí, tak by som musel hľdanie upresniť, nakoľko pod týmto menom je redirekt na prezidenta USA Abraháma Lincolna. Taktiež niektoré redirekty na osoby sú ich prezývkami, ktoré však v bežnej reči majú úplne iný význam. Jeden konkrétny príklad je enita "In a world" ktorá je redirektom na dabléra Don LaFontaine známe z rôznych upútaviek, ktoré často začínali touto vetou. V zvyčajnom anglickom texte však slová "In a world" takmer nikdy neznamenajú odkaz na tohto človeka. Posledným nedostatkom je vyhľadávanie niektorých entít, ktoré nasledujú za sebou. Ak je v texte napríklad "Abe Lincoln" a za ním "Taylor Swift" tak program nájde iba prvú entitu a nie druhú. To je preto, lebo pri parsovaní sa našla entita "Abe Lincoln (trombonist)" a program sa snaží pokračovať v hľadaní celého výrazu.