3 Ağustos 2017 Perşembe

KNN Algoritması ve Örnek Uygulama

Merhaba;
Bu yazımızda sınıflandırma tekniğinde kullanılmakta olan En Yakın Komşu(KNN / k nearest neighbors) algoritmasından bahsedeceğiz. Anlatımın açık olması adına sınıf niteliği belli olmayan değerlere örnek, sınıf niteliği belli olan değerlerden bahsederken eleman diyeceğim.

Knn algoritması; (sınıf niteliği belli olan) elemanların meydana getirdiği uzaya yeni bir örnek (sınıf niteliği belli olmayan) eklendiğinde bu örneğin kendisine en yakın olan sınıfa dahil edilmesi gerektiğini kararlaştıran bir algoritmadır. Kendisine en yakın olan sınıfı belirlemek için bir k değişkeni kullanmaktadır. Belirlenen bu k değişkeni örneğe en yakın olan k adet (sınıf nitelikleri belli olan) elemanların sayısını temsil etmektedir. Örnek ile, elemanlar arasındaki mesafe hesaplanırken yaygın olarak aşağıdaki 3 uzaklık fonksiyonu kullanılmaktadır.


Öklid fonksiyonu ilk okul veya liseden beri aşina olduğumuz bir fonksiyon. Aslında gözünüzü korkmasın hepsi tek bir ana fonksiyondan türetilmektedir. Minkowski fonksiyonundaki q=1 değeri için manhattan uzaklığı; q=2 değeri için öklid uzaklık formulünü elde ediyoruz. Bu sebeple minkowski genel formulunu kullanarak uygulamamızı yapacağız. Böylece kişi diğer uzaklık ölçümleri için sadece q değerini değiştirecektir.





Algoritmayı birkaç madde ile özetlersek;
  1. Sınıf nitelikleri belli olan elemanlardan oluşan bir uzaya yeni bir örnek ekle.
  2. K sayısını belirle.
  3. Yeni gelen örnek ile elemanlar arasındaki uzaklığı hesapla.(Uzaklık fonksiyonlardan birini kullanarak)
  4. En yakın olan k tane elemanın sınıf niteliğine bak.
  5. En yakın olan k tane elemanlardan sınıf değeri sayıca fazla olan sınıfa örneği dahil et.
Algoritmanın teorik kısmı burada son bulmaktadır. Şimdi hem pratiğini hem de python ile bir uygulamasını yapalım. Bildiğiniz üzere bize gerekli olacak ilk şey uygun bir verisetidir. Yapacağımız uygulama için şurdaki veri setini kullanacağız. Bu veri setinde, farklı yaşlarda, cinsiyetlerde, ırklardan insanların olduğu resimlerdeki insan yüzünün(sima) renk değerleri (r,g,b) alınmıştır. Ayrıca datasetteki renk değerlerinden insan yüzü olmayan örnekler de mevcuttur. Alınan bu değerler neticesinde 4. sutunda, bu değer bir insan yüzüne ait ise 1, değil ise 2 değerinin tutulduğu bir sınıf niteliğimiz var. Veri setimiz çok büyük olduğu için kişisel bilgisayarlarımız işlemek için zorlanacağından(en azından benim ki) veri setinin sadece bir kısmını kullanacağız. Veri setindeki sınıf ayrımı 50.859 satırdan itibaren başladığından bizde bu bilgiyi göz önünde bulundurarak veri setini okuyacağız. Pandas gibi kütüphaneler ile veri setini parse etmek biraz daha kolay olsa da biz bu uygulamamızda parse işlemi için herhangi bir kütüphane kullanmayacağız. Kodu parça parça paylaşmak yerine bir bütün halinde paylaşıp, gerekli açıklamarı comment ile yapmanın daha uygun olacağını düşündüm.
#!python3
#50859 (Sınıf sınırımız)

# Grafik için gerekli kütüphaneler. Axes3D 3 boyutlu bir grafik için.
from matplotlib import pyplot as  plt
from mpl_toolkits.mplot3d import Axes3D

