Stablo odlučivanja u R: Klasifikacijsko stablo s primjerom

Što su stabla odlučivanja?

Stabla odlučivanja su svestrani algoritam strojnog učenja koji može obavljati i zadatke klasifikacije i regresije. Oni su vrlo moćni algoritmi, sposobni prilagoditi složene skupove podataka. Osim toga, stabla odlučivanja temeljne su komponente nasumičnih šuma, koje su među najmoćnijim algoritmima strojnog učenja koji su danas dostupni.

Obuka i vizualizacija stabla odlučivanja u R

Za izgradnju vašeg prvog stabla odlučivanja u R primjeru, postupit ćemo kako slijedi u ovom vodiču za stablo odlučivanja:

  • Korak 1: Uvezite podatke
  • Korak 2: Očistite skup podataka
  • Korak 3: Stvorite set za treniranje/testiranje
  • Korak 4: Izgradite model
  • Korak 5: Napravite predviđanje
  • Korak 6: Izmjerite učinak
  • Korak 7: Podesite hiperparametre

Korak 1) Uvezite podatke

Ako vas zanima kakva je sudbina Titanica, ovaj video možete pogledati na Youtube. Svrha ovog skupa podataka je predvidjeti koji ljudi imaju veću vjerojatnost da će preživjeti nakon sudara s santom leda. Skup podataka sadrži 13 varijabli i 1309 opažanja. Skup podataka je poredan po varijabli X.

set.seed(678)
path <- 'https://raw.githubusercontent.com/guru99-edu/R-Programming/master/titanic_data.csv'
titanic <-read.csv(path)
head(titanic)

Izlaz:

##   X pclass survived                                            name    sex
## 1 1      1        1                   Allen, Miss. Elisabeth Walton female
## 2 2      1        1                  Allison, Master. Hudson Trevor   male
## 3 3      1        0                    Allison, Miss. Helen Loraine female
## 4 4      1        0            Allison, Mr. Hudson Joshua Creighton   male
## 5 5      1        0 Allison, Mrs. Hudson J C (Bessie Waldo Daniels) female
## 6 6      1        1                             Anderson, Mr. Harry   male
##       age sibsp parch ticket     fare   cabin embarked
## 1 29.0000     0     0  24160 211.3375      B5        S
## 2  0.9167     1     2 113781 151.5500 C22 C26        S
## 3  2.0000     1     2 113781 151.5500 C22 C26        S
## 4 30.0000     1     2 113781 151.5500 C22 C26        S
## 5 25.0000     1     2 113781 151.5500 C22 C26        S
## 6 48.0000     0     0  19952  26.5500     E12        S
##                         home.dest
## 1                    St Louis, MO
## 2 Montreal, PQ / Chesterville, ON
## 3 Montreal, PQ / Chesterville, ON
## 4 Montreal, PQ / Chesterville, ON
## 5 Montreal, PQ / Chesterville, ON
## 6                    New York, NY
tail(titanic)

Izlaz:

##         X pclass survived                      name    sex  age sibsp
## 1304 1304      3        0     Yousseff, Mr. Gerious   male   NA     0
## 1305 1305      3        0      Zabour, Miss. Hileni female 14.5     1
## 1306 1306      3        0     Zabour, Miss. Thamine female   NA     1
## 1307 1307      3        0 Zakarian, Mr. Mapriededer   male 26.5     0
## 1308 1308      3        0       Zakarian, Mr. Ortin   male 27.0     0
## 1309 1309      3        0        Zimmerman, Mr. Leo   male 29.0     0
##      parch ticket    fare cabin embarked home.dest
## 1304     0   2627 14.4583              C          
## 1305     0   2665 14.4542              C          
## 1306     0   2665 14.4542              C          
## 1307     0   2656  7.2250              C          
## 1308     0   2670  7.2250              C          
## 1309     0 315082  7.8750              S

