Sunteți pe pagina 1din 30

1

Arbori de decizie

Problema 1

Se instaleaza pachetul party:

>install.packages("party")
>library(party)

>set.seed(123)

> ind<-sample(2,nrow(iris),replace=TRUE,prob=c(0.7,0.3))

Se extrag 2 esantioane din numarul liniilor setului de date (aici iris), 70% sunt in
primul esantion si 30% in al doilea esantion.

prob=c(0.7,0.3)=un vector de ponderi probabilistice

Extragerea poate fi cu revenire (replace=TRUE) sau fara revenire (replace=FALSE).


La extragerea fara revenire, o observatie extrasa din populatie este eliminata. La
extragerea cu revenire, observatia extrasa din populatie este pusa inapoi.

In cazul nostru, indivizii trebuie sa aiba aceeasi sansa de a fi extrasi, deci


extragerea trebuie sa fie cu revenire.

> ind

Se afiseaza apartenenta la cele 2 esantioane.

>traindata<-iris[ind==1,]

Se extrage setul de date de antrenare. “==” este operatorul logic “exact egal cu”.

>traindata

> testdata<-iris[ind==2,]
2

> testdata

>myformula<-Species~Sepal.Length+Sepal.Width+Petal.Length+Petal.Width

~ inseamna dependenta liniara

Se construieste un arbore de decizie cu functia “ctree”.

> iris_ctree<-ctree(myformula, data=traindata)

>print( iris_ctree)

> table(predict(iris_ctree),traindata$Species)

Se afiseaza matricea de confuzie pentru setul de antrenare:

Valori reale

setosa versicolor virginica

setosa 35 0 0

Valori previzionate versicolor 0 36 3

virginica 0 0 32

O comanda echivalenta este:

> table(pred=predict(iris_ctree),true=traindata$Species)

true

pred setosa versicolor virginica

setosa 35 0 0

versicolor 0 36 3
3

virginica 0 0 32

Pe diagonala principala este reprezentat nr. observatiilor corect previzionate.

Restul sunt erori.

>plot(iris_ctree) Este afisat arborele de decizie.

1
Petal.Length
p < 0.001

 1.9  1.9
3
Petal.Width
p < 0.001

 1.7  1.7
4
Petal.Length
p < 0.001

 4.6  4.6

Node 2 (n = 35) Node 5 (n = 30) Node 6 (n = 9) Node 7 (n = 32)


1 1 1 1
0.8 0.8 0.8 0.8
0.6 0.6 0.6 0.6
0.4 0.4 0.4 0.4
0.2 0.2 0.2 0.2
0 0 0 0
setosa setosa setosa setosa
4

Nodul 2 contine 35 observatii, nodul 5 contine 30 observatii, nodul 6 – 9


observatii si nodul 7 – 32 observatii.

Pe axa Oy sunt reprezentate sub forma de barplot probabilitatile ca o observatie


sa apartina uneia din cele 3 clase.

>print(iris_ctree) Printeaza arborele de decizie si regulile lui.

> plot(iris_ctree, type="simple")

Alt mod de reprezentare a arborelui decizional:


5

1
Petal.Length
p < 0.001

 1.9  1.9

2 3
n = 35 Petal.Width
y = (1, 0, 0) p < 0.001

 1.7  1.7

4 7
Petal.Length n = 32
p < 0.001 y = (0, 0, 1)

 4.6  4.6

5 6
n = 30 n=9
y = (0, 1, 0) y = (0, 0.667, 0.333)

Interpretare: Nodul 2 contine 35 observatii, probabilitatea de a apartine primei


specii este 1: y=(1,0,0).

Nodul 6 contine 9 observatii, probabilitatea de a apartine primei specii este 0,


speciei a 2-a este 0.667 si speciei a 3-a este 0.333.
6

Vectorul y contine probabilitatea de apartenenta la o clasa.

In continuare previzionam clasa datelor de testare. Arborele construit trebuie


testat cu datele de testare:

>testpredictie<-predict(iris_ctree, newdata=testdata)

>tab=table(testpredictie, testdata$Species)

Se calculeaza matricea de confuzie pentru setul de testare

> tab

Date reale

testpredictie setosa versicolor virginica

previzionate setosa 15 0 0

versicolor 0 13 2

virginica 0 1 13

> library(e1071)

>classAgreement(tab)

$diag

[1] 0.9318182

$kappa

[1] 0.8977537
7

$rand

[1] 0.9175476

$crand

[1] 0.8099668