class knn():
    # başlangıç fonksiyonumuz ve değişkenlerimiz. inp değişkenimiz sınıf niteliği
    # belli olmayan örneğimizdir. Siz isterseniz bu değeri dışardan da alabilirsiniz.
    # __init__ metodundaki dataset veri setimizi, k en yakın k komşuyu, nfrom veri
    # setini okumaya başlanacağı satır ve nto ise kaçıncı satıra kadar okuyacağını
    # belirtir. Son iki parametre çok büyük veri setlerini çözümlerken pc'ler yeter
    # siz kaldığından isteğe bağlı olarak sadece veri setinin belli bir kısmını
    # seçmek için ekledim. Ki bu örneğimizde öyle bir örnek.
    def __init__(self, dataset, k, nfrom, nto):
        self.b, self.g, self.r, self.class_attr = [], [], [], []
        self.inp = [264,124,183]
        self.k = k

    # Veri setimizi nfrom satırından nto satırına kadar okuyoruz.
    # Ayrıca veri setindeki her sutunu bir listeye atıyoruz. (r,g,b,class_attr)
        with open(dataset, "r") as f:
            for i in f.readlines()[nfrom:nto]:
                self.r.append(int(i.split()[0]))
                self.g.append(int(i.split()[1]))
                self.b.append(int(i.split()[2]))
                self.class_attr.append(i.split()[3])

    # Uzaklık hesaplamamızı yaptığımız metodumuz. dist parametresine göre
    # ilgili hesaplanma yapılmaktadır. Default oklid uzaklığı kullanılmaktadır.
    # Burda dikkat edilmesi gerekilen en önemli nokta; uzaklık değeri hesaplandıktan
    # sonra hangi uzaklığın başta hangi index numarasına sahip olduğunu bilmeyiz.
    # Çünkü bu indis numarasını kullanarak ilgili uzaklığın sınıf değerine ulaşacağız.
    # Bu sebeple uzaklığı ve uzaklığın indis değerini demet şeklinde
    # dist listemize ekliyoruz.Çünkü uzaklığı küçükten büyüğe sıraladığımızda
    # uzaklığa ait gerçek sınıf değerine ulaşamamaktayız.
    #
    # öklid = 1, manhattan=2
    def distance(self, dist=1):
        self.dist = []
        # for döngüsündeki karışık gibi gelen üs alma, mutlak değer gibi işlemler
        # minkowski formulunun karşılığından ibarettir.
        for i in range(len(self.class_attr)):
            self.dist.append((pow((pow((
            abs(int(self.b[i]) - int(self.inp[0])) +
            abs(int(self.g[i]) - int(self.inp[1])) +
            abs(int(self.r[i]) - int(self.inp[2]))), 2)), 1/dist), i))

        return self.dist

    # uzaklık hesaplanması yapıldıktan sonra örneğimize en yakın olan k tane
    # elemanı buluyoruz ve bu elemanların sınıf değerlerini class_values
    # listemizde tutuyoruz. Ve döngünün sununda class_values listesindeki 1(cilt)
    # 2(cilt değil) sayılarını hesaplayıp, örneğin hangi sınıfa ait olduğunu
    # buluyoruz.
    def findClass(self):
        self.class_values = []
        self.result = ""

        for i in sorted(self.dist)[:self.k]:
            self.class_values.append(self.class_attr[i[1]])

        self.first = self.class_values.count("1")
        self.secnd = self.class_values.count("2")

        print("Birinci Sınıf:", self.first)
        print("İkinci Sınıf:", self.secnd)

        if self.first > self.secnd:
            self.result = "1. Sınıf(Kırmızı)"
        else:
            self.result = "2. Sınıf(Yeşil)"

        print("SONUÇ: "+self.result)

#GORSELLEŞTİRME
    # Algoritmanın daha somut bir şekilde anlaşılması adına 3 boyutlu uzayda
    # grafiğini oluşturdur. Kırmızı noktalar cilt, yeşil noktalar cilt olmayan
    # ve mavi nokta ise sınıf değerin belli olmayan örneğimiz.
    def grafik(self):
        fig = plt.figure()
        ax  = fig.add_subplot(111, projection='3d')

        for bi, gj, rk, class_attr in zip(self.b, self.g, self.r, self.class_attr):
         if class_attr == "1":
          ax.scatter(bi,gj,rk, c='r', marker='.')
         else:
          ax.scatter(bi,gj,rk, c='g', marker='.')

        ax.scatter(int(self.inp[0]), int(self.inp[1]), int(self.inp[2]), c='b')
        ax.set_xlabel('X Ekseni')
        ax.set_ylabel('Y Ekseni')
        ax.set_zlabel('Z Ekseni')

        fig.text(0, 0, "Kırmızı(1)[Cilt] : "+str(self.first)+
                " -- Yeşil(2)[Cilt Değil] : "+str(self.secnd)+
                " -- {{SONUÇ : "+self.result+"}}")

        plt.legend()
        plt.show()

