Bu yazı Makine Öğrenmesi Matematiği yazı dizisinin 11. bölümüdür. Hatırlamak isterseniz:

Daha önceki bölümlerde regresyonun farklı uygulamalarına bakmıştık ve sadece sürekli veriler üzerinde çalışmıştık. Şimdi lojistik regresyon ile devam edelim.

  • Lojistik regresyon, bağımlı değişkenin kategorik bir değişken olduğu regresyon problemi gibidir. Doğrusal sınıflandırma problemlerinde yaygın bir biçimde kullanılır. Regresyon denilmesine rağmen burada bir sınıflandırma söz konusudur.

Lojistik regresyon, bir sonucu belirleyen bir veya daha fazla bağımsız değişken bulunan bir veri kümesini analiz etmek için kullanılan istatistiksel bir yöntemdir.

Önce lojistik regresyonun tanımını anlayıp sonra da daha önce yaptığımız gibi hipotez fonksiyonunun tanımı ile devam edeceğiz.

Basit olarak, lojistik regresyon, gözlemleri ayrık sınıflara atamak için kullanılan bir sınıflandırma algoritmasıdır. Çıktının eşleştiği bu ayrık sınıflar eğer iki tane ise buna ikili sınıflandırma denir. Sonuç, ikili bir değişkenle ölçülür (yalnızca iki olası sonuç vardır). Aşağıdaki örneklere baktığımızda, sağ taraftaki grafikte verileri temsil eden bir doğru görmekteyiz ve sol tarafta da verileri ayıran bir doğru ile karşılaşıyoruz.

Her iki grafikte de verileri temsil eden bir eğri ile karşı karşıyayız. İkinci çizimdeki örneği ev büyüklüğü-fiyat verileri olarak, ilk çizimi ise hasta veya sağlıklı bireylerin verileri olarak düşünebiliriz. Bu durumda değişen veri setimize uygun olarak, verimizi temsil edecek eğri farklı olacaktır.

Şimdi lojistik regresyona geri dönelim. İlk olarak ikili sınıflandırma ve çok-sınıflı (çoklu) sınıflandırma örneklerine bakalım.

İlk grafiği sınavdan geçer not alma veya kalma durumunun temsili, ikinci grafiği de üç ayrı çam ağacı türünün sınıflandırılması olarak düşünebiliriz.

Sınıflandırmanın, regresyondan farkı veri örneklerini ayırma işlemini yapmasıdır.

Hedefimiz, bu kırmızı düz çizgiyi (verileri en iyi şekilde ayıran eğriyi) bulmaktır, bu yüzden eğriyi çizmek için lojistik regresyon kullanabiliriz.

Lojistik regresyonun üç ayrı tipi vardır:

  • İkili (binary)
  • Çoklu (multi)
  • Sıralı (ordinal)

İkili sınıflandırma ile lojistik regresyona bir giriş yapalım.

Tahmin edilen değerleri olasılıklarına göre eşlemek için sigmoid fonksiyonunu kullanırız. Fonksiyon, herhangi bir gerçek değeri 0 ile 1 arasında başka bir değere eşler. Makine öğrenmesinde, tahminleri olasılıklara eşlemek için sigmoid fonksiyonunu sıklıkla kullanırız.

Sigmoid fonksiyonuna bakalım.

sigmoid

  • S(z) = 0 ile 1 arasında değer alan çıktı (olasılık tahmini)
  • z = fonksiyonumuzun girdisi
  • e = Euler sayısı

Sigmoid fonksiyonu aşağıdaki gibidir.

sigmoid2

  • Sigmoid fonksiyonuna lojistik fonksiyonu da denir.
  • Sigmoid fonksiyonu, doğrusal olmayışı nedeni ile yapay sinir ağlarında aktivasyon fonksiyonu olarak sıkça kullanılır. Bunun sebebi, sigmoid fonksiyonunun sürekli ve türevinin alınabilir bir fonksiyon olmasından kaynaklıdır.
  • Doğrusal olmaması nedeni ile sigmoid fonksiyonunu kullandığımız makine öğrenmesi modellerinde, lineer regresyonda sıkça kullandığımız MSE (Mean Squared Error) gibi metrikleri kullanamayız.
  • Sigmoid fonksiyonunu kullandığımız modellerde, MSE yerine Log Loss olarak da bilinen Cross Entropy adında bir maliyet fonksiyonu kullanılır.

Çapraz entropiyi kullanarak maliyet fonksiyonumuzu yazalım.

formul1

Yazdığımız bu maliyet fonksiyonlarını daha kolay anlayabilmek için şunlara bir bakalım;

  • Girdimiz x = 0 ve çıktımız y = 1 ise hipotez fonksiyonumuz htetax olur.
  • Girdimiz x = 0 ve çıktımız y = 0 ise hipotez fonksiyonumuz 1-htetax olur.

Yazdığımız maliyet hesabı ve maliyet fonksiyonlarını birleştirerek aşağıdaki gibi ifade edebiliriz.

formul2

Mevcut tahmin işlevimiz 0 ile 1 arasında bir olasılık değeri döndürür. Bunu ayrık bir sınıfa eşlemek için,  çıktı değerlerimizi sınıflayacağımız bir eşik değeri veya devrilme noktası seçeriz. Bu değere karar sınırı da denilir. Karar sınırını daha iyi anlayabilmek için aşağıdaki görsele bakalım.

karar_siniri.png

Şimdi de maliyet fonksiyonlarımızın grafiklerine bakalım. Burada Andrew Ng’nin sunumundaki görsellere başvuruyoruz.

_images/y1andy2_logistic_function.png

Çıktı değerimizin 1 veya 0 olduğunda gözlemlediğimiz monoton fonksiyonlardır. (sürekli artan veya azalan) Bunun bizim için önemi dereceli azalmayı hesaplayabilir ve maliyeti minimize edebiliriz.

Buraya kadar öğrendiklerimizi kodlayalım. Kullanacağımız veri seti AndrewNG’nin Coursera’da verdiği Machine Learning dersinden aldığımız ex2data1.txt verileridir.

Daha önce yaptığımız örneklerde olduğu gibi bunda da main dosyamız calistir.py olacaktır. Lojistik regresyonu implement ederken dereceli azalmayı kullanacağız ve maliyet hesabı yaparak bulacağımız teta değerini optimize etmek için scipy’dan yararlanacağız. Veri setinin önce dağılım grafiğini inceleyeceğiz, daha sonra modelimizi oluşturup, bazı test verileri ile tahminlerimizi gerçekleştireceğiz.

Programın tamamını aşağıda bulabilirsiniz:

calistir.py

# coding=utf-8
""" Main
Calistir """

import pandas as pd
import numpy as np

from ciz import dagilim_grafigi, hipotez_grafigi
from maliyeti_hesapla import maliyeti_hesapla
from dereceli_fonksiyon import dereceli_fonksiyon
from sigmoid import sigmoid

from scipy import optimize

u""" 1. Veri Setinin Yuklenmesi """
print ('1. Veri Seti Yukleniyor ...')
# Veri Setini Txt Dosyasindan Okuma
ex2data1 = pd.read_csv('ex2data1.txt', delimiter=',', header=None, names=['Exam1', 'Exam2', 'Admission'])

# orjinal veri setini bozmamak icin kopya olusturalim.
veri_seti = ex2data1.copy()

u""" 2. Dagilim Grafigi"""
print ('2. Dagilim Grafigi Gosteriliyor ...')
dagilim_grafigi(veri_seti)

# Tahmin Etmeye Calisacagimiz Verileri Okuma
y = veri_seti['Admission'].as_matrix()
del veri_seti['Admission']

# Toplam Girdi Sayisi
m, n = veri_seti.shape

# Ongorucu Veriler, ilk iki degisken: exam1 ve exam2
X_veri = veri_seti.as_matrix()

u""" 3. Kesme Degerinin Eklenmesi"""
print ('3. Kesme Degeri Ekleniyor ...')
X = np.ones(shape=(m, (len(X_veri[0]) + 1)))
X[:, 1:(len(X_veri[0]) + 1)] = X_veri

u""" 4. Tetanin ilk Degeri(initial) Ayarlaniyor ..."""
print ('4. Tetanin ilk Degeri(initial) Ayarlaniyor ...')
teta = np.zeros(n + 1)

maliyet = maliyeti_hesapla(teta, X, y)
gradyan = dereceli_fonksiyon(teta, X, y)

print (' Initial tetaya gore maliyet: ' + str(maliyet))
print (' Initial tetaya gore gradyan: ' + str(gradyan))

u""" 5. scipy ile Optimizasyon Yapiliyor ..."""
print ('5. scipy ile Optimizasyon Yapiliyor ...')

result = optimize.minimize(
    lambda theta: maliyeti_hesapla(theta, X, y),
    teta,
    method='Nelder-Mead',
    options={
        'maxiter': 400}
)

teta = result.x
maliyet = result.fun
print (' Maliyet: ' + str(maliyet))
print (' Teta :' + str(teta))

u""" 6. Hipotez Grafigi Gosteriliyor ..."""
print ('6. Hipotez Grafigi Gosteriliyor')
# grafik cizilirken kesme degerini ekledigimiz bolumu cikartarak cizdiriyoruz
hipotez_grafigi(X[:, 1:], y, teta)

u""" 7. Tahminler Yapalim ..."""
print ('7. Tahminler Yapalim ...')
print (' 45 ve 85 notlarini alan bir ogrencinin kabul edilme olasiligi' + str(sigmoid(np.array([1, 45, 85]).dot(teta))))
print (' 50 ve 50 notlarini alan bir ogrencinin kabul edilme olasiligi' + str(sigmoid(np.array([1, 50, 50]).dot(teta))))
print (' 65 ve 70 notlarini alan bir ogrencinin kabul edilme olasiligi' + str(sigmoid(np.array([1, 65, 70]).dot(teta))))

