Albero decisionale in R: albero di classificazione con esempio

⚡ Riepilogo intelligente

Gli alberi decisionali in R dividono i dati in rami utilizzando semplici regole sì/no fino a quando ogni foglia non contiene una singola classe dominante. Questa guida illustra come costruire, visualizzare, valutare e ottimizzare un albero di classificazione rpart sul dataset dei sopravvissuti del Titanic.

  • 🌳 Definizione di base: Un albero partiziona ricorsivamente lo spazio dei predittori, scegliendo a ogni nodo la divisione che riduce al minimo l'impurità di classe.
  • 🔄 Preparazione dei dati: Mescola il file Titanic ordinato con sample(), elimina le colonne degli identificatori, converti i fattori e poi rimuovi le righe con valori NA.
  • Sintassi del modello: Chiama rpart(survived~., data = data_train, method = 'class') e visualizza il risultato con rpart.plot(fit, extra = 106).
  • ⚙️ tuning: La funzione rpart.control() espone i parametri minsplit, minbucket, maxdepth e cp, portando la precisione al 79.90%.
  • 📊 Valutazione: Crea una matrice di confusione con table(), quindi dividi la diagonale per il totale per ottenere un'accuratezza del test del 78.47%.

Albero decisionale in R

Cosa sono gli alberi decisionali?

Alberi decisionali Gli alberi decisionali sono un algoritmo di apprendimento automatico versatile, in grado di eseguire sia attività di classificazione che di regressione. Si tratta di algoritmi molto potenti, capaci di adattarsi a set di dati complessi. Inoltre, gli alberi decisionali sono componenti fondamentali delle foreste casuali, che sono tra gli algoritmi di apprendimento automatico più potenti attualmente disponibili.

Prima di implementarlo tramite codice, è utile capire come un albero decide dove effettuare la divisione.

Come funziona un albero decisionale?

Un albero decisionale trasforma un set di dati in un diagramma di flusso di domande sì o no costruito da tre tipi di nodi: il radice contiene ogni osservazione di addestramento, un nodo interno pone una domanda su un predittore e divide i dati in due, e un foglia interrompe la suddivisione e restituisce la classe maggioritaria.

La crescita segue una procedura avida chiamata partizionamento binario ricorsivo:

  1. Valutare ogni suddivisione dei candidati. Per ogni predittore e punto di taglio, misurare il grado di impurità dei due gruppi risultanti.
  2. Tieni il migliore. La suddivisione che riduce maggiormente le impurità diventa la domanda che ci si pone in quel nodo.
  3. Ripeti per ogni bambino finché una regola di controllo non lo arresta: minsplit, minbucket, maxdepth o cp.
  4. Fesso. cp quindi pota i rami che non si autofinanziano, impedendo così all'albero di memorizzare il set di addestramento.

Poiché ogni domanda confronta una variabile con una soglia, l'algoritmo non necessita mai di scalatura o codifica fittizia.

Indice di Gini contro entropia negli alberi decisionali

Questa impurità può essere misurata in due modi e rpart ti permette di scegliere.

Criteri Indice di Gini Entropia (guadagno di informazione)
Formula 1 – somma dei quadrati delle proporzioni di classe -somma di p volte log2(p)
Gamma (due classi) 0 a 0.5 0 a 1
Calcolo Più veloce, senza logaritmo Più lento, utilizza i logaritmi
impostazione rpart Predefinito parametri = elenco(split = “informazioni”)
fit_entropy <- rpart(survived~., data = data_train, method = 'class',
    parms = list(split = "information"))

In pratica, entrambi i criteri scelgono la stessa suddivisione nella maggior parte dei casi, quindi l'indice di Gini predefinito è una scelta sicura.

Vantaggi e svantaggi degli alberi decisionali

I compromessi indicano quando un singolo albero è sufficiente e quando è opportuno passare a un insieme di alberi.

Vantaggi

  • Completamente interpretabile: Il modello adattato è un diagramma che qualsiasi soggetto interessato può leggere.
  • Pre-elaborazione minima: Non è necessario alcun ridimensionamento o normalizzazione e i fattori funzionano in modo nativo.
  • Gestisce entrambi i compiti: Il metodo = 'class' si adatta a un classificatore e il metodo = 'anova' si adatta a un albero di regressione.
  • Facile da addestrare: I grandi insiemi di dati possono essere elaborati in pochi secondi, quindi gli alberi rappresentano un utile punto di partenza.

Svantaggi

  • Variabilità elevata: Una piccola modifica ai dati di addestramento può produrre un albero completamente diverso.
  • Propenso all'overfitting: Un albero senza vincoli cresce finché ogni foglia non è pura, a meno che cp e maxdepth non lo limitino.
  • Solo divisioni parallele agli assi: I confini diagonali richiedono numerosi tagli a forma di scala.

Il rimedio per le prime due debolezze è quello di fare una media di molti alberi, che è ciò che un foresta casuale fa.

Come addestrare e visualizzare un albero decisionale in R

Per costruire il tuo primo albero decisionale in R, dovrai seguire sette passaggi:

  • 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

Diverse variabili contengono valori NA. La pulizia si articola in tre fasi:

  • Elimina 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)