# Sınıfımızdan nesne türetip gerekli metodlarımızı çağırıyoruz. En yakın 17 komşuya bakıyoruz. Ola ki eşit çıkma durumu olduğundan k değerinin tek seçilmesinde yarar vardır. Ve sonuç.
ins = knn("ten_dataset.txt", 17, 50300, 51000)
ins.distance(1)
ins.findClass()
ins.grafik()
Uygulamamızın 3 boyutlu uzaydaki görünümü aşağıdaki gibidir. Mavi nokta örneğimiz(sınıfı belli olmayan), kırmızı noktalar cilt(sima) sınıfını, yeşil noktalar ise cilt olmayan sınıfı temsil etmektedir. Grafikte açık bir şekilde göreceğiniz üzere; Örneğimiz, uygulamamız tarafından kendisine en yakın olan sınıfa dahil edilmiştir.
Uygulamada kullandığımız kodlara şurdan erişebilirsiniz. Sağlıcakla kalınız.

20 Mart 2017 Pazartesi

Matplotlib ile log analizi yapmak

Merhabalar; Bu blog yazımızda access.log dosyasımızdaki logları matplotlib kütüphanesini kullanarak grafiğini çıkaracağız. Dilerseniz bu log dosyasını indirebilir veya aynı formataki kendi log dosyanızı kullanabilirsiniz.
Matplotlib veriler üzerinde her türlü çizgi, histogram, bar, faz, dairesel ve daha nice grafik formatlarını sadece basit birkaç satır kod ile çıktı alabileceğimiz harika bir python kütüphanesidir. Nufus dağılımlarından, ülkedeki okuyan bilgisi, matematiksel bir denklemin grafiğinden, zararlı bir yazılımın dağılım hızı gibi aklınıza gelebilecek her türlü konuda rahatlıkla kullanabilirsiniz. İşin içine istatistiğin girdiği her konuda işinize ve ihtiyaçlarınıza fazlasıyla cevap verecektir. Günlük hayatta bir çok konuda uygulanabilir diyerek konunun girizgahını yapalım.
Yukarıda da bahsetmiş olduğumuz üzere biz bu yazımızda bir web sitesine ait access.log dosyasındaki belli bilgileri kullanarak matplotlib yardımıyla yazacağımız scripte herhangi bir access.log dosyasını vererek en çok request yapan ip adreslerini ve request değerlerini grafiğe dökeceğiz. Başlayalım!
Öncellikle aşağıdaki komut ile kütüphanemizi kuralım.
pip3 install matplotlib
Kodumuza kütüphanelerimizi dahil etmekle başlayalım.
from matplotlib import pyplot as plt #Grafikleri çizeceğimiz alan(plot)
from sys import argv #Dışarıdan argüman alacağımız için import ediyoruz.
En çok istekte bulunan n. kayda kadar listeleyeceğimiz için n argüman değerimizi ve log dosya adımızı dışardan alıyoruz.
logfile = argv[1]
n = int(argv[2])
access.log dosyamızın her bir satırı bir liste elemanı olacak şekilde log listemize atıyoruz.
with open(logfile, "r") as f:
 log = f.readlines()
Sonrasında access.log dosyamızdaki yalnızca ip sutununu alacak şekilde parse edelim ve ip değerlerimizi bir ip listesine atayalım.
ip = [i.split()[0] for i in log]
access.log dosyamızda tekrar eden ip adreslerini bire indirgiyoruz.(Tekrar durumundan önüne geçmek için)
uniq_ip = list()
[uniq_ip.append(i) for i in ip if i not in uniq_ip]
Şimdi ise her ip'den gelen toplam request sayısını bulalım. Yani frekansı.
freq = list()
[freq.append(ip.count(i)) for i in uniq_ip if i not in freq]
Request yapan ip'ler ve ip sayılarını bir liste içerisinde 2 elemanlı demetler şeklinde request sayısına göre büyükten küçüğe doğru sıralıyoruz.
eq = sorted(zip(freq, uniq_ip), reverse=True)
Şimdi plota çizeceğimiz eksen noktalarımızı belirleyelim.
y_axis  = [i[0] for i in eq] # y ekseni

# x ekseni. Her bir x noktasına bir y noktası denk geleceği için x ve y liste uzunluklarının eşit olmasına dikkat ediniz.
x_axis  = range(len(y_axis))

x_label = [i[1] for i in eq] # x eksenindeki etiket isimleri (ip adresleri)
y_axis değişkenimizde frekans sayıları, x_label değişkenimizde ise ip adresleri yer almaktadır.
# Grafiğimizi çizdik. marker ile x ve y ekseninin kesiştiği yere .(nokta) koyduk.
plt.plot(x_axis[:n], y_axis[:n], marker='.')

# x, y eksenindeki bilgi etiketlerini ve başlığı yazdırıyoruz.
plt.title(argv[1]+" File Analysis")
plt.ylabel("Total Request")
plt.xlabel("Ip Address")