Iz ispisa glave i repa možete primijetiti da podaci nisu pomiješani. Ovo je veliki problem! Kada podijelite podatke između skupa vlakova i skupa za testiranje, odabrat ćete samo putnik iz klase 1 i 2 (Nijedan putnik iz klase 3 nije u prvih 80 posto opažanja), što znači da algoritam nikada neće vidjeti značajke putnika iz klase 3. Ova će pogreška dovesti do lošeg predviđanja.

Da biste prevladali ovaj problem, možete koristiti funkciju sample().

shuffle_index <- sample(1:nrow(titanic))
head(shuffle_index)

R kod stabla odlučivanja Objašnjenje

  • sample(1:nrow(titanic)): Generirajte nasumični popis indeksa od 1 do 1309 (tj. najveći broj redaka).

Izlaz:

## [1]  288  874 1078  633  887  992

Koristit ćete ovaj indeks za miješanje titanskog skupa podataka.

titanic <- titanic[shuffle_index, ]
head(titanic)

Izlaz:

##         X pclass survived
## 288   288      1        0
## 874   874      3        0
## 1078 1078      3        1
## 633   633      3        0
## 887   887      3        1
## 992   992      3        1
##                                                           name    sex age
## 288                                      Sutton, Mr. Frederick   male  61
## 874                   Humblen, Mr. Adolf Mathias Nicolai Olsen   male  42
## 1078                                 O'Driscoll, Miss. Bridget female  NA
## 633  Andersson, Mrs. Anders Johan (Alfrida Konstantia Brogren) female  39
## 887                                        Jermyn, Miss. Annie female  NA
## 992                                           Mamee, Mr. Hanna   male  NA
##      sibsp parch ticket    fare cabin embarked           home.dest## 288      0     0  36963 32.3208   D50        S     Haddenfield, NJ
## 874      0     0 348121  7.6500 F G63        S                    
## 1078     0     0  14311  7.7500              Q                    
## 633      1     5 347082 31.2750              S Sweden Winnipeg, MN
## 887      0     0  14313  7.7500              Q                    
## 992      0     0   2677  7.2292              C	

Korak 2) Očistite skup podataka

Struktura podataka pokazuje da neke varijable imaju NA. Čišćenje podataka izvršiti na sljedeći način

  • Ispustite varijable home.dest,cabin, name, X i kartu
  • Stvorite faktorske varijable za pclass i survived
  • Odbaci NA
library(dplyr)
# Drop variables
clean_titanic <- titanic % > %
select(-c(home.dest, cabin, name, X, ticket)) % > % 
#Convert to factor level
	mutate(pclass = factor(pclass, levels = c(1, 2, 3), labels = c('Upper', 'Middle', 'Lower')),
	survived = factor(survived, levels = c(0, 1), labels = c('No', 'Yes'))) % > %
na.omit()
glimpse(clean_titanic)

Objašnjenje koda

  • select(-c(home.dest, cabin, name, X, ticket)): Ispustite nepotrebne varijable
  • pclass = faktor(pclass, razine = c(1,2,3), labels= c('Gornji', 'Srednji', 'Donji')): Dodajte oznaku varijabli pclass. 1 postaje gornji, 2 postaje srednji i 3 postaje donji
  • faktor(preživio, razine = c(0,1), oznake = c('Ne', 'Da')): Dodajte oznaku varijabli preživio. 1 postaje Ne, a 2 postaje Da
  • na.omit(): Ukloni NA opažanja

Izlaz:

## Observations: 1,045
## Variables: 8
## $ pclass   <fctr> Upper, Lower, Lower, Upper, Middle, Upper, Middle, U...
## $ survived <fctr> No, No, No, Yes, No, Yes, Yes, No, No, No, No, No, Y...
## $ sex      <fctr> male, male, female, female, male, male, female, male...
## $ age      <dbl> 61.0, 42.0, 39.0, 49.0, 29.0, 37.0, 20.0, 54.0, 2.0, ...
## $ sibsp    <int> 0, 0, 1, 0, 0, 1, 0, 0, 4, 0, 0, 1, 1, 0, 0, 0, 1, 1,...
## $ parch    <int> 0, 0, 5, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 4, 0,...
## $ fare     <dbl> 32.3208, 7.6500, 31.2750, 25.9292, 10.5000, 52.5542, ...
## $ embarked <fctr> S, S, S, S, S, S, S, S, S, C, S, S, S, Q, C, S, S, C...		

