Albero decisionale in R: albero di classificazione con esempio

Cosa sono gli alberi decisionali?

Alberi decisionali sono algoritmi di apprendimento automatico versatili che possono eseguire sia attività di classificazione che di regressione. Sono algoritmi molto potenti, in grado di adattare dataset complessi. Inoltre, gli alberi decisionali sono componenti fondamentali delle foreste casuali, che sono tra gli algoritmi di apprendimento automatico più potenti disponibili oggi.

Addestramento e visualizzazione di alberi decisionali in R

Per costruire il tuo primo albero decisionale nell'esempio R, procederemo come segue in questo tutorial sull'albero decisionale:

  • Passaggio 1: importa i dati
  • Passaggio 2: pulire il set di dati
  • Passaggio 3: creare un set di training/test
  • Passaggio 4: costruisci il modello
  • Passaggio 5: fare una previsione
  • Passaggio 6: misurare le prestazioni
  • Passaggio 7: ottimizzare gli iperparametri

Passaggio 1) Importa i dati

Se sei curioso riguardo al destino del Titanic, puoi guardare questo video su Youtube. Lo scopo di questo set di dati è prevedere quali persone avranno maggiori probabilità di sopravvivere dopo la collisione con l’iceberg. Il set di dati contiene 13 variabili e 1309 osservazioni. Il set di dati è ordinato dalla variabile X.

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

Produzione:

##   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)

Produzione:

##         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

Dall'output head e tail, puoi notare che i dati non vengono mescolati. Questo è un grosso problema! Quando dividerai i tuoi dati tra un set di treni e un set di prova, selezionerai esclusivamente il passeggero della classe 1 e 2 (nessun passeggero della classe 3 rientra nell'80% superiore delle osservazioni), il che significa che l'algoritmo non vedrà mai le caratteristiche del passeggero della classe 3. Questo errore porterà a una previsione inadeguata.

Per superare questo problema, è possibile utilizzare la funzione sample().

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

Codice R dell'albero decisionale Spiegazione

  • sample(1:nrow(titanic)): genera un elenco casuale di indici da 1 a 1309 (ovvero il numero massimo di righe).

Produzione:

## [1]  288  874 1078  633  887  992

Utilizzerai questo indice per mescolare il set di dati del Titanic.

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

Produzione:

##         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	

Passaggio 2) Pulisci il set di dati

La struttura dei dati mostra che alcune variabili hanno NA. La pulizia dei dati deve essere eseguita come segue

  • Rilascia le variabili home.dest,cabin, name, X e ticket
  • Creare variabili fattoriali per pclass e sopravvissute
  • Lascia perdere il 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)

Spiegazione del codice

  • select(-c(casa.dest, cabina, nome, X, biglietto)): elimina le variabili non necessarie
  • pclass = factor(pclass, Levels = c(1,2,3), label= c('Upper', 'Middle', 'Lower')): aggiunge un'etichetta alla variabile pclass. 1 diventa Superiore, 2 diventa MEDIO e 3 diventa inferiore
  • factor(sopravvissuto, livelli = c(0,1), etichette = c('No', 'Sì')): aggiunge l'etichetta alla variabile sopravvissuta. 1 diventa No e 2 diventa Sì
  • na.omit(): rimuove le osservazioni NA

Produzione:

## 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...		

Passaggio 3) Creare un set di training/test

Prima di addestrare il modello, devi eseguire due passaggi:

  • Creare un treno e un set di test: addestrare il modello sul set di treni e testare la previsione sul set di test (ovvero dati invisibili)
  • Installa rpart.plot dalla console

La pratica comune è quella di dividere i dati 80/20, l'80% dei dati serve per addestrare il modello e il 20% per fare previsioni. È necessario creare due frame di dati separati. Non vuoi toccare il set di prova finché non finisci di costruire il tuo modello. Puoi creare una funzione denominata create_train_test() che accetta tre argomenti.

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, ])
    }
}