Rata de precizie a algoritmului este 93,18% (diag).

Coeficientul lui Cohen este 0.8977 (kappa) , rezulta un puternic acord intre
etichetele reale si cele previzionate.

Problema 2

>install.packages("ISLR")

> library(ISLR)

Pachetul “rpart” foloseste arbori de decizie de tip CART=classification and


regression trees.

Functia rpart() foloseste masura de impuritate Gini pentru a diviza nodul.


Cu cat coeficientul este mai mare cu atat observatiile sunt mai diferite in
nodul respectiv.

>library(rpart)

>install.packages("pROC")

> library(pROC)
8

> data(Carseats)

>range(Carseats$Sales)

>hist(Carseats$Sales)

Se transformă variabila numerică “Sales” în variabila binară “High” cu valorile


“Yes”, dacă “Sales>=8”, “No”, în caz contrar.

> High<-ifelse(Carseats$Sales>=8, "Yes", "No")

Se elimina coloana numerica Sales:

> Carseats$Sales <- NULL

La setul de date se adauga variabila binara “High”.

>Carseats=data.frame(Carseats, High)

Se extrag doua esantioane aleatoare, unul pentru setul de antrenare si unul


pentru setul de testare.Setul de antrenare este egal cu setul de testare cu 50% din
date.

>set.seed(123)

>antrenare<-sample(1:nrow(Carseats), nrow(Carseats)/2)

>setantrenare<-Carseats[antrenare,]

>setantrenare

>settestare<-Carseats[-antrenare,]

>settestare

>arbore<-rpart(setantrenare$High~. , data=setantrenare, method="class")


9

Relatia de dependenta liniara este intre eticheta (High) cu valorile Yes (Vanzari
mari) si No (Vanzari mici) si restul atributelor setului de date.

>plot(arbore)

>text(arbore, pretty=0)

Fiecare nod terminal al arborelui are reprezentata clasa dominant.

O vizualizare mai sugestiva este realizata cu functia rpart.plot() din biblioteca


“rpart.plot”:

>install.packages("rpart.plot")

>library(rpart.plot)

>rpart.plot(arbore, extra= 106)


10

Indicatorii “No”, “Yes” de pe nodurile arborele de mai jos reprezinta clasa


dominanta.

Pentru o documentatie asupra parametrilor functiei rpart.plot vezi

https://www.rdocumentation.org/packages/rpart.plot/versions/3.0.9/topics/rpar
t.plot

extra=106: variabila de raspuns este binara

extra=104 : variabila de raspuns are mai multe valori

La radacina arborelui, probabilitatea ca vanzarile sa fie mari este 0.43.

ShelveLoc= o variabila factor cu 3 valori (Bad, Good, Medium), indicand calitatea


locului de depozitare a produselor.
11

Daca ShelveLoc este Bad, Medium, atunci probabilitatea ca vanzarile sa fie mari
este 0.35 (81% din date).

>print(arbore)

In nodul 1, sunt 200 observatii, dintre care 86 sunt etichetate cu clasa “Yes” ( high
sales). Vectorul de probabilitate (0.57, 0.43) arata ca 86 observatii sunt in
categoria Yes cu probabilitatea 0.43. Clasa dominanta in nodul 1 este “No”
(vanzari mici), avand probabilitatea cea mai mare, 0.57.

Split reprezinta atributul dupa care se realizeaza divizarea arborelui in nodul


respectiv.

>table(setantrenare$High)

Probabilitatile reprezentate pe arbore se refera la a doua clasa, “Yes” .


(probabilitatea ca vanzarile sa fie mari).

Realizam predictia observatiilor din setul de testare:

>predictie<-predict(arbore, settestare, type="class")


12

>confuzie<-table(settestare$High, predictie)

>confuzie

In matricea de confuzie am reprezentat pe linie datela reale, iar pe coloane


predictiile.

Din 97+25=122 regiuni cu vanzari scazute, 97 regiuni au fost corect previzionate si


25 regiuni au fost incorect previzionate.

Din cele 22+56=78 regiunie cu vanzari mari, 56 regiuni au fost corect previzionate
si 22 regiuni au fost incorect previzionate.

Eroarea de clasificare:

>mean(predictie!=settestare$High)

23.5 % din observatiile setului de testare au fost eronat clasificate.

>predictie1<-predict(arbore, settestare, type="prob")

>predictie1

Curba ROC:

>library(pROC)
13

>curbaroc<-roc(settestare$High, predictie1[,"Yes"])

>plot(curbaroc)