Korak 3) Stvorite set za treniranje/testiranje

Prije nego što uvježbate svoj model, morate izvršiti dva koraka:

  • Stvorite vlak i skup testova: Vi trenirate model na skupu vlakova i testirate predviđanje na test skupu (tj. nevidljivi podaci)
  • Instalirajte rpart.plot s konzole

Uobičajena praksa je podijeliti podatke 80/20, 80 posto podataka služi za treniranje modela, a 20 posto za predviđanje. Morate stvoriti dva odvojena podatkovna okvira. Ne želite dirati testni set dok ne završite izradu svog modela. Možete stvoriti ime funkcije create_train_test() koja uzima tri argumenta.

create_train_test(df, size = 0.8, train = TRUE)
arguments:
-df: Dataset used to train the model.
-size: Size of the split. By default, 0.8. Numerical value
-train: If set to `TRUE`, the function creates the train set, otherwise the test set. Default value sets to `TRUE`. Boolean value.You need to add a Boolean parameter because R does not allow to return two data frames simultaneously.
create_train_test <- function(data, size = 0.8, train = TRUE) {
    n_row = nrow(data)
    total_row = size * n_row
    train_sample < - 1: total_row
    if (train == TRUE) {
        return (data[train_sample, ])
    } else {
        return (data[-train_sample, ])
    }
}

Objašnjenje koda

  • funkcija (podaci, veličina=0.8, vlak = TRUE): Dodajte argumente u funkciju
  • n_row = nrow(data): Broj redaka u skupu podataka
  • total_row = size*n_row: Vratite n-ti red za konstrukciju vlaka
  • train_sample <- 1:total_row: Odaberite prvi red do n-tog reda
  • if (train ==TRUE){ } else { }: Ako se uvjet postavi na istinito, vrati skup niza, inače ispitni skup.

Možete testirati svoju funkciju i provjeriti dimenziju.

data_train <- create_train_test(clean_titanic, 0.8, train = TRUE)
data_test <- create_train_test(clean_titanic, 0.8, train = FALSE)
dim(data_train)

Izlaz:

## [1] 836   8
dim(data_test)

Izlaz:

## [1] 209   8

Skup podataka o vlaku ima 1046 redaka, dok testni skup podataka ima 262 reda.

Koristite funkciju prop.table() u kombinaciji s table() da biste provjerili je li proces nasumičnog odabira točan.

prop.table(table(data_train$survived))

Izlaz:

##
##        No       Yes 
## 0.5944976 0.4055024
prop.table(table(data_test$survived))

Izlaz:

## 
##        No       Yes 
## 0.5789474 0.4210526

U oba skupa podataka, broj preživjelih je isti, oko 40 posto.

Instalirajte rpart.plot

rpart.plot nije dostupan iz conda biblioteka. Možete ga instalirati s konzole:

install.packages("rpart.plot")

Korak 4) Izgradite model

Spremni ste za izradu modela. Sintaksa za Rpart funkciju stabla odlučivanja je:

rpart(formula, data=, method='')
arguments:			
- formula: The function to predict
- data: Specifies the data frame- method: 			
- "class" for a classification tree 			
- "anova" for a regression tree	

Koristite metodu klase jer predviđate klasu.

