wiki:cs/ZpracovaniMetainformaci

Version 1 (modified by xkocinc, 10 years ago) (diff)

--

Zpracování metainformací


Tento článek popisuje využití metainformací. Ty jsou využitelné pro zjištění statistik o korpusových datech a pro vytváření specializovaných korpusů.

Co je cílem

Naším primárním cílem je z vertikálního textu vytvořit korpus. Pokud vytváříme specializovaný korpus (např. dokumenty jen z oblasti ekonomie), využíváme metainformace, kde jsou vyznačeny potřebné údaje.

Metainformace jsou uloženy jako textové soubory ve stejném adresáři jako vertikál. Pokud chceme s nimi pracovat nabízejí se nám tyto možnosti: programy typu textutils - grep, sort, cut, ... anebo SQL databáze.

Metainformace jako textová databáze

Pro využití nástrojů ze sady textutils je vhodné metainformace trochu přeskupit - a to tak aby jeden řádek odpovídal jednomu dokumentu. V praxi použitý program make_doc_list pro každý soubor s metainformacemi vytiskne na jeden řádek dvojtečkou oddělené atributy Signatura:Size:Lemmat:Offset:Doc_id:Vertikal:T_Main:T_Sub

A3B7550:3614:52%;10%:19446,23372:S/NWS/1992/lnfi9210/011:cnk25/LNFI/lnfi9210.vert:MIX:MIX
AAAA366E:400:96%;84%:9751,2827:S/NWS/1996/ln96238p/006:cnktag/LN/1996/ln96238p.vert:sci2:pol

V adresáři /nlp/corpora/vertical/INFO_O_DUPLICITACH/ je několik souboru *.list, které byly vytvořeny vždy jako textová databáze metainformací pro každý korpus a to takto:

$ cd korpus
$ traverse_dir meta make_doc_list > korpus.list

Viz také /nlp/corpora/vertical/INFO_O_DUPLICITACH/Makefile.

Pokud chceme tedy vytvořit ekonomický korpus ze všech zdrojů, které jsou k dispozici tak zadáme:

$ cat /nlp/corpora/vertical/INFO_O_DUPLICITACH/vertikal.list \
| egrep ':eco:eco$' \          #vybereme radky odpovidajici dokumentum z ekonomiky
| cut -d: -f4-6 \                #vybereme udaje pro program list2vert
| list2vert                     #ze seznamu dokumentu vytvorime vertikalni text

Metainformace jako SQL databáze

Metainformace jsou uloženy v SQL databázi MySQL na stroji faunus. Tato forma uložení poskytuje oproti textové databázi mocnější dotazovací prostředek a u netriviaálních dotazů mnohem rychlejší vyhodnocení.

Struktura SQL databáze

Jsou vytvořeny dvě tabulky:

tabulka vertical
25 sloupců - primární klíč doc
tabulka vertical_M
4 sloupce 
mysql> explain vertical_M;
+--------+---------------------+------+-----+---------+-------+
| Field  | Type                     | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| Doc     | varchar(255) binary |        | MUL |            |         |
| M_Auth | varchar(255)          | YES  |      | NULL     |         |
| M_Date | date                     | YES  |      | NULL     |         |
| M_Desc | varchar(255)          | YES  |      | NULL     |         |
+--------+---------------------+------+-----+---------+-------+

Rozložení do dvou tabulek je nutné, protože atributy typu M_Auth se mohou pro jeden dokument opakovat. Takže dotazy na atributy typu M_Auth se pak musí provádět přes spojení tabulek:

SELECT size FROM vertical NATURAL LEFT JOIN vertical_M;

Založení SQL databáze v MySQL

Tento krok je samozřejmě v ideálním případě provést třeba jen jednou. V případě, že se databáze nějak pokazí (a u tak velké databáze, kdy každá operace trvá dlouho je mnohem pravděpodobnější, že dojde k nějakému nedokončení opearce a tím k nekonzistenci DB) je nejjednodušší ji smazat a založit znovu.

Pro tento účel máme připravený skript:

$ cat /nlp/corpora/vertical/BIN/sql-init
CREATE DATABASE IF NOT EXISTS metainfo;
use metainfo;