>auc(curbaroc)

Clasificatorul poate distinge in proportie de 81% intre vanzari mici si mari.

Curatarea arborelui=Pruning the tree (daca este cazul, daca arborele este stufos)

S-a determinat eroarea de clasificare pe setul de testare de 23.5%.


14

Un arbore mai simplu reduce fenomenul de “overfitting”. Acest fenomen apare


când arborele de decizie construit pe baza setului de antrenament se potriveşte
prea accentuat cu datele de antrenare, nefiind capabil să generalizeze pe date
noi. În pachetul rpart, acest lucru este controlat de parametrul de complexitate
(CP), care impune o penalizare pentru prea multe divizări ale arborelui. Valoarea
implicită a lui CP este 0.01. Cu cât CP este mai mare, cu atât arborele este mai
mic.

O valoare prea mică a lui CP conduce la overfitting; o valoare prea mare a lui CP
va duce la un arbore prea mic. Ambele cazuri scad performanța predictivă a
modelului.

O valoare optimă a lui CP poate fi estimată prin testarea diferitelor valori ale CP,
utilizând abordări de validare încrucișată pentru a determina acuratețea de
predicție corespunzătoare a modelului. Cel mai bun CP este apoi definit ca fiind
cel care va maximiza acuratețea validării încrucişate.

>plotcp(arbore)
15

Un parametru de complexitate optim corespunde erorii minime de validare


incrucisata.

>mincp<-arbore$cptable[which.min(arbore$cptable[,"xerror"]),"CP"]

>mincp

>printcp(arbore)

Eroarea relativa de validare incrucisata este minima (xerror=0.77907) pentru o


valoare a parametrului de complexitate de 0.040698, iar arborele curatat are
aproximativ 2 noduri terminale (poate sa aiba si 3 noduri terminale).
16

Nsplit reprezinta numarul de noduri terminale (cu aproximatie) ale arborelui


curatat.

Construim arborele curatat:

>arbore1<-prune(arbore,
cp=arbore$cptable[which.min(arbore$cptable[,"xerror"]),"CP"])

>rpart.plot(arbore1, extra= 106)

Arborele curatat are 3 noduri terminale.


>printcp(arbore1)
17

Se confirma faptul ca cp_minim este 0.040698, corespunzator unui arbore curatat


cu aproximativ 2 noduri terminale iar eroarea relativa este minima 0.61628,
respectiv eroarea de validare incrucisata este minima, 0.77907.
Predictia pe arborele curatat

>predictie2<-predict(arbore1, settestare, type="class")


>predictie2
Matricea de confuzie:
>confuzie<-table(settestare$High, predictie2)
>confuzie

Eroarea de clasificare a arborelui curatat pe setul de testare:


>mean(predictie2!=settestare$High)

Eroarea de clasificare a crescut de la 23.5% la 28.5%.


>predictie3<-predict(arbore1, settestare, type="prob")

>predictie3
18

Curba ROC:

>library(pROC)

>curbaroc1<-roc(settestare$High, predictie3[,"Yes"])

>plot(curbaroc1)

>auc(curbaroc1)

Desi arborele curatat are doar 3 noduri terminale, eroarea de clasificare a crescut
si capacitatea clasificatorului de separare a claselor a scazut la 76.16%.

Problema 3 Arbori de regresie cu pachetul tree. Curatarea arborilor de regresie.

>library(tree)

>library(ISLR)
19

>data(Hitters)

Folosim setul de date Hitters din biblioteca ISLR pentru a previziona salariul unui
jucator de baseball in functie de vechimea in liga (Years) si de numarul de meciuri
castigate (Hits).

Se omit datele lipsa:

>Hitters<- na.omit(Hitters)

>hist(Hitters$Salary)

Se aplica logaritmul asupra Salariului pentru a-l face normal distribuit.

>Hitters$Salary <- log(Hitters$Salary)

>hist(Hitters$Salary)
20

>install.packages("caret")

>library(caret)

>split <- createDataPartition(y=Hitters$Salary, p=0.5, list=FALSE)

>split

Biblioteca “caret” conţine functiacreateDataPartition() pentru a împărţi setul


de date în set de antrenare şi set de testare. Parametrul p are valoarea cuprinsă
între 0 şi 1 şi arată proporţia între setul de antrenare şi setul de testare. Aici
p=0.5, deci setul de antrenare conţine 50% din date, iar cel de testare conţine
50% din date. Parametrul “list=TRUE” returnează o lista pe linie “list=FALSE”
returnează o lista pe coloana.

