wiki:cs/JakVytvoritKorpus1

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

--

Jak vytvořit korpus


Tento článek slouží jako průvodce při vytváření korpusu. Je určen pro studenty a další zájemce, kteří chtějí pořizovat a převádět data pro potřeby korpusů. Za prvé popisuje strukturu korpusů, s využitím odkazů na příslušné normy. Za druhé popisuje možnosti kontroly správnosti korpusových dat. A za třetí podává návod, jak vytvářet korpusy převodem z HTML stránek.

Úvod

Co jsou to korpusy

Obecně - počítačový korpus je rozsáhlý, vnitřně strukturovaný a ucelený soubor textů daného jazyka, elektronicky uložený a zpracovávaný. Práci s korpusovými daty zprostředkovává program nazývaný korpusový manažer.

Aby mohl být určitý text do korpusu zařazen, musí být připravena dvojice textových souborů - tzv. vertikální text (zkráceně vertikál) a metainformace. Vertikál obsahuje samotná korpusová data, metainformace obsahují doplňující údaje o těchto datech. V tomto textu bude množina takových dvojic souborů označována zjednodušeně jako korpus (viz dále).

Struktura korpusových dat

Jak jsou korpusy uloženy

Korpusy jsou uloženy jako textové soubory. Korpus je jednoznačně určen jménem adresáře. Všechny soubory, které končí .vert (vertikály) a .meta (metainformace) a které jsou obsaženy v tomto adresáři a všech jeho podadresářích, tvoří korpus.

Struktura vertikálů

Strukturu vertikálů popisuje norma pro vertikály Popis vertikálů .

Struktura metainformací

Strukturu metainformací popisuje norma pro metainformace Popis metainformací .

Vazby mezi vertikály a metainformacemi

  1. V každém adresáři či podadresáři si musejí co do počtu i do jmen (až na příponu) tyto odpovídat.
  2. Každý z dvojice (vertikál, metainformace) obsahuje dokumenty stejných jmen ve stejném pořadí. Příklad:
    • mf-1999-05-17.vert obsahuje dokumenty "<doc mf/1999/05/17/1>" až "<doc mf/1999/05/17/159>"
  • mf-1999-05-17.meta obsahuje dokumenty "Doc : mf/1999/05/17/1" až "Doc : mf/1999/05/17/159"

Nástroje pro kontrolu správnosti korpusových dat

Dají se rozdělit na tři skupiny:

  • kontrola konzistence mezi vertikály a metainformacemi
  • kontrola vertikálů
  • kontrola metainformací

Všechny jsou dostupné po přidání modulu:

$ module add corpus

na strojích aurora (Linux), aisa (IRIX) a oreias (SunOS).

Pomocné programy

Většina programů pracuje se standardním vstupem a výstupem. To znamená, že kontrolní program nezná jméno souboru, jehož obsah mu byl přesměrován na jeho standardní vstup. Proto je tu program check_file. Použití:

check_file [-l číslo -s -S] program file

$ check_file -l 20 meta_check neco.meta

Jako argumenty mu dáme jméno kontrolního programu a souboru, který chceme zkontrolovat. Jeho výstup obsahuje jméno kontrolovaného souboru a výstup kontrolního programu. Volby:

  • -l číslo ... výstup kontrolního programu se ořeže na 'číslo' řádek
  • -s ... totéž co -l 0
  • -S ... pokud kontrola byla bez chyby, potlačí všechen výstup

Další pomocný program je traverse_dir, který je vystavěn na programu find . Použití:

traverse_dir [-v] suffix program [argumenty pro program]

$ traverse_dir vert check_file -S xml_check

Suffix je buď vert nebo meta. Program vyhledá všechny soubory s příponou suffix a provede volání specifikovaného programu s jeho argumenty a jako poslední argument přidá jméno nalezeného souboru. Takže v ukázkovém případu se volá check_file -S xml_check neco.vert. Volba -v provede navíc výpis těchto volání.

Kontrola konzistence mezi vertikály a metainformacemi

Kontroluje se, jestli si odpovídají soubory .vert a .meta:

$ v2m_files

Dále se kontrolují seznamy jmen dokumentů - program v2m_docs. Kontrola jedné dvojice souborů .meta a .vert:

$ v2m_docs soubor.meta                        #Zadám jen jméno metainformací

Kontrola celého korpusu:

$ traverse_dir meta v2m_docs

Kontrola vertikálů a metainformací

K dispozici jsou tyto programy:

  1. il2_check
    Určeno pro: *.vert, *.meta. Kontroluje kódování češtiny. Ohlásí podezřelé znaky. Je nutno zvážit, zda se jedná o skutečnou chybu nebo ne.
  1. tags_check
    Určeno pro: *.vert. Kontroluje, zda řádky, které vypadají jako značky, jsou ze seznamu povolených značek.
  1. pozice_check
    Určeno pro: *.vert. Kontroluje, zda řádky, které nejsou značkami, jsou dále nedělitelné pomocí funkce Corpus::split().
  1. heuristic_check
    Určeno pro: *.vert. Kontrola pozic, zda neobsahují řídící a značkovací řetězce originálního textu. Hledá HTML značky a příkazy LATEXu.
  1. xml_check
    Určeno pro: *.vert. Kontrola struktury vertikálů.
  1. meta_check
    Určeno pro: *.meta. Kontrola struktury metainformací.

Všechny tyto programy jsou filtry. Proto je používáme jedním z těchto tří způsobů:

$ xml_check < soubor.vert > zde_je_vystup 2>&1

nebo:

$ check_file xml_check soubor.vert > zde_je_vystup

nebo:

$ cd adresar_s_daty 
$ traverse_dir vert check_file xml_check > zde_je_vystup

Všechny kontroly se dají spustit pomocí dávky check_all:

$ check_all > zde_je_vystup 2>&1 

Jak číst výstupy kontrolních programů

  • v2m_files, v2m_docs
    Oba programy používají při hlášení rozdílů v seznamech jmen (v2m_files - jmen souborů a v2m_docs - jmen dokumentů) standardní program comm s parametrem -3. Ten uvede rozdíly ve dvou tabulátorem odsazených sloupcích. Viz také man comm.
  • il2_check, tags_check, pozice_check, heuristic_check, meta_check
    Tyto programy mají snadno čitelný výstup, a není tedy nutno jej zde dále komentovat.

Výstup programu bude vyložen na několika příkladech:

VSTUP č.1:
<?xml version="1.0"?>
<!DOCTYPE vertical SYSTEM "/net/aisa/corpus/vertical.dtd">
<vertical>
</vertical>

VÝSTUP:
Warning: Content model for vertical does not allow it to end here
 in unnamed entity at line 4 char 11 of <stdin>

VYSVĚTLENÍ:
Vertikál neobsahoval žádný dokument, ale párová značka
<vertical> nesmí být prázdná.

----------
VSTUP č.2:        (jen jeho relevantní část)
<doc id="neco">
Ahoj
<head>
Jaroslav

VÝSTUP:
Warning: Content model for doc does not allow element z here
 in unnamed entity at line 5 char 3 of <stdin>

VYSVĚTLENÍ:
Po značce <doc> musí bezprostředně následovat npaříklad <head> 
nebo <p> a nikoli pozice  (element z označuje pozici Ahoj).

---------
VSTUP č.3:        (jen jeho relevantní část)
<p>
<head>
V
zázemí
</head>
blabla
</p>

VÝSTUP:
Content model for p does not allow element head here
 in unnamed entity at line 6 char 6 of <stdin>

VYSVĚTLENÍ:
V <p> nesmí být zanořen <head>

---------
VSTUP č.4:        (jen jeho relevantní část)
<doc id="a">
<p>
V
<p>
A
</doc>

VÝSTUP:
Warning: Content model for p does not allow element p here
 in unnamed entity at line 7 char 3 of <stdin>
Error: Mismatched end tag: expected </p>, got </doc>
 in unnamed entity at line 9 char 6 of <stdin>
  
VYSVĚTLENÍ:
Neuzavřené značky <p>.


---------
VSTUP č.5:        (jen jeho relevantní část)
<p>
<g/>
konec

VÝSTUP:
Warning: Content model for p does not allow element g here
 in unnamed entity at line 6 char 3 of <stdin>
 