# Grid ile x ve y ekseninde yatay ve dikey referans çizgilerini aktif ediyoruz.
plt.grid(True)

# X eksenimizdeki etiket alanında sayi görünmesi yerine ip adreslerini gösteriyoruz. 90 derece göndererek overlop olmasının önüne geçiyoruz.
plt.xticks(x_axis[:n], x_label[:n], rotation=90)

# y eksenimizi 50 birimlik referans çizgileri ile belirliyoruz. Daha fazla detay için küçük değer verilebilir.
plt.yticks(range(0,max(y_axis),50))

#Grafiğimizi gösteriyoruz.
plt.show()
Time to test :) En çok istek yapan ilk 10 ip'ye bakalım.
python3 log_analiz.py test_log 10
İlk paragrafta verdiğim örnek access log dosyasına bakalım.
python3 log_analiz.py access_log 30
Bu yazımızda matplotlib kütüphanesinin temel kullanımını güzel bir örnek ile anlatmış olduk. Sonraki yazılarımızda farklı grafik türlerini kullanarak örnekler yapacağız. Siz aynı örnek üzerinde request-time şeklinde grafik oluşturabilirsiniz. Tamamen size kalmış. Bir sonraki yazımızda ise dinamik grafik oluşturmayı göreceğiz. Ayrıca bu yazıda kullandığımız kodlara şuradan erişebilirsiniz. Sağlıcakla kalınız.

Kaynaklar:
http://matplotlib.org/api/pyplot_api.html

17 Mart 2017 Cuma

Merhabalar,
Bu yazıda Django'nun kendi user modelinden kalıtım alarak kendi user modelimizi oluşturmayı ve authentication modeli olarak oluşturduğumuz modeli göstermeyi basit bir şekilde anlatacağım. Bu yazıyı yazmamın sebebi gözlemlediğim kadarı ile insanlar user modeline extra fieldlar eklemek istediklerinde OneToOneField kullanarak extra bir model oluşturduklarını görmem. Bunu daha basit, temiz ve tavsiye edilen yöntem olan hali hazırda Django'da yazılmış AbstractUser sınıfından kalıtım alarak nasıl çözeriz hemen bahsedelim.

OneToOneField


OneToOneField bildiğiniz gibi iki modeli ilişkilendirmek için kullanıyoruz. ForeignKey'de 1'e n bir ilişki varken, örneğin bir(1) yazarın birden fazla(n) kitabı olabilir. OneToOneField'de ise 1'e 1 ilişki bulunmaktadır. OneToOneField'in bu durumda nasıl kullanıldığını örneklemek amacı ile stackoverflow.com'dan bu örneği aldım. Tam olarak demek istediğim haliyle kullanmış buradaki arkadaş. Ama biz bunu istemiyoruz. Biz istiyoruz ki siz en güzel ve temiz yöntemi kullanın.
from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    nim = models.CharField(max_length=10, blank=True)

    def __str__(self):
        return self.user.username
Örnekte gördüğümüz gibi arkadaş Django'nun var olan User modeline nim adında bir field daha eklemek istemiş. Bunun için ise Profile adında bir model oluşturmuş ve bunu Django User modeli ile OneToOneField ile bağlamış.

Custom Model


Şimdi aynı işlemi kalıtım alarak uygulayalım.
from django.contrib.auth.models import AbstractUser
from django.db import models

class Profile(AbstractUser):
    email = models.EmailField('email address', unique=True)
    nim = models.CharField(max_length=10, blank=True)

    def __str__(self):
        return self.username
Burada ben ekstradan email alanını tekil ve zorunlu hale getirdim. Bildiğiniz gibi default user modelinde bu alan tekil ve zorunlu değil. Son olarak yapmamız gereken ise settings.py dosyası içerisinde bu modelin authentication modeli olduğunu Django'ya bildirmek.
AUTH_USER_MODEL = 'app_name.Profile'
Bu işlemden sonra Django'nun sadece bizim oluşturduğumuz modele ait tabloyu veritabanında oluşturduğunu görebilirsiniz. Son olarak oluşturduğumuz modeli admin sayfasında görebilmek için register işlemini yapalım.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import Profile


admin.site.register(Profile, UserAdmin)
Faydalı olması dileğiyle. Kolay gelsin.

23 Ocak 2017 Pazartesi

PYTHON İLE BASİT BİR YSA UYGULAMASI

