Evet R ve Python üzerinde geçişler yaparak makine öğrenimi algoritmalarını uygulamaya devam ediyoruz. Son yazıyı Python üzerinde yazdıktan sonra bu yazıda da R üzerinde devam edeceğiz. Makine öğreniminin en güzide algoritmalarından biri olan tesadüfi(rastgele) orman (random forest) metodu ile arabaların bir değerlendirmesini yapacak ve seviyelerini sınıflandıracağız.

Veri setini tanımlayarak başlayalım. Veri seti, arabaların belli başlı özelliklerinden yola çıkarak değerlendirmesini yapıyor. Bu özellikler; alım ve bakım fiyatları, kapı sayısı, kişi taşıma kapasitesi, bagaj büyüklüğü ve güvenlik seviyesi olarak gösteriliyor. Biz ise bunları kullanarak arabanın genel değerlendirme notunu yani hangi sınıfa düştüğünü tahmin etmeye çalışacağız. Veri setinin linki aşağıda:

Araba Değerlendirme Verisi

Öncelikle veriyi alırken bazı manuel düzenlemeler yapmanız gerekecektir. Verinin kendisi “car.data” klasöründe, kolon adları ise “car.names” klasöründe bulunuyor. Ayrıca veri text formatında ve virgülle ayrılmış. Bu yüzden kolay bir biçimde csv formatına çevirip başlıklar ile de birleştirebilirsiniz. Veriyi R içerisine alalım ve incelemeye başlayalım.

getwd()
Data <- read.csv("CarEvaluation.csv", stringsAsFactors = FALSE)
nrow(Data)
ncol(Data)
head(Data, n = 10)

Satır ve sütun sayıları:

1

Evet veri 1728 satır(gözlem) ve 7 sütun(değişken) şeklinde. İlk 10 satırı da inceleyelim:

2

Evet veri setinin ilk satırları da bu şekilde. Herhangi bir pre-processing işlemi yapmadan önce, veriyi inceleyelim ve hakkında fikir sahibi olalım. Örneğin sütunların hangi değerleri içerdiğini, hedef değişkenin verideki sınıf dağılımının nasıl olduğunu ve değişkenlerin veri tiplerinin neler olduğunu görelim.

ColumnValues <- sapply(Data, unique)
print(ColumnValues)

Sonuç:

3

Evet kolonların hangi değerleri içerdiğini buradan görüyoruz. Alım ve bakım fiyatları “very high” seviyesinden “low” seviyesine kadar gidiyor. Kapı sayıları da 2’den “5 ve fazlasına” kadar gidiyor. Diğer kolonların da içerisinde barındırdıkları değerleri görebiliyoruz. Bu çıktıyı almak adına verinin her kolonuna “sapply” komutu vasıtasıyla “unique” fonksiyonunu uyguladık ve sonucu da “list” tipinde aldık. Bu veri çeşitliliğinden yola çıkarak kolonların veri tiplerini tahmin etmek de zor değil fakat yine de veri tiplerini inceleyelim:

DataTypes <- as.data.frame(sapply(Data, class))
print(DataTypes)

Veri tipleri:

4

Evet verinin tüm kolonları karakter tipinde. Yine üstteki kod bloğunun mantığı ile bu kez “class” fonksiyonunu uyguladık ve bu kez çıktıyı “data frame” tipinde aldık. Bir önceki kod bloğunda “list” şeklinde almamızın sebebi ise çıktının aynı satır sayısına sahip olmamasıydı. Veri inceleme aşamasına devam edelim. Bu kez görselleştirmeler yaparak ilerleyelim:

library(ggplot2)
ggplot(data = Data,
mapping = aes(x = factor(class))) +
geom_bar(stat = "count",
width = 0.8,
fill = "blue") +
theme_minimal() +
coord_flip() +
xlab("Gözlem Sayısı") +
ylab("Değerlendirme Sınıfı") +
ggtitle("Hedef Değişken Dağılımı")