library(rpart)
library(rpart.plot)
fit <- rpart(survived~., data = data_train, method = 'class')
rpart.plot(fit, extra = 106

Objašnjenje koda

  • rpart(): Funkcija za uklapanje u model. Argumenti su:
    • preživio ~.: Formula of the Decision Trees
    • data = data_train: Skup podataka
    • method = 'class': Fit binarni model
  • rpart.plot(fit, extra= 106): Iscrtajte stablo. Dodatne značajke postavljene su na 101 za prikaz vjerojatnosti 2. klase (korisno za binarne odgovore). Možete se obratiti na vinjeta za više informacija o drugim izborima.

Izlaz:

Izgradite model stabala odlučivanja u R

Počinjete od korijenskog čvora (dubina 0 na 3, vrh grafikona):

  1. Na vrhu, to je ukupna vjerojatnost preživljavanja. Prikazuje udio putnika koji su preživjeli nesreću. Preživjelo je 41 posto putnika.
  2. Ovaj čvor pita je li spol putnika muški. Ako da, onda idete dolje do korijenskog lijevog podređenog čvora (dubina 2). 63 posto su muškarci s vjerojatnošću preživljavanja od 21 posto.
  3. U drugom čvoru pitate je li muški putnik stariji od 3.5 godine. Ako da, onda je šansa za preživljavanje 19 posto.
  4. Nastavite tako da shvatite koje značajke utječu na vjerojatnost preživljavanja.

Imajte na umu da je jedna od mnogih kvaliteta stabala odlučivanja to što zahtijevaju vrlo malo pripreme podataka. Konkretno, ne zahtijevaju skaliranje ili centriranje značajki.

Prema zadanim postavkama, funkcija rpart() koristi Gini nečistoća mjera za podjeljivanje note. Što je veći Gini koeficijent, to je više različitih instanci unutar čvora.

Korak 5) Napravite predviđanje

Možete predvidjeti svoj testni skup podataka. Da biste napravili predviđanje, možete koristiti funkciju predict(). Osnovna sintaksa predviđanja za R stablo odlučivanja je:

predict(fitted_model, df, type = 'class')
arguments:
- fitted_model: This is the object stored after model estimation. 
- df: Data frame used to make the prediction
- type: Type of prediction			
    - 'class': for classification			
    - 'prob': to compute the probability of each class			
    - 'vector': Predict the mean response at the node level	

Želite predvidjeti za koje putnike postoji veća vjerojatnost da će preživjeti nakon sudara iz testnog skupa. Znači, među tih 209 putnika ćete znati tko će preživjeti ili ne.

predict_unseen <-predict(fit, data_test, type = 'class')

Objašnjenje koda

  • predict(fit, data_test, type = 'class'): Predvidite klasu (0/1) skupa testova

Testiranje putnika koji nisu uspjeli i onih koji jesu.

table_mat <- table(data_test$survived, predict_unseen)
table_mat

Objašnjenje koda

  • table(data_test$survived, predict_unseen): Napravite tablicu za brojanje koliko je putnika klasificirano kao preživjeli i preminuli u usporedbi s ispravnom klasifikacijom stabla odlučivanja u R

Izlaz:

##      predict_unseen
##        No Yes
##   No  106  15
##   Yes  30  58

Model je točno predvidio 106 mrtvih putnika, ali je 15 preživjelih klasificirao kao mrtve. Analogno tome, model je pogrešno klasificirao 30 putnika kao preživjele dok se pokazalo da su oni mrtvi.

Korak 6) Mjerite učinak

Možete izračunati mjeru točnosti za zadatak klasifikacije s matrica zabune:

Korištenje električnih romobila ističe matrica zabune je bolji izbor za procjenu učinkovitosti klasifikacije. Opća ideja je brojati koliko su puta True instance klasificirane kao False.

Izmjerite izvedbu stabala odlučivanja u R

Svaki redak u matrici zabune predstavlja stvarni cilj, dok svaki stupac predstavlja predviđeni cilj. Prvi redak ove matrice uzima u obzir mrtve putnike (klasa lažnih): 106 je ispravno klasificirano kao mrtvi (Istinski negativan), dok je preostali pogrešno klasificiran kao preživjeli (Lažno pozitivno). U drugom redu su preživjeli, pozitivna klasa je 58 (Prava pozitiva), dok Istinski negativan bio 30.

Možete izračunati test točnosti iz matrice zabune:

Izmjerite izvedbu stabala odlučivanja u R

To je udio stvarnog pozitivnog i pravog negativnog u zbroju matrice. S R možete kodirati na sljedeći način:

accuracy_Test <- sum(diag(table_mat)) / sum(table_mat)

