HTML

Az élet kódjai

Csináld maga. Senki nem csinálja meg helyetted.

Friss topikok

A fától az erdőt

2019.03.10. 23:07 Travis.CG

Korábban azt írtam, hogy a döntési fák nem stabilak és az adat kismértékű változására is gyökeresen más megoldást adhatnak. Ez nem jó hír, de szerencsére van rá megoldás. A megoldás pedig - mint annyi más esetben - a véletlen perturbáció használata nagyon sokszor, végül vesszük az eredmények eredőjét. Ezt hívjuk véletlen erdőnek (random forest).

Tehát generálunk nagyon sok döntési fát, mindegyiket egy kicsit másképp és reménykedünk benne, hogy a sok próbálkozás összegzése egy stabil eredmény. Attól függően, hogy mit változtatunk a fák között, különböző típusú véletlen erdők vannak. Abban is lehet eltérés, miként összesítjük a sok eredményt.

De nézzük meg, hogy történik mindez a gyakorlatban. Mivel a véletlen erdő igen népszerű klasszifikáló eljárás, megpróbálok több implementációt is bemutatni.

Python

Ha a scikit-learn csomagot használjuk, a kód rendkívül hasonló lesz a döntési fánál bemutatott kódhoz. Ez az API tervezési sajátságából is adódik. A különböző tanuló algoritmusok egységes felülettel rendelkeznek, hogy könnyebb legyen elsajátítani azokat.

from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_estimators = 100)
rf = rf.fit(data, category)

Az n_estimators paraméterrel a döntési fák számát adhatjuk meg. Az algoritmus ezek eredményeit fogja összevonni. A data és category változók megegyeznek a döntési fánál leírt változókkal, ugyan úgy két tüdőrák típus expressziós adatait tartalmazzák. Az eredő fát viszont nem tudjuk kirajzolni a korábban bemutatott módon. Ha megpróbáljuk, hibaüzenetet kapunk.

R

A legelterjedtebb véletlen fa csomag R-ben - nem meglepő módon - a randomForest nevet viseli. A használata sem bonyolultabb egy hipotézis tesztnél.

rf <- randomForest(outcome ~ ., data = input, ntree = 500)

A bemenet egy data.frame vagy mátrix, ahol egy oszlop a kimeneti változót jelenti, a többi a független adatokat. Az ntree opcióval adhatju meg, mennyi fát akarunk generálni. Azért, hogy az egész ne csak a levegőben lógjon, bemutatom, hogy miként használható a korábban is bemutatott tüdőrákos adatokon.

Miután letöltöttük az adatokat, először beolvassuk azokat és táblázatot csinálunk belőlük. A könnyebbség kedvéért két táblázatot mindkét tumor típusnak.

library(randomForest)

readData <- function(initdir){
   files <- list.files(initdir, recursive = T, pattern =    "txt.gz",full.names = T)
   data <- read.table(files[1])
   rownames(data) <- data$V1
   data <- data[,2,drop=F]
   for(i in 2:length(files)){
      new <- read.table(files[i])
      data <- cbind(data, new[,2])
   }
   return(data)
}

luad <- readData("luad/")
lusc <- readData("lusc/")

Ebből a két táblázatból készítünk egy harmadikat, ahol minden egyes sor egy minta lesz, az oszlopok a gének expressziói. Ehhez még egy oszlopot rakunk, ami a tumor típusát definiálja. Ez lesz egyébként a függő változónk is.

data <- as.data.frame(rbind(t(lusc),t(luad)))
data <- cbind(data, c(rep("lusc", ncol(lusc)),rep("luad", ncol(luad))))
colnames(data)[60484] <- "cancer"

Végül a tanítási fázis:

rf <- randomForest(cancer ~ ., data = data, ntree = 500)

Legalábbis elméletileg. Nekem a tanítás segfaulttal elszállt, ha az összes génre akartam futtatni. Ha csak 100 génre limitáltam, akkor gond nélkül lefutott.

A ranger csomag szintaxisa is teljesen hasonló. Érdekessége, hogy van C++-os futtatható változata is.

rf <- ranger(cancer ~., data = data)

A teljes génszetten ez sem futott le az R halála nélkül, de száz génre gond nélkül alkalmazható volt.

Szerencsére a következő csomagunk, az Rborist megtöri a fenti hagyományt, és ezzel megakadályozza, hogy telefonkönyv-szerű felsorolássá degradálódjon ez a poszt. Szintaxisa közelebb áll a scikit-learn filozófiájához. Az adatok generálása egy kicsit ezért más lesz:

data <- as.data.frame(rbind(t(lusc),t(luad)))
response <- as.factor(c(rep("lusc", ncol(lusc)),rep("luad", ncol(luad))))
rf3 <- Rborist(data, response)

Ez az egyedüli csomag, ami több szálat is képes használni és ez volt az egyedüli (az általam próbáltak közül), ami képes volt a teljes adatszettet feldolgozni fagyás nélkül!

Összegzés

Habár R és Python nyelven is elérhetőek véletlen erdő implementációk, ha masszív adatmennyiséggel kell számolni, célszerű Pythont használni. Ez igazából nekem is meglepő eredmény, nem tudom, miért nem működtek hatvanezer génre az R implementációk többsége. A memória nem fogyott el, az biztos (6% memóriát használtak egy 32GB memóriával rendelkező gépen). Az Rborist rendesen kihasználta az alatta futó vas erőforrásait. Kb. 20% memóriát használt és 7 magot a nyolcból. Igaz, a példák nem voltak életszerűek (nem csináltunk külön tanuló és teszt adatsort), nem is mértük, mennyire jók az egyes implementációk. Azt sem szabad elfelejteni, hogy R-ben további csomagok érhetőek el, amelyekre nem tértem ki. A Jupyte notebookok elérhetőek itt.

Szólj hozzá!

Címkék: machine learning

A bejegyzés trackback címe:

https://cybernetic.blog.hu/api/trackback/id/tr9614606556

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása