Merhabalar, Bu makalemde sizlerle beraber Data Mining(Veri Madenciliği) algoritmalarından Naive Bayes algoritmasını inceleyeceğiz. Algoritmanın çalışma şeklini çözdükten sonra ise bu algoritmayı çalıştırıp bize sonuçları üretebilecek bir bileşen yazacağız. Data Mining elde bulunan verilerin işlenerek bilgiye ulaşılması işlemidir. Naıve Bayes ise bu işlemde kullanılabilecek sınıflandırma algoritmalarının en basitlerinden bir tanesidir. Açıklamak gerekirse naive bayes algoritmasında her kriterin sonuca olan etkilerinin olasılık olarak hesaplanması temeline dayanmaktadır. Data mining işlemini en çok verilen örneklerden biri ile açıklayacak olursak elimizde tenis maçının oynanıp oynanmamasına dair bir bilgi olduğunu düşünelim. Ancak bu bilgiye göre tenis maçının oynanması veya oynanmaması durumu kaydedilirken o anki hava durumu, sıcaklık, nem ve rüzgar durumu bilgileri de alınmış olsun. Biz bu bilgileri değerlendirdiğimizde varsayılan tahmin yöntemleri ile hava bugün rüzgarlı tenis maçı bugün oynanmaz şeklinde kararları farkında olmasak'da veririz. Ancak Data Mining bu kararların tüm kriterlerin etkisi ile verildiği bir yaklaşımdır. Dolayısıyla biz ileride öğrettiğimiz sisteme bugün hava güneşli, sıcak, nemli ve rüzgar yok şeklinde bir bilgiyi verdiğimizde sistem eğitildiği daha önce gerçekleşmiş istatistiklerden faydalanarak tenis maçının oynanma ve oynanmama ihtimalini hesaplar ve bize tahminini bildirir. Bu tür tahminler gsm, bankacılık, sigortacılık, market gibi birçok alanda kullanılmaktadır. Bilhassa gelecek yıllara ait yönetimsel kararların alınmasında, sahtekarlık denetlenmesinde, birlikte gerçekleşen koşulların ortaya çıkarılmasında kullanılmaktadır. Belirttiğimiz sektörlere örnekler verecek olursak GSM operatörlerinde sahtekarlık denetlenmesinde, Bankacılık sektöründe karakteristiğiniz dışında yüklü bir kredi kartı harcaması, havale yaptığınızda sahtekarlık olabileceğine dair, Sigortacılıkta sigorta edilen kişi araç veya mülkün belirli kriterlere göre o risk'e uğrama olasığının tespit edilmesinde, Marketlerde hangi ürünlerin birlikte satıldığının ortaya çıkarılmasında kullanılmaktadır. Bu belirttiklerimizin yanısıra sağlık sektöründe bir kişinin tahlil sonuçlarının değerlendirilerek bir hastalığa yakalanmış olup olmama olasılığının değerlendirilmesindede sıkça kullanılmaktadır. Data Mining'in kullanım alanları sadece belirttiğimiz örneklerle sınırlandırılamaz. Kişisel görüşümü belirtmem gerekirse bugüne kadar yazdığımız uygulamalarda firmaların verilerini irili ufaklı veritabanlarında topladık. Artık bu veriler işlenebilecek ve bu verilerden bilgi denen esas değerli kavram çıkarılabilecek düzeye gelmiştir. Data Mining için elinizdeki verinin çokluğundan ziyade verinin kaliteli olması önemlidir. Kaliteli veriler kirli bilgiler içermeyen, eksik veriler içermeyen, gruplanabilir ve ölçeklenebilir veriler içeren veritabanlarından elde edilebilir veya data mining adımlarından biri olan pre-processing aşamasında bu bilgiler silinerek veya çeşitli yöntemler uygulanarak kaliteli hale getirilirler.bu adımda veri aktarımları, kirli verinin temizlenmesi, boş alanların sonucu etkilemeyecek şekilde doldurulması veya boş alan içceren verilerin silinmesi gibi işlemler yapılmaktadır. Bir sonraki adım ise çeşitli algoritmaların uygulanması ve bu algoritmalardan çıkan verilerin test edilmesi sonucu en sağlıklı algoritmaya karar verilmesi ve bu algoritmanın karar verme mekanizması olarak uygulamalara implement edilmesi hedeflenmektedir. Peki bilgisayar dediğimiz yapı bu işlemleri nasıl yapıyor ve nasıl karar verebilecek zeka yapısına ulaşabiliyor. Machine Learning denilen bu sistem esasında belirli algoritmaların (Tree algoritmaları, Logistic algoritmaları, Bayes algoritmaları, Neural Network algoritmaları) elimizde bulunan veriye uygulanması sonucu gerçekleşir. Elimizde bulunan verinin yapısına
ve içeriğine göre algoritmaların farklı problemlerde farklı başarı oranları göstermesi doğaldır. Dolayısıyla en iyi algoritma budur diye genel birşey yoktur problemin tipine göre değişebilmektedir. Algoritma ilk önce belirli bir training(eğitim) data'sı ile eğitilir. Daha sonra eğitilen bu algoritma(genellikle test datasının yarısı hacminde bir data ile) testing(test) datası ile test edilir. Buradaki amaç daha önceden eğitilmiş algoritmanın test datasında bulunan kriterler ile test datasında bulunan sonuçları doğru tahmin edip edememesinin incelenmesidir. Buda algoritmanın başarısı anlamına gelmektedir. Bu kısımda algoritma tarafından üretilen değerlerin TruePositive, TrueNegative, FalseNegative, FalsePositive sayılarına göre değerlendirilmesi gerekmektedir. TP: Olumlu sonucu olan ve olumlu öngörülmüş örnek sayısıdır. FN: Olumlu sonucu olan ve olumsuz öngörülmüş örnek sayısıdır. FP : Olumsuz sonucu olan ve olumlu öngörülmüş örnek sayısıdır. FP : Olumsuz sonucu olan ve olumsuz öngörülmüş örnek sayısıdır. Bu oranlar ile ilgili örnek bir tablo aşağıdadır. Doğru Öngörülen Sonuç 1 0 1 TP FN 0 FP TN Şimdi ise doğruluk ve hata oranı hesaplamalarına bakalım. Doğruluk = (TP+TN)/(TP+FN+FP+TN) Hata Oranı = (FN + FP)/(TP+FN+FP+TN) Şimdi bu işlemleri yapabilmek için Naive Bayes algoritmasının nasıl çalıştığını inceleyelim. Elimizde bulunan örnek veri kümesinin aşağıdaki gibi olduğunu düşünelim.
Elimizde bulunan bu verilere göre 15. gün oluşabilecek bir olayın sonucunu tahmin etmeye çalışalım. Bu 15. gün'de bulunan veri Outlook(Sunny), Temperature(Cool), Humidity(High), Wind(Strong) şeklinde olsun ve tenis maçının oynanıp oynanmayacağını tahmin edelim. Naive Bayes algoritmasının formülü aşağıdaki gibidir. Söz ile anlatmak gerekirse bir sonucun çıkma olasılığı o sonuca etkiyen tüm faktörlerin o sonucu sağlama olasılıklarının çarpımıdır. Şimdi yukarıdaki örnek için bu hesabı yapacak olursak. PlayTennis sonucunun yes çıkması olasılığı sonuçlardan 9 tanesi yes olduğundan 9/14'dür. Bu olasılık için bundan sonraki tüm hesaplarımız bu 9 kayıt üzerinden yapılacaktır. Outlook Sunny iken PlayTennis'in yes çıkma olasılığı : 2/9 Temperature Cool iken PlayTennis'in yes çıkma olasılığı : 3/9 Humidity High iken PlayTennis'in yes çıkma olasılığı : 3/9 Wind Strong iken PlayTennis'in yes çıkma olasılığı : 3/9 Dolayısıya sonucun Yes çıkma olasılığı P(y)=9/14 x 2/9 x 3/9 x 3/9 x 3/9=0,0053 Şimdi ise sonucun No çıkma olasılığını inceleyelim. PlayTennis sonucunun no çıkması olasılığı sonuçlardan 5 tanesi no olduğundan 5/14'dür. Bu olasılık için bundan sonraki tüm hesaplarımız bu 5 kayıt üzerinden yapılacaktır.
Outlook Sunny iken PlayTennis'in no çıkma olasılığı : 3/5 Temperature Cool iken PlayTennis'in no çıkma olasılığı : 1/5 Humidity High iken PlayTennis'in no çıkma olasılığı : 4/5 Wind Strong iken PlayTennis'in no çıkma olasılığı : 3/5 Dolayısıya sonucun No çıkma olasılığı P(n)=5/14 x 3/5 x 1/5 x 4/5 x 3/5=0,0205 No çıkma olasılığı yes çıkma olasılığından büyük olduğundan dolayı (P(n)>P(y)) algoritmanın öğrendiği verilerden tahmini tenis maçının oynanmayacağı yönündedir. Şimdi bu algoritmayı C# ile yazalım. Öncelikle NaiveBayes algoritmasını çalıştırabileceğimiz bir class yapalım ve bu class'ın adını NaiveBayes koyalım. using System; using System.Collections.Generic; using System.Text; using System.Data; namespace NaiveBayes public class NaiveBayes Şimdi ise Training ve Testing datalarını taşıyacağımız iki property olan training ve testing dataset propertylerini yazalım. Bu uygulamamızda veriler DataTable ile taşınacaktır.
private DataTable _TrainingSet; public DataTable TrainingSet get return _TrainingSet; set _TrainingSet = value; private DataTable _TestingSet; public DataTable TestingSet get return _TestingSet; set _TestingSet = value; Şimdi yazacağımız property'ler ise sonuçların bulunduğu kolonun adını taşıyan ResultColumnName, datanın sonuç üretmek için ilk önce bir sefere mahsus işleme tabi tutulmasının gerekliliğini denetleyebilmek amacıyla IsDataProcessed ve test sonucu doğru ve yanlış tahmin sayısının tutulduğu CorrectlyPredictedCount ve IncorrectlyPredictedCount propertyleridir. private string _ResultColumnName; public string ResultColumnName get return _ResultColumnName; set _ResultColumnName = value; private bool _IsDataProcessed = false; public bool IsDataProcessed get return _IsDataProcessed; private int _CorrectlyPredictedCount = 0; public int CorrectlyPredictedCount get return _CorrectlyPredictedCount; private int _IncorrectlyPredictedCount = 0; public int IncorrectlyPredictedCount get return _IncorrectlyPredictedCount; Şimdi yazacağımız 3 yerel değişkende sonuç üretiminde kullanılacak verinin biraz önce bahsettiğim ön işlem sonuçlarının tutulması için gereklidir. Bu değişkenlerden bir tanesi Dictionary tipinde dir ve adı decolumnvalues dir. Bu değişkende her kolonda bulunan veriler distinct bir şekilde tutulmaktadır. Yukarıdaki örnek için bu değerler Outlook'ta Sunny,Overcast ve Rain olabilmektedir. Bir diğer değişken ise DataTable tipinde dtresultpossibilityratio değişkenidir. Bu değişkende ise daha önceden tanımlanmış ResultColumnName alanında bulunan farklı kayıtlara göre sonuçların gelme olasılığı tutulmaktadır. Yukarıdaki örnekte bu değişkenin değeri Yes için 9 No için 5 değerini barındıracak bir datatable'dır. Ve bu datatable'ın yapısı
aşağıda gösterilmektedir. Son değişkenimiz ise hangi kolonda bulunan verinin hangi sonucu ne kadar etkileyeceğine dair bilgilerin tutulduğu datatable dır ve adı dtresult'tur. Bu datatable'ın yapısını inceleyelim ve yorumlayalım. Bu tabloda bulunan veriden sonuç No olduğunda Outlook'un sunny olduğu 3 kayıt vardır. sonuç yes olduğunda ise 2 kayıt vardır şeklindeki bir bilgiye çok çabuk bir şekilde ulaşabilmekteyiz. Şimdi bu değişkenleri dolduracağımız metodumuzu yazalım.ilk önce tanımladığımız datatable lara verileri saklayabilmemiz için gerekli kolonları ekliyoruz. public void ProcessData() dtresult.columns.add("columnname", typeof(string)); dtresult.columns.add("columndata", typeof(string)); dtresult.columns.add("resultcolumnvalue", typeof(string)); dtresult.columns.add("count", typeof(int)); dtresultpossibilityratio.columns.add("columnvalue", typeof(string)); dtresultpossibilityratio.columns.add("ratio", typeof(int)); Şimdi ise her bir kolon için bulunan farklı değerleri bir list'e toplayacağız ve daha sonrasında bu listi kolon adı key kendisi ise value olacak şekilde bir hashtable'a atacağız. foreach (DataColumn dc in TrainingSet.Columns) List<string> l = new List<string>(); foreach (DataRow dr in TrainingSet.Rows) if (!l.contains(dr[dc.columnname].tostring()))
l.add(dr[dc.columnname].tostring()); decolumnvalues.add(dc.columnname, l); bsp; Şimdi ise her bir sonucun oluşma ihtimalini hesaplayıp datatable'a yazacağız. foreach (string res in decolumnvalues[resultcolumnname]) dtresultpossibilityratio.rows.add(new object[] res, TrainingSet.Select(ResultColumnName + "='" + res + "'").Length ); Şimdi bulunan her kolondaki her farklı verinin sonuca etki etme olasılığını hesaplayarak bunu dtresult datatable değişkeninde saklayacağız. Bu işlemler bittikten sonra datanın hesap için hazırlanması bitmiş durumdadır. bundan dolayı IsDataProcessed değişkeninin true ya set ediyoruz. foreach (DataColumn dc in TrainingSet.Columns) if (dc.columnname!= ResultColumnName) foreach (string s in decolumnvalues[dc.columnname]) foreach (string s1 in decolumnvalues[resultcolumnname]) int count = TrainingSet.Select(dc.ColumnName + "='" + s + "' AND " + ResultColumnName + "='" + s1 + "'").Length; dtresult.rows.add(new object[] dc.columnname, s, s1, count ); _IsDataProcessed = true; Bu kısımda ise kullanıcı tarafından verilen bir datarow'da bulunan verilerin predict edilmesi işlemini gerçekleştirecek metodu yazacağız. Bu metod her olasılık için sonuçları hesaplayacak ve en yüksek olasılığa sahip olanı bize döndürecektir. Kodu açıklamak gerekirse bu kodda ilk önce datanın process edilip edilmediğine bakılmaktadır. Data process edilmediyse data ilk önce process edilmektedir. Daha sonra olası her sonucun gerçekleşme ihtimali ile verilen datarowda bulunan verilerin bu sonuca etki oranları yukarıda anlattığımız gibi çarpılarak o sonucun çıkma olasılığı hesaplanmaktadır. Kodun son kısmında ise en büyük olasılığa sahip olan sonuç string olarak geri döndürülmektedir. public string Predict(DataRow dr) if (!IsDataProcessed) ProcessData();
string winner = ""; decimal winnervalue = 0; foreach (string s in decolumnvalues[resultcolumnname]) int resultcount = Convert.ToInt32(dtResultPossibilityRatio.Select("ColumnValue='" + s + "'")[0]["Ratio"]); decimal result = Convert.ToDecimal(resultCount) / TrainingSet.Rows.Count; foreach (DataColumn dc in TrainingSet.Columns) if (dc.columnname!= ResultColumnName) result = result * Convert.ToDecimal(dtResult.Select("ColumnName='" + dc.columnname + "' AND ColumnData='" + dr[dc.columnname] + "' AND ResultColumnValue='" + s + "'")[0]["Count"]) / resultcount; if (result > winnervalue) winnervalue = result; winner = s; return winner; Kullanacağımız bir metod ise verimizi test etmek için kullanacağımız Test metodudur. Bu metodda ise verilen Test datasında bulunan her datarow için predict metodu çalıştırılmakta ve tahmin edilen sonucun doğru sonuç olup olmadığı kontrol edilip duruma göre doğru veya yanlış cevap sayısı arttırılmaktadır. public void Test() foreach (DataRow dr in TestingSet.Rows) if (Predict(dr) == dr[resultcolumnname].tostring()) _CorrectlyPredictedCount++; else _IncorrectlyPredictedCount++; Oluşturduğumuz class'ın genel yapısını inceleyecek olursak şeması aşağıdaki gibidir.
Şimdi bu yazdığımız algoritmaları test etmek amacıyla ufak bir windows uygulaması yazalım.bu uygulamada iki tane button bulunsun ve bu buttonlardan biri belirli bir koşulun sonucunu bize verirken diğeri ise algoritmamızın uyumluluğu için test yapıyor olsun. İlk butonumuz verilen koşullara göre sonucu tahmin etmektedir. Bu kısımda kullanılan Örnek DMHelper.GetSampleData() metodu bize birazönceki örnekte incelediğimiz datayı döndürecek static bir metoddur. Örnek kodun içinde mevcuttur. DataTable dt = DMHelper.GetSampleData(); NaiveBayes nb = new NaiveBayes(); nb.trainingset = dt; nb.resultcolumnname = "PlayTennis"; DataRow dr = dt.newrow(); dr["outlook"] = "Sunny"; dr["temperature"] = "Hot"; dr["humidity"] = "Normal"; dr["wind"] = "Strong";
MessageBox.Show(nb.Predict(dr)); İkinci button ise bize verdiğimiz datatable'lar sonucunda algoritmamızın başarılılık oranını vermektedir. DataTable dt = DMHelper.GetSampleData(); NaiveBayes nb = new NaiveBayes(); nb.trainingset = dt; nb.testingset = dt; nb.resultcolumnname = "PlayTennis"; nb.test(); MessageBox.Show("Correctly Classified Instances : " + nb.correctlypredictedcount.tostring()); MessageBox.Show("Inorrectly Classified Instances : " + nb.incorrectlypredictedcount.tostring()); Bu makalemde naive bayes algoritmasının C# kullanılarak nasıl yazılabileceğini inceledik. Umarım faydalı olmuştur. tamer.oz@bilgeadam.com tamer.oz@yazgelistir.com oztamer@hotmail.com