Gelişen teknolojiyle beraber dijitalleşen hayatlar sonucunda her geçen saniye binlerce veri kayıt altına alınmaktadır. Bu veriler; açık veya kapalı devre kameralardan alınan veriler, bir sunucu veya data centerın log kayıtları, bir gsm şireketinin ses kayıtları, bir sosyal medyadaki veriler diye uzayıp giden devasa veri yığınlarının da dahil olduğu uzunca bir liste. Dijital sahada bu kadar veri dururken bunların insan gücüyle analiz edilmesi neredeyse imkansız hale gelmiştir. Çünkü bu büyük veri yığının içerisinde gerekli olan anlamlı verileri çıkarmak yada bu verileri kullanarak anlamlı bir sonuç çıkarsama birçok insanın bile yapabileceği bir iş değildir. Bu problemlere çözüm olacak yöntem ise makinelerin de kendilerine özgü karar verme ve çıkarım yapabilme yeteneklerine sahip olmasıdır. Bu kadar veriler içerisinde anlamlı olan verileri ayıklamak veya bu verileri kullanarak bir çıkarsama yapabilmesi artık çağımızın bir zorunluluğu haline gelmiştir.

İşte bu noktadan sonra biyolojik olarak insan zekasının çalışma mantalitesinden esinlenerek yapay zeka tekniği geliştirilmeye başlandı ve hala ciddi çalışmalar ile devam etmektedir. Bu yazımızda yapay zekanın öğrenme tekniklerden biri olan yapay sinir ağı(YSA) mimarisini kullanarak python ile basit bir uygulama yapacağız. Bildiğiniz üzere python veri madenciliğinden, bilimsel çalışmalara, yapay zekadan siber güvenliğe kadar yelpazesi çok geniş olan bir dildir. Yapay sinir ağı konusunda çok ciddi kütüphaneleri de bulunmaktadır. Bunlardan bazıları coffe, theano, tensorflow, scikit, panda ve torch kütüphaneleridir.

Keras ise arkada tensorflow veya theano kütüphanesini kullanan bir arabirimdir. Biz ise keras ile arkada tensorflow kullanarak bir uygulama yapacağız. Tensorflow, google tarafından geliştirilmiş ve 2015 yılında bir kısmı public hale getirilen makina öğreniminde kullanılan ciddi bir kütüphanedir.

Ancak örnek uygulamamızı yazmaya geçmeden önce yapacağımız uygulamayı anlamak için yapay sinir ağı mimarisinin nasıl çalıştığını bilmemiz ve bu konudaki terminolojiye biraz hakim olmamız gerekmektedir. Bu sebeble kısa bir şekilde biraz değineceğiz. Ancak bu yazıyı konuya biraz hakim olduğunuzu ve yazacaklarımı hatırlamanız amacıyla yazdığımı belirtmek isterim.

Aşağıdaki resimde giriş ve ara katmanlar(hidden layers) olmak üzere üç katmanlı yapıya sahip bir yapay sinir ağı modeli görmektesiniz.


Yukarıdaki gördüğünüz her bir düğüm aslında bir yapay sinir hücresini temsil etmektedir. Ve bunlara perceptron denmektedir. Perceptronlar arasındaki çizgiler ise ağırlıkları temsil etmektedir. Ve bir perceptronun değeri; kendisinden bir önceki katmanda bulunan bütün perceptronlardaki değerin ilgili ağırlıklarıyla çarpıldıktan sonra bir toplam fonksiyonundan geçtikten sonra bulunan değerin bir aktivasyon fonksiyonundan geçmesi sonucu bir değere sahip olacaktır. Bu bulunan sonuç, bir sonraki katmana girdi olarak verilmektedir Anlatmak istediğimizi aşağıdaki resim açıkça izah etmektedir. Aşağıdaki resim, yukarıda gördüğünüz her düğüm içerisinde olan işlemleri göstermektedir.

Yandaki resimde Xi’ler bizim girdi değerlerimiz, Wi’ler ise ağırlıklarımızı ifade etmektedir. Her girdi kendi ağırlığıyla çarpıldıktan sonra çıkan değeri bir sonraki katmandaki bulunan perceptronlara aktarmaktadır ve bu perceptronda toplam fonksiyonundan geçtikten sonra çıkan değer aktivasyon fonksiyonuna göndererek ortaya nihai bir değer çıkacaktır. Ve varsa bu değer bir sonraki katmana aktarılarak bu döngü çıkışa varıncaya kadar böyle devam edecektir. Bu her değer için bu iterasyon yapılacaktır. Ve her iterasyonda uygun bir sonuç bulmak için ağırlıklar yeniden düzenlenecektir. Bu olaya epoch denilmektedir. Çünkü sonuçları etkileyen en önemli etkenlerden biri de ağırlık değerlerimizdir. En basit haliyle bir ysa modeli bu şekildedir. Şimdi ise verilerin bu model içerisinde nasıl işlenildiğine kısaca değinelim;