Spiegazione del codice

  • function(data, size=0.8, train = TRUE): aggiunge gli argomenti nella funzione
  • n_row = nrow(data): conta il numero di righe nel set di dati
  • total_row = size*n_row: restituisce l'ennesima riga per costruire il treno
  • train_sample <- 1:total_row: seleziona la prima riga fino all'ennesima riga
  • if (train ==TRUE){ } else { }: se la condizione è vera, restituisce il train set, altrimenti il ​​test set.

Puoi testare la tua funzione e controllare la dimensione.

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)

Produzione:

## [1] 836   8
dim(data_test)

Produzione:

## [1] 209   8

Il set di dati del treno ha 1046 righe mentre il set di dati di test ha 262 righe.

Si utilizza la funzione prop.table() combinata con table() per verificare se il processo di randomizzazione è corretto.

prop.table(table(data_train$survived))

Produzione:

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

Produzione:

## 
##        No       Yes 
## 0.5789474 0.4210526

In entrambi i dati, il numero di sopravvissuti è lo stesso, circa il 40%.

Installa rpart.plot

rpart.plot non è disponibile dalle librerie conda. Puoi installarlo dalla console:

install.packages("rpart.plot")

Passaggio 4) Costruisci il modello

Sei pronto per costruire il modello. La sintassi per la funzione dell'albero decisionale Rpart è:

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	

Usi il metodo della classe perché prevedi una classe.

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

Spiegazione del codice

  • rpart(): funzione per adattarsi al modello. Gli argomenti sono:
    • sopravvissuto ~.: Formula degli alberi decisionali
    • dati = treno_dati: set di dati
    • metodo = 'class': adatta un modello binario
  • rpart.plot(fit, extra= 106): traccia l'albero. Le funzionalità extra sono impostate su 101 per visualizzare la probabilità della 2a classe (utile per risposte binarie). Puoi fare riferimento a vignette per ulteriori informazioni sulle altre scelte.

Produzione:

Costruisci un modello di alberi decisionali in R

Inizi dal nodo radice (profondità 0 su 3, la parte superiore del grafico):

  1. In alto c’è la probabilità complessiva di sopravvivenza. Mostra la percentuale di passeggeri sopravvissuti allo schianto. Il 41% dei passeggeri è sopravvissuto.
  2. Questo nodo chiede se il sesso del passeggero è maschio. Se sì, scendi al nodo figlio sinistro della radice (profondità 2). Il 63% sono maschi con una probabilità di sopravvivenza del 21%.
  3. Nel secondo nodo chiedi se il passeggero maschio ha più di 3.5 anni. Se sì, la possibilità di sopravvivenza è del 19%.
  4. Continui così per capire quali caratteristiche influiscono sulla probabilità di sopravvivenza.

Tieni presente che una delle tante qualità degli alberi decisionali è che richiedono pochissima preparazione dei dati. In particolare, non richiedono il ridimensionamento o la centratura delle funzionalità.

Per impostazione predefinita, la funzione rpart() utilizza il file Gini misura di impurità per dividere la banconota. Maggiore è il coefficiente Gini, maggiore è il numero di istanze diverse all'interno del nodo.

Passaggio 5) Fai una previsione

Puoi prevedere il set di dati di test. Per fare una previsione, puoi utilizzare la funzione predit(). La sintassi di base di predit per l'albero decisionale R è:

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	

Vuoi prevedere quali passeggeri hanno maggiori probabilità di sopravvivere dopo la collisione dal set di prova. Ciò significa che saprai tra quei 209 passeggeri quale sopravviverà o no.

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

Spiegazione del codice

  • predire(fit, data_test, type = 'class'): prevedere la classe (0/1) del set di test

Testare il passeggero che non ce l'ha fatta e quelli che ce l'hanno fatta.

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

Spiegazione del codice

  • table(data_test$survived, suggest_unseen): crea una tabella per contare quanti passeggeri sono classificati come sopravvissuti e sono deceduti rispetto alla corretta classificazione dell'albero decisionale in R

Produzione:

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

