Machine Learning #2 — Korelasyon Matrisi, Özellik Seçimi, Sınıfların Dengesizliği, Karar Ağaçları, Kesinlik/Duyarlılık/F1 Skoru
Merhabalar, Machine Learning serimin ikinci yazısında
- Yeni bir sınıflandırma modelini kullanacak
- Tahminleyici değişkenlerin hedef değişken ile aralarındaki ilişkiyi inceleyecek
- Veri önişlemesi kısmında yeni yöntemler görecek
- Modelimizin başarımını ölçmek için kullanabileceğimiz yeni yöntemlere değineceğiz.
Aynı zamanda veri kümesi dengesizliklerine, model başarımını değerlendirirken yapabileceğimiz hatalara ve bunları gidermek için yapılabileceklere değineceğimiz bir yazı olacak.
Temel kütüphanelerimizi import ederek başlıyoruz.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as snsdf = pd.read_csv(‘winequality-red.csv’)
Bu yazıda, şarap örneklerinin kalitelerini, kimyasal değerlerine göre tahmin etmeye çalışan bir şarap tadımcısı modeli geliştireceğiz. Veri kümesini, ilk yazıda da faydalandığımız kaynaktan edindim. Buradan ulaşabilirsiniz.
Serinin ilk yazısında değindiğimiz metodlara tekrar ayrıntılı olarak değinmeyeceğiz. İlk olarak Keşifsel Veri Analizi kısmıyla başlıyoruz. Bu bölüm ile ilgili bilgiyi bu yazıyı inceleyerek edinebilirsiniz.
Nümerik EDA
df.info()
Veri kümemiz 1599 satır ve 12 sütundan oluşuyor. İlk 11 özelliği öğrenerek, quality özelliğini tahmin etmeye çalışacağız.
df.describe()
Burada, özellik değerlerimize dair birtakım özetler görüyoruz. Her bir sütunun mean, max, std ve min değerlerinin yanı sıra, %25, %50 ve %75 gibi ifadelerimiz var.
- Min ve max, o sütundaki en küçük ve en büyük sayı değerlerini,
- mean değeri sütun değerlerinin ortalamasını, std standart sapma değerini
- %25, %50 ve %75 değerleri de sütundaki değerlerin yüzde kaçının o değere eşit veya altında olduğunu gösterir.
Tablodaki quality sütununu incelediğimizde, değerlerin 3 ve 8 arasında değiştiğini görüyoruz(min değeri 3, max değeri 8). Ve, bu sütundaki verilerin dörtte biri 5 ve altında(3, 4, 5) iken, dörtte üçü de 6 ve altında (3, 4, 5, 6). Ortalama değerimiz de 5.63.
Bu değerler bize veri kümemizdeki quality değerlerinin çoğunun ortalama değerlere(5 ve 6 gibi) sahip olduğunu, dağılımın dengesiz olduğunu göstermektedir.
Problem: Bu dengesizlik, modelimizin orta kalite şarabı iyi ayırt edebilmesine, ancak düşük kaliteli veya yüksek kaliteli şarabı ayırt edememesine sebep olacaktır. Sınıfların Dengesizliği(Class Imbalanced) adı verilen bu probleme, ilgili başlıkta bir çözüm geliştirmeye çalışacağız.
df.head(10)
volatile acidity, citric acid gibi değerlerin 0'a oldukça yakınken, free sulfur dioxide, total sulfur dioxide değerlerinin ise genellikle 0'dan çok büyük olduğunu görmekteyiz.
İlk yazıda değindiğimiz kNN gibi sınıflandırıcıların, uzaklık hesabı yaparak çalıştığını hatırlayın. Bu durumda, sayısal olarak büyük değerler analitik düzlemin dış köşelerinde konumlanacak, uzaklık hesabında çıkan büyük değerlerden dolayı modelimiz yanlış tahminler yapabilecektir. Bu durumun da çözümüne değineceğiz.
Özellik Seçimi & Korelasyon Matrisi
İnceleyeceğimiz diğer bir durum da, tahminleyici değişkenlerimizin arasındaki artış/azalış ilişkisidir. Özellik seçimi, herhangi bir makine öğrenimi problemini çözerken gerçekleştirilen ilk ve önemli adımlardan biridir. Veri kümemizdeki her bir özellik, basitçe bir sütunla temsil edilir. Her sütunun (özelliğin) hedef değişkeni üzerindeki etkisi aynı olmayabilir.
Hedef değişkenle arasındaki ilişkinin zayıf olduğu bir tahminleyici değişkeni modele eklemek performans üzerine bazı olumsuz etkileri vardır. Daha fazla tahminleyici değişken, training süresinin daha uzun olmasına, hesaplama karmaşıklığının artmasına ve bazı önemli olabilecek özelliklerin etkisinin azalmasına sebep olur.
Bu durum, özellik seçimi yapma ihtiyacını doğurur.
seaborn kütüphanesini kullanarak bir korelasyon matrisi oluşturduk. Bu matris, bütün özelliklerin birbirleri ile aralarındaki ilişkiyi bir renk paletinde bize gösterir.
Korelasyon matrisinde değerler, -1 ile +1 arasında konumlanır. -1' e yakın değerler negatif korelasyon, +1'e yakın değerler pozitif korelasyon olarak yorumlanır.
Pozitif korelasyona sahip iki değişkenin değerleri birlikte artar veya birlikte azalır.
Negatif korelasyona sahip iki değişkenlerden birinin değeri artarken diğerininki azalır.
Değerin 0'a yakın olması durumu ise bu iki değişken arasında bir bağlantı olmadığını gösterir. Hedefimiz quality özelliği ile arasındaki korelasyon değeri 0'a yakın olan özellikleri bulup bunları elemektir.
quality özelliği ile arasındaki korelasyon değeri -0.1 ile +0.1 arasında olan özellikleri relevant_features ismiyle oluşturduğumuz değişkene atadık. Bu değişkenlerden biri normal olarak korelasyon değeri 1 olan quality değişkenimiz. Geriye kalan 8 değişkeni tahminleyici olarak kullanacağız.
to_drop = cor_target[cor_target<0.1]
residual sugar, free sulfur dioxide ve pH değişkenleri de, düşük korelasyon tespit ettiğimiz ve kullanmayacağımız özellikler. Bunları da to_drop değişkeninde topladık.
to_drop değişkenini incelediğimizde bize Name ve dtype adında iki bilgi daha dönüyor. Yani bu değişken şu anda bildiğimiz Python listesi değil. Ancak training kümemizden düşürebilmek için liste olarak vermeliyiz. type() komutuyla veri tipini öğrenelim.
type(to_drop)
Veri tipini öncelike bir diğer pandas veri tipi olan frame’e çeviriyoruz.
to_drop_frame = to_drop.to_frame()
Son olarak, bu değişkenleri bir listeye çevirip, quality değişkenini de ekleyerek düşüreceğimiz değişkenler listesini son haline getiriyoruz.
Sınıfların Dengesizliği
Tahminleyici ve hedef değişkenlerimizi belirleyerek X ve y değişkenlerine atadıktan sonra bu bölümle ilgili yapacağımız son bir işlem daha kaldı. df.describe()’ın bize gösterdiği üzere, quality özelliğimiz 3, 4, 5, 6, 7 ve 8 değerlerini alıyor. Test kümesi için, toplam kümedeki 1599 verinin yaklaşık 5'te 1'ini ayıracağımızı düşünürsek, yaklaşık 320 örneği 6 farklı sınıfa ayırmasını bekliyor olacağız. Bu durum, modelimizin başarımını düşürebilir.
df.describe() kısmında değindiğimiz üzere, elimizdeki örnekler genellikle orta kaliteden oluşmakta. Bundan dolayı, yüksek ve düşük kalite şarapları da tanıyabilmesi için Senaryo olarak, 3 ve 4 puanlı şarapların düşük, 5 ve 6 puanlı şarapların orta, 7 ve 8 puanlı şarapların da yüksek kaliteli şaraplar olduğunu düşünerek, modelimizin öğrenmesi gereken sınıf sayısını 6'dan 3'e düşürelim.
Elimizdeki veri kümesinin daha büyük olması durumunda daha efektif,literatürde yeri olan, algoritmik çözümler de geliştirmek mümkündür.
Bu çözümlere dair bir ileri okuma olarak: https://medium.com/quantyca/how-to-handle-class-imbalance-problem-9ee3062f2499
Karar Ağaçları
Bir karar ağacı, veri kümesini bir dizi karar kuralları uygulayarak daha küçük kümelere bölmek için kullanılan bir yapıdır.
Karar ağacı, istatistik, veri madenciliği ve makine öğreniminde kullanılan tahmine dayalı modelleme yaklaşımlarından biridir. Bir öğe hakkındaki gözlemlerden (dallarda temsil edilen tahminleyici değişkenler) öğenin hedef değeri (yapraklarda temsil edilen hedef değişken) ile ilgili sonuçlara gitmek için bir karar ağacı (tahminleyici model) kullanır. Hedef değişkenin ayrı bir değer kümesi alabildiği ağaç modellerine sınıflandırma ağaçları denir; bu ağaç yapılarında, yapraklar sınıf etiketlerini temsil eder ve dallar, bu sınıf etiketlerine götüren özelliklerin birleşimlerini temsil eder.
Karar ağaçlarında en üstte yer alan noktalara kök denir. Her bir gözlem kökteki koşula göre sınıflandırılır.
Kök hücrelerinin altında düğümler bulunur. Her bir gözlem düğümler yardımıyla sınıflandırılır. Düğüm sayısı arttıkça modelin karmaşıklığı da artar.
Karar ağacının en altında yapraklar bulunur. Yapraklar, bize sonucu verir.
Pipeline oluştururken, grid search için iki parametre kullanacağız, scikit-learn’in DecisionTreeClassifier’ına ait criterion ve max_depth parametreleri. Basitçe, modelimiz veriyi dallara ayırırken hangi bilgi kriterini kullanacak, ve en fazla kaç adımda bilgiyi optimize edecek sorularının cevaplarını arayacağız.
Bu ve diğer tüm karar ağacı parametrelerine dair detaylı bilgi için; scikit-learn dokümanını inceleyip, bu örneği farklı parametreler, farkı değerler için deneyebilirsiniz.
Karar ağacımızı kodlamaya başlamadan önce, modelimiz için yapacağımız son bir iyilik daha var.
Normalizasyon (Merkezileştirme veya Ölçekleme)
Yazının giriş kısmında, tahminleyici değişkenlerimizden bazılarının değerlerinin 0'a oldukça yakın, bazılarının da 0'dan oldukça büyük olduğundan söz etmiştik. Bu durum, büyük değerlere sahip değişkenlerin modeli daha fazla(olumsuz yönde) etkilemesine sebep olur. Bütün tahminleyici değişkenlerimizi, birbirleriyle benzer ölçülerde temsil etmek isteriz.
Bunun için, scikit-learn’in StandardScaler metodunu kullanacağız.
Sırada, tanımladığımız bütün bu önişleme süreçlerini kodlamak var.
Bu adımda, gini ve entropy kavramlarından da kısaca bahsedecek olursak,
Gini(veya Gini Safsızlığı): Veri kümesindeki rastgele seçilen bir öğeyi yanlış bir şekilde sınıflandırma olasılığıdır.
Entropi: Bir değişkenin entropisi, değişkenin olası sonuçlarının doğasında bulunan ortalama “bilgi”, “sürpriz” veya “belirsizlik” seviyesidir. Karar ağacının kök kısmında sınıflandırma, entropi miktarı en az olan özellikten başlar.
Entropi kavramını bir örnekle anlatacak olursak, havanın güneşli mi yağmurlu mu olduğu bilgisinin entropisi, sinemada gösterimde olan filmlerin bilgisinin entropisine göre daha düşüktür. Bunun anlamı, günü nasıl geçireceğinize dair karar verirken, hava durumundan başlamanızın daha olası olduğudur. Eğer hava yağmurluysa, sinemaya gitmek yerine evde oturmayı tercih edersiniz, böylece sinemada hangi filmlerin olduğunu düşünmenize de gerek kalmaz.
Entropi ve bilgi teorisi kavramlarına dair ileri okumalar için: https://en.wikipedia.org/wiki/Entropy_(information_theory)
İlk yazıda değindiğimiz Grid Search tekniğini kullanarak, en iyi kriterimizin gini, en uygun derinliğimizin de 4 olduğu sonucuna vardık. Bu kriterleri kullandığımızda, modelimizin %86 başarıma ulaştığını gördük. Peki gerçekten de modelimiz bu kadar iyi mi çalışıyor?
Kesinlik/Duyarlılık/F1 Skoru
Özellikle de eşit dağılmayan veri kümelerinde modelin doğruluğu(accuracy) tek başına yeterli değildir. Modelimizin başarımını tam olarak ölçmek için, bazı farklı metriklerden yararlanmak gerekir.
Bunun için öncelikle Karışıklık Matrisi kavramına değinelim.
True Positive ve True Negative doğru tahminlerimizi, False Positive ve False Negative ise yanlış tahminlerimizi içeren alanlardır. Örnek olarak görevimizin elimizdeki bir mail kümesindeki spam mailleri belirlemek olduğunu düşünelim.
- True Positive : Modelimiz maili spam olarak tahmin etti ve bu doğru.
- True Negative: Modelimiz maili spam değil olarak tahmin etti ve bu doğru.
- False Positive : Modelimiz maili spam olarak tahmin etti ve bu yanlış.
- False Negative: Modelimiz maili spam değil olarak tahmin etti ve bu yanlış.
Modelin doğruluğu(accuracy), True tahminlerin toplam sayıya bölümüyle bulunur. 100 kişilik bir insan topluluğunda 10 kanser hastası, 90 sağlıklı insan olduğunu düşünelim. Modelimiz, bu grubun tamamının sağlıklı olduğunu tahmin ederse, %90 oranında başarıya ulaşır. Ancak aynı zamanda o 10 hastayı da sağlıklı olarak tahmin ettiği için, başarılı olduğu kadar ölümcül de bir model olur.
Bu nedenle, modelin başarımını ölçmek için farklı metriklere ihtiyacımız vardır.
Kesinlik, False Positive tahminlerin maliyetinin yüksek olduğu durumlarda çok önemlidir. Örneğin Gelen Kutusu’na düşmesi gereken mailleriniz modelinizin hatalı tahmini sonucu Spam Kutusu’na düşerse bu durumda görmeniz gereken önemli mailleri görememiş olur ve kayıp yaratan bir durumda kalırsınız. Bu durumda Kesinlik değerinin yüksek olması modelin başarımını değerlendirmede önemli bir kriterdir.
Mail örneği konusunda, Spam olarak yakalamamız gereken maillerin bir bölümünün Gelen Kutusu’na düşmesi zararsız görünebilir, ancak Recall skorunun yüksek olması özellikle Sağlık ve Bankacılık konusundaki veri kümelerinde hayati bir öneme sahip olabilir.
Şimdi, elde ettiğimiz en iyi parametrelerle birlikte, karar ağacımızı best_tree isimli bir değişkene atayarak, eğitim/tahmin sürecini tekrar çalıştıralım ve öğrendiğimiz başarım metrikleri üzerinden model performansını inceleyelim.
Modelimizin düşük kaliteli şaraplardan hiçbirini (17 örnek) tanıyamadığını görüyoruz. Dolayısıyla, accuracy değerinin birkaç puan daha az, ama düşük kaliteli şarapları da tanıyan bir modelimizin olması daha doğru olabilir.
Bu örneklerin ayırt edilememesinin bir sebebi, yeteri kadar önekle eğitilmemiş olması olabilir. Dolayısıyla bir sonraki adımda, test_size’ımızı küçülterek eğitim sürecini tekrar başlatalım.
Yeni modelimizi, en iyi parametreleriyle tekrar best_tree değişkenine atayıp, başarı metriklerimizi tekrar inceleyelim.
Bu kez, düşük kaliteli olarak işaretlediği şarapların %75'inin(precision) gerçekten de düşük kaliteli olduğunu, ve düşük kaliteli olan şarapların da %30'unu(recall) doğru tahmin edebildiğini görüyoruz.
Bir önceki denemede, 17 örnekten hiçbirini doğru tahmin edemezken, bu kez 10 örnek olduğu halde düşük kaliteli şarap sınıfında başarımın yükseldiğini görüyoruz.
Eğitim kümemizde, daha fazla 0 ile etiketlenmiş örnek olduğu için, test kümemizde kalan düşük kaliteli şarapların tahmin skorunu artırabildik.
Bu veri kümemizdeki gibi (ama etkisini görebilmek için daha büyük veri kümelerinde uygulanabilecek) dengesizlik problemlerini çözmek için, Rastgele Örnekleme(Random Sampling) tekniğini de inceleyebilirsiniz. Bu tekniği uygulamak için, temelde iki yol vardır:
- Oversampling, azınlıkta kalan sınıfların örneklerini çoğaltarak
- Undersampling, çoğunlukta kalan sınıfların örneklerini azaltarak
Daha dengeli sınıflar elde edebilirsiniz.
Python dilinde bu problem için geliştirilmiş bir kütüphane vardır. Linkte örnekleriyle birlikte bu kütüphaneyi inceleyebilir,
Bu yaklaşıma dair ayrıntılı bir okuma için de bu yazıyı inceleyebilirsiniz.
Son olarak, scikit-learn kütüphanesinin tree metoduyla birlikte karar ağacımızın şeklini çizdirerek, yazımızı noktalıyoruz. Sonraki yazılarda görüşmek üzere.