Elimizde bir dataset(veri kümesi) olur. Bu dataset bizim kullanacağımız teknik gereği birden fazla girdinin ama bir çıktının olacağı bir yapıya sahip olmalıdır. Örneğin; bir kullanıcının mouse hareketlerini, tıklama sayıları, girdiği siteleri, bu sitelerde kaldığı süre gibi çevresel değişkenleri alıp bu değerler sonunda bu kişinin bot mu? Insan mı? Değerini saklayan bir dataset düşünelim.

10 bin kullanıcıdan alınan değerler sonucunda bu kişilerin bot mu? Insan mı? Olduğu değerini tutan böyle bir datasetimizin olduğunu varsayalım. Bu değerlerimiz gerçek değerlerdir. Yani herhangi bir lab ortamında bot davranışlarını tuttuklarını ve binlerce insanın bilgisayar kullanırken ki aktivitelerini kayıt altına aldıklarını düşünelim. Çünkü bizim ysa modelimiz bu örneklerden bir çıkarım yaparak kendisine daha önce hiç gösterilmemiş bir örnek gösterildiğinde bunun bot mu? Insan mı? Olduğunu bu gerçek değerlerle kendisini eğiterek bulacaktır. Ama öncesinde tabi ki de sistemimizin öğrenme eğitimini tamamlaması gerekir.

Biz bu 10 bin veriden 9 bin tanesini ysa modelimize eğitim verisi olarak vereceğiz. Eğitim verileri, bir ysa modelini eğitmek için verilen verilerdir. Bizim bu örneğimizde ise girdi ve çıktı değerlerinin olduğu veriye verilen isimdir. Çünkü modelimiz girdi değerleri ile çıktı arasında bir matematiksel model oluşturmaya çalışacak. Bu model oluştururken ağırlıklar, aktivasyon fonksiyonu, ara katmanlar, katmanlardaki perceptron sayıları gibi değişkenler değiştirilip en uygun değer bulunmaya çalışılır. Ve modelimiz belirlediğimiz bir eşik değerine vardığında öğrenme sona erer. Öğrenme bitmesi ysa modelimizin girdi ve çıktılarımız arasında bir matematiksel model bulduğu anlamına gelmektedir. Sistem eğitimi tamamladıktan sonra test etmemiz gerekmektedir. Testi ise 10 bin veriden bir köşeye ayırdğımız bin adet veriyle yapacağız. Ancak burda önemli olan nokta şudur; Test verilerimizi verdiğimiz de sadece girdi değişkenlerimizi vereceğiz. Yani o kişinin bot mu? Insan mı? Olduğu değerini vermeyeceğiz aksine modelimiz bu değeri kendisi bulacak. Ve bulacağı bu değeri gerçek değer ile mukayese ederek sistemimizin yüzde kaç başarılı olduğunu hesaplayacağız. Örneğin yüzde 90 ve üzeri bir başarı bizim için kabul edilebilir bir değer ise modelimiz başarılı olmuştur demektir. Zaten hiçbir ysa modeli size %100 kesin sonuçla bir değer veremez. Her zaman bir hata payı vardır ve olmak zorundadır. Çünkü sistem kendisi verilen değerlerden bir sonuç çıkarmaktadır. Eğer yüzde 100 doğru cevap veriyorsa bir sistem o sistem öğrenmemiş ezber yapmıştır. Bu duruma overfitting de denilmektedir.

Ayrıca dikkat ettiyseniz tabloları kullanıyoruz bu da YSA’da özellikle matrisleri çok yoğun kullanacağımız anlamına gelir. Zaten uygulamamızı yaptığımızda numpy kütüphanesini de kullanacağımızı göreceksiniz. Unutmadan aslında yaptığımız anlatığımız bunca şeyin arkada nasıl çalıştığını ve öğrenme dediğimiz o olayın nasıl gerçekleştirildiğini çok güzel simüle eden tensorflow’un bu web uygulamasına kesinlikle bakınız. Parametrelerle oynayın, kurcalayın biraz işte ;)

Şimdi bir ysa modeli için bir kaç önemli hususu maddeler halinde verelim.
  • Herşeyden önce sistemimizi eğiteceğimiz bir datasetine sahip olmalıyız. Bunun için belli başlı dataset repoları var. Şu ve şu adreslere bakabilirsiniz.
  • Datasetinde bir sistemin öğrenmesi için yeterli sayıda veri bulunmalıdır. Az veri olursa sistem ezbere düşecektir.
  • Datasetimizdeki veriler makul olmalıdır. Çünkü sistem o verileri kullanarak öğrenme yapmaktadır.
  • Eksik ve yanlış verilerin olması sistemin öğrenmesini çok ciddi bir şekilde etkilemese de sistem belli bir seviyeden sonra öğrenemez.
  • Eğitim verilerinizi aynı zamanda test verisi olarak hiçbir zaman kullanmayınız. Alacağınız sonuçlar sağlıklı olmayacaktır. Sistemin daha önce hiç görmediği veriler ile test ediniz.