Hedef değişkeninin verideki dağılımını incelemek adına bir bar grafik üretiyoruz. Bunu da “ggplot2” kütüphanesini kullanarak yapıyoruz. x eksenine hedef değişkenini attıktan sonra stat = “count” diyerek veri sayısını bar grafiğe döküyoruz. Sonuç:

5

Evet çoğu zaman olduğu gibi yine veride sınıf dağılımı dengesiz. Bu da bizi yine buna ilişkin bazı önlemler almaya zorlayacak. Bu kez araba değerlendirmesini güvenlik seviyesi ile beraber inceleyelim:

ggplot(data = Data,
mapping = aes(x = factor(class),
fill = factor(safety))) +
geom_bar(stat = "count",
width = 0.8,
color = "red") +
theme_minimal() +
xlab("Gözlem Sayısı") +
ylab("Değerlendirme Sınıfı") +
ggtitle("Güvenlik-Kalite Dağılımı")

Bu kez “fill” komutu ile başka bir değişken adını verdik ve barların içinin bu değişkenin “count” değeri ile dolmasını sağladık. Sonucu inceleyelim:

6

Evet bu grafik bize güvenlik düzeyine göre değerlendirmelerin nasıl dağıldığı hakkında bir ön bilgi sağlıyor. Örneğin “vgood” yani çok iyi olarak kategorize edilmiş arabaların tamamının güvenlik seviyesi “high” yani yüksek olarak görülüyor ki bu çok doğal. En düşük yani “unacc” sınıfındaki arabalarda da “low” yani düşük güvenlik oranının miktarının ne kadar fazla olduğunu yeşil renkle görebiliyoruz. Bu tarz ikili incelemeler hedef değişkenin bağımsız değişkenlere göre nasıl etkilendiği hakkında görsel olarak bize bilgi sağlar. Veri incelemesine bir de kayıp veri oranını inceleyerek devam edelim ve sonrasında bu bölümü sonlandıralım:

MissingCols <- names(which(sapply(Data, anyNA)))
print(MissingCols)

Sonuç:

7

Evet gördüğümüz üzere veride kayıp gözlemler bulunmuyor. Zaten veri setinin kendi açıklamasında da kayıp veri bulunmadığı yazıyor. Kayıp veri bulunsaydı bunun için bazı teknikler uygulamak ya da bunları veriden çıkarmak durumunda kalabilirdik. Buna dair örnekleri yazılarımızda çokça yaptık. Devam edelim ve artık “Data Pre-processing” aşamasına geçelim.

Veride herhangi bir nümerik değişken veya kayıp veri yok ve elimizde sadece karakter değişkenler var. Bu yüzden herhangi bir “scaling” yapmayacağız. Aynı zamanda kayıp veri bakımı yapmanın da gereği olmadığı için sadece kategorik değişkenleri kodlama aşamasını gerçekleştireceğiz. Aşağıdaki kod bloğu ile uygulayalım:

Data$buying = factor(Data$buying,
levels = c("low", "med", "high", "vhigh"),
labels = c(1, 2, 3, 4),
ordered = FALSE)
Data$maint = factor(Data$maint,
levels = c("low", "med", "high", "vhigh"),
labels = c(1, 2, 3, 4),
ordered = FALSE)

Evet kod bloğunu açıklamak gerekirse, elimizdeki tüm değişkenleri factor biçimine çeviriyoruz. Çevirirken de değişkenin kategorilerini fonksiyona verip, daha sonra bunlara da 1’den başlamak üzere kategori sayısı kadar etiket atıyoruz. Bu kategorilerin sıralaması ve karşılık gelen etiket değerleri son derece önemli. Sonrasında ise “ordered = FALSE” argümanıyla beraber bunların nominal değişkenler olduğunu söylüyoruz fakat aslında nominal değiller. Sadece şimdilik nominal olarak gösteriyoruz çünkü ordinal olduklarında birazdan kullanacağımız SMOTE fonksiyonu problem çıkartabiliyor. Bu yüzden şimdilik böyle devam edip SMOTE’tan sonra bunlara tekrar ordinal sıfatı atayacağız.