u""" 8. Modelin Basarisi ..."""
print ('8. Modelin Basarisi ...')
tahminler = sigmoid(X.dot(teta)) >= 0.5
basari = 100 * np.mean(tahminler == y)
print (' Egitimin Basarisi : ' + str(basari) + '%')

ciz.py

# coding=utf-8
""" Plotting Data
Veri Setinin Grafiginin Cizilmesi"""

import matplotlib.pyplot as plt
import numpy as np

def dagilim_grafigi(veri_seti):
    """
    :param veri_seti: Dagilim Grafiginin Yapilacagi Veri Seti
    """

    pos_veri = veri_seti[veri_seti['Admission'] == 1]
    neg_veri = veri_seti[veri_seti['Admission'] == 0]

    plt.figure()

    plt.plot(pos_veri['Exam1'], pos_veri['Exam2'], '+', markeredgecolor='black', markeredgewidth=2)
    plt.plot(neg_veri['Exam1'], neg_veri['Exam2'], 'o', markeredgecolor='black', markerfacecolor='yellow')
    plt.xlabel('Exam 1 Score')
    plt.ylabel('Exam 2 Score')
    plt.title('Dagilim Grafigi')
    plt.legend(['Admitted', 'Not admitted'])
    plt.show()

def hipotez_grafigi(X, y, teta):
    """
    :param X: Ongorucu Degiskenler, Sinav Notlari
    :param y: Hedef Degisken, Kabul Edilip Edilmedigi
    :param teta: Parametreler
    """

    pos_index = y.nonzero()[0]
    neg_index = (y == 0).nonzero()[0]

    plt.plot(X[pos_index, 0], X[pos_index, 1], '+', markeredgecolor='black', markeredgewidth=2)
    plt.plot(X[neg_index, 0], X[neg_index, 1], 'o', markeredgecolor='black', markerfacecolor='yellow')
    plt.title('Hipotez Grafigi')
    plt.xlabel('Exam 1 score')
    plt.ylabel('Exam 2 score')

    x_hipotez = np.array([X.min() - 2, X.max() + 2])
    y_hipotez = (-teta[0] - teta[1] * x_hipotez) / teta[2]

    plt.plot(x_hipotez, y_hipotez, color='blue')
    plt.legend(['Admitted', 'Not admitted'])
    plt.show()

dereceli_fonksiyon.py

# coding=utf-8
""" Gradient Descent
 Dereceli Fonksiyon """

from sigmoid import sigmoid
import numpy as np

def dereceli_fonksiyon(theta, X, y):
    """
    :param theta:
    :param X:
    :param y:
    :return: gradyan
    """
    m = X.shape[0]
    h = sigmoid(X.dot(theta))
    # cost = sum(-y * np.log(h) - (1.0 - y) * np.log(1.0 - h))
    grad = X.T.dot(h - y)
    return grad / m

maliyeti_hesapla.py

# coding=utf-8
""" Compute Cost Function
 Maliyet Fonksiyonunu Hesapla"""

import numpy as np
from sigmoid import sigmoid

def maliyeti_hesapla(theta, X, y):
    """
    :param theta:
    :param X:
    :param y:
    :return: maliyet
    """
    m = X.shape[0]
    h = sigmoid(X.dot(theta))
    cost = sum(-y * np.log(h) - (1.0 - y) * np.log(1.0 - h))
    return cost / m

sigmoid.py

# coding=utf-8
""" Sigmoid
Sigmoid """

import numpy as np

def sigmoid(z):
    """
    :param z: veri
    :return: sigmoid fonksiyonu
    >> sigmoid(0) == 0.5
    """
    return 1.0 / (1.0 + np.exp(-z))

 

dagilim

hipotez

 

1. Veri Seti Yukleniyor …
2. Dagilim Grafigi Gosteriliyor …
3. Kesme Degeri Ekleniyor …
4. Tetanin ilk Degeri(initial) Ayarlaniyor …
Initial tetaya gore maliyet: 0.69314718056
Initial tetaya gore gradyan: [ -0.1 -12.00921659 -11.26284221]
5. scipy ile Optimizasyon Yapiliyor …
Maliyet: 0.20349770159
Teta :[-25.16130062 0.20623142 0.20147143]
6. Hipotez Grafigi Gosteriliyor
7. Tahminler Yapalim …
45 ve 85 notlarini alan bir ogrencinin kabul edilme olasiligi0.776291590411
50 ve 50 notlarini alan bir ogrencinin kabul edilme olasiligi0.00835787437461
65 ve 70 notlarini alan bir ogrencinin kabul edilme olasiligi0.91267489481
8. Modelin Basarisi …
Egitimin Basarisi : 89.0%

Designed by Freepik