Sprawozdanie
Sztuczna Inteligencja
Laboratorium nr 7 i 8
Metody bagging i Random Forests oraz ich porównanie z algorytmem Quinlana
Opracowała: Anna Grzeszyk
Grupa: I0X4S1
Data: 10-01-2012
Prowadzący: dr Jarosław Olejniczak
Na laboratorium otrzymaliśmy następujące zadanie
(źródło - http://akson.sgh.waw.pl/~jolej/SI_LAB7.html):
Proszę przypomnieć sobie tekst zadania 2 za lab 5 (Agencja nieruchomości).
Proszę wygenerować dane losowych preferencji dla 500 przypadków mieszkań dla cech: Duże (D), Tanie (T), Uzbrojone (U), Blisko Centrum (BC). Każda z tych cech może przybrać wartości wag od 1 do 8. Należy wykorzystać funkcję LOS().
Następnie proszę zbudować w Excelu własna funkcje klasyfikującą mieszkania do dwóch grup bardziej i mniej atrakcyjne wykorzystując funkcję JEŻELI. Można wykorzystać funkcję z LAB 6.
Proszę podzielić utworzony zbiór na walidacyjny i uczący
Wkorzystując pakiet ipred proszę utworzyć metodą bagging regułę decyzyjną podziału na klasy.
Przetestować wyniki działania reguły decyzyjnej na zbiorze walidacyjnym.
Sformułować wnioski, porównać skuteczność metody bagging dla omawianego przykładu z algorytmem Quinlana oraz sztuczną siecią neuronową.
Całość proszę ująć w formie raportu.
Do sprawozdania dołączam plik xls o nazwie LAB7_AGrzeszyk, w którym zawarłam wszelkie niezbędne dane potrzebne do wykonania zadania metodą bagging. Zawarłam w nim dwa arkusze – Funkcje i Dane. W pierwszym można mieć pogląd na funkcje obliczające wartości poszczególnych kolumn, są w nim objaśnione ich nazwy. W drugim zaś zamieściłam dane, które będą importowane przez program R. Uczyniłam tak, gdyż funkcja los jest silnie zmienna, a starałam się uzyskać takie losowanie, w którym miałabym możliwie równoliczne zbiory przyporządkowane do preferencji 1 i 2.
Do wykonania przewidywań metodą bagging użyłam pakietu ipred programu R. Oto kod przeze mnie użyty:
library(ipred)
library(RODBC)
setwd("e:/")
dane <- odbcConnectExcel("LAB7_AGrzeszyk.xls")
DATA <- sqlQuery(dane, "select * from [DaneUcz$]")
DATA2 <- sqlQuery(dane, "select * from [DaneWal$]")
Preferencja <- sqlQuery(dane, "select * from [GrupaPreferencji$]")
Preferencja=as.vector(Preferencja)
names(DATA)<-c("Duze","Tanie","Uzbrojone","BliskoCentrum","Grupa")
names(DATA2)<-c("Duze","Tanie","Uzbrojone","BliskoCentrum","Grupa")
mod <- bagging(Grupa~., data=DATA, coob=TRUE)
print(mod)
summary(mod)
Przewidywanie<-predict(mod, newdata=DATA2)
Rezultat<- data.frame(round(Przewidywanie),Preferencja)
A także wynik jego wykonania:
> library(ipred)
Loading required package: rpart
Loading required package: MASS
Loading required package: mlbench
Loading required package: survival
Loading required package: splines
Loading required package: nnet
Loading required package: class
Warning messages:
1: package ‘ipred’ was built under R version 2.14.1
2: package ‘mlbench’ was built under R version 2.14.1
> library(RODBC)
> setwd("e:/")
> dane <- odbcConnectExcel("LAB7_AGrzeszyk.xls")
> DATA <- sqlQuery(dane, "select * from [DaneUcz$]")
> DATA2 <- sqlQuery(dane, "select * from [DaneWal$]")
> Preferencja <- sqlQuery(dane, "select * from [GrupaPreferencji$]")
> Preferencja=as.vector(Preferencja)
> names(DATA)<-c("Duze","Tanie","Uzbrojone","BliskoCentrum","Grupa")
> names(DATA2)<-c("Duze","Tanie","Uzbrojone","BliskoCentrum","Grupa")
> mod <- bagging(Grupa~., data=DATA, coob=TRUE)
> print(mod)
Bagging regression trees with 25 bootstrap replications
Call: bagging.data.frame(formula = Grupa ~ ., data = DATA, coob = TRUE)
Out-of-bag estimate of root mean squared error: 0.0388
> summary(mod)
Length Class Mode
y 350 -none- numeric
X 4 data.frame list
mtrees 25 -none- list
OOB 1 -none- logical
comb 1 -none- logical
err 1 -none- numeric
call 4 -none- call
> Przewidywanie<-predict(mod, newdata=DATA2)
> Rezultat<- data.frame(round(Przewidywanie),Preferencja)
> Rezultat
round.Przewidywanie. GP
1 2 2
2 2 2
3 2 2
4 2 2
5 2 2
6 2 2
7 2 2
8 2 2
9 1 1
10 2 2
11 1 1
12 2 2
13 2 2
14 2 2
15 1 1
16 2 2
17 2 2
18 2 2
19 2 2
20 2 2
21 2 2
22 2 2
23 2 2
24 1 1
25 2 2
26 2 2
27 1 1
28 2 2
29 2 2
30 2 2
31 2 2
32 2 2
33 2 2
34 2 2
35 2 2
36 2 2
37 1 1
38 2 2
39 1 1
40 2 2
41 1 1
42 2 2
43 1 1
44 2 2
45 2 2
46 2 2
47 2 2
48 2 2
49 2 2
50 2 2
51 2 2
52 2 2
53 2 2
54 2 2
55 2 2
56 2 2
57 2 2
58 2 2
59 2 2
60 1 1
61 2 2
62 2 2
63 2 2
64 2 2
65 2 2
66 2 2
67 2 2
68 2 2
69 2 2
70 2 2
71 2 2
72 2 2
73 2 2
74 2 2
75 2 2
76 2 2
77 2 2
78 2 2
79 2 2
80 2 2
81 2 2
82 2 2
83 2 2
84 2 2
85 2 2
86 2 2
87 2 2
88 2 2
89 2 2
90 2 2
91 2 2
92 1 1
93 2 2
94 2 2
95 2 2
96 2 2
97 2 2
98 2 2
99 2 2
100 2 2
101 2 2
102 2 2
103 2 2
104 2 2
105 2 2
106 2 2
107 1 1
108 1 1
109 2 2
110 2 2
111 2 2
112 2 2
113 2 2
114 2 2
115 2 2
116 2 2
117 2 2
118 2 2
119 2 2
120 2 2
121 2 2
122 2 2
123 2 2
124 2 2
125 2 2
126 2 2
127 2 2
128 2 2
129 1 1
130 1 1
131 2 2
132 2 2
133 1 1
134 1 1
135 2 2
136 2 2
137 2 2
138 2 2
139 1 1
140 2 2
141 2 2
142 2 2
143 2 2
144 2 2
145 2 2
146 2 2
147 2 2
148 2 2
149 1 1
150 2 2
Jak można zauważyć, przy zastosowaniu zbioru uczącego w postaci 350 rekordów przyporządkowania do grupy preferencji, pozostałe 150 rekordów walidacyjnych zostało dopasowane w 100% poprawnie. Jest to bardzo dobry wynik, jednakże liczność zbioru walidacyjnego mogłaby być wyższa. Algorytm bagging daje nam zatem doskonałe wyniki i z powodzeniem można go stosować do dużych zbiorów danych. Gdy próbowałam go zastosować dla danych bez podziału na zbiór walidacyjny i uczący, skuteczność dopasowani była rzędu 70-80% wobec tego zastosowanie dwóch wymienionych powyżej zbiorów przyniosło znaczące rezultaty.
A oto zrzuty ekranowe z wykonania programu:
Następnie do tego samego zbioru użyłam metody Random Forests, zaimplementowanej w paczce radomForest. Oto kod użyty przeze mnie:
library(randomForest)
library(RODBC)
setwd("e:/")
dane <- odbcConnectExcel("LAB7_AGrzeszyk.xls")
DATA <- sqlQuery(dane, "select * from [DaneUcz$]")
DATA2 <- sqlQuery(dane, "select * from [DaneWal$]")
Preferencja <- sqlQuery(dane, "select * from [GrupaPreferencji$]")
Preferencja=as.vector(Preferencja)
names(DATA)<-c("Duze","Tanie","Uzbrojone","BliskoCentrum","Grupa")
names(DATA2)<-c("Duze","Tanie","Uzbrojone","BliskoCentrum","Grupa")
mod <- randomForest(Grupa~., data=DATA)
print(mod)
summary(mod)
Przewidywanie<-predict(mod, newdata=DATA2)
drzewko<-getTree(mod)
plot(mod)
drzewko
Rezultat<- data.frame(round(Przewidywanie),Preferencja)
Rezultat
Dał on następujące rezultaty:
> library(randomForest)
randomForest 4.6-6
Type rfNews() to see new features/changes/bug fixes.
Warning message:
package ‘randomForest’ was built under R version 2.14.1
> library(RODBC)
> setwd("e:/")
> dane <- odbcConnectExcel("LAB7_AGrzeszyk.xls")
> DATA <- sqlQuery(dane, "select * from [DaneUcz$]")
> DATA2 <- sqlQuery(dane, "select * from [DaneWal$]")
> Preferencja <- sqlQuery(dane, "select * from [GrupaPreferencji$]")
> Preferencja=as.vector(Preferencja)
> names(DATA)<-c("Duze","Tanie","Uzbrojone","BliskoCentrum","Grupa")
> names(DATA2)<-c("Duze","Tanie","Uzbrojone","BliskoCentrum","Grupa")
> mod <- randomForest(Grupa~., data=DATA)
Warning messages:
1: In randomForest.default(m, y, ...) :
The response has five or fewer unique values. Are you sure you want to do regression?
2: closing unused RODBC handle 1
> print(mod)
Call:
randomForest(formula = Grupa ~ ., data = DATA)
Type of random forest: regression
Number of trees: 500
No. of variables tried at each split: 1
Mean of squared residuals: 0.01930077
% Var explained: 81.72
> summary(mod)
Length Class Mode
call 3 -none- call
type 1 -none- character
predicted 350 -none- numeric
mse 500 -none- numeric
rsq 500 -none- numeric
oob.times 350 -none- numeric
importance 4 -none- numeric
importanceSD 0 -none- NULL
localImportance 0 -none- NULL
proximity 0 -none- NULL
ntree 1 -none- numeric
mtry 1 -none- numeric
forest 11 -none- list
coefs 0 -none- NULL
y 350 -none- numeric
test 0 -none- NULL
inbag 0 -none- NULL
terms 3 terms call
> Przewidywanie<-predict(mod, newdata=DATA2)
> drzewko<-getTree(mod)
> plot(mod)
> drzewko
left daughter right daughter split var split point status prediction
1 2 3 4 3.5 -3 1.911429
2 0 0 0 0.0 -1 2.000000
3 4 5 2 4.5 -3 1.817647
4 0 0 0 0.0 -1 2.000000
5 6 7 2 7.5 -3 1.500000
6 8 9 3 2.5 -3 1.480769
7 10 11 3 1.5 -3 1.600000
8 12 13 4 7.5 -3 1.650000
9 14 15 4 7.5 -3 1.375000
10 0 0 0 0.0 -1 1.000000
11 16 17 4 5.5 -3 1.666667
12 18 19 2 5.5 -3 1.866667
13 0 0 0 0.0 -1 1.000000
14 20 21 4 4.5 -3 1.413793
15 0 0 0 0.0 -1 1.000000
16 0 0 0 0.0 -1 1.500000
17 0 0 0 0.0 -1 1.800000
18 0 0 0 0.0 -1 2.000000
19 0 0 0 0.0 -1 1.750000
20 22 23 3 3.5 -3 1.200000
21 24 25 1 2.5 -3 1.526316
22 0 0 0 0.0 -1 1.500000
23 26 27 2 5.5 -3 1.125000
24 0 0 0 0.0 -1 2.000000
25 0 0 0 0.0 -1 1.000000
26 0 0 0 0.0 -1 1.200000
27 0 0 0 0.0 -1 1.000000
> Rezultat<- data.frame(round(Przewidywanie),Preferencja)
> Rezultat
round.Przewidywanie. GP
1 2 2
2 2 2
3 2 2
4 2 2
5 2 2
6 2 2
7 2 2
8 2 2
9 1 1
10 2 2
11 1 1
12 2 2
13 2 2
14 2 2
15 2 1
16 2 2
17 2 2
18 2 2
19 2 2
20 2 2
21 2 2
22 2 2
23 2 2
24 1 1
25 2 2
26 2 2
27 1 1
28 2 2
29 2 2
30 2 2
31 2 2
32 2 2
33 2 2
34 2 2
35 2 2
36 2 2
37 1 1
38 2 2
39 1 1
40 2 2
41 1 1
42 2 2
43 1 1
44 2 2
45 2 2
46 2 2
47 2 2
48 2 2
49 2 2
50 2 2
51 2 2
52 2 2
53 2 2
54 2 2
55 2 2
56 2 2
57 2 2
58 2 2
59 2 2
60 1 1
61 2 2
62 2 2
63 2 2
64 2 2
65 2 2
66 2 2
67 2 2
68 2 2
69 2 2
70 2 2
71 2 2
72 2 2
73 2 2
74 2 2
75 2 2
76 2 2
77 2 2
78 2 2
79 2 2
80 2 2
81 2 2
82 2 2
83 2 2
84 2 2
85 2 2
86 2 2
87 2 2
88 2 2
89 2 2
90 2 2
91 2 2
92 1 1
93 2 2
94 2 2
95 2 2
96 2 2
97 2 2
98 2 2
99 2 2
100 2 2
101 2 2
102 2 2
103 2 2
104 2 2
105 2 2
106 2 2
107 1 1
108 1 1
109 2 2
110 2 2
111 2 2
112 2 2
113 2 2
114 2 2
115 2 2
116 2 2
117 2 2
118 2 2
119 2 2
120 2 2
121 2 2
122 2 2
123 2 2
124 2 2
125 2 2
126 2 2
127 2 2
128 2 2
129 2 1
130 2 1
131 2 2
132 2 2
133 1 1
134 1 1
135 2 2
136 2 2
137 2 2
138 2 2
139 1 1
140 2 2
141 2 2
142 2 2
143 2 2
144 2 2
145 2 2
146 2 2
147 2 2
148 2 2
149 1 1
150 2 2
Dzięki tej metodzie uzyskałam także bardzo dobre rezultaty, chociaż przewidywania tego algorytmu nie były bezbłędne. Zaklasyfikował on wszystkie przypadki, jednakże 3 z nich były błędne, 147 poprawnych, co daje wynik 98% poprawnych klasyfikacji.
Poniżej zamieszczam niezbędne zrzuty ekranowe:
Wnioski:
Najskuteczniejsza z zastosowanych przeze mnie na laboratoriach metod okazała się być metoda bagging, w której uzyskałam 0 braków dopasowań, 0 błędów i 150 na 150 poprawnych klasyfikacji.
Kolejna okazała się być metoda Random Forests, mimo iż jest udoskonaloną wersją metody bagging, w moim przypadku dała ona 0 braków dopasowań, 3 błędy i 147 na 150 poprawnych klasyfikacji.
Następna w kolejności była metoda Quinlana z 0 brakiem dopasowań, 38 błędami i 62 na 100 poprawnymi klasyfikacjami.
Na ostatnim miejscu pod względem skuteczności uplasowała się sztuczna sieć neuronowa, gdzie również nie było braków dopasowań, zaobserwowałam 47 błędów i 53 dobre klasyfikacje.
Podczas doboru metody wiele zależy od liczności zbioru, doboru jego zbioru uczącego i walidacyjnego, a także umiejętności i znajomości algorytmu przez przeprowadzającego doświadczenie. Poznane przeze mnie algorytmy pomagają w znajdowaniu klasyfikacji danych, przewidywaniu, i odpowiedniemu podziałowi. Stanowią znaczną pomoc dla ludzi i mogą ułatwić ich egzystencję i pomóc przewidywać niektóre sytuacje.