Evet pre-processing aşamasını bitirdikten sonra veriyi bölmeye geçebiliriz. Boyut düşürmeye dair herhangi bir uygulama yapmak istemiyorum çünkü zaten verimizin boyutu küçük. Sadece 6 bağımsız değişken var. Bu yüzden veriyi train ve test olarak ikiye ayırıp train setine “SMOTE” uygulayalım ve veriyi dengelemeye çalışalım.

library(caTools)
set.seed(123)
split = sample.split(Data$class, SplitRatio = 0.80)
training_set = subset(Data, split == TRUE)
test_set = subset(Data, split == FALSE)
nrow(training_set)
nrow(test_set)

İhtiyacımız olan “caTools” kütüphanesini indirdik ve “set.seed” komutu ile her çalışmada aynı sonuçların üretilmesini sağladık. %80’lik bir split oranı belirledik ve split “TRUE” olanları training sete, “FALSE” olanları da test sete atadık. Son olarak da satır sayılarını inceleyelim:

8

Evet satırların 1382 tanesi training sete, 346 tanesi de test sete gitti. Sırada dengesiz sınıf problemini aşmak için daha önce de kullandığımız SMOTE metodunu kullanmak geliyor. Unutmamak gerekir ki bu noktada SMOTE tek çözüm değil. Biz de zaten SMOTE metodunun yanında model değerlendirmelerinde de farklı metriklere bakarak (örneğin Cohen’s Kappa gibi) bu problemin üstesinden gelmeye çalışıyoruz. SMOTE dışında oversampling ve undersampling gibi yani az olan sınıftan fazla örneklem çekme ve çok olan sınıftan da az örneklem çekme gibi metodlar da literatürde uygulanmaktadır. Ek olarak, model maliyet fonksiyonlarına az olan sınıfı yanlış tahmin etmesi durumunda daha çok maliyet yüklemesi gibi ek düzeltmeler de yapılabilir. Bunları başka yazılarımızda uygulayabiliriz. Biz yine burada SMOTE ile devam edeceğiz.

library(DMwR)
library(dplyr)
library(UBL)

training_set %>%
group_by(class) %>%
summarise(number = n())

Balanced_training_set = SmoteClassif(class ~ .,
training_set,
C.perc = list("1" = 1,
"2" = 3,
"3" = 18,
"4" = 19),
dist = "Overlap",
k = 5)

Balanced_training_set %>%
group_by(class) %>%
summarise(number = n())

Evet yine gerekli kütüphaneleri indirdikten sonra training setteki bağımlı değişken dağılımı inceledik. Sonuç:

9

Görüldüğü gibi dengesizlik hakim. Sonrasında SMOTE ile tüm sınıfları yanlarındaki katsayı ile çarptık ve böylece tamamının gözlem sayısını birbirbirine yakınlaştırdık. Daha önce de bahsettiğimiz gibi SMOTE metodu k-en yakın komşu yöntemini kullanarak yapay gözlemler ürettiği için kullanılacak komşu sayısını da 5 olarak belirttik ve 5-NN metodunu kullanmasını söyledik. Sonuçta da yeni veri setinde dağılımı inceledik:

10

Evet tüm sınıflar birbirine yakın miktara ulaştı. Sıra geldi kategori sınıflandırmalarını düzeltmeye. Değişkenlerin nominal değil ordinal olduklarını belirtmek adına aşağıdaki kod bloğunu çalıştıralım:

Balanced_training_set$buying = factor(Balanced_training_set$buying,
levels = c(1, 2, 3, 4),
labels = c(1, 2, 3, 4),
ordered = TRUE)
Balanced_training_set$maint = factor(Balanced_training_set$maint,
levels = c(1, 2, 3, 4),
labels = c(1, 2, 3, 4),
ordered = TRUE)

sapply(Balanced_training_set, unique)

Evet üstte iki değişken için çalıştırdığım kodu tüm değişkenler için çalıştırdığımızda artık önceden sayıya çevirdiğimiz ve nominal olduklarını söylediğimiz etiketler artık ordinale dönmüş durumda. Unutmamak gerekir ki aynı işlemi test set için de yapıp oradaki değişkenleri de ordinal hale döndürmek gerekiyor. Son olarak “unique” komutunu veriye uygulayıp kolon tiplerini görmek istediğimizde:

11

Evet gördüğümüz gibi kategoriler sıralanmış durumda. Bu faktöre çevirme olayı biraz karışık olmuş olabilir o yüzden netleştirmek adına birkez daha açıklayalım. Öncelikle ilk aşamada küçükten büyüğe olmak üzere kategorik değişkenlerin kategorilerine 1’den başlamak üzere yine küçükten büyüğe sayılardan oluşan etiketler verdik ve ordered argümanını FALSE yaparak nominal yani kategorilerinin sıralamasız olduğunu söyledik. Bunu yapmamızın sebebi ise SMOTE komutunun sorunsuz çalışmasını sağlamaktı. Sonrasında bunların artık sayıya dönmüş etiketlerini tekrar kullanarak küçükten büyüğe yine aynı etiketleri verdik fakat bu kez ordered argümanını TRUE yaparak aslında nominal değil ordinal olduklarını söyledik.

Artık modeli oluşturmaya başlayabiliriz. Yukarıda da bahsettiğimiz gibi Tesadüfi Orman modelini uygulayacağız. Biraz bu metodun teorik altyapısından bahsedelim. Tesadüfi orman, önceki yazılarımızda kullandığımız güçlendirme metoduyla aynı şekilde “Ensemble” dediğimiz topluluk modellerine dahildir. Bu modellerde, birden fazla zayıf model birleştirilir ve en son bir topluluk oluşur. Problemin türüne göre de bu topluluğun ortaya çıkardığı en son final tahmin kullanılır. Regresyon problemlerinde tüm zayıf modellerin ortalaması, sınıflandırma problemlerinde ise en çok tahmin edilen kategori bize final tahmini verir.

Topluluk modellerinin en önemli özelliği, birden fazla sınıflandırıcının birleşerek değişkenlik problemini ciddi oranda azaltmasıdır. Bu özelliği sayesinde topluluk modelleri literatürde çokça kullanılmaktadır. Topluluk modelleri oluşturulurken en çok kullanılan iki yöntem “bagging” ve “boosting” dir. Boosting yani güçlendirme metodundan bahsetmiş, bu konuda çalışmalar da gerçekleştirmiştik. Biraz da bagging’den bahsedelim. Bu yöntem esnasında training aşamasındayken veriden iadeli olarak örneklemler çekilir ve çekilen örneklemler her seferinde sınıflandırma modellerinin oluşturulmasında kullanılır. Hatırlarsanız boosting metodunda bir önceki safhada yanlış sınıflandırılan veriler bir sonraki safhada daha çok öneme sahip oluyorlardı bu yüzden her yeni örneklemde ortaya çıkma oranları yükseliyordu. Bu kural bagging için geçerli değil. Her veri noktasının örneklemde ortaya çıkma olasılığı eşit. Bunu aşağıdaki gibi gösterebiliriz:

bb3-800x307

Ayrıca final tahminler ortaya koyulurken de, boosting her sınıflandırıcıya bir ağırlık verip o ağırlıkları sınıflandırıcının final tahmine etkisi olarak kullanırken, bagging metodunda her sınıflandırıcının final tahmine etkisi eşittir.

Gelelim tesadüfi orman algoritmasına. Yukarıda bahsettiğimiz gibi bu algoritma da bagging altyapısına sahip. Bu da demek oluyor ki yukarıda bagging için saydığımız kurallar tesadüfi orman için de geçerli. Adından da anlaşılabileceği gibi bu algoritma zayıf sınıflandırıcı olarak karar ağaçlarını baz alır ve birden fazla karar ağacı oluşturarak final tahmine bunların hepsinin katkı yapmasını sağlar. Karar ağaçlarının çalışma prensibinden boosting ile ilgili yazılarımda bahsetmiştim. Fakat tesadüfi orman algoritması karar ağaçlarını oluştururken bildiğimiz yapının biraz dışına çıkıyor. Her karar ağacının oluşturulma aşamasında özelliklerin(features) ve gözlemlerin rastgele bir kısmı seçiliyor ve o kısım baz alınarak ağaç oluşturuluyor. Aynı şekilde diğer ağaçlarda da başka rastgele seçilmiş örneklemler kullanılıyor. Bu da en sonunda bize rastgele ağaçlardan oluşmuş bir orman veriyor.