Bu kadar cümleden sonra işin hikaye kısmını bitirdik ve artık teknik kısma geçmek için hazırız. Bizim kullanacağımız dataset yaklaşık 800 insanın vucudundan alınmış yaklaşık 8 değer var yani girdiler. Bunlar; hamilelik sayısı, plazma glukoz konsantrasyonu, diastolic kan basıncı, deri kalınlığı, kullanılan insulin miktarı, vucut kitle indexi, diyabet soyağacı ve yaş değerleridir. Ve son sutunda ise 1 veya 0 değeri yer almakta. Eğer 1 ise kişinin şeker hastası(diabet) olduğu, 0 ise diabet hastası olmadığı anlamına gelmektedir. Buradan ufak bir parantez açayım. Datasetimizdeki her verinin numerik olması gerekmektedir. Çünkü bu değerler üzerinde matematiksel işlemler yapılmaktadır. Çıkışlar bile numerik olmalıdır en azından o şekilde ifade edilmelidir.
Öncellikle kullanacağımız kütüphaneleri varsa diğer projelerde kullandığımız kütüphaneleri etkilememesi için bir virtual environment kullanarak uygulamamızı diğer python kütüphanelerinde izole hale getireceğiz. Bunun için;
$sudo pip3 install virtualenv
Kurulum bitince ardından ;
$sudo virtualenv keras
diyerek keras adından bir izola ortam oluşturup;
source /bin/activate
diyerek izole ortamımızı aktif hale getirelim. Şimdi ihtiyaç duyacağımız kütüphanleri yükleyelim.
$sudo pip3 install numpy $sudo pip3 install tensorflow $sudo pip3 install keras

İşlem bittiğinde uygulamamız için gerekli herşey hazır demektedir. Artık python kodumuzu yazmaya başlayabiliriz. Öncellikle kullanacağımız paketleri import edelim.
#Kullanacağımız ysa modeli için.
from keras.models import Sequential

#YSA modelimizde katmanlar oluşturabilmek için.
from keras.layers import Dense

#Çıktımızı terminalden aldığımızda sonuçları renklendiriyoruz. Yanlışlar kırmızı, doğrular yeşil. Bunu kullanmasanızda olur yani.
from termcolor import cprint

#YSA matrislerle çalıştığı için numpy olmazsa olmaz.
import numpy
Datasetimizi yüklüyoruz.
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
numpy kütüphanesindeki loadtxt() metodumuz verilen ilk parametredeki dosya/string I delimiter(ayırıcı) ile split ederek bir matrise atamaktadır. Datesetimizi ayrıştırıyoruz. X, 8 adet girdimiz. Yani 600 satır ve 8 sutun. Y ise çıkışımız 600 satır 1 sutundan oluşmaktadır. Eğer bu parçalamayı anlamadıysanız lütfen şu konuya bakınız.
X = dataset[:600,0:8]
Y = dataset[:600,8]
Şimdi modelimizi oluşturup katmanlarımızı yerleştirelim. Modelimizden model adında bir nesne türettik.
model = Sequential()
Ve ilk katmanımızı modelimize add metodu ile dense tipindeki katmanımızı ekliyoruz. Parametrelerden 12 olanı ilk katmandaki perceptron sayısı. İnput dim bizim girdi değer sayımız. Hatırlarsanız 8 değerimiz vardı. Init parametremiz yapay sinir hücrelerimiz arasındaki ağırlıklarımızın rastgele verilmesi yerine belli bir algoritmaya göre vermektedir. Aktivation ise o katmanda kullandığımız aktivasyon fonksiyonumuz.
model.add(Dense(20, input_dim=8, init='uniform', activation='relu'))
#İkinci katmanımızda 12 yapay sinir hücresi. 
model.add(Dense(12, init='uniform', activation='relu'))

#Üçüncü katmanımızda 8 yapay hücremiz var.
model.add(Dense(8, init='uniform', activation='sigmoid'))

#Dördüncü katmanımızda 1 yapay hücremiz var. Yani çıkışımız.
model.add(Dense(1, init='uniform', activation='sigmoid')) 