Code Spiegazione

  • select(-c(casa.dest, cabina, nome, X, biglietto)): elimina le variabili non necessarie
  • pclass = factor(pclass, levels = c(1,2,3), labels= c('Superiore', 'Medio', 'Inferiore')): Aggiunge un'etichetta alla variabile pclass. 1 diventa Superiore, 2 diventa Medio e 3 diventa Inferiore
  • factor(survived, levels = c(0,1), labels = c('No', 'Yes')): Aggiunge etichette alla variabile survived. 0 diventa No e 1 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, ])
    }
}

Code Spiegazione

  • 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 di addestramento ha 836 righe e 8 colonne, mentre il set di dati di test ha 209 righe e le stesse 8 colonne.

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

Code Spiegazione

  • 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. L'argomento extra è impostato su 106, che visualizza la probabilità della seconda classe più la percentuale di osservazioni in ciascun nodo. Puoi fare riferimento a vignette per ulteriori informazioni sulle altre scelte.

Produzione:

 Costruisci un modello di alberi decisionali in R

Si parte dal nodo radice, in cima al grafico e alla profondità 0 di 3:

  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 è maschile. In caso affermativo, si passa al figlio sinistro della radice (profondità 1). 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 Gini Misura dell'impurità per scegliere ogni suddivisione. Più alto è il valore di Gini, più le classi all'interno di quel nodo sono mescolate, quindi l'algoritmo sceglie sempre la suddivisione che lo riduce maggiormente.

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	

Ora devi prevedere, per ciascuno dei 209 passeggeri del set di test, se il modello si aspetta che sopravvivano alla collisione.

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

Code Spiegazione

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

Ora confrontate le classi previste con i risultati reali.

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

Code Spiegazione

  • tabella(data_test$survived, predict_unseen): Crea una tabella di contingenza delle classi previste rispetto al risultato reale

Produzione:

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

Le righe rappresentano i valori effettivi, le colonne le previsioni. Il modello ha identificato correttamente 106 non sopravvissuti e 58 sopravvissuti, ma ha etichettato 15 non sopravvissuti come sopravvissuti e 30 sopravvissuti come deceduti.

Passaggio 6) Misurare le prestazioni

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

Migliori 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 deceduti (la classe negativa): 106 sono stati correttamente classificati come deceduti (Vero negativo), mentre 15 sono stati classificati erroneamente come sopravvissuti (Falso positivo). La seconda riga considera i sopravvissuti: 58 sono stati identificati correttamente (Vero positivo), mentre 30 sono stati mancati (Falso negativo).

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)

Code Spiegazione

  • 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"

L'accuratezza sul set di test è 0.7847, ovvero il 78.47%. Ripeti l'esercizio sul set di training per vedere quanto il modello si adatta eccessivamente ai dati.

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 a terminal node, i.e. the leaf
-maxdepth: Set the maximum depth of any node of the final tree. The root node is treated as 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
}

Ora regola i parametri e verifica se riesci a migliorare il modello predefinito. Ricorda che devi superare un'accuratezza di 0.7847.

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 = 3
cp = 0

L'accuratezza aumenta da 0.7847 a 0.7990, quindi l'albero ottimizzato supera la configurazione predefinita di circa 1.4 punti percentuali.

Alberi decisionali in R: Guida rapida alle funzioni

La tabella seguente elenca ogni funzione utilizzata nei sette passaggi precedenti, insieme al pacchetto che la fornisce e ai parametri che si aspetta in R.

Biblioteca Obiettivo Funzione Classe Scheda Sintetica 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 in un nodo terminale, ovvero la foglia
profondità massima Imposta la profondità massima di ogni nodo dell'albero finale. Il nodo radice viene considerato di 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.

DOMANDE FREQUENTI

Entrambi sono adatti ad alberi di classificazione e regressione. rpart() implementa CART con potatura a convalida incrociata integrata tramite cp e si abbina a rpart.plot per diagrammi chiari, il che lo rende la scelta più comune.

cp definisce il miglioramento minimo che una suddivisione deve fornire per essere mantenuta. Valori più elevati comportano una potatura più aggressiva e producono alberi più piccoli. Utilizzare printcp() e plotcp() per trovare il valore con l'errore di convalida incrociata più basso.

Sì. La funzione rpart() utilizza suddivisioni surrogate per indirizzare le osservazioni con predittori mancanti verso il ramo più simile. Questo tutorial utilizza invece na.omit(), semplicemente per mantenere semplice il set di dati di esempio.

Gli alberi decisionali sono alla base dell'intelligenza artificiale spiegabile in settori come il credito, le assicurazioni e la sanità, dove un ente regolatore può richiedere la spiegazione precisa del ragionamento alla base di una decisione. Costituiscono inoltre la base per l'apprendimento nei modelli di gradient boosting e random forest.

Sì. Gli assistenti IA possono tradurre le regole di suddivisione in linguaggio semplice, suggerire valori cp da testare e segnalare l'overfitting nell'output di printcp(). Verifica ogni suggerimento confrontandolo con i tuoi risultati di convalida incrociata prima di metterlo in pratica.

Riassumi questo post con: