YZ04: KNN (En Yakın K Komşu = K Nearest Neighbor) Algoritması ile Veri Sınıflama

Merhabalar. Yapay Zeka pratik örnekler serimize devam ediyoruz. Bu yazıda verileri kolayca sınıflamak için kullanılan KNN (En Yakın K Komşu = K Nearest Neighbor) algoritmasının temel prensiplerini açıkladıktan sonra her zamanki gibi Python ile örnek uygulamamızı yapacağız. Yeni yazılardan ve duyurulardan anında haberdar olmak için sağ taraftaki menüden e-posta listemize abone olmayı unutmayın.

Öncelikle sınıflandırmadan bahsetmek istiyorum. Sınıflandırma yapabilmek için elimizde eğitim verilerinin olması gereklidir. Eğitim verileri dediğimiz şey girdileri ve çıktıları içeren bir veri kümesidir. Örneğin bir kişiden nabız, çeşitli tahlil sonuçları vb. gibi bir çok ölçüm aldığımızı varsayalım. Konunun uzmanı doktor tarafından yapılan teşhise göre bu kişinin HASTA olduğunu ortaya çıkmış olsun. O halde bu verileri kullanarak bir eğitim verisi oluşturabiliriz. Çünkü elimizde ÖLÇÜLEN DEĞERLER ve bunun sonucunda doktor tarafından VERİLEN KARAR verileri mevcut. Peki elimizde bir çok hastanın ölçüm değerleri ve doktorlar tarafından yapılan hastalık teşhisi olsaydı nasıl olurdu? Bu verileri kullanarak doktorun yapmış olduğu teşhisi bilgisayara yaptırabilir miydik? İşte yapay zeka bu noktada devreye giriyor. Önceden bilinen verileri kendi eğitimi için kullanarak daha önce hiç karşılaşmadığı ölçüm verilerini kullanarak bir insanın hasta olup olmadığını tespit ediyor.

Sınıflandırma özetle; elimizde giriş ve çıkış değerleri bilinen verileri kullanarak daha önce karşılaşılmayan giriş verisine göre çıkışı TAHMİN ETMEK demektir. Tabi buradaki tahmin dediğim şey sınırsız bir tahminden ziyade, eğitim verilerindeki sınıflara göre tahmin etmektir. Yani eğer elimizdeki eğitim verileri hasta ya da sağlam şeklinde çıktı veriyorsa, biz yeni girdilerin sadece hastasağlam mı olduğunu anlayabiliriz. Eğer elimizdeki veriler hastalık tipine göre doktorlar tarafından sınıflandırılmışsa biz de yeni verilerin sadece hangi hastalık tipine ait olduğunu tespit edebiliriz.

KNN ALGORİTMASI NASIL ÇALIŞIR?

KNN algoritmasının çalışma mantığı çok basittir. Elimizde X1 ve X2 girişlerine göre A ve B sınıflarına ayrılmış verilerin olduğunu düşünelim. Görüldüğü üzere aşağıda X1 ve X2 eksenli iki boyutlu bir grafik vardır. Elimizdeki her bir X1 ve X2 giriş çifti verisi için değerleri grafiğe plotlayalım. Grafikte SARI renkli noktalar A sınıfına ve MOR renkli noktalar ise B sınıfına ait verileri göstermektedir.

Daha önceden X1 ve X2 girişlerine göre A ya da B sınıfına ait olduğu bilinen verilerin olduğu grafiği kullanarak kırmızı renkli yıldızın hangi sınıfa ait olduğunu bulabilir miyiz? Zaten elimizde çok fazla seçenek yok. Yıldız ya A sınıfına ya da B sınıfına aittir. Çünkü bizim eğitim verileri sadece bu iki sınıfı içermektedir. Üstte de bahsettiğim gibi yıldızın eğitim verileri içerisinde olmayan bir sınıfa (örneğin C sınıfı) ait olma olasılığı yoktur.

KNN algoritmasında isminden de anlaşılacağı yeni herhangi bir verinin (bu örnekte kırmızı renkli yıldız) hangi sınıfa ait olduğunu bulmak için çevresine bakıyoruz. Eğer kırmızı yıldızın çevresinde bulunan K adet veri içerisinde;

  • A sınıfından daha fazla veri varsa yıldız A sınıfındandır.
  • B sınıfından daha fazla veri varsa yıldız B sınıfındandır.

diyoruz.

KNN Algoritması

Peki yıldızın çevresinde A sınıfından mı yoksa B sınıfından mı daha fazla veri olduğunu belirlemek için kaç tane komşuya bakmamız gerekir? Bu tamamen size kalmış. Algoritmanın adındaki K sayısı, bakılacak komşu sayısını gösterir. K’nın açılımını da araştırdım. Neden L ya da M falan dememişler de K demişler diye ama bir açıklamaya denk gelmedim. Yani adlandırırken öyle adlandırmışlar sadece. 🙂

Yukarıdaki grafikten devam edelim.

Komşu sayısını yani K’yı 3 olarak seçelim ve kırmızı yıldıza en yakın 3 komşuya bakalım. Görüldüğü üzere K=3 seçilmesi durumunda kırmızı yıldıza en yakın 3 komşudan 2’si MOR (B sınıfı) ve 1’i SARI (A sınıfı) renklidir. Yani K=3 seçilmesi durumunda 2 tane komşunun çoğunlukta olması nedeniyle yıldız B sınıfındandır diye karar verilir.

Komşu sayısının belirlenmesi tamamen size kalmış. Şimdi de K’yı 3 değil de 6 olarak seçmeyi deneyelim. Yani bu sefer kırmızı yıldıza en yakın 6 komşunun hangi sınıfa ait olduğunu tespit edip ona göre karar vereceğiz. Aaa o da ne? Eğer K=6 seçersek 4 SARI (A sınıfı) ve 2 MOR (B Sınıfı) renkli veriyle karşılaştık. Bu durumda K=6 seçersek A sınıfı yani SARI’lar çoğunlukta olduğu için kırmızı yıldızın A sınıfına ait olduğuna karar veririz. K sayısının optimum seçilmesi durumda hatayı en aza indirebiliriz.

K sayısının seçimi bize kalmış ama neye göre belirleyeceğiz? Bunun için sırayla her bir K değeri için elde ettiğinimiz doğruluk oranlarını hesaplayıp bizi en yüksek doğruluk değerine ulaştıran K değerini uygulamalarımızda kullanabiliriz.

VERİNİN İNDİRİLMESİ

İşin mantığını anladıysak şimdi uygulamaya geçelim ve Python ile KNN algoritmasını kullanarak hızlıca bir sınıflandırma yapalım.

Peki neyi mi sınıflandıracağız?  Aşağıda fotoğrafta görülen Iris bitkisinin (Türkçe: zambak ya da süsen) Iris setosaIris virginica ve Iris versicolor olmak üzere 3 farklı türü bulunmaktadır.

1936 yılında Ronald Fisher, 150 adet Iris bitkisinin çanak yaprak genişliği, çanak yaprak uzunluğu, taç yaprak genişliği ve taç yaprak uzunluğunu ölçüp kayıt altına almıştır. Bu 150 bitkiden 50 tanesi Iris setosa türünden, 50 tanesi Iris virginica türünden ve 50 tanesi de Iris versicolor türündendir.

Amacımız 4 tane özelliği (feature) bulunan ve toplamda 3 sınıfa ait verileri KNN algoritması ile sınıflamak.

Iris verisetini Python içerisinde yüklü olarak geliyor fakat ben dosyalarla çalışmayı işi öğrenmek açısından daha uygun buluyorum. Verileri indirmek için https://archive.ics.uci.edu/ml/datasets/Iris adresinden önce Data Folder daha sonra iris.data linklerine tıklayarak https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data sayfasına erişiyoruz. Bu sayfada kullanacağımız verileri görebilirsiniz. Bu sayfanın tamamını kopyalayıp bilgisayarımızda metin editörüne yapıştırıyoruz. Sayfanın en üstüne de aralarda virgül olacak şekilde

canak_yaprak_uzunlugu,canak_yaprak_genisligi,tac_yaprak_uzunlugu,tac_yaprak_genisligi,bitki_turu

yazıyor ve dosyayı iris.csv adıyla bilgisayarımızda Python dosyasının olduğu klasöre ya da Jupyter notebook kullanıyorsanız Home klasörünün içine kaydediyoruz. Benim hazırlamış olduğum iris.csv dosyasını indirebilirsiniz.

Verilerimiz şöyle bir şey:

Üstteki veriler ilk bakışta anlamlı gelmeyebilir. https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.names adresinden de görüleceği üzere buradaki veriler sırasıyla;

  • çanak yaprak (sepal) uzunluğu, 
  • çanak yaprak (sepal) genişliği, 
  • taç yaprak (petal) uzunluğu, 
  • taç yaprak (petal) genişliği ve 
  • bitkinin ait olduğu türü yani sınıfı

belirtmektedir.

Yani örneğin ilk veri için

  • çanak yaprak (sepal) uzunluğu 5.1
  • çanak yaprak (sepal) genişliği 3.5
  • taç yaprak (petal) uzunluğu 1.4
  • taç yaprak (petal) genişliği 0.2 ve
  • bitkinin türü yani sınıfı Iris-setosa

KODLAMA

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.neighbors import KNeighborsClassifier

# csv dosyasından ilk satır başlık (header) satırı olacak şekilde verileri okuyalım.
veri=pd.read_csv("iris.csv", header=0)

# okuduğumuz verinin neye benzediğini görmek için ilk 5 satırını ekrana yazdıralım.
veri.head()

# verilerin %80'ini eğitim için ve kalan %20'sini de test için ayıralım.
# ayırma işlemi rastgele (random) yapılmaktadır.
egitim=veri.sample(frac=0.8,replace=False)
test=veri.drop(egitim.index)

# verinin %80'nini eğitim için ayırdığımız için 120 veri olması gerekiyor. 
print (len(egitim))

# eğitim verisinin ilk 5 satırını ekrana yazdıralım.
egitim.head()

# verinin %20'sini test için ayırdığımız için 30 veri olması gerekiyor. 
print (len(test))

# test verisinin ilk 5 satırını ekrana yazdıralım.
test.head()

# bir eksen canak_yapak_uzunlugu ve bir eksen canak_yaprak_genisligi olacak şekilde çizim yapalım.
# verilerin nasıl dağıldığına dikkat ediniz.
sns.FacetGrid(veri, hue="bitki_turu", size=6) \
   .map(plt.scatter, "canak_yaprak_uzunlugu", "canak_yaprak_genisligi") \
   .add_legend()

# K=5 olacak şakilde knn adında sınıflandırıcı tanımlayalım.
knn = KNeighborsClassifier(n_neighbors=5)

# başlık (header) isimlerinden faydalanarak girişlerimizin hangi sütunlar olacağını tanımlayalım. 
girdiler = ['canak_yaprak_uzunlugu', 'canak_yaprak_genisligi', 'tac_yaprak_uzunlugu', 'tac_yaprak_genisligi']

# girdiler ve çıktılara göre KNN'yi eğitim verilerimize uyduralım. 
knn.fit(egitim[girdiler], egitim['bitki_turu'])

# KNN algoritmamızı test verisi üzerinde deneyelim.
tahmin = knn.predict(test[girdiler])

# test verileri için hangisi doğru hangisi yanlış tespit edilmiş bakalım.
tahmin==test['bitki_turu']

# test sonucumuzu ekrana yazdıralım.
print("Test sonucu: {:.2f}".format(np.mean(tahmin == test['bitki_turu'])))


SONUÇ
Yukarıdaki kodları çalıştırırsanız %97’lik bir başarı elde edebilirsiniz. Farklı K değerleri için elde ettiğiniz sonuçları yorum kısmında paylaşırsanız sevinirim. Kodlarla ya da KNN algoritmasıyla alakalı sorunuz olursa yorum yaparak sorabilirsiniz. Bol yapay zekalı günler diliyorum.

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Google fotoğrafı

Google hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Connecting to %s