Gradient Descent, Maliyet (Cost/Loss) Fonksiyonu ve Python ile Doğrusal Regresyon Uygulaması

Yiğit Şener
5 min readJun 30, 2020

--

Makine öğrenmesinde algoritma sonuçlarındaki hata payının azaltılması için çeşitli optimizasyon teknikleri uygulayabiliriz. Optimizasyonu kimi zaman regresyonda eğim ve kesişim değerlerine en uygun (fit) doğruyu hesaplarken ya da kimi zaman lojistik regresyonda sigmoid fonksiyonundaki parametrelerin en optimum olanını bulmaya çalışırken kullanırız. Peki Gradient Descent (dereceli azaltma/iniş) algoritması bu işin neresinde? Önce genel kavramları bir açıklayalım.

Kavramlar

Cost/Loss (Maliyet/Kayıp) Fonksiyonu: Bu fonksiyon kurulan makine öğrenmesi modelinin ne kadar bir kayıp/hata ile çalıştığını hesaplar. Bu fonksiyonun farklı varyasyonları bulunsa bile içerisine temelde iki değer alır. Bunlar modelin tahmin ettiği değerler ile gerçekte bilinen değerlerdir. Eğitim kümesi sonucunda kurulan modelin çıktıları ile test için ayrılan sonuçlar bu fonksiyon üzerinden karşılaştırılır. Bu karşılaştırmada kullanılan temel fonksiyon çeşitleri:

Regresyon için olan ölçütler (Bu metriklerin açıklamalarına aşağıdaki yazımdan ulaşabilirsiniz).

  • L1 Loss /Ortalama Mutlak Hata (MAE)
  • L2 Loss / Hata Karelerinin Ortalaması (MSE)
  • Root Mean Squared Error (RMSE)

Sınıflandırma için loss fonksiyonları:

  • Log Loss (Cross Entropy Loss)
  • SVM Loss (Hinge Loss)

Learning Rate (Öğrenme Hızı/Oranı): En basit tanımı ile learning rate bir hiper parametre olarak ağırlıkların (sinir ağları) ya da katsayıların (lineer ya da lojistik regresyon) nasıl bir hızda değiştiğini tanımlar. Günlük hayattan bir örnekle açıklamaya çalışayım; küçük bir çocuk arabaları hep 4 kapılı olan ve hareket eden her şeyi zihninde araba olarak canlandırmıştır. Ancak bir gün 2 kapılı hareket eden bir şey gördüğünde ne olduğunu anlayamaz ve ailesine sorar “baba baba bu nedir?” der. Baba cevap verir “araba” (gözetimli öğrenme supervised learning). Eğer ki çocuğun learning rate’i oldukça yüksek ise hemen karar verir ve tüm arabaları 2 ve 4 kapılı olarak kafasında tanımlar. Ancak yavaş yavaş, sindire sindire düşük seviye bir learning rate ile arabaları tanımlamaya başlarsa tüm arabalar içinde çok az bir orana sahip 2 kapılı araba olduğunu fark edecektir.

Kıssadan hisse learning rate kullanılan algoritmaların çalışılan (train) data seti üzerindeki parametre optimizasyonundaki gelişim hızını tanımlar. Genellikle alpha terimi ile ifade edilirler.

Gradient Descent (Dereceli Azaltma/İniş): Temel olarak, örneğin bir regresyon doğrusundaki eğimin seviyesini ölçen fonksiyon denilebilir. Ve teknik olarak, fonksiyondaki tüm değişkenlerin birinci dereceden türevlerinin toplamı bize gradyanı verir. Fonksiyon çıktılarının döngüsel (iterative) olarak parametrelerinin optimize edilerek yukarıdan aşağıya doğru inecek şekilde hatayı minimize etme sürecinden dolayı Azaltma/İniş (descent/descending) olarak tanımlanır.

Gradient Descent algoritmasının çalışma mantığını daha iyi anlamak için Python’nun Numpy kütüphanesinden yararlanarak doğrusal (linear) regresyon uygulaması yapacağız. Görselleştirme için ise Matplotlib kütüphanesinden yararlanacağız. Önce kütüphaneleri kuralım.

import numpy as np
import matplotlib.pyplot as plt

Bu uygulamayı öncelikle analitik yöntemler ile çözümleyip ardından Gradient Descent algoritmasının matematiksel arka planını inceledikten sonra uygulamasını yapacağız. Böylece aradaki farkları anlamamız daha kolay olacaktır.

Analitik Uygulama

Numpy üzerinden doğrusal regresyon eğrisi çizebileceğimiz sentetik bir veri seti yaratarak bunu scatter plot üzerinden gösterelim.

# Sentetik veri seti
x = 4 * np.random.rand(100,1)
y = 12 + (3 * x) + np.random.rand(100,1)

# Scatterplot
plt.scatter(x,y)
plt.xlabel("X",fontsize = 15)
plt.ylabel("Y",fontsize = 15, rotation = 0)
plt.show()

