R-tahák
Vytvořeno na základě zápisků ze cvičení k Úvodu do strojového učení, ZS 2008/9 -- Tuetschek 16:20, 24 Jan 2009 (CET)
- Short R Reference Card, obsahuje většinu důležitých základních funkcí
Základní příkazy
Nápověda:
- > ?func # nápověda pro funkci func
Potlačení chyb:
- try( ... ) # nezastaví program, když se stane chyba
- Debugging: Debugging in R
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 <- 15 # přiřazovací příkaz, nepoužívat =, je to obsolete!
- a <- c(10,12, 16, pi) # vytvoření vektoru pomocí funkce c() (konkatenace)
- b <- (1:8)*3 # sekvence čísel, může jít i pozpátku: c <- (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 <- 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 <- x/2 + 1 # a x je vektor
- y <- 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
# definice funkce, v názvech se slova zpravidla oddělují tečkou foo.bar <- 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 <- 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 <- lm( y ~ ., data= ... ) # model, kde y závisí na všech ostatních sloupcích data framu
Predikce modelu a testování:
- trainedModel <- lm(y ~ ., data=train) # vytvoření modelu
- prediction <- predict.lm(trainedModel, data=test) # vytvoření predikce, dá se pak porovnávat s výsledky testování
Lokální polynomická regrese:
- model <- 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 <- 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 <- list(..); vector <- 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 <NA>; 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 zapisovat
Informace 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 <- c(1,3,5,7); dummy[indices,]; # vybrání jen některých řádků (můžu např. použít funkci sample), můžu i přímo zadat vektor
- dummy[[column]] # vybere z data framu sloupec, který má název rovný hodnotě proměnné column (název se dá získat např. pomocí names)
Vytváření dat
Generování vzorků:
- x <- 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 <- sample(39)[1:25]; train <- 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 Curse of dimensionality).
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 <- 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 <- 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 <- 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 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 <- rpart(y ~ feat1 + feat2, train.data) # vytvoření rozhodovacího stromu
- prediction <- 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 nainstalovat
- model <- 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 / 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 <- 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 nainstalovanou
- model <- naiveBayes(y ~ ., train) # natrénování modelu, nelze používat interakce featur!
- test1 <- test; test1$y <- 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 nainstalovanou
- model <- 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 <- function( real, predict ){ tp <- 0; fp <- 0; for(i in 1:length(real)){ if (predict[i] == 1){ if (real[i] == 1) tp <- tp + 1 else fp <- fp + 1; } } return ( tp / (tp + fp)); } recall <- function( real, predict ){ tp <- 0; fn <- 0; for(i in 1:length(real)){ if (real[i] == 1){ if (predict[i] == 1) tp <- tp + 1 else fn <- fn + 1; } } return ( tp / (tp + fn)); } f.measure <- function( real, predict ){ r <- recall( real, predict ) p <- precision( real, predict ) return ( 2 * p * r / ( p + r ) ); }