1_Yd2JS7Jo7W6DHf6VBmGnIg

Evet aynı üstteki orman gibi diyebiliriz. Oluşturulacak ağaç sayısının belirlenmesi ve her karar ağacı oluşturulurken gerekli ayarların yapılması tabii ki yine hiperparametre optimizasyonu ile sonuçlanıyor. Biz de burada hiperparametre optimizasyonu yapacağız fakat çok detaya girip tamamı için yapmayacağız. Eğer n ağaçtan oluşan bir orman oluştursaydık aşağıdaki gibi olurdu.

1_i0o8mjFfCn-uD79-F1Cqkw

Gördüğünüz gibi finalde en çok oyu alan kategori final tahmin olarak açıklanıyor. Üstte de bahsettiğimiz gibi ağaçların kökleri dallara bölünürken veri setindeki özelliklerin tamamı değil, rastgele seçilmiş bir kısmı kullanılıyor ve gözlemlerin de rastgele seçilmiş bir kısmı işleme giriyor. Bu şekilde rastgele oluşturulmuş ağaçlar da varyansı ciddi oranda düşürüyor. Over-fitting problemine de değinecek olursak, tüm özellik ve gözlemleri kullanmak yerine ağaçlar oluşturulurken sürekli bunların rastgele altkümeleri kullanıldığından oluşturulan karar ağaçlarının zayıf bir öğrenici olması kuralı asla bozulmuyor ve böylece aşırı öğrenme problemi de pek ortaya çıkmıyor. Genellikle, veride ne kadar çok özelliğiniz var ise oluşturulan modelin kompleksliği de o kadar artacağından over-fitting tehlikesi de aynı oranda artacaktır. İşte tesadüfi orman üstteki özelliği sayesinde bunun da büyük oranda üstesinden gelmeyi başarıyor.

Evet teorik altyapıyı hazırladıktan sonra, artık uygulamaya geçelim.

library(caret)
library(e1071)

ControlMethod <- trainControl(method = "cv",
number = 5,
search = "grid")
Models <- list()

for (mtry in c(1, 2, 3)) {
TuneGrid <- expand.grid(mtry = mtry)
for (ntree in seq(100, 1000, 100)) {
set.seed(123)
RFModel <- train(class ~.,
data = Balanced_training_set,
method = "rf",
metric = "Kappa",
tuneGrid = TuneGrid,
trControl = ControlMethod,
ntree = ntree)
NumTrees <- toString(ntree)
NumPredictors <- toString(mtry)
Models[[paste(NumTrees, NumPredictors)]] <- RFModel
}
}

Yine kod bloğunun ne yaptığını açıklayarak başlayalım. Öncelikle 2 tane for döngüsü kullanıyoruz. Birinci döngü “mtry” hiperparametresini, ikinci döngü ise “ntree” hiperparametresini optimize ediyor. “mtry” hiperparametresi, karar ağaçları oluşurken köklerin dallara ayrılmasında kullanılan rastgele seçilmiş özellik sayısını belirtiyor. Yani ağaçlar yapılırken özelliklerin kaçı rastgele seçilsin bunu bildirdik. “ntree” hiperparametresi ise tahmin edebileceğiniz gibi kurulacak karar ağacı sayısını temsil ediyor. İlk döngüden gelen “mtry” değerlerinin hepsi için teker teker aşağıdaki “seq” komutu ile beraber oluşturduğumuz karar ağacı sayılarının tamamı denenecek ve en iyi sonucu verenleri biz seçeceğiz. Bunu yaparken de öncesinde “set.seed” komutu ile tekrar eden sonuçlar ya da değişmeyen sonuçlar oluşmasını sağlıyoruz. Son 3 satırda bu modelleri öncesinde oluşturduğumuz “Models” adlı boş listeye atıyoruz ve atarken de her elemana ayırt edici olması adına dahil oldukları hiperparametre ikilisini yani “ntree” ve “mtry” değerlerini yazdırıyoruz. Çıktıyı gördüğümüzde daha net anlaşılacaktır:

print(Models)

Sonuç:

12

Evet “Models” nesnesinin ürettiği çıktı çok uzun olduğu için sadece ilk elemanı gösteriyoruz. Bu ilk eleman en üstte görüldüğü gibi “mtry = 1” ve “ntree = 100” değerleri için oluşturulmuş model ve accuracy değeri 0.76 iken Kappa değeri 0.68 olarak gözüküyor. Bu şekilde tüm hiperparametre ikilileri için modeller oluşturuldu ve bu listeye atandı. Biz de şimdi bunları inceleyip en iyi performans göstereni tahminleme aşamasında kullanacağız. Evet bu modellerin ürettikleri sonuçları aşağıdaki gibi inceleyelim:

summary(resamples(Models))

“summary” komutu içerideki modellerin sonuçlarını bize aşağıdaki gibi özetliyor:

1314

Evet üstte hiperparametre ikilileri için sonuçlar gözüküyor ve tablo yine büyük olduğu için bir kısmını koydum. Her ikili için özet istatistikler çıkmış durumda ve bu çıktılar da hem “accuracy” hem de “kappa” metrikleri için hesaplanmış. Fakat buradan en iyi modeli görmek biraz zor gibi. Daha iyi belirleyebilmek için aşağıdaki gibi inceleyelim:

results <- summary(resamples(Models))
Acc_df <- as.data.frame(results$statistics[[1]])
Kappa_df <- as.data.frame(results$statistics[[2]])

Acc_graph <- ggplot(data = Acc_df,
mapping = aes(x = rownames(Acc_df),
y = Mean,
group = 1)) +
geom_line(color="red")

print(Acc_graph)

Kappa_graph <- ggplot(data = Kappa_df,
mapping = aes(x = rownames(Kappa_df),
y = Mean,
group = 1)) +
geom_line(color="blue",
linetype = "dashed")

print(Kappa_graph)

Kappa_df[which.max(Kappa_df$Mean), ]

Üstteki kodlarla öncelikle az önce gösterdiğimiz summary tablolarını iki metrik için de ayrı ayrı data frame nesnelerine dönüştürüyoruz ve sonrasında da grafiklerini çiziyoruz. Son satırda ise Kappa metriğini baz alarak hangi hiperparametre ikilisinin maksimum Kappa değerini verdiğini görmek istiyoruz. Sonuçları inceleyelim:

1516

Grafikler birbirlerine çok benziyor ve sayılar arasındaki farklar çok ufak küsüratlarda olduğu için grafik üzerinde de ayırt edilemiyor. Metrikler en düşük değerleri “mtry” hiperparametresi 1 iken, en yüksekleri ise 3 iken alıyorlar. Bu da aslında gayet mantıklı bir sonucu bize ima ediyor.   Ne de olsa ağaçları oluştururken rastgele sadece tek bir değişkeni kullanmak çok da iyi sonuçlar doğurmayacaktır. Son satırın da sonucunu öğrenerek en iyi hiperparametre ikilisini tespit edelim:

17

Evet gördüğünüz gibi en yüksek Kappa değeri 0.968 civarı ve bu değeri de ntree = 700 ve mtry = 3 hiperparametre ikilisindeyken almış. Biz de final modelde bu ikiliyi baz alacağız. Artık final modeli oluşturup tahminleme aşamasına geçelim:

cm <- trainControl(method = "none")

FinalRF <- train(class ~ .,
data = Balanced_training_set,
method = "rf",
tuneGrid = expand.grid(mtry = 3),
trControl = cm,
ntree = 700)

pred <- predict(FinalRF, test_set[ , -7])

confusionMatrix(pred, test_set$class)