VYSVĚTLENÍ:
Značka <g/> zde nemůže být, protože musí být vždy z obou stran obklopena
pozicemi, které spojuje a zde je nad ní nikoli pozice, ale značka <p>.
Tato chyba nemůže vzniknout, pokud se použije na "rozsekání"
textu funkce Corpus::split nebo program corus_split.

Převod HTML stránek na vertikální tvar

Pokud si jako zdroj zvolíme webovské HTML stránky, potom jsou zde k dispozici nástroje pro převod do vertikálu. Jsou založeny na perlovském modulu HTML::Parser (man HTML::Parser) a na funkci Corpus::split.

HTML stránky obsahují kromě značek také ještě posloupnosti znaků zvané entity, například & nebo anebo °. Tyto entity je třeba převést na odpovídající znaky. K tomu je k dipsozici filtr nazvaný html. Dokumenty jsou často v jiném kódování (1250), v tom případě je třeba použít filtr cstocs 1250 il2 a to až po aplikaci filtru html (jinak by došlo k chybnému převodu entit typu °).

Pomocný program vert2xml vznikl k překlenutí rozdílů mezi starší a novější definicí struktury vertikálu. Pracuje jako filtr, který přidá ke svému vstupu hlavičku vertikálu (první tři řádky), opraví tvar některých značek a přidá na konec řádek </vertical>. Programy dále popsané dávají výstup ve starším formátu, proto jako postprocessing je vhodné zařadit filtr vert2xml.

Vzhledem k tomu, že struktura HTML dokumentů je celkem volná, pouhým překladem značek nedospějeme ke dobře utvořenému vertikálu. Proto jsou dále popsány prográmky na úpravu některých neduhů - provádějí párování, rušení nebo vkládání značek. Několik programů je spojeno do dávky tags_all, kterou je možné použít jako poslední postprocessing.

Příklad 1. - nejjednodušší použití

Je implementováno v programu html2vert.1 . Program funguje jako filtr. Použití:

 html <  muj.html | html2vert.1 |vert2xml | tags_all > muj.vert 

Výpis programu:

BEGIN {push @INC ,                                                                  #Do seznamu cest modulu pridej
"/usr/local/lib/perl5/site_perl/5.005",          #Cestu k modulu HTML::Parser
"/packages/share/corpus/lib"                         #Cestu k modulu Corpus        
};

use Corpus;                                                                                #Vyzada si balik Corpus                
require HTML::Parser;                                                                #Vyzada si balik HTML::Parser
package Muj_Parser;                                                                  #Odtud zacne balik Muj_Parser

#Nastavuje dedicnost
@ISA=qw(HTML::Parser);

sub start {}                  #vola se, kdyz je rozpoznana nekoncova znacka, zatim nedela nic
sub end        {}                  #vola se, kdyz je rozpoznana koncova znacka, zatim nedela nic

#Tato procedura se vola vzdy, kdyz je rozpozan nejaky text
sub text                                                                  
{
  my($self, $text) = @_;                                  #do $self, $text si ulozim parametry 
  return unless $text;                                         #pokud $text je prazdny, vrat se
  my $t=(Corpus::split($text));                 #do $t uloz rozdeleny text
  print $t unless $t =~ /^$/;                        #tiskni $t, pokud neni prazdny
}

$p = Muj_Parser->new;                  #Vytvorim novy objekt tridy  Muj_Parser
$p->parse_file(\*STDIN);                  #Volam parsovani standardniho vstupu

Program převede entity, vypustí všechny HTML značky a text "rozseká" pomocí funkce Corpus::split na pozice. Proto jediná značka ve výstupu bude <g>.
Program funguje takto:
Metoda parse_file postupně zpracovává STDIN a vždy, když rozpozná nějakou značku, zavolá proceduru start, případně end, a tuto značku, převedenou na malá písmena a zbavenou atributů, předá jako druhý argument. Text mezi značkami je předán proceduře text.

Příklad 2. - přidání některých značek