#Modelimizi derliyoruz.
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
Modelimizi çalıştırıyoruz. İlk parametre girdilerimiz, ikincic parametre çıktığımız. 3. paramtre epoch değerimiz. Yani ağırlıkların yeniden düzenleyerek çözüme en yakın değeri buluncaya kadar yapacağı deneme sayısı. Batch size tek seferde alınacak veri sayısını ifade etmektedir. Verbose ise herhangi bir hata oluşması durumunda göstermemeisini istedik.
model.fit(X, Y, nb_epoch=150, batch_size=10,  verbose=2)
Modelimizin başarı yüzdesini hesaplıyoruz.
scores = model.evaluate(X, Y)
Ve son olarak modelimizin sonucunu ekrana basıyoruz.
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
Evet buraya kadar modelimiz verdiğimiz örnekleri kullanarak girdi ve çıktılar arasında ilişkisel olarak bir model buldu ve eğitim sona erdi. Bundan sonra sisteme test verilerimizi vererek ne kadar başarılı bir sonuç bulduğunu hesaplayacağız. Şimdi köşeye ayırdığımız 1000 değeri sistemimize vereceğiz ve ysa modelimizin bulduğu sonuçlar ile gerçek sonuçları karşılaştırıp ne kadar başarılı olduğunu görelim. Aşağıdaki kodlarıda yine aynı python dosyasına yazarak devam edelim.
#96 adet test verimizin sadece 8 girdisini sisteme veriyoruz.
test_verisi = dataset[600:696, 0:8]

#Sistemin verdiğimiz değerlerden yola çıkarak kişinin diyabet hastası olup olmadığını tahmin ediyor.
predictions = model.predict(test_verisi)
Buradan sonrası ise sonuçları ekrana basma olayı.
dogru = 0
yanlis = 0
toplam_veri = len(dataset[600:696,8])

for x, y in zip(predictions, dataset[600:696,8]):    
    x = int(numpy.round(x[0]))
    if int(x) == y:
        cprint("Tahmin: "+str(x)+" - Gerçek Değer: "+str(int(y)), "white", "on_green", attrs=['bold'])
        dogru += 1
    else:
        cprint("Tahmin: "+str(x)+" - Gerçek Değer: "+str(int(y)), "white", "on_red", attrs=['bold'])
        yanlis += 1

print("\n", "-"*150, "\nISTATISTIK:\nToplam ", toplam_veri, " Veri içersinde;\nDoğru Bilme Sayısı: ", dogru, "\nYanlış Bilme Sayısı: ",yanlis,
      "\nBaşarı Yüzdesi: ", str(int(100*dogru/toplam_veri))+"%", sep="") 

Eğer herhangi bir hata ile karşılaşmadan buraya kadar geldiyseniz artık python dosyanızı çalıştırabilirsiniz. Çalıştırdığınızda arkada tensorflow kütüphanesinin çalıştığına dair bir bilgilendirme mesajı da görebilirsiniz. Bendeki eğitim öğrenme yüzdesi:


Test verilerindeki başarı değeri ise;
Sonuç olarak; yapay zeka kendi başına çok derin ve ayrı bir yetkinlik isteyen konu. Daha değinmediğim birçok şey var. Ancak yazının başında da belirtiğim gibi zaten bu konuya en azından çalışma mantalitesi hakkında bilgi sahibi olduğunuzu varsayarak yazdım. Ağırlıkların neye göre hesaplandığı, eşik değerlerinin belirlenmesi, neye göre hangi aktivasyon fonksiyonunun kullanılacağı, regresyon, sınıflandırma baya birçok anlatılacak nokta var gördüğünüz üzere ancak benim burda yaptığım konuya yeteri kadar hakim olan birinin pythonda keras yardımıyla tensorflow kullanarak nasıl uygulama yapabileceğine dair giriş mahiyetinde bir örnekti. Artık her olasılık için bir kural tanımlama günümüz dünyasında yetersiz bir durumdur bu nedenle dev veriler karşısında kısmen de olsa mantıklı çıkarımlar yapacak sistemlere ihtiyacımız var. Geleceğin burda yattığı şüphesiz doğrudur. Hatta günümüzde bile farkında olmadan kullanmaya başladık bile. Karakter tanıma, yüz ve parmak izi tanıma, ses tanıma, dudak okuma diye gider. Anlamadığınız veya hatalı noktalar varsa lütfen yorum kısmında belirtiniz.
Sağlıcakla kalın.

Bu uygulamada kullandığımız bütün kodlara buradan erişebilirsiniz.
KAYNAKLAR:
https://archive.ics.uci.edu/ml/index.html
https://keras.io/
https://www.tensorflow.org/
http://machinelearningmastery.com/tutorial-first-neural-network-python-keras/