Il modello prevedeva correttamente la morte di 106 passeggeri, ma classificava come morti 15 sopravvissuti. Per analogia, il modello ha classificato erroneamente 30 passeggeri come sopravvissuti mentre si sono rivelati morti.

Passaggio 6) Misurare le prestazioni

Puoi calcolare una misura di precisione per l'attività di classificazione con matrice di confusione:

Le matrice di confusione è una scelta migliore per valutare le prestazioni della classificazione. L'idea generale è contare il numero di volte in cui le istanze Vere vengono classificate come False.

Misurare le prestazioni degli alberi decisionali in R

Ogni riga in una matrice di confusione rappresenta un obiettivo effettivo, mentre ogni colonna rappresenta un obiettivo previsto. La prima riga di questa matrice considera i passeggeri morti (la classe False): 106 sono stati correttamente classificati come morti (Vero negativo), mentre il restante è stato erroneamente classificato come sopravvissuto (Falso positivo). La seconda riga considera i sopravvissuti, la classe positiva era 58 (Vero positivo), Mentre la Vero negativo era 30.

Puoi calcolare il prova di precisione dalla matrice di confusione:

Misurare le prestazioni degli alberi decisionali in R

È la proporzione tra vero positivo e vero negativo sulla somma della matrice. Con R, puoi codificare come segue:

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

Spiegazione del codice

  • sum(diag(table_mat)): somma della diagonale
  • sum(table_mat): somma della matrice.

È possibile stampare la precisione del set di prova:

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

Produzione:

## [1] "Accuracy for test 0.784688995215311"

Hai un punteggio del 78% per il set di test. Puoi replicare lo stesso esercizio con il set di dati di addestramento.

Passaggio 7) Ottimizza gli iperparametri

L'albero decisionale in R ha vari parametri che controllano gli aspetti dell'adattamento. Nella libreria dell'albero decisionale rpart, puoi controllare i parametri usando la funzione rpart.control(). Nel seguente codice, introduci i parametri che ottimizzerai. Puoi fare riferimento a vignette per altri parametri.

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

Procederemo come segue:

  • Costruisci una funzione per restituire la precisione
  • Regola la profondità massima
  • Regola il numero minimo di campioni che un nodo deve avere prima di potersi dividere
  • Regola il numero minimo di campioni che deve avere un nodo foglia

È possibile scrivere una funzione per visualizzare la precisione. Avvolgi semplicemente il codice che hai usato prima:

  1. predire: predire_unseen <- predire(fit, data_test, type = 'class')
  2. Produci tabella: table_mat <- table(data_test$survived, suggest_unseen)
  3. Precisione del calcolo: accuratezza_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
}

Puoi provare a ottimizzare i parametri e vedere se riesci a migliorare il modello rispetto al valore predefinito. Come promemoria, è necessario ottenere una precisione superiore a 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)

Produzione:

## [1] 0.7990431

Con il seguente parametro:

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

Ottieni prestazioni più elevate rispetto al modello precedente. Congratulazioni!

Sommario

Possiamo riassumere le funzioni in cui addestrare un algoritmo dell'albero decisionale R

Biblioteca Obiettivo Funzione Classe parametri Dettagli
parte Albero di classificazione dei treni in R parte() classe formula, df, metodo
parte Albero di regressione del treno parte() anova formula, df, metodo
parte Traccia gli alberi rpart.plot() modello montato
base predire prevedere () classe modello montato, tipo
base predire prevedere () probabilmente modello montato, tipo
base predire prevedere () vettore modello montato, tipo
parte Parametri di controllo rpart.control() minsplit Imposta il numero minimo di osservazioni nel nodo prima che l'algoritmo esegua una suddivisione
minbucket Imposta il numero minimo di osservazioni nella nota finale, ovvero la foglia
profondità massima Imposta la profondità massima di qualsiasi nodo dell'albero finale. Il nodo radice viene trattato con profondità 0
parte Modello di treno con parametri di controllo parte() formula, df, metodo, controllo

Nota: addestrare il modello su dati di addestramento e testare le prestazioni su un set di dati invisibile, ovvero un set di test.