*Vytvořeno na základě zápisků ze cvičení k <Úvod%20do%20strojového%20učení%20%28v%20počítačové%20lingvistice%29>, ZS 2008/9 -- <User:Tuetschek> 16:20, 24 Jan 2009 (CET)*

* [Short R Reference Card](http://cran.r-project.org/doc/contrib/Short-refcard.pdf), obsahuje většinu důležitých základních funkcí

## Základní příkazy ##

Nápověda:

* `&gt; ?func`  # nápověda pro funkci `func`

Potlačení chyb:

* `try( ... )`  # nezastaví program, když se stane chyba
* Debugging: [Debugging in R](http://www.stats.uwo.ca/faculty/murdoch/software/debuggingR/)

### Objekty, paměť ###

Úplně všechno v R je objekt.

* `summary(obj) `  # Použít pro zjištění něčeho o libovolném objektu
* `str(obr)`  # zjištění typu objektu (jiná informace
* `ls()`  # seznam všech objektů
* `ls.str()`  # zavolá `str()` na všechny existující objekty
* `rm(object)`  # smaže objekt `object`
    * `rm(list=ls())`  # smaže úplně všechny objekty

Zavřu-li nějaký příkaz do závorek, vytiskne se jeho výsledek na výstup.

### Počty ###

Ovládání:

* `ls`  # použitím jména funkce bez závorek se vypíše její zdroják, nezavolá se
* `m &lt;- 15`  # přiřazovací příkaz, nepoužívat `=`, je to obsolete!
* `a &lt;- c(10,12, 16, pi)`  # vytvoření vektoru pomocí funkce `c()` (konkatenace)
* `b &lt;- (1:8)*3`  # sekvence čísel, může jít i pozpátku: `c &lt;- (8:1)/2 - 3`
* R nemá ternární operátor (?), operátor `?` je nápověda
    * Místo ternárního operátoru se dá použít `x &lt;- if (condition){ value1 }else{ value2 };`

Funkce s jedním argumentem, do kterého dám `c(..)` mi vrátí `c(..)` s výsledky pro každý člen původního vektoru. Všechny početní operace jsou totiž definovány na vektorech.

S vektory se dá počítat všelijak. Dát ale pozor na **sčítání vektorů různé délky**, R si kratší z nich zacyklí a nevydá žádný warning.

* `w &lt;- x/2 + 1`  # a `x` je vektor
* `y &lt;- x + w * rnorm(x)`
* `predict == test`# je vektor hodnot `TRUE` a `FALSE`, podle toho, jestli se shodují hodnoty na stejných pozicích

### Vnější vztahy ###

Pracovní adresář (pro čtení, zápis souborů) -- vždycky je nějaký nastaven:

* `getwd()`  # zjištění
* `setwd()`  # nastavení

Volání příkazů operačního systému:

* `system("ls")`

R-**balíčky** = knihovny: soubory funkcí, struktura: použít v Unixu `locate`, pak `00Index.html`. Základní knihovna se jmenuje *base*.

* `library(MASS)`  # nahrání knihovny MASS do paměti, umožní používat funkce v ní obsažené
* `installed.packages()`  # seznam všech nainstalovaných balíčků, co můžu nahrát do paměti
* `available.packages()`  # seznam všech balíčků, které se dají stáhnout
* `download.packages(pkgs="e1071", destdir=getwd())`  # stažení balíčku *e1071* do aktuálního adresáře
    * Stáhne se pod Windows ve formátu ZIP, pod Unixem v TGZ
* `install.packages(pkgs="e1071_1.5-18.tgz", lib.loc=getwd(), repos = NULL)`  # instalace balíčku do aktuálního adresáře (nebo adresáře `libloc`; v `pkgs` je celá cesta k nim), `repos = NULL` znamená, že se instalace provádí offline, šlo by instalovat i přímo z CRAN mirroru.
* `library(e1071,lib.loc=getwd())`  # nahrání separátně nainstalované knihovny z nějakého adresáře

Před uzavřením R je možné uložit všechny objekty v paměti, ale lepší je to nedělat, ať mám opakovatelné pokusy.

### Funkce ###

1. 

    definice funkce, v názvech se slova zpravidla oddělují tečkoufoo.bar &lt;- function( x, y=2 ) # můžu dát iniciální hodnoty parametrů{    # komentář    return ( x ^ y ) # návratová hodnota: závorky nutné!}

Přímá editace funkce z prostředí R se provádí příkazem `edit(func)`.

## Statistika ##

Generátor náhodných čísel -- iniciální nastavení:

* `set.seed(123)`  # pozor, některé hodnoty jsou vhodnější než jiné

### Distribuce pravděpodobnosti ###

Pro každou distribuci je v R několik funkcí, které se starají o generování apod., mají spec. prefixy (první znak názvu):

* `r`  # generování náhodných vzorků, je tu opravdu dobrý generátor náh. čísel (tedy používat tohle!)
    * První parametr je číslo (požadovaný počet vzorků), nebo vektor (počet vzorků = délka vektoru)
* `d`  # funkce hustoty pravděpodobnosti (pro každý bod mám "něco jako" pravděpodobnost, suma přes $\mathbb{R}$ dává 1)
* `p`  # kumulativní distribuční funkce
* `q`  # kvantilová distribuční funkce

Distribuce

* `-norm`  # normální rozdělení
* `-unif`  # rovnoměrné rozdělení
* `-binom`  # binomické rozdělení
* `-multinom`  # multinomické rozdělení

Testování parametrů rozdělení pro náhodný výběr (v proměnné `x`)

* `mean(x)`  # střední hodnota
* `var(x)`  # rozptyl

### Regrese ###

Vytvoření modelu lineární regrese:

*`fm &lt;- lm( y ~ x, data= ... )`  # na základě data framu, který má sloupce `y` a `x`, vytvořím model lin. regrese, kde `y` závisí na `x`

* Proměnná, která je závislá, musí být spojitá, ostatní se převedou na spojité, pokud jsou kategoriální

*`fm &lt;- lm( y ~ ., data= ... )`  # model, kde `y` závisí na všech ostatních sloupcích data framu

Predikce modelu a testování:
*`trainedModel &lt;- lm(y ~ ., data=train)`  # vytvoření modelu

*`prediction &lt;- predict.lm(trainedModel, data=test)`  # vytvoření predikce, dá se pak porovnávat s výsledky testování

Lokální polynomická regrese:
*`model &lt;- loess(y ~ x, data=train)`  # vytvoření modelu (má spoustu dalších parametrů)

*`predict`  # predikce nemá vlastní funkci, používá se standardní pro všechno

## Operace s daty ##

### I/O ###

Načtení dat ze souboru:

* `read.csv(filename, header=TRUE, sep=",")`  # načte data z CSV souboru, `sep` je oddělovač polí, pokud je `header=TRUE`, první řádek se bere jako hlavička

### Převody datových typů ###

Vytváření jednoho datového typu z jiného:

* `c()`  # konkatenace vektorů / prvků do jednoho vektoru
* `dummy &lt;- data.frame(x,y,w)`  # vytvoření data framu, vektory `x,y,w` budou jeho sloupce.
    * Jedná se o kopírování, původní proměnné můžu zahodit
* `matrix(data, cols, rows)`  # vytvoření matice o dané šířce a výšce z vektoru
    * Matici vytvoří i když délka dat není rovna `cols*rows`, ale vydá warning
* `rbind(col1, col2, col3)`  # vytvoří matici z dat, která budou jejími sloupci
* `cbind(row1, row2, row3)`  # totéž s řádky
* `l &lt;- list(..); vector &lt;- unlist(l);`  # vytvoření seznamu z vektoru a převod zpět (seznam může obsahovat vektory a seznamy, vektor je jednorozměrný)
* `factor(data, levels=c(...), labels=c(...))`  # vytvoření faktoru = enumu (`levels` -- udávám přípustné hodnoty, všechny další jsou hozeny na `&lt;NA&gt;`; `labels` -- udaným úrovním můžu dát jména, pokud chci).
    * `levels(my.factor)`  # ukáže jména všech hodnot faktoru
    * 

* `levels(my.factor) <- c("a","b","c")`  # do jmen hodnot faktoru lze i zapisovatInformace o matici nebo data frame:`ncol(dummy); length(dummy[1,])`  # počet sloupců
* `nrow(dummy)`  # počet řádků

Explicitní konverze:

* `as.`*-matrix, data.frame, vector, factor*  # podle toho, na co chci konvertovat

### Dělení dat ###

Výběr dat z matice nebo data frame:

* `dummy[1,3]`  # 3. sloupec, 1. řádek (1 element) 
* `dummy[1,]`  # první řádek (výsledek je jednořádkový data frame)
* `dummy[,-1]`  # vše až na první sloupec (výsledek je data frame)
* `dummy[,1]`  # první sloupec (výsledek je vektor)
* `indices &lt;- c(1,3,5,7); dummy[indices,];`  # vybrání jen některých řádků (můžu např. použít funkci <#Vytv.C3.A1.C5.99en.C3.AD_dat>), můžu i přímo zadat vektor
* `dummy<nowiki>[[column]]</nowiki>`  # vybere z data framu sloupec, který má název rovný hodnotě proměnné `column` (název se dá získat např. pomocí `[[#P.C5.99evody_datov.C3.BDch_typ.C5.AF|names]]`)

### Vytváření dat ###

Generování vzorků:

* `x &lt;- seq(start, finish, step)`  # vytvoří vektor, který obsahuje čísla od `start` do `finish` s krokem `step`. Zavolám-li `seq(1,20,5)`, dostanu čísla `1 6 11 16`.
* `sample(x, length, ...)`  # vybírání náhodných vzorků -- z vektoru `x` vyberu `length` vzorků
    * defaultní hodnota `length` je délka `x`, tedy vytváří náhodnou permutaci daného vektoru
    * je-li `x` ne vektor, ale číslo, bere se vektor čísel od 1 do `x`.
* `indices &lt;- sample(39)[1:25]; train &lt;- data[indices,];`  # vybrání náhodné podmnožiny, aby se zabránilo hierarchii v datech

Použití funkce na celý vektor / matici:

* `apply(dummy, 1, mean)`  # použití funkce `mean` (jde definovat i vlastní bezejmenná funkce a přímo napsat do parametru) na řádky (prostř. hodnota = `1`) / sloupce (`2`) data framu
* `lapply(vector, func)`  # použití funkce na všechny prvky vektoru, vrací vždy seznam
* `sapply(vector, func)`  # to samé, ale když dostane vektor, vrátí vektor

### Převody charakteru dat ###

Data atributů, se kterými pracuji, jsou buď **spojitá (continuous)** nebo **kategoriální (categorical, disktrétní)**. Některé modely, algoritmy atd. pracují jen s jedním typem.

Převod kategoriálních atributů na spojité: mám-li např. atribut *color* se 3 hodnotami: *red, blue, black*, potom vytvořím 3 atributy: *f-blue, f-black, f-red* a dávám jim hodnoty *0* a *1*. To, že je vždy *1* jen jeden, vůbec nevadí - sice to enormně zvětšuje dimenzi (počet atributů), ale to v praxi často vůbec nevadí (jen pozor na <wen:Curse%20of%20dimensionality>).

Převod spojitých na kategoriální: např. vyrobím kategoriální parametr se 4 hodnotami *excellent, good, average, bad* ~ např. *4, 3, 2, 1* -- ale musím si pořád pamatovat, že to je jenom kódování a např. průměr nebo medián nemá moc smysl (v praxi ale často funguje). Jak přesně rozdělit data je otázka praxe, musíme o datech něco vědět, aby dělení mělo smysl. Funkce na dělení:

* `categ &lt;- cut(continuous.data, c(-Inf,5,20,Inf), labels=c("low", "mid", "high") )`  # pozor, velikost vektoru s hranicemi musí být o 1 větší než velikost vektoru s názvy jednotlivých levelů
    * Pokud nedodám názvy levelů, vyrobí si R pochybné svoje s popisem intervalů, ze kterých hodnoty pocházejí
* `quantile(continuous.data, c(0,0.2,0.4,0.6,0.8,1))`  # Pro dělení podle pravděpodobností padnutí do nějakého intervalu, defaultní je `c(0,0.25,0.50,0.75,1)`.

Některé modely předpokládají určité vlastnosti dat (např. standardní normální rozdělení apod.). Měly by se upravit trénovací data a podle nich upravit stejně i testovací:

* `x &lt;- scale(data, center=TRUE, scale=TRUE)`  # vycentruje všechny sloupce matice kolem průměru a vyškáluje: vydělí jejich kvadratickým průměrem (použít pro trénovací data)
    * pokud jsou `center` a `scale` čísla, použijí se přímo na odečtení / vydělení (použít pro testovací data)
    * pokud jsou hodnoty `FALSE` necentruje se a/nebo se neškáluje
* `attr(x, "scaled:center")`  # jediný možný přístup k `center` a `scale` spočítaných na trénovacích datech, která se pak mohou použít pro testovací data

### Výpisy ###

* `paste("a", "b", "c", sep="")`  # slepování stringů
* `gettextf("Insert a string here:%s", string.data)`  # vkládání stringů do nějakého vzorce
    * `%s` je string, `%d` integer (`%x` hexadecimálně), `%f` je double (`%e` v plovoucí čárce a `%g` se rozhoduje, jestli použít normální nebo plovoucí čárku), procento se píše `%%`.

### Grafy, kreslení ###

Histogram:

* `truehist(x, nbins=25)`  # `nbins` určuje počet "přihrádek"

Graf:

* `plot(x, y1); lines(x, y2); ...`  # první a další proměnná (čára) do grafu 
    * parametr `type` je informace o druhu čar / bodů: `b` bod a čára, `l` jen čára, `p` jen body
    * u libovolných čar `lty` je druh (plná, čárkovaná, tečkovaná, čerchovaná ...), `col` je barva, `pch` je písmeno, které se použije jako bod, pokud `type` je nastaveno na `b`.
    * nastavení min. a max. hodnoty u obou os: `xlim=c(min,max)`, `ylim`

Grafické zobrazení distribuce:

* `dd &lt;- kde2d(x,y)`  # `kde2d` je z knihovny *MASS*, 2-rozměrná funkce hustoty
* `contour(dd)`  # dvourozměrná hustota ve "vrstevnicích"
* `image(dd)`  # barevný obrázek téhož

Výstup do souboru:

* `png("output.png"); plot(x); dev.off();`  # otevře PNG, zapíše požadovaný graf a zavře
* `pdf("output.pdf");`  # totéž s PDF, výstup se dá potom importovat do <wen:Inkscape> a dál editovat (a např. uložit jako EPS a vložit do TeXového zdrojáku)

## Metody strojového učení ##

### Rozhodovací stromy ###

Rpart (funguje na kategoriální proměnné):

* `library(rpart)`  # nachází se v knihovně *rpart* (součástí std. balíčku R).
* `decision.tree &lt;- rpart(y ~ feat1 + feat2, train.data)`  # vytvoření rozhodovacího stromu
* `prediction &lt;- predict(decision.tree, test.data, type="class")`  # predikce podle testovacích dat; kdyby nebyl nastavený parametr `type`, potom by vracelo matici pravděpodobností klasifikace pro jednotlivé typy

Trees 

* Funguje i na spojité proměnné, dělí vždy na dvě skupiny a kde dělit se rozhoduje podle maximálního snížení nějakého koeficientu přes všechna možná dělení.
* `library(tree)`  # součástí knihovny *tree*, kterou je nutné si <#Vn.C4.9Bj.C5.A1.C3.AD_vztahy>
* `model &lt;- tree(y ~ ., train)`  # natrénování, vytvoření stromu; interakce atributů jsou zakázané
    * `split`  # kritérium dělení (co se má co nejvíce snížit -- `deviance` / `[[wen:Gini_coefficient|gini]]`)
* Predikce stejná jako pro Rpart.

### K-nn ###

K-nn funguje jen na spojité proměnné, je nutné tedy převést kategoriální data.

* `library(class)`  # k-nn algoritmus se nachází v knihovně *class* (součást standardního balíčku R)
* `predict &lt;- knn(train, test, cl.train, k, use.all)`  # samotný algoritmus
    * `train` a `test` jsou trénovací a testovací data bez klasifikací (sloupce s výslednými proměnnými)
    * `cl.train` je sloupec klasifikací pro trénovací data
    * `k` je parametr *k*, tj. počet vzorků, které se mají použít
    * `use.all` -- pokud je více vzorků ve stejné vzdálenosti, mají se použít všechny, nebo jen vybraných max. *k*?
* Rovnou vrací vektor předpovězených klasifikací pro testovací data. 

### Naive Bayes ###

Je součásti knihovny *e1071*, pracuje se spojitými proměnnými i kategoriálními daty:

* `library(e1071)`  # nutné ji mít <#Vn.C4.9Bj.C5.A1.C3.AD_vztahy>
* `model &lt;- naiveBayes(y ~ ., train)`  # natrénování modelu, nelze používat interakce featur!
* `test1 &lt;- test; test1$y &lt;- NULL; predict(model, test1);`  # predikce, sloupec s výslednými hodnotami testovacích dat se pro použití ve funkci `predict` musí vyhodit, aby to fungovalo.

### SVM ###

Je součástí knihovny *e1071*, pracuje se spojitými proměnnými

* `library(e1071)`  # nutné ji mít <#Vn.C4.9Bj.C5.A1.C3.AD_vztahy>
* `model &lt;- svm(y ~ ., train, type="C-classification", kernel="linear", cost=100)`  # natrénování
    * `type` používat jen `C-classification`
    * `kernel` máme i `radial` (s parametrem `gamma` (měřítko)) nebo `polynomial` (s parametrem `gamma` (měřítko), `coef0` (posun) a `degree` (stupeň polynomu))
    * `cost` je váha penalizací (slack variables)
* `predict(model, test)`  # predikce
* Funguje i na víc kategorií než *+* a *-*.

### Testy úspěšnosti ###

* `mean(predict == test);`  # accuracy
* `table(predict, test);`  # vytvoří confusion matrix (kontingenční tabulku s počtem jednotlivých hodnot)

    precision &lt;- function( real, predict ){    tp &lt;- 0; fp &lt;- 0;    for(i in 1:length(real)){	if (predict[i] == 1){	    if (real[i] == 1) tp &lt;- tp + 1	    else fp &lt;- fp + 1;	}    }    return ( tp / (tp + fp));}recall &lt;- function( real, predict ){    tp &lt;- 0; fn &lt;- 0;    for(i in 1:length(real)){	if (real[i] == 1){	    if (predict[i] == 1) tp &lt;- tp + 1	    else fn &lt;- fn + 1;	}    }    return ( tp / (tp + fn));  }f.measure &lt;- function( real, predict ){    r &lt;- recall( real, predict )    p &lt;- precision( real, predict )    return ( 2 * p * r / ( p + r ) );}

## Help ##

* [Hlavní stránka R](http://www.r-project.org/)
* [R Site Search](http://finzi.psych.upenn.edu/search.html)
* [Jiný způsob hledání (?)](http://finzi.psych.upenn.edu/cgi-bin/namazu.cgi?#query=as.dummy&max=100&result=normal&sort=score&idxname=functions)