DROP TABLE IF EXISTS vertical_M;
CREATE TABLE vertical_M (
    Doc varchar(255) binary NOT NULL,
    M_Auth varchar(255),
    M_Date date,
    M_Desc varchar(255),
    KEY (Doc)
);


DROP TABLE IF EXISTS vertical;
CREATE TABLE vertical (
    Auth_N varchar(255) NOT NULL,
    Auth_S enum('m','f','n','t','X','Y','NA','MIX','ALT'),
    Avail varchar(255),
    D_Publ date DEFAULT '0000-00-00' NOT NULL,
    Date date,
    Doc varchar(255) binary NOT NULL,
    Doc_source varchar(255) NOT NULL,
    F_Publ date,
    Form enum('txb','enc','pop','cri','adv','X','Y','NA','MIX','ALT'),
    Lang enum('aa','ab','af','am','ar','as','ay','az','ba','be','bg','bh','bi','bn','bo','br','ca','co','cs','cy','da','de','dz','el','en','eo','es','et','eu','fa','fi','fj','fo','fr','fy','ga','gd','gl','gn','gu','ha','hi','hr','hu','hy','ia','ie','ik','in','is','it','iw','ja','ji','jw','ka','kk','kl','km','kn','ko','ks','ku','ky','la','ln','lo','lt','lv','mg','mi','mk','ml','mn','mo','mr','ms','mt','my','na','ne','nl','no','oc','om','or','pa','pl','ps','pt','qu','rm','rn','ro','ru','rw','sa','sd','sg','sh','si','sk','sl','sm','sn','so','sq','sr','ss','st','su','sv','sw','ta','te','tg','th','ti','tk','tl','tn','to','tr','ts','tt','tw','uk','ur','uz','vi','vo','wo','xh','yo','zh','zu','X','Y','NA','MIX','ALT'),
    Lemmat1 int(11) DEFAULT '0' NOT NULL,
    Lemmat2 int(11) DEFAULT '0' NOT NULL,
    Medium enum('b','nws','j','scr','net','oc','cdrom','X','Y','NA','MIX','ALT'),
    Position_offset int,
    Position_length int,
    S_Lang enum('aa','ab','af','am','ar','as','ay','az','ba','be','bg','bh','bi','bn','bo','br','ca','co','cs','cy','da','de','dz','el','en','eo','es','et','eu','fa','fi','fj','fo','fr','fy','ga','gd','gl','gn','gu','ha','hi','hr','hu','hy','ia','ie','ik','in','is','it','iw','ja','ji','jw','ka','kk','kl','km','kn','ko','ks','ku','ky','la','ln','lo','lt','lv','mg','mi','mk','ml','mn','mo','mr','ms','mt','my','na','ne','nl','no','oc','om','or','pa','pl','ps','pt','qu','rm','rn','ro','ru','rw','sa','sd','sg','sh','si','sk','sl','sm','sn','so','sq','sr','ss','st','su','sv','sw','ta','te','tg','th','ti','tk','tl','tn','to','tr','ts','tt','tw','uk','ur','uz','vi','vo','wo','xh','yo','zh','zu','X','Y','NA','MIX','ALT'),
    Signat varchar(8),
    Size int(11) DEFAULT '0' NOT NULL,
    T_Main enum('cnk_nove','eco','lit','sci1','sci2','sct','sport','X','Y','NA','MIX','ALT') DEFAULT 'sci1' NOT NULL,
    T_Orig varchar(255),
    T_Sub enum('arc','ars','ast','bot','bui','cin','com','ene','env','let','lif','man','mem','mer','min','nat','reg','scf','sec','tec','trv','zoo','eco','ind','adm','son','ver','nov','crm','sci','adv','ero','bio','tra','tab','fab','hum','jun','ess','chr','exc','inf','phy','geo','ggr','mat','che','bio','med','agr','eth','lin','lit','pol','art','soc','psy','edu','phi','mil','jur','his','rel','sct','amu','hou','tvf','the','mus','dra','spo','X','Y','NA','MIX','ALT') DEFAULT 'inf' NOT NULL,
    Title varchar(255) NOT NULL,
    Tran_N varchar(255),
    Tran_S enum('m','f','n','t','X','Y','NA','MIX','ALT'),
    Vertikal varchar(255),
    PRIMARY KEY (Doc),
    KEY D_Publ (D_Publ),
    KEY T_Sub (T_Sub),
    KEY T_Main (T_Main),
    KEY Lemmat1 (Lemmat1),
    KEY Lemmat2 (Lemmat2),
    KEY Size (Size)
);