Objašnjenje koda

  • sum(diag(table_mat)): Zbroj dijagonale
  • sum(table_mat): Zbroj matrice.

Možete ispisati točnost testnog skupa:

print(paste('Accuracy for test', accuracy_Test))

Izlaz:

## [1] "Accuracy for test 0.784688995215311"

Imate rezultat od 78 posto za set testova. Istu vježbu možete ponoviti sa skupom podataka o vježbanju.

Korak 7) Podesite hiper-parametre

Stablo odlučivanja u R ima različite parametre koji kontroliraju aspekte prilagodbe. U biblioteci stabla odlučivanja rpart možete kontrolirati parametre pomoću funkcije rpart.control(). U sljedećem kodu uvodite parametre koje ćete podešavati. Možete se obratiti na vinjeta za ostale parametre.

rpart.control(minsplit = 20, minbucket = round(minsplit/3), maxdepth = 30)
Arguments:
-minsplit: Set the minimum number of observations in the node before the algorithm perform a split
-minbucket:  Set the minimum number of observations in the final note i.e. the leaf
-maxdepth: Set the maximum depth of any node of the final tree. The root node is treated a depth 0

Postupit ćemo na sljedeći način:

  • Konstruirajte funkciju za vraćanje točnosti
  • Podesite maksimalnu dubinu
  • Podesite minimalni broj uzoraka koji čvor mora imati prije nego što se može podijeliti
  • Podesite minimalni broj uzoraka koji listni čvor mora imati

Možete napisati funkciju za prikaz točnosti. Jednostavno omotate kod koji ste prije koristili:

  1. predvidi: predict_unseen <- predict(fit, data_test, type = 'class')
  2. Izradi tablicu: table_mat <- table(data_test$survived, predict_unseen)
  3. Izračunaj točnost: accuracy_Test <- sum(diag(table_mat))/sum(table_mat)
accuracy_tune <- function(fit) {
    predict_unseen <- predict(fit, data_test, type = 'class')
    table_mat <- table(data_test$survived, predict_unseen)
    accuracy_Test <- sum(diag(table_mat)) / sum(table_mat)
    accuracy_Test
}

Možete pokušati podesiti parametre i vidjeti možete li poboljšati model u odnosu na zadanu vrijednost. Podsjećamo, morate postići točnost veću od 0.78

control <- rpart.control(minsplit = 4,
    minbucket = round(5 / 3),
    maxdepth = 3,
    cp = 0)
tune_fit <- rpart(survived~., data = data_train, method = 'class', control = control)
accuracy_tune(tune_fit)

Izlaz:

## [1] 0.7990431

Sa sljedećim parametrom:

minsplit = 4
minbucket= round(5/3)
maxdepth = 3cp=0

Dobivate veću izvedbu od prethodnog modela. svaka čast!

rezime

Možemo sažeti funkcije za treniranje algoritma stabla odlučivanja R

Knjižnica Cilj funkcija Klasa Parametri Detaljnije
rpart Stablo klasifikacije vlakova u R rpart() razred formula, df, metoda
rpart Uvježbavanje regresijskog stabla rpart() anova formula, df, metoda
rpart Nacrtajte drveće rpart.plot() ugrađeni model
baza predvidjeti predvidjeti() razred opremljeni model, tip
baza predvidjeti predvidjeti() prob opremljeni model, tip
baza predvidjeti predvidjeti() vektor opremljeni model, tip
rpart Kontrolni parametri rpart.control() minsplit Postavite minimalni broj promatranja u čvoru prije nego što algoritam izvrši dijeljenje
minbucket Postavite minimalni broj opažanja u završnoj bilješci tj. listu
najveća dubina Postavite maksimalnu dubinu bilo kojeg čvora konačnog stabla. Korijenski čvor se tretira na dubini 0
rpart Model vlaka s kontrolnim parametrom rpart() formula, df, metoda, kontrola

Napomena: obučite model na podacima za obuku i testirajte izvedbu na nevidljivom skupu podataka, tj. testnom skupu.