Setul de antrenare:
21

>train <- Hitters[split,]

>train

>test <- Hitters[-split,]

>test

>install.packages("tree")

>library(tree)

>arbore <- tree(Salary~., train)

>plot(arbore)

>text(arbore, pretty=0)
22

Fiecare nod terminal al arborelui are afisat salariul mediu logaritmat salariul
mediu al jucatorilor de baseball din acel nod.

Validarea incrucisata (cross validation) este o tehnica statistica aplicata pentru


evaluarea generalizarii rezultatelor unei analize statistice pe un nou set de date.

Urmează etapa de curăţare a arborelui. Prin validarea încrucişată (cross


validation), se validează modelul, pentru a verifica acurateţea datelor. Funcţia
cv.tree, bazată pe generarea de numere aleatoare, determină în ce loc din arbore
se opreşte curăţarea.

>cv.trees <- cv.tree(arbore)

Variabila cv.tree are printre atribute “size”, mărimea arborelui(=numărul de


noduri terminale) şi “dev” devianţa, aici exprimată prin eroare.

>cv.trees$size

>cv.trees$dev

Cea mai mică eroare, 35.14 corespunde unui arbore cu 5 noduri terminale.

Reprezentăm grafic devianţa (eroarea) în funcţie de mărimea arborelui:

> plot(cv.trees$size, cv.trees$dev, type="b")


23

Din grafic se observă că minimul erorii se atinge pentru o mărime a arborelui


egală cu 5 noduri terminale. Se construieşte arborele curăţat:

>arbore1 <- prune.tree(arbore, best=5)

Best este un parametru care se egaleaza cu numarul de noduri terminale ale


arborelui curatat.

>plot(arbore1)

>text(arbore1, pretty=0)
24

Se foloseste arborele curatat pentru a face predictii pe setul de testare.

>pred<-predict(arbore1, test)

>pred

Se afiseaza predictia salariului fiecarui jucator de baseball.

>plot(pred, test$Salary)

Eroarea de predictie este calculata ca media patratelor diferentelor dintre salariul


previzionat si salariul real.

>mean((pred - test$Salary)^2)

Problema 4 Arbori de clasificare- curatarea arborelui

>library(rpart.plot)
25

>library(ISLR)

>attach(Carseats)

>Carseats$Sales <- ifelse(Sales <= median(Sales), 'Low', 'High')

>Carseats$Sales <- factor(Carseats$Sales)

>Carseats<-na.omit(Carseats)

>set.seed(111)

>library(caret)

Setul de antrenare=60% din date, setul de testare=40% din date

>split <- createDataPartition(y=Carseats$Sales, p=0.6, list=FALSE)

>split

>train <- Carseats[split,]

>train

>test <- Carseats[-split,]

>test

>arbore <- tree(Sales ~., data=train)

>plot(arbore)

>text(arbore, pretty=0)
26

Predictia vanzarilor pe setul de testare:

>pred <- predict(arbore, test, type='class')

>pred

>mean(pred==test$Sales)

72.32% din datele de testare sunt corect etichetate.

>confuzie<-table(pred,test$Sales)

>confuzie
27

Imbunatatirea acuratetei predictiei folosind validarea incrucisata.

>set.seed(12)

>cv.tree1 <- cv.tree(arbore, FUN=prune.misclass)

Variabila cv.tree are printre atribute “size”, mărimea arborelui(=numărul de


noduri terminale) şi “dev” devianţa, aici exprimată prin nr. de observatii incorect
etichetate.

>cv.tree1$size

>cv.tree1$dev

Eroarea cea mai mica, 52, corespunde unui arbore cu 14 noduri terminale (un
arbore mai simplu).

Reprezentăm grafic eroarea în funcţie de mărimea arborelui:

>plot(cv.tree1$size, cv.tree1$dev, type="b")


28

>arbore1 <- prune.misclass(arbore, best=14)

>plot(arbore1)

>text(arbore1, pretty=0)
29

Predictia vanzarilor pe setul de testare si arborele curatat:

>prune.predictie <- predict(arbore1, test, type='class')

>prune.predictie

>mean(prune.predictie==test$Sales)

75.47% din datele de testare sunt corect etichetate. Acuratetea predictiei pe setul
de testare a crescut.

Se afiseaza si matricea de confuzie pentru arborele curatat si setul de testare.

>confuzie1<-table(prune.predictie,test$Sales)

>confuzie1
30

S-ar putea să vă placă și