Bu kez “trainControl” fonksiyonunu kullanırken “method = “none”” diyerek direkt olarak modelin eğitilmesini ve başka herhangi bir işlem yapılmamasını istiyoruz. Çünkü zaten hiperparametrelerimizi belirledik. Sonrasında “train” metodunu aynı şekilde kullanıyoruz ve “predict” fonksiyonu ile de tahminleri gerçekleştiriyoruz. Burada test setten 7.kolonu yani bağımlı değişkeni çıkardığımıza dikkat edelim. Son aşamada da “confusion matrix” tablosunu yani sonuçları gösteren tabloyu oluşturuyoruz. Sonucu görelim:

18

Evet accuray değeri 0.9682 ve Kappa değeri de 0.9324 gibi son derece yüksek değerler. Model gayet başarılı. Zaten üstteki confusion matrix’i inceleyecek olursanız köşegen üzerindeki sayıların fazlalığını yani doğru tahmin oranının çok yüksek olduğunu görebilirsiniz. Kaçan tahmin sayısı oldukça düşük. Bir de değişkenlerin önem sıralamasını inceleyelim:

varImp(FinalRF, scale = FALSE)

Sonuç:

19

Baktığımızda en önde gelen kategori değerlerine sahip olan değişkenin “safety” yani arabanın güvenliği olduğunu görüyoruz. Bu da aslında bize çizdiğimiz bar grafikteki sonucun mantıklı bir desteklenişini gösteriyor diyebiliriz. Değişken önemlerini bu şekilde inceleyerek modele etkisi az olan değişkenler çıkarılıp hem hesaplama yükü düşürülürken hem de model performansi artırılabilir. Fakat bizim veri setimizde zaten az değişken olduğundan böyle bir şeye ihtiyaç duymuyoruz.

Yazıyı bitirmeden önce son bir uygulama daha yapmak istiyorum. Tesadüfi orman metodunu bu kez de caret paketini kullanarak değil, “randomForest” paketini kullanarak uygulayalım. Herhangi bir hiperparametre optimizasyonu yapmadan direkt üstte seçtiklerimizle çalıştıracağız ve sonuçları karşılaştıracağız. Aşağıdaki gibi uygulayalım:

FinalRF_2 <- randomForest(formula = class ~.,
data = Balanced_training_set,
ntree = 700,
mtry = 3,
replace = TRUE,
importance = TRUE)

pred_2 <- predict(FinalRF_2, test_set[ , -7])

confusionMatrix(pred_2, test_set$class)

Bu kez “randomForest” fonksiyonu ile modeli eğittik ve hiperparametrelerimizi de verdik. “replace” argümanıyla iadeli seçimi sağladık ve en sonda da değişken önemlerinin de hesaplanmasını söyledik. Son 2 satır üstteki gibi tahminleri gerçekleştirip confusion matrix’i oluşturuyor. Sonuca bakalım:

20

Evet bu kez accuracy değeri 0.9595 ve Kappa da 0.9143 olarak hesaplandı. Bir önceki modelden az da olsa daha kötü bir performans göstermiş durumda. Yani bu problem için “caret” kütüphanesi “randomForest” kütüphanesine göre daha başarılı oldu.

Evet yazıyı burada bitirelim. Araba değerlendirmesi yapmak üzere tesadüfi orman metodunu kullandık ve bu algoritmayla yaptığımız tahminleri inceledik. Bir dahaki yazıda görüşmek üzere.

 

NOTLAR

  1. Random Forest algoritmasında çok detaylı bir hiperparametre optimizasyonu yapmayıp sadece iki hiperparametreyi optimize etmemize rağmen, elde ettiğimiz performans gayet iyiydi. Bu da bu algoritmanın aslında ne kadar güçlü olduğunu göstermektedir.
  2. Üstte çalıştırdığımız for döngüleri veri seti boyutu küçük olduğu için hızlı çalıştı. Literatürde kullanılan büyük veri setlerinde bu algoritmanın eğitilmesi uzun süreceği gibi, aynı şekilde tahminleme yapması da uzun sürecektir.

REFERANSLAR

Tune Machine Learning Algorithms in R (random forest case study)

https://topepo.github.io/caret/train-models-by-tag.html#random-forest

https://www.rdocumentation.org/packages/ggplot2/versions/2.1.0/topics/ggplot