R Programlamayı Kullanarak Naive Bayes Sınıflandırmayı Anlamak

En İyi Algoritmalar En Basittir 

Veri Bilimi alanı basit doğrusal regression modellerinden karmaşık topluluk tekniklerine doğru ilerlemiştir, ancak en çok tercih edilen modeller hala en basit ve en yorumlanabilir modellerdir. Bunlar arasında; regression, logistic, trees ve naive bayes teknikleri vardır.  Özellikle Naive Bayes algoritması, basit ama bir o kadar da güçlü olan mantık temelli bir tekniktir, çok büyük veri kümeleri için karmaşık algoritmalardan daha iyi performans gösterdiği bilinmektedir. 

Naive Bayes, Tıp Biliminde yaygın olarak kullanılan bir tekniktir ve özellikler Kanser tesbiti için kullanılmaktadır. Bu makalede, Naive Bayes ve uygulama örneklerinin arkasındaki temel mantık açıklanmaktadır.  

Olasılık Herşeyi Nasıl Tanımlar? 

Olasılığı, bir olayın gerçekleştiği durumların oranı olarak hesaplıyoruz ve buna olayın olasılığı diyoruz. Tek bir olay için olasılık olduğu gibi, bir grup olayın olasılığını, olay grubunun birlikte gerçekleştiği durumların oranı olarak görürüz. Olasılıktaki bir başka kavram, olayların belirli bir sırayla meydana gelmesini hesaplamaktır, yani bir şeyin zaten olduğu biliniyorsa, bundan sonra başka bir olayın gerçekleşme olasılığı ne olaraktır? Mantıken, kapsamımızı yalnızca bir şeyin zaten gerçekleştiği duruma daralttığımızı ve ardından ikinci olayımızın gerçekleştiği durumların oranını hesapladığımızı anlayabiliriz. Matematiksel olarak temsil etmek için, Eğer A ilk olayımız ve B ikinci olayımız ise P(B\A), B olayının oluşundan sonra A olayının olasılığını hesaplamak için istediğimiz olasılıktır( A’nın gerçekleşmesi koşulu altında B’nin gerçekleşme olasılığı.) 

P(A∩B), iki olayın birlikte meydana gelme olasılığıdır.  

P(B\A) = (P(B∩A))/P(A) 

P(B\A) = P(B)* P(A\B)/P(A) 

Bu, Naive Bayes algoritması için temeldir. Bu nedenle, Naive Bayes olayın olasılıkları ile ayrı ayrı farklılaşan farklı türde olayları ele alabilir, Yani, P(B) ve koşullu olasılık P(B\A). Eğer iki olasılık aynı ise, o zaman A olayının oluşunun B olayı üzerinde hiçbir etkisi olmadığı ve olayların bağımsız olaylar olarak bilindiği anlamına gelir. Koşullu olasılık 0 olursa, o zaman A olayının ortaya çıkması , B olayının gerçekleşmeyeceği anlamına gelir. Terside doğruysa, olaylar birbirini dışlayan olaylardır ve aynı anda olaylardan yalnızca birinin meydana gelmesi mümkündür. Diğer tüm durumlar, koşullu olasılığın orijinalinden daha düşük veya daha yüksek olabileceği Bağımlı olaylar olarak sınıflandırılır. Gerçek Hayatta,  her madeni para atma işlemi daha önce yapılan diğer tüm madeni para atma işlemlerinden bağımsızdır ve bu nedenle madeni para atma işlemleri bağımsızdır. Tek bir madeni para atmanın sonucu, birbirini dışlayan olaylardan oluşur. Aynı anda hem başımız hem de kuyruğumuz olamaz.  Birden fazla madeni para atma işlemini düşündüğümüzde, bağımlı olaylardan bahsederiz. 3 madeni paranın bir kombinasyonu için, nihai sonuç, birinci, ikinci ve üçüncü madeni para atma işlemine bağlıdır.  

Bu Olasılıkları Nasıl Hesaplarız? 

Tek bir olayın olasılığını hesaplamak kolaydır. Olayın gerçekleştiği durumların sayısının, olası vakaların toplam sayısına bölünmesi ile elde edilir. Örneğin,  Bir zar atıldığında 6 gelme olasılığı, tüm taraflar eşit gelme şansına sahipse, 1/6’dır.  Bununla birlikte, iki ve ya daha fazla olayın olasılıkları hesaplanırken dikkatli olunmalıdır. Her olayın olasılığını ayrı ayrı bilmek, birden fazla olayın gerçekleşme olasılığını hesaplamak için yeterli değildir. Ek olarak; olayların bağımsız olduğunu biliyorsak, bunların birlikte olma olasılığı, her olayın ayrı ayrı çarpımıdır.  

Bunu  matematiksel olarak şöyle gösteririz; P(A and B) = P(A)*P(B)- Bağımsız olaylar için 

Daha öncede belirttiğim gibi her yazı/tura işlemi diğer yazı/turalardan bağımsızdır.  Yani, iki madeni para atışında, Yazı-Yazı kombinasyonuna sahip olma olasılığı; P(Y-Y) = P(ilk atıştaki Y)* P(İkinci atıştaki Y) =1/2 * 1/2 = 1/4  

Eğer olaylar bağımsız değilse, Herhangi bir olayın olasılığını, ilk olay gerçekleştikten sonra ikinci olayın olasılığı ile çarparak bulabiliriz. 

Bunu matematiksel olarak şöyle gösterebiliriz;  P(A ve B) = P(A) * P(B\A) – Bağımlı Olaylar için 

Bağımlı olaylara bir örnek, değiştirilmeden kart çekmek olabilir. Çekilen 2 kartın papaz ve kız olduğunu bilmek istiyorsanız, ilk olayın olasılığının 52 karta, ikinci olayın olasılığının 51 karta bağlı olduğunu biliyorsunuz. 

Böylece, P(King ve Queen) = P(King)* P(Queen\King) 

Burada, P(K)=4/52. King çekildikten sonra , 51 kart içerisinde 4 Queen vardır. Bu yüzden, P(Q\K)= 4/51, P(K ve Q) =4/52 * 4/51 = 0,6% 

Bu,  Genel Çarpım Kuralı olarak bilinir. Aynı zamanda bağımsız olaylar senaryosu için de geçerlidir, ancak olaylar bağımsız olduğundan , P(B\A) P(B)’ eşit olur.  

Üçüncü durum birbirini dışlayan olaylar içindir. Eğer olaylar birbirini dışlıyorsa olaylardan yalnızca birinin gerçekleşebileceğini biliyoruz. Yani iki olayın birlikte olma olasılığı sıfırdır. Bazen olaylardan birinin meydana gelme olasılığı ile ilgileniyoruz ve bu, senaryodaki bireysel olasılıkların toplamıdır.  

P(A or B) = P(A) + P(B) –Birbirini dışlayan olaylar için 

Tek bir adil zar atışından bahsediyorsak, herhangi 2 sayının birlikte ortaya çıkma olasılığı sıfırdır. Bu durumda, herhangi bir asal sayının oluşma olasılığı, her bir asal sayının oluşum toplamıdır. 

Olaylar birbirini dışlamamış olsaydı, olaylardan birinin olasılığı, iki olayın bir araya gelme olasılığını 2 kez sayardır. Dolayısı ile bu olasılığı çıkarıyoruz.  

P(A or B) = P(A) + P(B)-P(A and B)- Birbirini dışlamayan olaylar için 

Tek bir 6 yüzlü adil bir zar atışında, 2 ve ya 3’ün katlarını atma olasılığı, 6’nın hem 2 hem de 3’ün katı olduğu ve iki kez sayıldığı için birbirini dışlamayan bir olay senaryosunu tanımlar.  

Böylece,  

P(multiple of 2 or 3) = P(multiple of 2) + P(multiple of 3)- P(multiple 2 AND 3)  

=P(2,4,6)+P(3,6) –P(6) = 3/6 + 2/6 -1/6 = 2/3 

Bu, Genel Toplam Kuralı olarak bilinir ve Çarpma Kuralına benzer şekilde, birbirini dışlayan olaylar senaryosu içinde geçerlidir, ancak bu durumda P(A and B) sıfırdır.  

Naive Bayes Algoritmasının nasıl çalıştığını anlamak için ihtiyacımız olan tek şey budur. Algoritma, tüm bu senaryoları dikkate alır ve öğrenir. Örnek vir veri seti üzerinden bu algoritmayı çalıştıralım. 

Naive Bayes – Çok Naive(Naif) Olmayan Bir Algoritma 

Naive Bayes Algoritmasının Naive olarak adlandırılmasının nedeni basit ve ya aptal olması değildir. Bunun nedeni, Algoritmanın, verilerin birbirinden bağımsız özelliklere sahip olduğu konusunda çok güçlü varsayımda bulunması, gerçekte ise bir şekilde bağımlı olabilmeleridir. Başka bir deyişle, bir sınıftaki bir özelliğin varlığının, diğer tüm özelliklerin varlığıyla ilgisiz olduğunu varsayar. Bu bağımsızlık varsayımı geçerli ise, Naive Bayes son derece iyidir ve genellikle diğer modellerden daha iyi performans gösterir.Naive Bayes, Sürekli(Continous) özelliklerle de kullanılabilir ancak kategorik değişkenler (categorical variables) için daha uygundur. Tüm giriş özellikleri Categorical ise Naive Bayes önerilir.Bununla birlikte, sayısal özellikler söz konusu olduğunda, sayısal değişkenin normal dağıldığına dair başka bir güçlü varsayımda bulunur.  

R, Naive Bayes eğitim fonksiyonunu sağlayan ‘e1071’ adlı bir paketi destekler. 

Naive Bayes R Eğitimi için klasik Titanic veri setini kullanacağız ve Naive Bayes algoritmasının “Hayatta Kalmış” olarak tanımlayabileceği durumları bulacağız.  

R’daki Titanic veriseti , 4 faktöre göre özetlenen yaklaşık 2200 yolcu için bir tablodur. Dört Faktör; 

  1. Ekonomik Durum(Class) :   1.sınıf, 2.sınıf, 3.sınıf ve mürettebat  
  1. Cinsiyet (Gender): Kadın, Erkek  
  1. Yaş(Age) : Çocuk, Yetişkin 
  1. Hayatta Kalıp Kalmamak(Survived Status). 

Her Yaş, cinsiyet, sınıf ve Hayatta Kalma durumu kombinasyonu için tablo, kombinasyona giren yolcu sayısını verir. Yolcuları sınıflandırmak ve ne kadar iyi performans gösterdiğini kontrol etmek için Naive Bayes tekniğini kullanacağız. Bildiğimiz gibi Bayes Teoremi koşullu olasılığa dayanır ve şu formül kullanılır; 

P(A\B) = P(A) * (P(B\A)/P(B)) 

Artık bu Koşullu olasılığın olayların çarpımından nasıl geldiğini biliyoruz, dolayısı ile genel çarpım kuralını kullanırsak , teoremin başka bir vasyasyonunu elde ederiz. Yani;  

P(A and B) = P(A) * P(B\A)    kullanarak,  Bayes Teoreminin varyasyonu olan koşullu olasılık değerini elde edebiliriz : P(B\A) = P(A and B) / P(A) 

P(A and B) de P(B)* P(A\B)’ ye eşit olduğundan , onu değiştirebilir ve orijinal P(B\A) = P(B) * P(A\B) formülünü geri alabiliriz. P(A); yaş cinsiyet ve ekonomik durum arasındaki özelliklerinin herbiri için kullanılarak , Naive Bayes Algoritmasının kombinasyonunun koşullu Hayatta Kalma olasılığını hesaplayacaktır.  

#Getting started with Naive Bayes
#Install the package
#install.packages(“e1071”)
#Loading the library
library(e1071)
?naiveBayes #The documentation also contains an example implementation of Titanic dataset
#Next load the Titanic dataset
data(“Titanic”)
#Save into a data frame and view it
Titanic_df=as.data.frame(Titanic)

Sınıf, Cinsiyet, Yaş ve Hayatta Kalma gibi olası tüm kombinasyonları sıklıkları ile temsil eden 32 gözlem olduğu görünmektedir.Özetlendiği için bu tablo modelleme amaçlı değildir.Tabloyu ayrı satırlara genişletmemiz gerekiyor. Tablodaki frekanslara göre tekrar eden bir satır dizisi oluşturalım; 

#Creating data from table
repeating_sequence=rep.int(seq_len(nrow(Titanic_df)), Titanic_df$Freq) #This will repeat each combination equal to the frequency of each combination
#Create the dataset by row repetition created
Titanic_dataset=Titanic_df[repeating_sequence,]
#We no longer need the frequency, drop the feature
Titanic_dataset$Freq=NULL

Veriler artık Naive Bayes Algoritmasının işlemesi için hazırdır. Modele uyalım; 

#Fitting the Naive Bayes model
Naive_Bayes_Model=naiveBayes(Survived ~., data=Titanic_dataset)
#What does the model say? Print the model summary
Naive_Bayes_Model

Ayrık Tahminciler için Naive Bayes Sınıflandırıcısı; 

Call:
naiveBayes.default(x = X, y = Y, laplace = laplace)

A-priori probabilities:
Y
      No      Yes 
0.676965 0.323035 

Conditional probabilities:
     Class
Y          1st          2nd         3rd         Crew
  No    0.08187919  0.11208054  0.35436242  0.45167785
  Yes   0.28551336  0.16596343  0.25035162  0.29817159

     Sex
Y          Male         Female
  No    0.91543624  0.08456376
  Yes   0.51617440  0.48382560

     Age
Y         Child         Adult
  No    0.03489933  0.96510067
  Yes   0.08016878  0.91983122

Model, herbir özellik için ayrı ayrı koşullu olasılık oluşturur. Ayrıca verilerimizin dağılımını gösteren a-priori olasılıklara da sahibiz. Veriler üzerinde nasıl performans gösterdiğimizi hesaplayalım; 

#Prediction on the dataset
NB_Predictions=predict(Naive_Bayes_Model,Titanic_dataset)
#Confusion matrix to check accuracy
table(NB_Predictions,Titanic_dataset$Survived)
NB_Predictions      No      Yes
                No      1364    362
                Yes     126     349

Sonuçlara sahibiz. 1490 “Hayır” durumundan 1364’ünü doğru, 711 “Evet” durumundan 349’unu doğru olarak sınıflandırabiliyoruz. Bu, Naive Bayes Algoritmasının “Hayır” durumlarının tahin etme yeteneğinin yaklaşık %91,5 olduğu, ancak “Evet” durumlarının yalnızca %49’una düştüğü ve %77,8 lik bir genel doğrulukla sonuçlandığı anlamına gelir.  

Sonuç: Daha İyisini Yapabilir miyiz? 

Naive Bayes, veriler aynı kaldığı sürece farklı çalıştırmalarda farklı sonuçlar/performans gösteremeyeceğinizi ifade eden parametrik bir algoritadır. Bununla birlikte, “mlr” paketini kullanarak Naive Bayes Algoritmasının başka bir uygulamasını deneyeceğiz/öğreneceğiz.  Okuyucular için aynı oturumun devam ettiğini varsayarsak, paketi(“mlr”) kurup yükleyeceğim ve bir model uyarlamaya başlayacağım; 

#Getting started with Naive Bayes in mlr
#Install the package
#install.packages(“mlr”)
#Loading the library
library(mlr)

“mlr” paketi bir çok modelden oluşur ve  görevler yaratarak ve eğitilmiş öğrenciler ile çalışır. Titanic verisetini kullanarak bir sınıflandırma görevi oluşturalım ve Naive Bayes Algoritması ile bir model uyarlayalım; 

#Create a classification task for learning on Titanic Dataset and specify the target feature
task = makeClassifTask(data = Titanic_dataset, target = "Survived")
#Initialize the Naive Bayes classifier
selected_model = makeLearner("classif.naiveBayes")
#Train the model
NB_mlr = train(selected_model, task)

“e1071” paketinde yazdırılan modelin özeti, öğrenen modelinde saklanır. Yazdıralım ve karşılaştıralım; 