Je k dispozici v souboru html2vert.2 . Pokud budeme chtít, aby se ve výsledném vertikálu objevily značky <doc>, resp. <p>, tehdy, když ve zdroji byly značky <HTML>, resp. <p>, změníme definici procedur start a end tak, aby tiskly značky, když se rozpoznají jejich HTML ekvivalenty. Navíc do značky <doc> se přidá jako atribut jméno, které je prvním argumentem programu. Použití :

 html < muj.html | html2vert.2 blabla | vert2xml | tags_all > muj.vert 

Změněné procedury:

sub start
{
        my($self, $tag) = @_;
        if ($tag eq "html") {print "<doc $ARGV[0]>\n"}; 
        if ($tag eq "p") {print "<p>\n"}; 
}

sub end
{
        my($self, $tag) = @_;
        if ($tag eq "html") {print "</doc>\n"};
}

Příklad 3. - pokročilejší značení

Je k dispozici v souboru html2vert.3 . Testovací soubor lidových novin je v souboru ln-1999-11-10.all? . Použití:

 html < ln-1999-11-10.all | html2vert.3 l n | vert2xml | tags_all > muj.vert 

Předpokládejme strukturu HTML dokumentu reprezentovanou těmito zanořenými značkami (text byl vypuštěn - viz html_pp):

        <HTML>
                <HEAD>
                        <SCRIPT LANGUAGE="JavaScript">
                        </SCRIPT>
                </HEAD>
                <BODY>
                        <P ALIGN="center">
                        <DIV CLASS="vlclanek">
                                <P ALIGN="right">
                                <B>
                                        <I>
                                        </I>
                                </B>
                        </DIV>
                        <HR ALIGN="center" NOSHADE SIZE=2 WIDTH="30%">
                        <DIV CLASS="vlclanek">
                                <P ALIGN="right">
                                <B>
                                        <I>
                                        </I>
                                </B>
                        </DIV>
                </BODY>
        </HTML>

Toto je zjednodušená struktura HTML souborů na serveru www.trafika.cz (dnes již na noviny.trafika.cz deníky Lidové noviny, Mladá fronta Dnes a Právo nenajdete). Jeden soubor bude převeden na vertikál s několika dokumenty. Jeden dokument odpovídá kontejneru značek <div> a </div>. Proto do vertikálu pustíme jen text z těchto oblastí. Navíc víme, že text zanořený ve značkách <b> a <i> je tučnou kurzívou vysázené jméno autora, které chceme mít ve vertikálu mezi značkami <sign> a </sign>. Dále budeme jednotlivé dokumenty číslovat, dvanáctý dokument Lidových novin bude <doc ln/12>.

Předefinujeme procedury start, end a text:

sub start
{
         my($self, $tag) = @_;
         if ($tag eq "div") {$self->{"poradi"}++;                        #zvysim si pocitadlo
                        print "<doc $ARGV[0]/$self->{poradi}>\n"; #tisknu <doc jm/cislo>
                                                                $self->{"div"}=1;                                                         #indikuju oblast div 
                                                          } 
         elsif ($tag eq "p") {print "<p>\n" if $self->{"div"}; }         #tisknu <p>, pokud  je div
         elsif ($tag eq "b") {$self->{"b"}=1}                                                          #indikuju b
         elsif ($tag eq "i") {$self->{"i"}=1;                                                #indikuju i 
                                print "<sign>\n" if $self->{"b"};  #tisknu <sign>, pokud je b
                                                                }
}

sub end
{
         my($self, $tag) = @_;
         if         ($tag eq "b") {$self->{"b"}        =0}                        #konci b
         elsif ($tag eq "i") {$self->{"i"}        =0;                        #konci i
                                                                 print "</sign>\n" if $self->{"b"};  #tisknu </sign>, je-li b
                                                                }
         elsif ($tag eq "div")  {$self->{"div"} =0;                        #konci div
                                                                         print "</doc>\n";                                         #tisknu </doc>
                                                                        } 
}


sub text {
        my($self, $text) = @_;          #do $self, $text si ulozim parametry
        return unless $self->{"div"};   #Pokud neni v mezich div, tak netiskni
        return unless $text;            #pokud $text je prazdny, vrat se
        my $t = (Corpus::split($text)); #do $t uloz rozdeleny text
        print $t unless $t =~ /^$/;     #tiskni $t, pokud neni prazdny
}

