Obsah
1. Torch: framework pro strojové učení i pro zpracování vektorů a tenzorů
3. První spuštění interaktivního prostředí
4. Základní datová struktura, s níž se ve frameworku Torch pracuje
5. Základní konstruktory tenzorů
9. Způsob uložení tenzorů v paměti počítače
10. Manipulace s objektem typu Storage
11. Operace sub aplikovaná na vektory
12. Operace sub aplikovaná na matice a tenzory vyšších řádů
13. Operace narrow aplikovaná na vektory
14. Operace narrow aplikovaná na matice a tenzory vyšších řádů
15. Operace sub a narrow ve funkci zapisovatelných pohledů
16. Repositář s demonstračními příklady
1. Torch: framework pro strojové učení i pro zpracování vektorů a tenzorů
Jednou poměrně rozsáhlou oblastí v IT je zpracování vektorů, matic i tenzorů, protože s těmito strukturami se můžeme setkat v různých disciplínách, například ve finančnictví, pojišťovnictví, statistice, zpracování numerických dat, simulacích, strojovém učení atd. Současně se jedná i o velmi zajímavou oblast, neboť právě kvůli co nejrychlejší práci s velkými maticemi byly vytvořeny speciální výpočetní bloky v některých superpočítačích (příkladem mohou být superpočítače Cray). Současné knihovny dokážou v případě potřeby využít jak některá rozšíření instrukčních sad (SIMD instrukce typu SSE, původně též MMX či 3DNow!, viz též článek na toto téma), tak i programovatelné grafické akcelerátory (GPU, v současnosti je lídrem v tomto oboru NVidia s GPU Tesla).
Práce s vektory a maticemi byla (a samozřejmě doposud je) podporována v překladačích FORTRANu, které začaly být po vzniku superpočítačů vybaveny algoritmy, které dokázaly převést některé typy programových smyček na „vektorové operace“. Paralelně vznikly i specializované jazyky určené téměř výhradně pro práci s vektory i maticemi – příkladem jsou jazyky APL a J.
V současnosti je používáno relativně velké množství programovacích jazyků popř. specializovaných knihoven orientovaných na práci s vektory, maticemi, tenzory atd. Z komerčních nástrojů je zapotřebí jmenovat především známý MATLAB vydávaný společností MathWorks, nativní práci s maticemi a vektory ovšem velmi dobře podporuje také nástroj GNU Octave (https://gnu.org/software/octave/), jazyk R (http://www.r-project.org/) a také relativně nový jazyk Julia (http://julialang.org/, zajímavé výsledky benchmarků lze najít na adrese http://julialang.org/benchmarks/). Z knihoven jmenujme především oblíbenou a dnes dosti intenzivně využívanou Pythonovskou knihovnu NumPy (http://www.numpy.org/).
Framework Torch je primárně určen pro zpracování vektorů, matic i tenzorů (tj. zobecnění vektorů), a to s využitím programovacího jazyka Lua namísto specializovaného jazyka (Julia, Matlab, R). Interně se prakticky všechny výpočty provádí v nativních céčkových knihovnách a popř. se využívá i CUDA, tj. možnosti grafických akcelerátorů. Možnosti frameworku Torch však ve skutečnosti přesahují „pouhou“ práci s tenzory, protože obsahuje i moduly pro lineární algebru a především pro neuronové sítě, což je poměrně rozsáhlé téma, kterému se budeme věnovat v samostatném článku.
2. Instalace frameworku Torch
Před čtením dalšího textu je vhodné si framework Torch nainstalovat. Není to nic složitého, protože postačuje dodržet instrukce, které naleznete na stránce http://torch.ch/docs/getting-started.html. Postačovat by mělo pouze těchto několik příkazů, které spustíte pod svým účtem (otestováno na Fedoře 26 a Linux Mintu, tedy na distribucích založených na odlišném systému balíčků):
git clone https://github.com/torch/distro.git ~/torch --recursive cd ~/torch bash install-deps ./install.sh source ~/.bashrc
Ve skutečnosti může nastat několik problémů:
- Nezapomeňte na volbu –recursive u prvního příkazu. Torch totiž používá submoduly.
- Uživatel musí získat práva superuživatele pro instalaci doplňkových balíčků (kterých je poměrně velké množství).
- Skript install-deps nepočítá s některými novějšími verzemi distribucí. Snadnou úpravou je ale možné docílit instalace na Fedoru 26 (změnou jedné podmínky) či novějším Linux Mintu.
3. První spuštění interaktivního prostředí
Po (doufejme) úspěšné instalaci si můžete vyzkoušet spustit interaktivní prostředí Torche. Je to snadné – postačuje spustit th (tento spustitelný soubor by se již měl nacházet na PATH):
$ th
______ __ | Torch7 /_ __/__ ________/ / | Scientific computing for Lua. / / / _ \/ __/ __/ _ \ | Type ? for help /_/ \___/_/ \__/_//_/ | https://github.com/torch | http://torch.ch
Alternativně lze přímo spustit skript uložený v externím souboru. Po dokončení skriptu se prostředí Torche ukončí:
$ th constructors.lua
Pokud budete chtít spustit nějaký skript a poté zůstat v interaktivním prostředí Torche, použijte tento příkaz:
$ th -i constructors.lua
Uživatelé textového editoru Vim mohou skripty postupně vytvářet ve svém oblíbeném vimovském prostředí a posléze je spouštět například klávesovou zkratkou F5 s využitím následujícího mapování:
:map <F5> :!th %<cr>
4. Základní datová struktura, s níž se ve frameworku Torch pracuje
Ve frameworku Torch se základní datová struktura jmenuje Tensor. Tato struktura umožňuje reprezentovat skalární hodnoty (tenzory nultého řádu), běžné vektory (tenzory prvního řádu), běžné matice, „3D matice“ atd. Interně je struktura objektů typu Tensor až překvapivě jednoduchá – základem je jednorozměrné pole doplněné o metadata, v nichž je uložen počet dimenzí, velikost dimenzí, hodnoty stride používané při přístupu k prvkům interního pole atd. Nad tenzory je navíc možné vytvářet různé pohledy (views), které mohou být určeny buď pouze pro čtení či pro čtení i zápis (pohled může například reprezentovat tenzor se změněným tvarem – shape). Samotné interní pole objektů typu Tensor je vždy homogenní, tj. může obsahovat pouze prvky stejného typu, ovšem tento typ je konfigurovatelný. Implicitně se jedná o hodnoty typu double (celý objekt má v takovém případě konkrétní typ DoubleTensor), ovšem existují i další typy, které je možné v případě potřeby zvolit (například při zpracování obrázků, audio dat atd.):
Jméno typu | Význam |
---|---|
ByteTensor | tenzor s prvky typu unsigned char |
CharTensor | tenzor s prvky typu char |
ShortTensor | tenzor s prvky typu short (16bitové celé číslo) |
IntTensor | tenzor s prvky typu int (32bitové celé číslo) |
LongTensor | tenzor s prvky typu long (64bitové celé číslo) |
FloatTensor | tenzor s prvky typu float (32bitová FP hodnota) |
DoubleTensor | tenzor s prvky typu double (64bitová FP hodnota) |
5. Základní konstruktory tenzorů
Již v úvodních kapitolách jsme si řekli, že základní datovou strukturou frameworku Torch jsou N-dimenzionální pole, která mohou být použita pro uložení komponent tenzorů. V této kapitole si ukážeme základní konstruktory objektů typu Tensor (prozatím se omezíme na komponenty tenzorů, které jsou typu Double).
Vytvoření skaláru, neboli tenzoru nultého řádu a inicializace jeho (jediné) komponenty:
th> s1=torch.Tensor(1) [0.0002s] th> s1[1]=42 [0.0001s]
Výsledek (povšimněte si typu – nejedná se o běžné číslo):
th> s1 42 [torch.DoubleTensor of size 1]
Vytvoření vektoru, neboli tenzoru prvního řádu. V tomto konkrétním případě se jedná o tříprvkový vektor:
th> v1 = torch.Tensor(3) [0.0001s]
Inicializace komponent:
th> v1[1]=10 [0.0001s] th> v1[2]=20 [0.0001s] th> v1[3]=40 [0.0001s]
Výsledek:
th> v1 10 20 40 [torch.DoubleTensor of size 3] [0.0001s]
Alternativně lze vektor (tenzor prvního řádu) vytvořit a současně inicializovat jeho komponenty. Použije se přitom běžné pole tak, jak ho známe z programovacího jazyka Lua:
th> v2=torch.Tensor({10,20,30}) [0.0001s] th> v2 10 20 30 [torch.DoubleTensor of size 3]
Vytvoření tenzoru druhého řádu:
th> m1 = torch.Tensor(3,3)
Vytvoření a inicializace tenzoru druhého řádu, který může být reprezentován maticí:
th> m2=torch.Tensor({{1,2,3}, {4,5,6}, {7,8,9}}) [0.0002s]
Výsledek:
th> m2 1 2 3 4 5 6 7 8 9 [torch.DoubleTensor of size 3x3]
A konečně tenzor třetího řádu reprezentovaný „3D maticí“:
th> q = torch.Tensor({{{1,2,3}, {4,5,6}, {7,8,9}}, {{9,8,7}, {6,5,4}, {3,2,1}}})
Výsledek se na 2D obrazovce zobrazí takto:
(1,.,.) = 1 2 3 4 5 6 7 8 9 (2,.,.) = 9 8 7 6 5 4 3 2 1 [torch.DoubleTensor of size 2x3x3]
6. Použití konstruktoru zeros
V knihovně Torch existují i další konstruktory. V mnoha případech potřebujeme vytvořit vektor, matici atd. vyplněný nulami. V tomto případě můžeme použít metodu (nikoli konstruktor) zero(), která se ovšem aplikuje na již vytvořený objekt:
th> x1 = torch.Tensor(10):zero() [0.0002s] th> x1 0 0 0 0 0 0 0 0 0 0 [torch.DoubleTensor of size 10] [0.0002s]
Podobný postup lze použít i u 2D matice:
th> x2 = torch.Tensor(4,4):zero() [0.0001s] th> x2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [torch.DoubleTensor of size 4x4]
Výhodnější a rychlejší je však použití konstruktoru zeros(), kterému se předá n hodnot reprezentujících velikosti jednotlivých dimenzí. Opět se podívejme na příklady:
Tenzor nultého řádu (skalár):
th> z0 = torch.zeros(1) [0.0003s] th> print(z0) 0 [torch.DoubleTensor of size 1] [0.0003s]
Tenzor prvního řádu (vektor):
th> z1 = torch.zeros(10) [0.0001s] th> print(z1) 0 0 0 0 0 0 0 0 0 0 [torch.DoubleTensor of size 10] [0.0002s]
Tenzor druhého řádu:
th> z2 = torch.zeros(3,4) [0.0000s] th> print(z2) 0 0 0 0 0 0 0 0 0 0 0 0 [torch.DoubleTensor of size 3x4]
Tenzor třetího řádu:
th> z3 = torch.zeros(2,3,4) [0.0001s] th> z3 (1,.,.) = 0 0 0 0 0 0 0 0 0 0 0 0 (2,.,.) = 0 0 0 0 0 0 0 0 0 0 0 0 [torch.DoubleTensor of size 2x3x4]
7. Použití konstruktoru ones
Způsob reprezentace tenzorů druhého řádu sice připomíná matice, ovšem zde se nesmíme nechat zmýlit – další konstruktor se sice jmenuje ones, ale nevytváří (v 2D případě) jednotkovou matici s jedničkami pouze na hlavní diagonále, nýbrž matici, v níž mají všechny prvky hodnotu 1. V ostatních ohledech se konstruktor ones podobá výše popsanému konstruktoru zeros, takže jen velmi krátce:
Skalár s hodnotou 1:
th> o0 = torch.ones(1) [0.0003s] th> print(o0) 1 [torch.DoubleTensor of size 1] [0.0003s]
Tenzor prvního řádu (zde vektor o deseti prvcích):
th> o1 = torch.ones(10) [0.0001s] th> print(o1) 1 1 1 1 1 1 1 1 1 1 [torch.DoubleTensor of size 10]
Tenzor druhého řádu:
th> o2 = torch.ones(3,4) [0.0001s] th> print(o2) 1 1 1 1 1 1 1 1 1 1 1 1 [torch.DoubleTensor of size 3x4] [0.0003s]
Tenzor třetího řádu:
th> o3 = torch.ones(2,3,4) [0.0001s] th> print(o3) (1,.,.) = 1 1 1 1 1 1 1 1 1 1 1 1 (2,.,.) = 1 1 1 1 1 1 1 1 1 1 1 1 [torch.DoubleTensor of size 2x3x4]
8. Použití konstruktoru range
Další typ konstruktoru je možné použít pro vytvoření vektoru obsahujícího aritmetickou řadu s volitelným krokem. Tento konstruktor se jmenuje range a lze mu předat hodnotu prvního a posledního prvku popř. i krok mezi hodnotami sousedních prvků. Krok může být kladný i záporný a samozřejmě se nemusí jednat o celé číslo. Podle očekávání je implicitní hodnota kroku rovna jedné. Knihovna Torch kontroluje nenulovost kroku a taktéž to, zda se skutečně vytvoří korektní aritmetická řada. Opět se podívejme na několik jednoduchých příkladů:
Použití implicitního kroku jedna (hodnota prvního a posledního prvku je reprezentována celými čísly, není to však nutnost):
th> r1 = torch.range(1, 10) [0.0002s] th> print(r1) 1 2 3 4 5 6 7 8 9 10 [torch.DoubleTensor of size 10] [0.0003s]
Explicitní specifikace kroku (opět pro jednoduchost používáme celá čísla):
th> r2 = torch.range(1, 10, 2) [0.0001s] th> print(r2) 1 3 5 7 9 [torch.DoubleTensor of size 5] [0.0001s]
Můžeme zadat i záporný krok:
th> r3 = torch.range(10, 0, -2) [0.0001s] th> print(r3) 10 8 6 4 2 0 [torch.DoubleTensor of size 6] [0.0001s]
Knihovna Torch samozřejmě hlídá, aby nebyl použit krok s hodnotou nula. Toto chování si můžeme snadno ověřit:
th> r4 = torch.range(10, 0, 0) bad argument #3 to '?' (step must be a non-null number at /home/tester/torch/pkg/torch/lib/TH/generic/THTensorMath.c:2003) stack traceback: [C]: at 0x7f3ff7194840 [C]: in function 'range' [string "r4 = torch.range(10, 0, 0)"]:1: in main chunk [C]: in function 'xpcall' /home/tester/torch/install/share/lua/5.1/trepl/init.lua:679: in function 'repl' ...novs/torch/install/lib/luarocks/rocks/trepl/scm-1/bin/th:204: in main chunk [C]: at 0x00405780
9. Způsob uložení tenzorů v paměti počítače
Ve čtvrté kapitole jsme si řekli, že objekty typu Tensor pro uložení svých komponent (prvků) interně používají jednorozměrná pole. To, že se tenzory uživateli jeví jako 1D, 2D, 3D atd. struktury je záležitostí pohledů (views) na zmíněná jednorozměrná pole (jedná se vlastně o běžná céčková pole). Pro některé nízkoúrovňové operace může být výhodné přistupovat přímo k internímu poli, což nám knihovna Torch umožňuje, protože nabízí objekty typu Storage. Existuje několik konkrétních typů Storage, protože interní (céčková) pole taktéž mohou obsahovat prvky různých typů. Implicitně se používá DoubleStorage:
Typ Storage | Význam |
---|---|
ByteStorage | pole s prvky typu unsigned char |
CharStorage | pole s prvky typu char |
ShortStorage | pole s prvky typu short (16bitové celé číslo) |
IntStorage | pole s prvky typu int (32bitové celé číslo) |
LongStorage | pole s prvky typu long (64bitové celé číslo) |
FloatStorage | pole s prvky typu float (32bitová FP hodnota) |
DoubleStorage | pole s prvky typu double (64bitová FP hodnota) |
10. Manipulace s objektem typu Storage
Ukažme si nyní, jak je možné pro existující tenzor získat objekt typu Storage a jak se dá tento objekt využít pro změnu hodnot komponent tenzoru. Nejprve vytvoříme běžný vektor s deseti prvky:
th> vector=torch.Tensor(10) [0.0001s]
Následně pro tento vektor získáme objekt typu Storage. Povšimněte si, že se při volání metody objektu používá dvojtečka a nikoli tečka! Jedná se o vlastnost programovacího jazyka Lua, díky níž nemusíme explicitně specifikovat parametr this:
th> storage=vector:storage() [0.0001s]
Objekt typu Storage se chová podobně jako běžné pole jazyka Lua. Musíme si jen dát pozor na to, že se prvky indexují od jedničky a nikoli od nuly (ovšem to je v matematice běžné). V následující smyčce do interního pole prvků typu double vložíme hodnoty 1/1, 1/2, 1/3 až 1/10:
th> for i=1,storage:size() do ..> storage[i] = 1.0/i ..> end
Pro jistotu se můžeme na prvky v poli podívat. Povšimněte si zejména typu vypsaného na předposledním řádku):
th> storage 1.0000 0.5000 0.3333 0.2500 0.2000 0.1667 0.1429 0.1250 0.1111 0.1000 [torch.DoubleStorage of size 10] [0.0002s]
Přes objekt typu Storage se ovšem změnil i vlastní vektor (tedy „pohled“ na Storage), o čemž se opět můžeme snadno přesvědčit:
th> vector 1.0000 0.5000 0.3333 0.2500 0.2000 0.1667 0.1429 0.1250 0.1111 0.1000 [torch.DoubleTensor of size 10] [0.0002s]
Podobně můžeme postupovat při naplnění složitější struktury s 2×3×4 prvky:
th> t=torch.Tensor(2,3,4) [0.0001s] th> s=t:storage() [0.0001s] th> s:size() 24
Vidíme, že se interně vytvořilo jednorozměrné pole s 24 prvky, které můžeme naplnit:
th> for i=1,s:size() do ..> s[i] = i ..> end
Současně se změnil i samotný tenzor:
th> t (1,.,.) = 1 2 3 4 5 6 7 8 9 10 11 12 (2,.,.) = 13 14 15 16 17 18 19 20 21 22 23 24 [torch.DoubleTensor of size 2x3x4]
11. Operace sub aplikovaná na vektory
Další zajímavou operací, která produkuje pohled (view) nad tenzorem, je operace nazvaná sub. Nejprve se podíváme na nejjednodušší použití této operace při práci s vektory. Vytvoříme si vektor s deseti prvky od 1/1 do 1/10:
th> vector=torch.Tensor(10) th> storage=vector:storage() th> for i=1,storage:size() do ..> storage[i] = 1.0/i ..> end
Vektor skutečně obsahuje deset prvků:
th> vector 1.0000 0.5000 0.3333 0.2500 0.2000 0.1667 0.1429 0.1250 0.1111 0.1000 [torch.DoubleTensor of size 10]
Pomocí operace sub můžeme získat pohled na prvky ležícími mezi specifikovaným dolním a horním indexem. Druhý až osmý prvek se tedy přečte takto:
th> vector:sub(2,9) 0.5000 0.3333 0.2500 0.2000 0.1667 0.1429 0.1250 0.1111 [torch.DoubleTensor of size 8]
Povšimněte si, že výsledkem operace sub je opět plnohodnotný tenzor.
Při zadávání indexů prvků je možné použít i záporné hodnoty. Jak je zvykem, jsou tyto hodnoty chápány jako indexy od konce vektoru. Další příklad nám tedy dá stejný výsledek, jako příklad předchozí (druhý prvek od začátku až druhý prvek od konce; povšimněte si, proč je konzistentní pracovat s indexy začínajícími od 1 a nikoli od 0):
th> vector:sub(2,-2) 0.5000 0.3333 0.2500 0.2000 0.1667 0.1429 0.1250 0.1111 [torch.DoubleTensor of size 8]
Můžeme samozřejmě vybrat i jediný prvek:
th> vector:sub(10,10) 0.1000 [torch.DoubleTensor of size 1]
Totožný výsledek s použitím záporných indexů:
th> vector:sub(-1,-1) 0.1000 [torch.DoubleTensor of size 1]
12. Operace sub aplikovaná na matice a tenzory vyšších řádů
Operaci sub je samozřejmě možné aplikovat i na matice a tenzory vyšších řádů; výsledkem je vždy opět tenzor. Nejprve si pro ukázku vytvoříme 2D matici a naplníme ji prvky s hodnotami 1 až 20:
th> x=torch.Tensor(4,5) [0.0001s] th> s=x:storage() [0.0001s] th> for i=1,s:size() do ..> s[i] = i ..> end
Matice se skutečně vytvořila:
th> x 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [torch.DoubleTensor of size 4x5]
Voláním x:sub(1,4) získáme pohled obsahující řádky 1 až 4 (včetně), tedy celou původní matici:
th> x:sub(1,4) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [torch.DoubleTensor of size 4x5]
Pohled můžeme snadno omezit na první tři řádky:
th> x:sub(1,3) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [torch.DoubleTensor of size 3x5]
Popř. na řádek druhý a třetí:
th> x:sub(2,3) 6 7 8 9 10 11 12 13 14 15 [torch.DoubleTensor of size 2x5]
I u operace sub je možné používat záporné indexy. Následující příkaz vrátí předposlední a poslední řádek původní matice:
th> x:sub(-2,-1) 11 12 13 14 15 16 17 18 19 20
To ovšem není zdaleka vše, protože je možné specifikovat indexy i ve druhé dimenzi. Následující příkaz tedy získá submatici 2×2 prvky:
th> x:sub(2,3,2,3) 7 8 12 13 [torch.DoubleTensor of size 2x2]
Další příkaz vrátí submatici 2×2 prvků, která leží v pravém dolním rohu původní matice:
th> x:sub(-2,-1,-2,-1) 14 15 19 20
13. Operace narrow aplikovaná na vektory
S operací sub do značné míry souvisí i operace narrow, která taktéž získá pohled na zvolený tenzor. Této operaci se předávají tři parametry: dimenze (resp. její index), první prvek v dané dimenzi a počet prvků. Podívejme se opět na ten nejjednodušší případ, tedy na získání pohledu do jednorozměrného vektoru. Ten má jen jednu dimenzi (=1) a budeme chtít získat čtyři prvky začínající druhým prvkem:
th> vector:narrow(1,2,4) 0.5000 0.3333 0.2500 0.2000 [torch.DoubleTensor of size 4]
14. Operace narrow aplikovaná na matice a tenzory vyšších řádů
Mnohem užitečnější je použití operace narrow na matice a tenzory vyšších řádů. Vraťme se k naší matici 4×5 prvků:
th> x 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [torch.DoubleTensor of size 4x5] [0.0003s]
Další příkaz získá první dva řádky matice (pohybujeme se tedy po řádcích, neboť jsme zvolili první dimenzi):
th> x:narrow(1,1,2) 1 2 3 4 5 6 7 8 9 10 [torch.DoubleTensor of size 2x5] [0.0004s]
Můžeme ovšem získat i první dva sloupce, tj. pohybovat se po dimenzi druhé:
th> x:narrow(2,1,2) 1 2 6 7 11 12 16 17 [torch.DoubleTensor of size 4x2]
15. Operace sub a narrow ve funkci zapisovatelných pohledů
Vzhledem k tomu, že pohled na tenzory může být použit i pro zápis, můžeme s operacemi sub a narrow provádět i poměrně složité operace, a to opět bez nutnosti explicitně zapisovat programové smyčky při přístupu k prvkům tenzoru.
Zkusme si například vytvořit matici 5×5 prvků, která bude ve svém středu obsahovat submatici 3×3 prvky naplněné jedničkami (zbylé prvky budou nulové). Pro výplň tenzoru (či pohledu na něj) nějakou hodnotou se používá metoda fill(hodnota):
th> x=torch.zeros(5,5) [0.0002s] th> x 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [torch.DoubleTensor of size 5x5]
Matici máme vytvořenou, takže získáme submatici 3×3 prvky a vyplníme ji jedničkami (povšimněte si, že se tato submatice vrátí jako výsledek, ten ovšem zahodíme):
th> x:sub(2,4,2,4):fill(1) 1 1 1 1 1 1 1 1 1 [torch.DoubleTensor of size 3x3] [0.0003s]
Současně se změnila i původní matice:
th> x 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 [torch.DoubleTensor of size 5x5]
Nyní si zkusme naplnění prostředního řádku nové nulové matice devítkami:
th> x=torch.zeros(5,5) [0.0001s] th> x 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [torch.DoubleTensor of size 5x5] [0.0003s]
Volání narrow(1,3,1) nám vrátí celý třetí řádek matice:
th> x:narrow(1,3,1):fill(9) 9 9 9 9 9 [torch.DoubleTensor of size 1x5] [0.0002s] th> x 0 0 0 0 0 0 0 0 0 0 9 9 9 9 9 0 0 0 0 0 0 0 0 0 0 [torch.DoubleTensor of size 5x5]
Doplnění trojek do posledního sloupce (dimenze=2):
th> x:narrow(2,5,1):fill(3) 3 3 3 3 3 [torch.DoubleTensor of size 5x1] [0.0004s] th> x 0 0 0 0 3 0 0 0 0 3 9 9 9 9 3 0 0 0 0 3 0 0 0 0 3 [torch.DoubleTensor of size 5x5]
Pohledy je možné získávat i pro již existující pohledy, takže:
th> x=torch.zeros(7,7) [0.0001s] th> x:narrow(1,3,4):narrow(2,2,2):fill(1) 1 1 1 1 1 1 1 1 [torch.DoubleTensor of size 4x2] [0.0001s] th> x 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 [torch.DoubleTensor of size 7x7] [0.0002s]
Další komplikovanější operace s tenzory, například získání řezu, změny tvaru atd., si popíšeme příště.
16. Repositář s demonstračními příklady
Všechny demonstrační příklady, které jsme si popsali v předchozích kapitolách, najdete v GIT repositáři dostupném na adrese https://github.com/tisnik/torch-examples.git. Následují odkazy na zdrojové kódy jednotlivých příkladů:
17. Odkazy na Internetu
- Stránka projektu Torch
http://torch.ch/ - Torch na GitHubu (několik repositářů)
https://github.com/torch - Torch (machine learning), Wikipedia
https://en.wikipedia.org/wiki/Torch_%28machine_learning%29 - Torch Package Reference Manual
https://github.com/torch/torch7/blob/master/README.md - Torch Cheatsheet
https://github.com/torch/torch7/wiki/Cheatsheet - An Introduction to Tensors
https://math.stackexchange.com/questions/10282/an-introduction-to-tensors - Differences between a matrix and a tensor
https://math.stackexchange.com/questions/412423/differences-between-a-matrix-and-a-tensor - Qualitatively, what is the difference between a matrix and a tensor?
https://math.stackexchange.com/questions/1444412/qualitatively-what-is-the-difference-between-a-matrix-and-a-tensor? - BLAS (Basic Linear Algebra Subprograms)
http://www.netlib.org/blas/ - Basic Linear Algebra Subprograms (Wikipedia)
https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms - Comparison of deep learning software
https://en.wikipedia.org/wiki/Comparison_of_deep_learning_software - TensorFlow
https://www.tensorflow.org/ - Caffe2 (A New Lightweight, Modular, and Scalable Deep Learning Framework)
https://caffe2.ai/ - PyTorch
http://pytorch.org/ - Seriál o programovacím jazyku Lua
http://www.root.cz/serialy/programovaci-jazyk-lua/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua
http://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua (2)
http://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua-2/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua (3)
http://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua-3/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua (4)
http://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua-4/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua (5 – tabulky a pole)
http://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua-5-tabulky-a-pole/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua (6 – překlad programových smyček do mezijazyka LuaJITu)
http://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua-6-preklad-programovych-smycek-do-mezijazyka-luajitu/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua (7 – dokončení popisu mezijazyka LuaJITu)
http://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua-7-dokonceni-popisu-mezijazyka-luajitu/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua (8 – základní vlastnosti trasovacího JITu)
http://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua-8-zakladni-vlastnosti-trasovaciho-jitu/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua (9 – další vlastnosti trasovacího JITu)
http://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua-9-dalsi-vlastnosti-trasovaciho-jitu/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua (10 – JIT překlad do nativního kódu)
http://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua-10-jit-preklad-do-nativniho-kodu/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua (11 – JIT překlad do nativního kódu procesorů s architekturami x86 a ARM)
http://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua-11-jit-preklad-do-nativniho-kodu-procesoru-s-architekturami-x86-a-arm/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua (12 – překlad operací s reálnými čísly)
http://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua-12-preklad-operaci-s-realnymi-cisly/ - Lua Profiler (GitHub)
https://github.com/luaforge/luaprofiler - Lua Profiler (LuaForge)
http://luaforge.net/projects/luaprofiler/ - ctrace
http://webserver2.tecgraf.puc-rio.br/~lhf/ftp/lua/ - The Lua VM, on the Web
https://kripken.github.io/lua.vm.js/lua.vm.js.html - Lua.vm.js REPL
https://kripken.github.io/lua.vm.js/repl.html - lua2js
https://www.npmjs.com/package/lua2js - lua2js na GitHubu
https://github.com/basicer/lua2js-dist - Lua (programming language)
http://en.wikipedia.org/wiki/Lua_(programming_language) - LuaJIT 2.0 SSA IRhttp://wiki.luajit.org/SSA-IR-2.0
- The LuaJIT Project
http://luajit.org/index.html - LuaJIT FAQ
http://luajit.org/faq.html - LuaJIT Performance Comparison
http://luajit.org/performance.html - LuaJIT 2.0 intellectual property disclosure and research opportunities
http://article.gmane.org/gmane.comp.lang.lua.general/58908 - LuaJIT Wiki
http://wiki.luajit.org/Home - LuaJIT 2.0 Bytecode Instructions
http://wiki.luajit.org/Bytecode-2.0 - Programming in Lua (first edition)
http://www.lua.org/pil/contents.html - Lua 5.2 sources
http://www.lua.org/source/5.2/ - REPL
https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop - The LLVM Compiler Infrastructure
http://llvm.org/ProjectsWithLLVM/ - clang: a C language family frontend for LLVM
http://clang.llvm.org/ - LLVM Backend („Fastcomp“)
http://kripken.github.io/emscripten-site/docs/building_from_source/LLVM-Backend.html#llvm-backend - Lambda the Ultimate: Coroutines in Lua,
http://lambda-the-ultimate.org/node/438 - Coroutines Tutorial,
http://lua-users.org/wiki/CoroutinesTutorial - Lua Coroutines Versus Python Generators,
http://lua-users.org/wiki/LuaCoroutinesVersusPythonGenerators