Takže pro založení databáze zadáme:

$ mysql -uroot -p mysql < /nlp/corpora/vertical/BIN/sql-init #bude to chtit
heslo spravce databaze

Založení uživatele, který bude spravovat DB metainfo:

$ mysql -uroot -p mysql -e "GRANT ALL ON metainfo.* TO mi_user@localhost
IDENTIFIED BY 'heslo';"
$ mysql -uroot -p mysql -e "GRANT ALL ON metainfo.* TO mi_user@%
IDENTIFIED BY 'heslo';"

A aby uživatel mohl pracovat se soubory, tak mu nastavíme práva:

$ mysql -uroot -p mysql -e "update user SET File_priv='Y' where User='mi_user';
"

A na závěr musíme dát reload, aby jsme změny uvedli v platnost:

$ mysqlacces -uroot -p reload;

Import dat do SQL databáze

Vzhledem k tomu, že současné vertikály obsahují více než milion dokumentů je i SQL databáze s více než milionem záznamů obrovská. Proto je třeba při práci používat co nejrychlejších prostředků. To nabízí program mysqlimport. Ten očekává, že data pro jednu tabulku (např. vertical) budou uložena ve stejnojmenném souboru, jeden řádek tabulky bude reprezentován jedním řádkem souboru, oddělovačem sloupců je znak tabulátor, hodnota NULL se reprezentuje pomocí sekvence 2 znaků "\N". Ukázka 2 řádků tabulky:

$ head -2 /nlp/corpora/vertical/SQL_DATA/vertical
Y    Y    \N    1998-01-01    \N    S/J/1998/150/001    150 hori    1998-01-01    \N    cs    99    88    j    101    5373    \N    6F59FE5D    695    cnk_nove    \N    sec    Y    \N    \N    cnk/150hori/150.vert
Y    Y    \N    1998-01-01    \N    S/J/1998/150/003    150 hori    1998-01-01    \N    cs    94    69    j    7858    4463    \N    5E84F5FB    662    cnk_nove    \N    sec    Y    \N    \N    cnk/150hori/150.vert

Převod z metainformací do tohoto formátu provede program meta2sql, který jako svůj vstup očekává jméno souboru a vytvoří dva soubory s koncovkami .sql1 a .sql2. Takže použití:

$ cd /nlp/corpora/vertical
$ traverse_dir meta meta2sql
$ traverse_dir sql1 cat > vertical
$ traverse_dir sql2 cat > vertical_M

Import dat do databáze se pak provede takto:

$ cd /nlp/corpora/vertical
$ mysqlimport -umi_user -pheslo metainfo vertical
$ mysqlimport -umi_user -pheslo metainfo vertical_M

Použití SQL databáze pro vytvoření korpusu

Tak jako v případě textové databáze použijeme program list2vert, kterému předáme na vstup seznam dokumentů ve formátu:

Offset,Length:Doc:Vertikal

Tento formát vytvoříme vhodným dotazem, např. dotaz

SELECT CONCAT(Position_offset,',',Position_length,':',Doc,':',Vertikal) from vertical where T_Sub='eco' AND Size BETWEEN 2000 AND 2010;
+------------------------------------------------------------------+
| CONCAT(Position_offset,',',Position_length,':',Doc,':',Vertikal) |
+------------------------------------------------------------------+
| 5231183,14467:S/NWS/1995/hnb5/1994:cnk/HN/hnb5.vert                  |
| 4645,15025:S/NWS/1999/ln99086e/003:cnk/LN/1999/ln99086e.vert      |
+------------------------------------------------------------------+
2 rows in set (0.07 sec)

vybral dokumenty, pro které je T_Sub='eco' a jejich velikost se pohybuje od 2000 do 2010 pozic. Výstup si uložíme do souboru nejlépe takto:

$ mysql -umi_reader -pmr metainfo \
-e "SELECT CONCAT(Position_offset,',',Position_length,':',Doc,':',Vertikal) \
from vertical where T_Sub='eco' AND Size BETWEEN 2000 AND 2010;" \
> seznam
$ list2vert  < seznam | encode