Objekt $p si nese informaci, ve kterém zanoření zrovna je, a to pomocí ukazatele $self na hash. Například $self->{"div"} =1; signalizuje, že jsme vstoupili do div kontejneru.

Příklad č.4 - program používaný pro převod periodik z www.trafika.cz (dnes noviny.trafika.cz)

Je k dispozici bez dalších komentářů v souboru html2corpora .

Pomocný nástroj pro analýzu struktury HTML - html_pp (pp - pretty printer)

Program slouží k tomu, aby bylo snadnější nahlédnout strukturu konkrétního HTML dokumentu. Ponechá pouze značky a odsadí je podle zanoření pomocí tabulátorů. Struktura v předchozím příkladu byla vygenerována právě pomocí html_pp. Použití:

cat ln-1999-11-10.all | html_pp 

K běhu potřebuje perlovský modul HTML::TreeBuilder?.

Programy na opravu častých chyb

Pro vertikály

Všechny jsou dostupné po přidání modulu:

$ module add corpus

na strojích aurora (Linux), aisa (IRIX) a oreias (SunOS). Jsou to:

  1. tags_pair_doc
    Páruje značku <doc>.
  1. tags_rm_bad_glue
    Maže značku <g/>, pokud není "obalena" pozicemi.
  1. tags_rm_multi
    Maže opakující se značky (nechá jen první výskyt z posloupnosti).
  1. tags_pair_item
    Páruje značku <item>.
  1. tags_rm_empty
    Maže počáteční a koncovou značku, pokud jsou bezprostředně za sebou.
  1. tags_insert_p
    Vkládá značku <p> před pozici tam, kde by tato pozice byla zahnízděná přímo v kontejneru značky <doc>.
  1. tags_pair_p
    Páruje značku <p>.
  1. tags_all
    Dávka, která kombinuje některé výše uvedené programy.

Použití: všechny programy pracují jako filtry, takže se dají přidat na konec kolony, která produkuje vertikál. Na už vygenerovaný vertikál je vhodné je spustit pomocí pomocného programu apply_filter:

úprava jednoho souboru:

$ apply_filter tags_all vertikal.vert

úprava všech vertikálů v korpusu:

$ cd korpus
$ traverse_dir vert apply_filter tags_all

Pro metainformace

atrib_insert_povinne - program, který doplní neuvedené povinné atributy a nastaví jim hodnotu Y (nezjistitelné). Je to také filtr, takže použití vypadá takto:

úprava jednoho souboru:

$ apply_filter atrib_insert_povinne vertikal.meta

úprava všech metainformací v korpusu:

$ cd korpus
$ traverse_dir meta apply_filter atrib_insert_povinne

Vložení dalších atributů zajišťují programy:

  1. atrib_insert_offset
  1. atrib_insert_size
  1. atrib_insert_lemmat
  1. atrib_insert_signat (běží zatím je na auroře)

Všechny programy očekávají jako svůj jediný argument jméno souboru s metainformacemi.

Použití: Úprava jednoho souboru:

$ atrib_insert_size vertikal.meta

úprava všech metainformací v korpusu:

$ cd korpus
$ traverse_dir meta atrib_insert_size

Doplňkové programy

  1. vert2xml
    Program vhodný pro transformaci starého formátu vertikálů na nový. Filtr, který vkládá tyto 3 řádky před svůj vstup:
<?xml version="1.0"?>
<!DOCTYPE vertical SYSTEM "/net/aisa/corpus/vertical.dtd">
<vertical>

a tento za svůj vstup:

</vertical>

a provádí změnu u značek <doc> , <pre> a <g>.

  1. cisti_corpus
    Najde soubory, které nekončí .vert nebo .meta (lze je potom smazat). Použití:
$ cd korpus
$ cisti_corpus                                #vypis
$ cisti_corpus | xargs rm -f                #smazani
  1. docs2meta
    Přejmenuje .docs soubory na .meta (docs - starší, již nepoužívaná koncovka pro metainformace). Použití:
$ cd korpus
$ docs2meta
  1. corpus_size
    Zjistí velikost korpusu. Na výstup dá počet pozic korpusu.
$ cd korpus
$ corpus_size