#Read the model learned  
NB_mlr$learner.model
Naive Bayes Classifier for Discrete Predictors

Call:
naiveBayes.default(x = X, y = Y, laplace = laplace)

A-priori probabilities:
Y
      No      Yes 
0.676965 0.323035 

Conditional probabilities:
     Class
Y               1st         2nd         3rd         Crew
    No      0.08187919  0.11208054  0.35436242  0.45167785
    Yes     0.28551336  0.16596343  0.25035162  0.29817159

     Sex
Y               Male        Female
     No     0.91543624  0.08456376
    Yes     0.51617440  0.48382560

     Age
Y           Child       Adult
    No      0.03489933  0.96510067
    Yes     0.08016878  0.91983122

Modelin a-priori olasılıkları ve koşullu olasılıkları, beklendiği gibi “e1071” paketi tarafından hesaplanana benzer. Bu, tahminleriizinde aynı olacağı anlamına gelir. 

#Predict on the dataset without passing the target feature
predictions_mlr = as.data.frame(predict(NB_mlr, newdata = Titanic_dataset[,1:3]))

##Confusion matrix to check accuracy
table(predictions_mlr[,1],Titanic_dataset$Survived)
        No      Yes
  No    1364    362
  Yes   126     349

Gördüğümüz gibi tahminlerimiz tamamen aynı. Geliştirmenin tek yolu, daha fazla özelliğe ve ya daha fazla veriye sahip olmaktır. Belki tam yaş, aile büyüklüğü, gemideki ebeveyn sayısı ve kardeş sayısı gibi daha fazla özelliğimiz olursa Naive Bayes Algoritması kullanarak daha iyi bir modele ulaşabiliriz. Özünde, Naive Bayes Algoritası güçlü bir temel oluşturma avantajına sahiptir ve çok sağlamdır. Naive Bayes Fonksiyonunu da içeren “CARET” paketini de biliyorum ancak aynı olasılıkları ve tahminleri bize verecektir. 

Makalede Kullanılan Kodun Tamamı: 

#Getting started with Naive Bayes
#Install the package
#install.packages(“e1071”)
#Loading the library
library(e1071)
?naiveBayes #The documentation also contains an example implementation of Titanic dataset
#Next load the Titanic dataset
data("Titanic")
#Save into a data frame and view it
Titanic_df=as.data.frame(Titanic)
#Creating data from table
repeating_sequence=rep.int(seq_len(nrow(Titanic_df)), Titanic_df$Freq) #This will repeat each combination equal to the frequency of each combination

#Create the dataset by row repetition created
Titanic_dataset=Titanic_df[repeating_sequence,]
#We no longer need the frequency, drop the feature
Titanic_dataset$Freq=NULL

#Fitting the Naive Bayes model
Naive_Bayes_Model=naiveBayes(Survived ~., data=Titanic_dataset)
#What does the model say? Print the model summary
Naive_Bayes_Model

#Prediction on the dataset
NB_Predictions=predict(Naive_Bayes_Model,Titanic_dataset)
#Confusion matrix to check accuracy
table(NB_Predictions,Titanic_dataset$Survived)

#Getting started with Naive Bayes in mlr
#Install the package
#install.packages(“mlr”)
#Loading the library
library(mlr)

#Create a classification task for learning on Titanic Dataset and specify the target feature
task = makeClassifTask(data = Titanic_dataset, target = "Survived")

#Initialize the Naive Bayes classifier
selected_model = makeLearner("classif.naiveBayes")

#Train the model
NB_mlr = train(selected_model, task)

#Read the model learned  
NB_mlr$learner.model

#Predict on the dataset without passing the target feature
predictions_mlr = as.data.frame(predict(NB_mlr, newdata = Titanic_dataset[,1:3]))

##Confusion matrix to check accuracy
table(predictions_mlr[,1],Titanic_dataset$Survived)

Kaynak: https://www.r-bloggers.com/2018/01/understanding-naive-bayes-classifier-using-r/

Eylem Batak tarafından Türkçe’ye çevrilmiştir.