Dataset yang akan digunakan adalah data klasifikasi Jamur berdasarkan jenis tidak beracun (edible) atau beracun (poisonous) dari 23 species gilled mushrooms dalam family Agaricus and Lepiota yang didapatkan dari The Audubon Society Field Guide to North American Mushrooms (1981).
Pada kesempatan kali ini, menggunakan informasi yang terdapat pada data mushroom akan dilakukan prediksi jenis jamur menggunakan pemodelan naive bayes, desicion tree dan random forest.
Pada data jamur diatas terdapat 1 kolom target (class) dan 22 kolom prediktor yang merupakan informasi karakteristik dari jamur dengan informasi sebagai berikut :
class : class jamur edible =e, poisonous = p
cap.shape : bentuk cap jamur bell=b,conical=c,convex=x,flat=f, knobbed=k,sunken=s
cap.surface : permukaan cap fibrous=f,grooves=g,scaly=y,smooth=s
cap.color : warna cap brown=n,buff=b,cinnamon=c,gray=g,green=r,pink=p,purple=u,red=e,white=w,yellow=y
bruises : bruises=t,no=f
odor : almond=a,anise=l,creosote=c,fishy=y,foul=f,musty=m,none=n,pungent=p,spicy=s
gill.attachment : penempatan gill attached=a, descending=d, free=f, notched=n
gill.spacing : jarak gill close=c,crowded=w,distant=d
gill.size : ukuran gill broad=b,narrow=n
gill.color : warna gill black=k,brown=n,buff=b,chocolate=h,gray=g, green=r,orange=o,pink=p,purple=u,red=e,white=w,yellow=y
stalk.shape : bentuk stalk enlarging=e,tapering=t
stalk.root : akar stalk bulbous=b,club=c,cup=u,equal=e,rhizomorphs=z,rooted=r,missing=?
stalk.surface.above.ring : fibrous=f,scaly=y,silky=k,smooth=s
stalk.surface.below.ring : fibrous=f,scaly=y,silky=k,smooth=s
stalk.color.above.ring : brown=n,buff=b,cinnamon=c,gray=g,orange=o,pink=p,red=e,white=w,yellow=y
stalk-color-below-ring: brown=n,buff=b,cinnamon=c,gray=g,orange=o,pink=p,red=e,white=w,yellow=y
veil-type: partial=p,universal=u
veil-color: brown=n,orange=o,white=w,yellow=y
ring-number: none=n,one=o,two=t
ring-type: cobwebby=c,evanescent=e,flaring=f,large=l,none=n,pendant=p,sheathing=s,zone=z
spore-print-color: black=k,brown=n,buff=b,chocolate=h,green=r,orange=o,purple=u,white=w,yellow=y
population: abundant=a,clustered=c,numerous=n,scattered=s,several=v,solitary=y
habitat: grasses=g,leaves=l,meadows=m,paths=p,urban=u,waste=w,woods=d
Cek type data yang masih belum sesuai
#> 'data.frame': 8124 obs. of 23 variables:
#> $ class : Factor w/ 2 levels "e","p": 2 1 1 2 1 1 1 1 2 1 ...
#> $ cap.shape : Factor w/ 6 levels "b","c","f","k",..: 6 6 1 6 6 6 1 1 6 1 ...
#> $ cap.surface : Factor w/ 4 levels "f","g","s","y": 3 3 3 4 3 4 3 4 4 3 ...
#> $ cap.color : Factor w/ 10 levels "b","c","e","g",..: 5 10 9 9 4 10 9 9 9 10 ...
#> $ bruises : Factor w/ 2 levels "f","t": 2 2 2 2 1 2 2 2 2 2 ...
#> $ odor : Factor w/ 9 levels "a","c","f","l",..: 7 1 4 7 6 1 1 4 7 1 ...
#> $ gill.attachment : Factor w/ 2 levels "a","f": 2 2 2 2 2 2 2 2 2 2 ...
#> $ gill.spacing : Factor w/ 2 levels "c","w": 1 1 1 1 2 1 1 1 1 1 ...
#> $ gill.size : Factor w/ 2 levels "b","n": 2 1 1 2 1 1 1 1 2 1 ...
#> $ gill.color : Factor w/ 12 levels "b","e","g","h",..: 5 5 6 6 5 6 3 6 8 3 ...
#> $ stalk.shape : Factor w/ 2 levels "e","t": 1 1 1 1 2 1 1 1 1 1 ...
#> $ stalk.root : Factor w/ 5 levels "?","b","c","e",..: 4 3 3 4 4 3 3 3 4 3 ...
#> $ stalk.surface.above.ring: Factor w/ 4 levels "f","k","s","y": 3 3 3 3 3 3 3 3 3 3 ...
#> $ stalk.surface.below.ring: Factor w/ 4 levels "f","k","s","y": 3 3 3 3 3 3 3 3 3 3 ...
#> $ stalk.color.above.ring : Factor w/ 9 levels "b","c","e","g",..: 8 8 8 8 8 8 8 8 8 8 ...
#> $ stalk.color.below.ring : Factor w/ 9 levels "b","c","e","g",..: 8 8 8 8 8 8 8 8 8 8 ...
#> $ veil.type : Factor w/ 1 level "p": 1 1 1 1 1 1 1 1 1 1 ...
#> $ veil.color : Factor w/ 4 levels "n","o","w","y": 3 3 3 3 3 3 3 3 3 3 ...
#> $ ring.number : Factor w/ 3 levels "n","o","t": 2 2 2 2 2 2 2 2 2 2 ...
#> $ ring.type : Factor w/ 5 levels "e","f","l","n",..: 5 5 5 5 1 5 5 5 5 5 ...
#> $ spore.print.color : Factor w/ 9 levels "b","h","k","n",..: 3 4 4 3 4 3 3 4 3 3 ...
#> $ population : Factor w/ 6 levels "a","c","n","s",..: 4 3 3 4 1 3 3 4 5 4 ...
#> $ habitat : Factor w/ 7 levels "d","g","l","m",..: 6 2 4 6 2 2 4 4 2 4 ...
Semua type data sudah sesuai yaitu factor dikarenakan sudah dilakukan perubahan pada saat read data sebelumnya menggunakan formula stringAsFactors
#> class cap.shape cap.surface
#> 0 0 0
#> cap.color bruises odor
#> 0 0 0
#> gill.attachment gill.spacing gill.size
#> 0 0 0
#> gill.color stalk.shape stalk.root
#> 0 0 0
#> stalk.surface.above.ring stalk.surface.below.ring stalk.color.above.ring
#> 0 0 0
#> stalk.color.below.ring veil.type veil.color
#> 0 0 0
#> ring.number ring.type spore.print.color
#> 0 0 0
#> population habitat
#> 0 0
Tidak terdapat missing value pada setiap kolom
#> class cap.shape cap.surface cap.color bruises odor
#> e:4208 b: 452 f:2320 n :2284 f:4748 n :3528
#> p:3916 c: 4 g: 4 g :1840 t:3376 f :2160
#> f:3152 s:2556 e :1500 s : 576
#> k: 828 y:3244 y :1072 y : 576
#> s: 32 w :1040 a : 400
#> x:3656 b : 168 l : 400
#> (Other): 220 (Other): 484
#> gill.attachment gill.spacing gill.size gill.color stalk.shape stalk.root
#> a: 210 c:6812 b:5612 b :1728 e:3516 ?:2480
#> f:7914 w:1312 n:2512 p :1492 t:4608 b:3776
#> w :1202 c: 556
#> n :1048 e:1120
#> g : 752 r: 192
#> h : 732
#> (Other):1170
#> stalk.surface.above.ring stalk.surface.below.ring stalk.color.above.ring
#> f: 552 f: 600 w :4464
#> k:2372 k:2304 p :1872
#> s:5176 s:4936 g : 576
#> y: 24 y: 284 n : 448
#> b : 432
#> o : 192
#> (Other): 140
#> stalk.color.below.ring veil.type veil.color ring.number ring.type
#> w :4384 p:8124 n: 96 n: 36 e:2776
#> p :1872 o: 96 o:7488 f: 48
#> g : 576 w:7924 t: 600 l:1296
#> n : 512 y: 8 n: 36
#> b : 432 p:3968
#> o : 192
#> (Other): 156
#> spore.print.color population habitat
#> w :2388 a: 384 d:3148
#> n :1968 c: 340 g:2148
#> k :1872 n: 400 l: 832
#> h :1632 s:1248 m: 292
#> r : 72 v:4040 p:1144
#> b : 48 y:1712 u: 368
#> (Other): 144 w: 192
dapat dilihat pada colom veil.type hanya terdapat satu
kategori saja, maka sebaiknya kolom tersebut di keluarkan dari data set
yang ada
Dilakukan pemisahan data train dengan test untuk mengevaluasi model dan melihat kemampuannya memprediksi data baru
RNGkind(sample.kind = "Rounding")
set.seed(123)
# index sampling
# ---- mengambil 80 persen index dari jumlah data -----
index <- sample(x = nrow(jamur),size = 0.8*nrow(jamur))
# splitting data
train <- jamur[index,] #ambil data 80%
test <- jamur[-index,] #ambil data 20%#>
#> e p
#> 0.52 0.48
model_bayes <- naiveBayes(class~., data = jamur, laplace = 1)
predict_bayes <- predict(model_bayes, test)
confusionMatrix(predict_bayes,
test$class,
positive = "p")#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction e p
#> e 832 58
#> p 7 728
#>
#> Accuracy : 0.96
#> 95% CI : (0.9493, 0.969)
#> No Information Rate : 0.5163
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 0.9198
#>
#> Mcnemar's Test P-Value : 0.0000000005584
#>
#> Sensitivity : 0.9262
#> Specificity : 0.9917
#> Pos Pred Value : 0.9905
#> Neg Pred Value : 0.9348
#> Prevalence : 0.4837
#> Detection Rate : 0.4480
#> Detection Prevalence : 0.4523
#> Balanced Accuracy : 0.9589
#>
#> 'Positive' Class : p
#>
Hasil confusionmatrix menunjukkan bahwa klasifikasi Naive Bayes memperkirakan 832 jamur tidak beracun (edible) dengan benar dan 7 prediksi salah, sedangkan model memprediksi 728 jamur beracun (poisonous) dengan benar dan 58 prediksi salah. Tingkat akurasi dari model ini adalah sebesar 96% dan sensitivity (recall) sebesar 93%.
Model selanjutnya yang akan dibuat adalah decision tree
Kita bisa melihat tingkat pertama adalah
odor yang
merupakan prediktor yang paling mempengaruhi klasifikasi dari jamur
#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction e p
#> e 839 0
#> p 0 786
#>
#> Accuracy : 1
#> 95% CI : (0.9977, 1)
#> No Information Rate : 0.5163
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 1
#>
#> Mcnemar's Test P-Value : NA
#>
#> Sensitivity : 1.0000
#> Specificity : 1.0000
#> Pos Pred Value : 1.0000
#> Neg Pred Value : 1.0000
#> Prevalence : 0.4837
#> Detection Rate : 0.4837
#> Detection Prevalence : 0.4837
#> Balanced Accuracy : 1.0000
#>
#> 'Positive' Class : p
#>
Hasil model decision tree memiliki sensitivity dan akurasi sebesar 100%, dimana tidak terdapat error atas semua prediksi yang dilakukan terhadap data test.
Tahap awal dalam membuat model random forest kita akan mereduksi prediktor yang memiliki nilai seragam (low variance)
proses cross validation
RNGkind(sample.kind = "Rounding")
set.seed(123)
index_var <- sample(nrow(jamur_var), nrow(jamur_var)*0.8)
var_train <- jamur_var[index_var, ]
var_test <- jamur_var[-index_var, ]set.seed(123)
ctrl <- trainControl(method = "repeatedcv",
number = 5, # k-fold
repeats = 3) # repetisi
jamur_forest <- train(class ~ .,
data = var_train,
method = "rf", # random forest
trControl = ctrl)
saveRDS(jamur_forest, "jamur_forest.RDS") # simpan modelDari hasil RF, mtry paling bagus adalah mtry = 46, nilai akurasi yang didapatkan adalah sebesar 100%
kita akan melakukan pengecekan OOB error yang merupakan persentase data OOB yang misklasifikasi
#>
#> Call:
#> randomForest(x = x, y = y, mtry = param$mtry)
#> Type of random forest: classification
#> Number of trees: 500
#> No. of variables tried at each split: 46
#>
#> OOB estimate of error rate: 0%
#> Confusion matrix:
#> e p class.error
#> e 3369 0 0
#> p 0 3130 0
Nilai OOB Error pada model model_rf sebesar 0%. Dengan
kata lain, akurasi model pada data OOB adalah 100%!
#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction e p
#> e 839 0
#> p 0 786
#>
#> Accuracy : 1
#> 95% CI : (0.9977, 1)
#> No Information Rate : 0.5163
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 1
#>
#> Mcnemar's Test P-Value : NA
#>
#> Sensitivity : 1.0000
#> Specificity : 1.0000
#> Pos Pred Value : 1.0000
#> Neg Pred Value : 1.0000
#> Prevalence : 0.5163
#> Detection Rate : 0.5163
#> Detection Prevalence : 0.5163
#> Balanced Accuracy : 1.0000
#>
#> 'Positive' Class : e
#>
Performa model random forest yaitu memiliki sensitivity (recall) dan akurasi sebesar 100%!
Selanjutnya, mari kita lihat prediktor penting yang paling sering digunakan dalam model random forest
#> rf variable importance
#>
#> only 20 most important variables shown (out of 91)
#>
#> Overall
#> odorn 100.000
#> odorf 32.620
#> gill.sizen 30.678
#> stalk.rootc 16.846
#> stalk.surface.above.ringk 9.497
#> bruisest 9.418
#> spore.print.colorr 7.741
#> stalk.surface.below.ringk 5.823
#> stalk.surface.below.ringy 5.193
#> stalk.rootr 4.931
#> odorl 4.723
#> spore.print.colorh 4.074
#> ring.typep 3.530
#> gill.spacingw 3.478
#> spore.print.colorw 3.110
#> odorp 2.350
#> cap.colory 2.213
#> ring.numbert 2.207
#> populationv 1.649
#> stalk.shapet 1.609
Prediktor yang paling penting dalam menentukan klasifikasi jamur
adalah odorn atau
jamur yang tidak memiliki bau
Model Naive Bayes : Sensitivity 93% dan Akurasi 96%
Model Decision Tree : Sensitivity 100% dan Akurasi 100%
Model Random Forest : Sensitivity 100% dan Akurasi 100%
Recall (sensitivity) lebih dititikberatkan karena ingin
mengurangi prediksi false negatif dalam hal ini diprediksi
`jamur tidak beracun namun sebenarnya jamur beracun
Model decision tree dan random forest memiliki performa paling baik pada data ini dimana menghasilkan tingkat akurasi 100%, namun hal tersebut sebagai catatan dalam pemodelan berisiko menjadi model yang overfitting.
Beberapa variable seperti odor (bau jamur), spore color (warna spora), stalk color (warna batang), cap surface sangat mempengaruhi klasifikasi jamur tersebut beracun atau tidak.