This is an old revision of the document!
Table of Contents
Eman
Ondrův e-mail z 4.2.2011:
musim se pochlubit, ze (az na jeste par much) mam ukazku pouziti emana pro preklad i pro ty, kdo to jeste vubec nezkouseli:
svn co https://svn.ms.mff.cuni.cz/svn/statmt/trunk statmt cd statmt/playground # podivejte se na README export PATH=$PATH:$(pwd)/../scripts eman init binaries # to jen proto, abyste mohla potvrdit certifikat sourceforge # a pak uz podle readme spustit mikropokus SKIP_IRSTLM=yes eman clone --start < eman.samples/cs-en-mini.traceback
Prikaz:
eman –man
ukaze manualovou stranku
Tvorba šablon (nové druhy kroků, seeds)
Jako příklad viz eman.seeds/lm. Toto je šablona na všechny kroky, které vytvářejí jazykové modely. Povinně vyžaduje nastavit tyto vstupní proměnné:
- BINARIES: odkaz na krok, ve kterém byly zkompilovány externí nástroje, např. SRILM. Spustitelné binární soubory leží zřejmě přímo ve složce tohoto kroku jako výstupní soubor.
- CORP: zkrácený název trénovacího korpusu. I jednotlivým korpusům odpovídají kroky, které vyrábějí či zpřístupňují dotyčné datové soubory. Na to slouží mj. nový skript
makecorp.pl
(nebo tak nějak), který částečně přebírá práci staršíhoaugment.pl
. - CORPAUG: faktory dotyčného korpusu, které se mají použít pro trénování.
- ORDER: řád modelu (např. 3 pro trigram).
Volitelně lze nastavit i další vstupní proměnné.
Konstruktor (skript eman.seeds/lm
) vytvoří soubor eman.tag
, obsahující stručnou jednořádkovou charakteristiku kroku (v tomto případě zejména charakteristiku korpusu, ze kterého byl jazykový model vyroben).
Dále vytvoří soubor eman.vars
, kam opíše všechny vstupní proměnné a jejich hodnoty ve formě přiřazení (tj. sourcnutí tohoto souboru umožní kdykoli zrekonstruovat příslušnou část prostředí).
Dále vytvoří soubor eman.deps
, kde jsou názvy kroků, na kterých tento krok závisí, tj. dotyčné kroky musí úspěšně skončit ještě před spuštěním tohoto kroku. V případě jazykového modelu je závislost pouze na BINARIES (proč ne taky na trénovacím korpusu?) Pro korpus se v tomto případě sahá přímo do augmented_corpora
– že by zastaralé použití? Pokud je seed skript puštěn v přípravném režimu a dotyčný korpus v augmented_corpora
nevidí, skončí chybou.
Teprve v přípravném režimu se také vyrobí hlavní skript eman.command
, který bude na clusteru vykonávat hlavní činnost kroku.
Založení nového kroku podle šablony
Použijeme příkaz eman init
. Typicky musíme předat nějaké vstupní parametry prostřednictvím proměnných prostředí. Můžeme samozřejmě nejdřív nastavit prostředí a pak zavolat eman init
, ale v bashové syntaxi můžeme také rovnou předřadit přiřazení do proměnných před příkaz, např. takhle vytvoříme nový krok typu dandata
pro jazykový pár en-cs (na všechny operace s emanem se musíme nacházet na hřišti):
cd $STATMT/playground SRC=en TGT=cs eman init dandata
Spuštění a opakované spuštění kroku
Spuštění kroku znamená, že se vygeneruje jeho skript (pustí se eman.seed
a z něj vypadne eman.command
) a odešle se jako úloha na cluster. Provádí se pomocí eman start
, např.
eman start dandata
(V tomto případě ovšem předpokládáme, že na hřišti leží jen jeden krok typu dandata
. Eman ho pak dokáže identifikovat.)
Kroky, které už byly spuštěny v minulosti a skončily úspěšně (jsou ve stavu DONE
), se fyzicky znova nespustí. Předpokládá se, že by výsledek byl stejný jako ten, který už leží nebo má ležet ve složce kroku. Jestliže chceme vynutit přepočítání kroku (třeba teprve ladíme způsob, jakým se krok počítá), musíme nejdříve ručně změnit stav na INITED
nebo PREPARED
. (Ale pozor, pokud teprve ladíme šablonu (seed) kroku, musíme zajistit, aby se nová šablona okopírovala jako eman.seed
do daného kroku. Taky potom musíme nastavit stav INITED
, nikoli PREPARED
, aby se přegeneroval eman.command
z eman.seed
. Možná by pak bylo jednodušší inicializovat nový krok podle aktuální šablony a ten starý časem vyhodit.)
cat s.dandata.038e9f18.20120118-2212/eman.status DONE echo INITED > s.dandata.038e9f18.20120118-2212/eman.status cp eman.seeds/dandata s.dandata.038e9f18.20120118-2212/eman.seed eman start dandata Executing: eval $(cat eman.vars) EMAN_READONLY=yes ./eman.seed Step s.dandata.038e9f18.20120118-2212 prepared. Executing: ( qsub -C '' -N s.dandata.038e9f18.20120118-2212 -o log.o\$JOB_ID -hard -j y -cwd -S /bin/bash -p -100 ./eman.command 2>&1 ) > log Step s.dandata.038e9f18.20120118-2212 submitted as job 2160759
Druhou možností je příkaz eman redo
. Ten ale vyrobí kopii stávajícího kroku a tu spustí.
Jestliže jsme úspěšně prošli stavy INITED
a PREPARED
a nepotřebujeme měnit základní nastavení kroku (zejména hodnoty proměnných), ale krok přesto skončil ve stavu FAILED
(např. proto, že došlo místo na disku), můžeme zavolat eman continue
, který pracuje v původní složce kroku a pokusí se krok dotáhnout do stavu DONE
. Continue pouze znova pustí skript eman.command
ve složce kroku. Tento skript můžeme nejdřív podle potřeby upravit, např. zakomentovat řádky, které při předcházejícím pokusu doběhly úspěšně a jejich výsledek už ve složce kroku leží.
Spuštění mnoha příbuzných kroků najednou
Řada emanových příkazů, zejména těch pro vypisování informací, je schopná operovat nad všemi kroky daného typu najednou. Např. takhle si vypíšeme proměnné všech kroků typu dandata
a jejich stav:
zeman@lrc1:~/projekty/statmt/playground$ eman vars dandata s.dandata.e91dcaed.20120119-0921 SRC=en TGT=fr s.dandata.eb2b73f5.20120119-0921 SRC=en TGT=es s.dandata.4bd447c7.20120119-0921 SRC=en TGT=de s.dandata.886c6804.20120119-0921 SRC=fr TGT=en s.dandata.038e9f18.20120118-2212 SRC=en TGT=cs s.dandata.18e4135a.20120119-0921 SRC=es TGT=en s.dandata.68958d57.20120119-0921 SRC=de TGT=en s.dandata.640d0845.20120119-0921 SRC=cs TGT=en zeman@lrc1:~/projekty/statmt/playground$ eman status dandata s.dandata.e91dcaed.20120119-0921 INITED s.dandata.eb2b73f5.20120119-0921 INITED s.dandata.4bd447c7.20120119-0921 INITED s.dandata.886c6804.20120119-0921 INITED s.dandata.038e9f18.20120118-2212 RUNNING s.dandata.18e4135a.20120119-0921 INITED s.dandata.68958d57.20120119-0921 INITED s.dandata.640d0845.20120119-0921 INITED
Tento přístup ale není možné použít ke spuštění všech kroků daného typu, které ještě nejsou ve stavu DONE
. eman start
chce vždy spustit právě jeden krok, a pokud ho na základě pouhého určení typu nedokáže jednoznačně určit, odmítne pokračovat:
zeman@lrc1:~/projekty/statmt/playground$ eman start dandata Ambiguous in dir listing: dandata: s.dandata.038e9f18.20120118-2212 s.dandata.18e4135a.20120119-0921 s.dandata.4bd447c7.20120119-0921 s.dandata.640d0845.20120119-0921 s.dandata.68958d57.20120119-0921 s.dandata.886c6804.20120119-0921 s.dandata.e91dcaed.20120119-0921 s.dandata.eb2b73f5.20120119-0921
Nejde dokonce ani zavolat eman start
s několika jednoznačně určenými kroky. Pustí se totiž jen ten první z nich:
zeman@lrc1:~/projekty/statmt/playground$ eman start `eman select t dandata s INITED` Executing: eval $(cat eman.vars) EMAN_READONLY=yes ./eman.seed Step s.dandata.e91dcaed.20120119-0921 prepared. Executing: ( qsub -C '' -N s.dandata.e91dcaed.20120119-0921 -o log.o\$JOB_ID -hard -j y -cwd -S /bin/bash -p -100 ./eman.command 2>&1 ) > log Step s.dandata.e91dcaed.20120119-0921 submitted as job 2160762
Proto použijeme řídící struktury bashe:
for sl in en cs de es fr; do for tl in en cs de es fr; do if [ $sl == en ] && [ $tl != en ] || [ $sl != en ] && [ $tl == en ] ; then SRC=$sl TGT=$tl eman init dandata --start; fi done; done
nebo:
for step in `eman ls dandata`; do eman start $step; done
Parametry clusteru
Pokud Eman běží na clusteru, odesílá zpracování kroků (eman.command
) jako clusterové úlohy. V opačném případě se pokouší pouštět místní procesy, které na sebe čekají. Někdy potřebujeme vznést konkrétní požadavky na stroj, na který plánovač clusteru naši úlohu umístí. Zejména jde o požadavky na operační paměť. V Emanovi momentálně nelze nastavit výchozí paměťové požadavky daného typu kroku (šablony). Musíme proto o paměť požádat explicitně pokaždé, když spouštíme konkrétní krok. Např. takto si řekneme o stroj, na kterém je dostupných 20 GB a který má alespoň 50 GB volného místa v /mnt/h/tmp
:
eman start danalign --mem 20g --disk 50g
Některé druhy kroků (např. mert
a translate
) samy generují paralelní úlohy pro cluster. Výše uvedený způsob nastaví požadavky pouze pro hlavní úlohu daného kroku, ale o případných dceřinných úlohách nic neví. To je potřeba zařídit pomocí parametrů kroku. Např. šablony obou uvedených druhů kroků počítají s proměnnou GRIDFLAGS
, ve které můžeme uvést doplňkové volby pro příkaz qsub
. Bohužel to musíme udělat už při inicializaci kroku. Takže když dodatečně zjistíme, že krok nedoběhl kvůli nedostatku paměti nebo místa na disku pro některou jeho podúlohu, nemůžeme jednoduše zavolat eman continue s.mert… –mem 30g
, musíme vytvořit nový krok pomocí eman redo
:
GRIDFLAGS="-hard -l mf=30g -l act_mem_free=30g -l h_vmem=30g" eman redo s.mert... --start
Navazování kroků
Typický experiment se skládá z několika kroků. Některé mohou probíhat paralelně, jiné na sobě závisí, takže jeden lze spustit až po úspěšném dokončení druhého. Emanovi je pochopitelně potřeba říct, že krok závisí na jiném kroku. Dělá se to tak, že mezi povinné vstupní proměnné v šabloně kroku zavedeme proměnnou, jejíž hodnota je jméno konkrétního jiného kroku. Rovnou při zavádění proměnné ji označíme za proměnnou typu reqstep
a eman zařídí vše potřebné (mimo jiné zapíše jméno požadovaného kroku do souboru eman.deps
ve složce nově zakládaného kroku). Eman nám také může poskytnout absolutní cestu do kroku, na kterém závisíme, abychom mohli k jeho výstupním souborům přistupovat i ze skriptu, který odesíláme na cluster. Do šablony (seedu) můžeme dát např. tohle:
eman defvar DATASTEP type=reqstep help='where are trainal.$SRC.gz and trainal.$TGT.gz' # convert the dependencies to absolute paths DATASTEPDIR=`eman path $DATASTEP`
Podle šablony pak můžeme vytvořit instanci nového kroku, která bude záviset na konkrétně vybrané instanci předchozího kroku. Např. v následujícím příkladu navazujeme nově zakládaný krok typu danalign
na existující krok typu dandata
, přičemž ze všech existujících kroků typu dandata
si vybereme ten, který má proměnnou SRC
nastavenou na en
a proměnnou TGT
nastavenou na cs
:
DATASTEP=`eman select t dandata v SRC=en v TGT=cs` eman init danalign
Kromě výstupních souborů můžeme chtít zdědit také hodnoty proměnných předcházejícího kroku, třeba právě kódy jazyků SRC
a TGT
. Do šablony nového kroku tedy připíšeme tohle:
eman \ defvar SRC inherit=DATASTEP help='source language code' \ defvar TGT inherit=DATASTEP help='target language code'
eman select
Když se ptáme na hodnotu proměnné, která obsahuje zvláštní (ale ne tak moc zvláštní) znaky, z nějakého neznámého je musíme obalit uvozovkami a ještě tyto uvozovky zachránit před shellem, aby se dostaly dovnitř do emana. Jinak dotaz nefunguje a eman vrátí dlouhý seznam obsahující nejspíš všechny známé kroky. Např. takhle:
eman select t augment v ACDESC=\"news-commentary-v6.cs-en+europarl-v6.cs-en/en+lcstem4\"
V tomto konkrétním případě bych se také místo hledání hodnoty proměnné mohl spokojit s hledáním kroku podle značky (tagu), ale to zatím eman neumožňuje, alespoň podle manuálových stránek.
Značkování kroků
Dvě veličiny nás u každého kroku budou zajímat velmi často: stav kroku (–status
nebo eman status <kroky>
) a hodnoty proměnných, které ho definují (–vars
nebo eman vars <kroky>
). Třetí veličina, která je doplňuje, je tzv. značka neboli tag (–tag
nebo eman tag <kroky>
). Jde o stručný popis pokud možno na jeden řádek, který nám pomůže rychle identifikovat mezi desítkami např. jazykových modelů „ten náš“. Často budeme chtít do značky zahrnout vybrané hodnoty proměnných, např. kódy jazyků a faktorů, použitých korpusů apod.
Značky jsou dvou druhů: ruční a automatické. Ruční značku můžeme přidat ke každému kroku zvlášť a je uložena ve složce daného kroku v souboru eman.tag
. Můžeme do něj psát přímo a pak zavolat eman reindex
, nebo rovnou zavolat eman add-tag <značka> <krok>
. V praxi ovšem tento příkaz často volá už šablona kroku, takže značka je opět tvořena více méně automaticky (to je zřejmě relikt z doby, kdy automatické značky v dnešním smyslu neexistovaly). (Ale pozor: Ondra potvrdil, že toto chování šablon je zastaralé a nyní se doporučuje, aby příkaz eman add-tag
byl vyhrazen pro ruční volání uživatelem.)
Automatické značky kroku vznikají z hodnot proměnných na základě pravidel (regulárních výrazů) v souboru eman.autotags
, který je jeden pro celé hřiště a musíme si ho vytvořit, v repozitáři jsou pouze ukázky. Kromě toho každý krok automaticky zdědí automatické značky svých předchůdců (kroků, na kterých závisí).
Ve výpisu eman tag
jsou značky seřazené podle abecedy.
Korpusové kroky
Některé kroky připravují části korpusů, které jsou pro experiment potřeba. Takový krok asi typicky bude přímo zasvěcen přípravě korpusu (a je pak obvykle typu corpus
), ale není ani vyloučeno, že korpus bude vedlejším produktem jiné činnosti. (Za zvláštní druh korpusového souboru se v tomto případě považuje i soubor se zarovnáním slov.) Každopádně pokud je výsledkem nebo jedním z výsledků kroku korpus, je vhodné ve složce daného kroku založit soubor corpman.info
, který popisuje, jaký korpus nám to tady vznikl. Skript pro tvorbu korpusů ho potom může využít při tvorbě kombinovaných korpusů, jiných faktorů apod.
Soubor corpman.info
lze také vytvořit pomocí příkazu corpman register
. Nástroj corpman je součástí hřiště a umožňuje také vyhledat podle zadaných parametrů (název korpusu, jazyk a faktory) krok emana, ve kterém už je daný korpus vytvořen.
Ondrův návod, jak převzít existující augmented corpus
Dříve se k práci s korpusy používala složka augmented_corpora
a nástroj augment.pl
. Pokud už v této složce máme připravený korpus se spoustou jazyků a hotových faktorů (např. ve složce augmented_corpora/newstest2010-v6b
) a chceme ho zapojit do práce s emanem, lze to zařídit tak, že mu vytvoříme falešný krok emana, který na něj bude odkazovat:
udelej si v playgroundu uplne prazdny adresar s.podvod.12345678.20120229-2355
v nem udelej
echo DONE > eman.status echo fake > eman.seed echo fake > eman.command touch eman.vars touch eman.deps
a pak v nem vyrob symlinky na vse, co potrebujes, cili treba:
ln -s /net/data/augmented_corpora/newstest2010-v6b/cs.gz ./ ln -s /net/data/augmented_corpora/newstest2010-v6b/de.gz ./ ln -s /net/data/augmented_corpora/newstest2010-v6b/en.gz ./ ln -s /net/data/augmented_corpora/newstest2010-v6b/es.gz ./ ln -s /net/data/augmented_corpora/newstest2010-v6b/fr.gz ./
Nakonec rucne vyrob corpman.info:
cs.gz TAB -1 TAB wmt10v6b TAB cs TAB form|lemma|tag TAB 2489 TAB 0
de.gz TAB -1 TAB wmt10v6b TAB de TAB form|lemma|tag TAB 2489 TAB 0
…
(DZ: Položky na každém řádku v corpman.info
mají následující význam:
- Název souboru (cs.gz)
- Číslo sloupce v tomto souboru (-1, pokud v souboru nerozlišujeme sloupce)
- Název korpusu (wmt10v6b)
- Kód jazyka (cs); může zahrnovat i identifikaci dalšího zpracování (csNm), protože platí, že všechny soubory jednoho korpusu mají stejný počet řádků a všechny soubory jednoho korpusu a jazyka mají stejný počet tokenů.
- Názvy a pořadí faktorů, ze kterých se skládá každý token (form|lemma|tag)
- Počet řádků souboru (2489)
- Informace, zda je tento korpus automaticky odvozen z jiného korpusu (0 nebo 1))
Pak dej ./corpman reindex
A pak over, ze to funguje:
./corpman wmt10v6b/cs+stc # vypise asi dva kroky, kterymi to samo vyrobi stc.
Kdybys chtel pouzit i sve stc, muzes ho taky symlinknout a pridat radek:
cs-stc.gz TAB -1 TAB wmt10v6b TAB cs TAB stc TAB 2489 TAB 0
ln -s /net/data/augmented_corpora/newstest2010-v6b/cs.factors/stc.gz cs-stc.gz ln -s /net/data/augmented_corpora/newstest2010-v6b/de.factors/stc.gz de-stc.gz ln -s /net/data/augmented_corpora/newstest2010-v6b/en.factors/stc.gz en-stc.gz ln -s /net/data/augmented_corpora/newstest2010-v6b/es.factors/stc.gz es-stc.gz ln -s /net/data/augmented_corpora/newstest2010-v6b/fr.factors/stc.gz fr-stc.gz
Alignment
Zarovnání (alignment) je taky svého druhu korpus. Má stejný počet řádků jako texty v jednotlivých jazycích a tyto řádky si navzájem odpovídají. Čtvrtý sloupec corpman.info
, který u textových částí korpusu obsahuje kód jazyka, u alignmentu popisuje oba jazyky, faktory použité pro výpočet zarovnání a také použitou symetrizační heuristiku: symetrizace – zdrojový jazyk – zdrojový faktor – cílový jazyk – cílový faktor. Naopak pátý sloupec, který u textových částí popisuje dostupné faktory, u alignmentu vždy obsahuje kód ali
(vlastně je to specifický faktor). Příklad corpman.info
vygenerovaného krokem typu align
:
alignment.gz 1 un.fr-en gdf-fr-lemma-en-lemma ali 10788000 alignment.gz 2 un.fr-en revgdf-fr-lemma-en-lemma ali 10788000 alignment.gz 3 un.fr-en gdfa-fr-lemma-en-lemma ali 10788000 alignment.gz 4 un.fr-en revgdfa-fr-lemma-en-lemma ali 10788000 alignment.gz 5 un.fr-en left-fr-lemma-en-lemma ali 10788000 alignment.gz 6 un.fr-en right-fr-lemma-en-lemma ali 10788000 alignment.gz 7 un.fr-en int-fr-lemma-en-lemma ali 10788000 alignment.gz 8 un.fr-en union-fr-lemma-en-lemma ali 10788000
Zarovnání obvykle vyrábí krok typu align
. Ten ale volá Gizu a trvá dost dlouho, pro opravdu velké korpusy třeba i několik dní. Pokud se náš paralelní korpus skládá z několika menších korpusů, můžeme trochu slevit na kvalitě výsledného zarovnání a zarovnat každý dílčí korpus zvlášť. Potom zarovnání spojíme za sebe do jednoho souboru. Bude asi bezpečnější, když dáme spojenému korpusu nové jednoznačné jméno, které nebude obsahovat +
, aby corpman
nepoznal, že jde o kombinaci několika menších korpusů, a nepokoušel se odvozené faktory taky získávat z dílčích korpusů.
Všimněte si, že proměnná COMMAND
obsahuje úplné cesty ke krokům s dílčími zarovnáními (zde prostřednictvím proměnné STATMT
, kterou mám ve svém prostředí vždy nastavenou). To je nutné, protože příkaz se nebude vykonávat v hlavní složce hřiště, ale o úroveň níž, ve složce nového korpusového kroku.
# Předpokládáme, že dílčí alignmenty obsahují stejné symetrizace ve stejném pořadí. # Takže se sice ptáme na gdfa, ale do cílového souboru zkopírujeme všechny sloupce. ALISTEPNEWSEURO=(`corpman news-europarl-v7.fr-en/gdfa-fr-lemma-en-lemma+ali`) ALISTEPUNCORPUS=(`corpman un.fr-en/gdfa-fr-lemma-en-lemma+ali`) COMMAND="zcat $STATMT/playground/${ALISTEPNEWSEURO[0]}/${ALISTEPNEWSEURO[1]} $STATMT/playground/${ALISTEPUNCORPUS[0]}/${ALISTEPUNCORPUS[1]}" LINES=`$COMMAND | wc -l` OUTCORP=news-euro-un.fr-en \ OUTFACTS=ali \ OUTLANG=gdfa-fr-lemma-en-lemma \ OUTLINECOUNT=$LINES \ TAKE_FROM_COMMAND=$COMMAND \ eman init corpus --start # Problém: Takto založený krok zaregistruje pouze zarovnání se symetrizací gdfa, navíc pro všechny sloupce souboru. # Opíšeme tedy popis sloupců od jednoho z dílčích korpusů. Musíme to ale dělat až po dokončení spojeného korpusu. NEWSTEP=(`corpman news-euro-un.fr-en/gdfa-fr-lemma-en-lemma+ali`) mv ${NEWSTEP[0]}/corpus.txt.gz ${NEWSTEP[0]}/alignment.gz perl -e 'my $i = 1; foreach my $sym qw(gdf revgdf gdfa revgdfa left right int union) { print("alignment.gz\t$i\tnews-euro-un.fr-en\t$sym-fr-lemma-en-lemma\tali\t'$LINES'\n"); $i++ }' > ${NEWSTEP[0]}/corpman.info corpman reindex ALISTEPNEWSEURO=(`corpman news-europarl-v7.fr-en/gdfa-en-lemma-fr-lemma+ali`) ALISTEPUNCORPUS=(`corpman un.fr-en/gdfa-en-lemma-fr-lemma+ali`) COMMAND="zcat $STATMT/playground/${ALISTEPNEWSEURO[0]}/${ALISTEPNEWSEURO[1]} $STATMT/playground/${ALISTEPUNCORPUS[0]}/${ALISTEPUNCORPUS[1]}" LINES=`$COMMAND | wc -l` OUTCORP=news-euro-un.fr-en \ OUTFACTS=ali \ OUTLANG=gdfa-en-lemma-fr-lemma \ OUTLINECOUNT=$LINES \ TAKE_FROM_COMMAND=$COMMAND \ eman init corpus --start # Teď ještě pod novým názvem publikovat i slepené textové části korpusů. STEPNEWSCOMM=(`corpman news-commentary-v7.fr-en/fr+form+lemma+tag`) STEPEUROPARL=(`corpman europarl-v7.fr-en/fr+form+lemma+tag`) STEPUNCORPUS=(`corpman un.fr-en/fr+form+lemma+tag`) COMMAND="zcat $STATMT/playground/${STEPNEWSCOMM[0]}/${STEPNEWSCOMM[1]} $STATMT/playground/${STEPEUROPARL[0]}/${STEPEUROPARL[1]} $STATMT/playground/${STEPUNCORPUS[0]}/${STEPUNCORPUS[1]}" LINES=`$COMMAND | wc -l` OUTCORP=news-euro-un.fr-en \ OUTLANG=fr \ OUTFACTS=form+lemma+tag \ OUTLINECOUNT=$LINES \ TAKE_FROM_COMMAND=$COMMAND \ eman init corpus --start STEPNEWSCOMM=(`corpman news-commentary-v7.fr-en/en+form+lemma+tag`) STEPEUROPARL=(`corpman europarl-v7.fr-en/en+form+lemma+tag`) STEPUNCORPUS=(`corpman un.fr-en/en+form+lemma+tag`) COMMAND="zcat $STATMT/playground/${STEPNEWSCOMM[0]}/${STEPNEWSCOMM[1]} $STATMT/playground/${STEPEUROPARL[0]}/${STEPEUROPARL[1]} $STATMT/playground/${STEPUNCORPUS[0]}/${STEPUNCORPUS[1]}" LINES=`$COMMAND | wc -l` OUTCORP=news-euro-un.fr-en \ OUTLANG=en \ OUTFACTS=form+lemma+tag \ OUTLINECOUNT=$LINES \ TAKE_FROM_COMMAND=$COMMAND \ eman init corpus --start
Vyhodnocovací kroky a sklizeň výsledků
V současnosti je k dispozici několik různých šablon pro vyhodnocení výsledků překladu na testovacích datech. Šablona eval
pouští Ondrův program testbleu
, šablona evaluator
pouští vyhodnocovací program Mosese upravený Matoušem Macháčkem, který umí několik různých metrik včetně BLEU, šablona daneval
spolupracuje s Joshuou.
Eman umí projít všechny kroky s výsledky a spojit je v jednom výstupu. K tomu slouží příkaz eman collect
, který na základě eman.results.conf
vyrobí eman.results
. Ukázkový a funkční konfigurační soubor je eman.results.conf.sample-wmt12
. Výstup eman.results
lze pak ještě dále vylepšit pomocí make bleu
(make bleu vlastně ten collect samo volá).
(Podle Ondřeje make bleu ještě možná závisí na skriptu ./sitename, který je tam pro konsolidaci výsledků z mnoha hřišť.)
Kombinace dvou a více hřišť
Normálně hledá Eman kroky pouze na aktuálním hřišti (v aktuální složce). Typicky má každý uživatel (nejméně jedno) svoje hřiště (playground), které leží v podstromu jeho pracovní kopie repozitáře StatMT. Co když ale chceme naklonovat pokus (se všemi závislostmi) nějakého kolegy? Můžeme připojit jeho hřiště k našemu. Obě složky zůstanou na svých místech, ale Eman bude vědět, že má od nynějška sledovat a indexovat obě. Uvidíme všechny kroky ve vzdáleném hřišti, budeme je moci klonovat a tvořit kroky na nich závislé. Tato operace je jednosměrná, tj. pokud současně nepřipojíme naše hřiště ke vzdálenému, tak ve vzdáleném hřišti to naše vidět nebude.
Je dobré si uvědomit, že spolu s krokem, o který nám jde, možná získáme stovky dalších kroků, které nás nezajímají a možná nám znepřehlední situaci na hřišti. Navíc připojení vzdáleného hřiště v současné době nejde nijak jednoduše odvolat. Z těchto důvodů je možná lepší vytvořit si nové prázdné hřiště a připojit k němu jak naše stávající hřiště, tak vzdálené hřiště.
Připojení vzdáleného hřiště se provede příkazem eman addremote DIR ALIAS
, např.
eman addremote /net/tmp/bojar/wmt12-bojar/playground obo
Stěhování hřiště za chodu
Příklad ze života: hřiště mám na /net/work/people/zeman
, jenže pokusy generují stále více souborů a kvůli kvótě se tam nevejdu. Chci to celé přestěhovat na /net/cluster/TMP
. Problém je, že prakticky neustále některé kroky běží a nemůžu jim ani jejich závislostem stěhovat půdu pod nohama. Takhle zjistím seznam kroků, které běží (na clusteru jim patří nějaká úloha) nebo na nich ty běžící závisí. (Všimněte si toho grep -v
ke konci. Eman bohužel odmítne pokračovat, jestliže se mu k nějakému číslu úlohy nepodaří přiřadit existující krok. Proto explicitně vyřazuju čísla, o kterých vím, že tento problém mají.)
eman ls > steps-all.txt eman traceback --no-tree `qstat | grep zeman | grep -P '\ss\.' | cut -d' ' -f1 | grep -v 4296093` | sort -u > steps-tabu.txt perl -e 'open(TABU, "steps-tabu.txt") or die; while(<TABU>) { $tabu{$_}++ } open(ALL, "steps-all.txt") or die; while(<ALL>) { print unless($tabu{$_}) }' > steps-free.txt for i in `cat steps-free.txt` ; do echo $i ; cp -r $i /net/cluster/TMP/zeman/statmt/playground ; done for i in `cat steps-free.txt` ; do echo $i ; rm -rf $i ; done
Je dobré si uvědomit, že stěhování existujícího hřiště má ještě jednu další nevýhodu. Mnoho Ondřejových kroků vytváří hardlinky na existující soubory s korpusy. Při stěhování na jiný souborový systém se z těchto hardlinků zřejmě stanou samostatné soubory a hřiště bude zabírat mnohem více místa než to stávající. Lze si pomoci skriptem find_hardlinks.pl
, který se pokouší hardlinky najít a znova pospojovat. Ale pozor! Tento skript není obecný a spoléhá na strukturu hřiště a na to, že hardlinky jsou v něm řádně označeny (mají v názvu .hardlink
) a vedle nich leží buď původní soubor, nebo symbolický odkaz na něj. Navíc skript obsahuje některé cesty specifické pro Danův případ, takže pokud nejste já, musíte si ho nejdříve upravit!
Jestliže stěhujete kroky, které jsou ve stavu FAILED, na novém hřišti je pravděpodobně nebudete moci spustit pomocí eman continue
, protože jejich eman.command
(který už se znova nepřegeneruje) nejspíš obsahuje cesty na staré hřiště (a např. když zavoláte corpman starého hřiště, bude vám hledat korpusy tam, ne tady). Můžete ale použít eman redo –start
, čímž se na novém hřišti vytvoří kopie kroku s novým eman.command
, bez přegenerování všech kroků, na kterých krok závisí.
Přechod na nové úložiště Redmine/git
ÚFALí server Redmine je na adrese https://redmine.ms.mff.cuni.cz/projects. Ondra na něj v říjnu 2012 přestěhoval podstatnou část repozitáře StatMT z svn/trac (https://svn.ms.mff.cuni.cz/trac/statmt). Konkrétně jsou tu teď projekty ufal-smt-playground a eman (na něj se z playgroundu odkazuje jako na podmodul).
Pro vybalení hřiště Ondra doporučil studentům následující příkaz. Předpokládám, že studenti, neznajíce Ondrovo heslo, to museli volat bez toho ondrej.bojar@
na začátku a získali nějaký read-only přístup. A já na rozdíl od nich můžu použít daniel.zeman a získám přístup i pro zápis.
git clone https://ondrej.bojar@redmine.ms.mff.cuni.cz/ufal-smt-playground.git jmeno_pracovni_kopie # Raději pracovat na 64bitovém stroji kvůli kompilacím. ssh sol12 cd /net/cluster/TMP/zeman git clone https://daniel.zeman@redmine.ms.mff.cuni.cz/ufal-smt-playground.git redplayground
Eman jako podmodul se asi neaktualizuje sám. Nějakou verzi k nějakému datu zřejmě získám automaticky s hřištěm, ale pokud chci mít jistotu, že budu mít ten aktuální, můžu/měl bych? udělat
cd redplayground git submodule init git submodule update
Další Ondrova doporučení (ale to druhé, vizualizace commitů, bude asi fungovat jen v ixech):
git svn crashcourse gitk -a
Dokumentace ke gitu je například tady.
git clone <url>
… naklonovat existující repozitář (dělá se na začátku podobně jakosvn checkout
, ale sémantika není stejná)git status
… v jakém stavu jsou jednotlivé soubory? (untracked / committed / modified / staged)git add <file>
… zkopírovat změněný soubor do staging oblasti nebo zahrnout do verzování dosud neverzovaný soubor (rovnou se dostane do staging oblasti)git reset HEAD <file>
… vyřadit soubor ze staging oblastigit checkout – <file>
… zapomenout změny v pracovní kopii a vrátit se k verzi souboru uložené v repozitářigit commit -m 'log'
… uložit soubory ze staging oblasti do (lokálního!) repozitáře; na vzdálený server to pořád nemá vlivgit commit -a
… přeskočit stageování a uložit i soubory, které už sledujeme, změnily se, ale nejsou ve staging oblasti.gitignore
… soubor se jmény či šablonami jmen souborů, které se nemají verzovat a nemají se ani hlásit jako neverzovanégit diff
… co jsem změnil, ale ještě nezkopíroval do staging oblastigit diff –cached
… co jsem změnil a zkopíroval do staging oblastigit log
… historie uložených verzígitk
… grafický program, který vizualizuje výstupgit log
git rm <file>
… odstranit soubor z pracovní složky a říct gitu, že ho má přestat sledovatgit rm –cached <file>
… přestat sledovat soubor, ale jeho kopii v pracovní složce ponechatgit mv <file1> <file2>
… přejmenovat nebo přesunout souborgit remote -v
… zobrazit názvy nakonfigurovaných vzdálených repozitářů včetně jejich URL. “origin” je ten, ze kterého jsme se naklonovali.git remote add <shortname> <url>
… přidat vzdálený repozitář, se kterým se můžeme synchronizovatgit fetch origin
… stáhnout nové změny ze vzdáleného repozitáře origin. Stáhnou se jako nová větev a neslijí se s mou aktuální větví, dokud to neudělám ručně.git pull origin
… stáhnout nové změny a pokusit se je automaticky slít s mými. Musíme mít nakonfigurováno automatické sledování vzdálené větve. Ale u originu to tak defaultně je.git push origin master
… odeslat změny v mé hlavní (master) větvi zpět na server, ze kterého jsem se naklonoval (origin)git remote show origin
… zobrazit informace o stavu vzdáleného repozitáře ve vztahu ke mněgit branch testing
… vytvořit novou větev testing (rozvětvení bude na aktuálním commitu), ale zatím do ní nepřepínat (na aktuální větev ukazuje ukazatel HEAD)git checkout testing
… přepnout se do existující větve testing a vybalit její soubory do pracovní složkygit checkout -b testing
… zkratka: vytvořit novou větev a hned se do ní přepnoutgit checkout -b testing dfcb57a2
… vrátit se k revizi (commitu) s kódemdfcb57a2
, na něm vytvořit novou větevtesting
a hned se do ní přepnout. Při návratu k revizi, která současně není na konci nějaké větve, se doporučuje založit novou větev, aby HEAD vždy ukazovalo na větev a ne na pouhou revizi. Předchází se tím případným problémům, ke kterým může dojít, jestliže nad touto revizí provedeme nové změny: fakticky by vznikla nová větev, ta by ale neměla název a systém by mohl usoudit, že ji smaže, protože není potřeba.git merge testing
… slít větev testing s mou aktuální větvígit branch -d testing
… zrušit větev, kterou už nepotřebujeme, protože jsme ji slili s jinougit checkout -b serverfix origin/serverfix
… založit větev serverfix na základě nové větve, kterou jsme získali fetchem ze serveru origin, a přepnout se do ní. Současně tím vzniká vztah mezi novou lokální a vzdálenou větví. Tento vztah se vezme v potaz při synchronizaci pomocí push a pull.git push origin :serverfix
… smazat větev serverfix na serveru origin (“na mé straně před dvojtečkou vezmi nic a udělej z toho aktuální stav větve serverfix na straně serveru”)git rebase <basebranch> <topicbranch>
… práce se záplatami (patches) je jiný způsob, jak slít dvě větve. Výsledek je stejný, ale historie je přímější, samostatná větev v ní nebude vidět. Rebase přehraje na větvi base změny provedené ve větvi topic. ALE: Nemají se rebaseovat commity, které už jsme odeslali do veřejného repozitáře. Rebasing vyrábí nové commity, které mají stejný obsah, ale nejsou stejné. Pokud spolupracuji s někým jiným, kdo měl v ruce ty předchozí, nyní zavržené commity, vznikne binec, který budeme obtížně dávat dohromady.
Strategie přechodu
- Získat stav ve chvíli, kdy Ondřej stěhoval hřiště pod git. Čili vybalit nějaký historický stav gitu. Této verzi bude odpovídat nějaký historický stav mého svn.
- Vyrobit si větev dansvn (v gitu) a nějak do ní promítnout aktuální stav v mém svn.
- Přepnout se do Ondřejovy (hlavní) větve a vybalit (pull) její aktuální stav (HEAD).
- Teď už teoreticky kdykoli můžeme obě větve opět slít. ALE!
- Já ještě potřebuju zařídit, aby moje pracovní kopie svn začala být pracovní kopií větve dansvn v gitu, aniž bych musel její obsah kopírovat (jsou tam ty obří neverzované hardlinky, které by se kopírováním rozpojily a zabíralo by to ještě více místa).
- Mějme dvě složky: gitplayground a svnplayground. Obě jsou pracovní kopií téže verze hřiště, ale jedna je navázaná na tuto verzi v gitu a druhá na odpovídající verzi v svn. Složka gitplayground kromě toho obsahuje už jen případné pomocné soubory gitu a nic jiného. Složka svnplayground obsahuje pomocné soubory svn a navíc neverzované podsložky-bumbrlíčky.
- Neverzované bumbrlíčky nechceme stěhovat, ty musí zůstat na místě. Proto musíme kolem nich uklidit, aby se k nim mohl nastěhovat git. Odstraníme všechny verzované podsložky svnplayground, všechny verzované soubory a složku
.svn
s pomocnými soubory svn. - Veškerý obsah složky gitplayground, včetně pomocných souborů git, rekurzivně zkopírujeme do složky svnplayground vedle neverzovaných bumbrlíčků.
- Ověříme, zda tato kopie funguje a ví, že je pracovní kopií repozitáře git.
- Přejmenujeme tuto kopii na
playground
. Složkugitplayground
můžeme smazat.