Yukarıdaki kodda Numpy üzerinden 2 adet dizi (array) oluşturduk. X bağımsız değişken ve Y bağımlı (target) değişken arasında scatter plot üzerinde açıkça görüldüğü üzere doğrusal bir ilişki olduğundan bahsedebiliriz. Doğrusal regresyonu tanımlayan fonksiyonu hatırlayalım.

http://www.nabla.hr/SlopeInterceptLineEqu.gif

Regresyon katsayılarını (M ve C) hesaplayan fonksiyonu yazıp katsayılarla oluşan doğrunun eğimini scatter plot üzerinde çizdirelim.

# Regresyon katsayılarını hesaplayan
# analitik fonksiyon
def analyticsMethod(x, y):
ssxy = (x * y).sum() - (len(x) * x.mean() * y.mean())
ssxx = ((x - x.mean()) ** 2).sum()
m = ssxy / ssxx
c = y.mean() - (m * x.mean())
return [m,c]

m, c = analyticsMethod(x, y)
# printing both the values
print(f'M (Theta 0) değeri: {m}')
print(f'C (Theta 1) değeri: {c}')
# ÇIKTI:
# M (Theta 0) değeri: 2.977
# C (Theta 1) değeri: 12.552

# M ve C ile doğruyu çizdirelim
# Scatter plot üzerinde regresyon doğrusu
plt.scatter(x, y)
plt.plot(x, (x * m + c), color = "red")
plt.xlabel("X", fontsize = 15)
plt.ylabel("Y", fontsize = 15, rotation = 0)
plt.show()

Yukarıdaki grafikte görüldüğü üzere noktalara en yakın mesafeden geçen doğruyu bulduk.

Peki analitik olarak bu katsayıları bulabiliyorsak neden Gradient Descent algoritmasına ihtiyaç duyarız? Çünkü elimizde milyonlarca hatta milyarlarca veri bulunduğunda bunun analitik bir yöntem ile çözülmesi hayli zaman almaktadır. Gradient Descent yöntemi ile bu süre aza indirgenirken hata değeri minimalize edebilmektedir.

Gradient Descent Algoritmasının Matematiksel Anlatımı

Doğrusal regresyon için kullanılan gradient descent algoritmasının temel formülü:

Formülde yer alan “:=” işaretinin, değişkene değer atamak ya da var olan değişkeni güncellemek anlamına gelmektedir.

J(θ) maliyet (cost) fonksiyonunu göstermektedir. “α” öğrenme hızını (learning rate) ifade etmektedir. Şimdi hataların kare ortalamasını (Mean Square Errors) veren maliyet fonksiyonunu tanımlayalım.

Yukarıdaki formülde yer alan m gözlem sayısını yani satır sayısını ifade etmektedir. “hθ(x(i))” tahmin edilen değerleri (predictions) göstermektedir. y gerçek değerlerdir. Bu iki değerler kümesinin farkının karesi ise bize MSE’yi vermektedir. Maliyet fonksiyonunun çıktısı her zaman “maliyet/cost >= 0” olduğundan dolayı pozitif yönlü bir çıktı verir. Eğer bu değer yüksek ise gerçek ve tahmin edilen değerler arasında hata oranı yüksektir. Bu yüzden burada amaç maliyet fonksiyonundan çıkan değerlerden en küçüğüne ulaşabilmektir.

Gradient Descent Uygulaması

Bu uygulama içerisinde 2 farklı fonksiyon bulunmaktadır. İlkinde maliyet fonksiyonu hesaplanmaktadır. İkincisinde ise iki dizi değer üreten bir Gradient Descent fonksiyonu yer almaktadır.

Yukarıdaki gradient descent fonksiyonun içerisine parametre olarak verdiğimiz maksimum iterasyon sayısı (3,000) gerçek hayat problemleri için verilmeyebilir. Yani maliyet fonksiyonundan çıkan değer istenilen düzeye gelene kadar döngü devam edebilir.

Alpha değeri ise öğrenme hızını (Learning Rate) göstermektedir. 0.01 yerine başka değerler denerek fonksiyonun çıktılarındaki değişiklik gözlenebilir.

Her bir iterasyon için maliyet fonksiyonundaki değişimleri gözlemleyebileceğimiz grafiği çizdirelim.

# Scatter plot ile analiz
plt.scatter(iter,costs)
plt.xlabel("İterasyon Sayısı")
plt.ylabel("Maliyet/MSE Fonksiyon Çıktısı")
plt.box(None)
plt.show()

Grafikte (Elbow Method) maliyet fonksiyonu içinde kullanılan MSE ile hataların her bir iterasyon için karşılık gelen değerleri yer almaktadır. Böylece hataların minimuma doğru giderken nasıl bir iterasyondan geçtiğini grafikten okuyabiliyoruz.

Sonuç

Gradient descent, algoritmaların parametrelerini optimize etmek için oldukça kullanışlıdır. Özellikle makine öğrenmesi uygulamalarında optimizasyona tabi tutulan her bir durum için denenip test edilmesi oldukça zevklidir.

--

--