Sıfırdan Python İle Neural Network (Yapay Sinir Ağ ) Oluşturmak: Bölüm 2— Yapay Sinir Ağlarının Eğitilmesi

Sergen Cansiz
9 min readMar 24, 2020

--

İleri beslemeli (Feed Forward) bir yapay sinir ağında (Neural Network) nöronların hangi görevleri üslendiğine ve yapılan ağırlıklandırma işlemlerine Bölüm 1'de değindik. Bu bölümde ise bir yapay sinir ağında eğitim sürecinin (Training) nasıl ilerlediğine değineceğim. Eğer Bölüm 1'de yer alan yazıyı okumadıysanız bu yazıya başlamadan önce Bölüm 1'e geri dönüp okumanızı tavsiye ederim.

Yapay sinir ağlarında nöronlar katmanlar bazında bir biriyle bağlanmakta ve ileri besleme ile birbirlerine ağırlıklıklandırılmış verileri iletmektedirler. Ağın eğitimi ise nöronlarda yer alan Ağırlık “W” ve Bias “b” değerlerinin, en iyi tahmin değeri elde edilene kadar güncellemesiyle sağlanmaktadır. Bu bağlamda, ağırlık değerlerinin güncellenmesi ise gerçek (doğru) değer ile tahmin değeri arasındaki farka göre gerçekleştirilmedik. Bu farkın standardize edilmesi için ise çeşitli metrikler kullanılmaktadır. Bu metriklerden elde edilen değerlere ise genel olarak “Loss” adı verilmektedir. “Loss” gerçek değerin tahmin değerinden ne kadar farklı olduğunu göstermektedir. MSE (Mean Squared Error) yani Ortalama Standart Hata en çok kullanılan “Loss” metriklerin biridir. Peki MSE nasıl hesaplanır.

MSE (Mean Squared Error) Hesaplanması

Ortalama standart hata gerçek (doğru) ve tahmin değerleri arasındaki farkı gösteren bir metriktir. Bu bağlamda, hesaplanırken tüm gerçek değerler tahmin edilen değerilerden çıkartılarak karesi alınır ve toplanır. Aşağıda MSE formulü belirtilmektedir.

Ortalama Standart Hata formülü

Şimdi Bölüm 1'de son kısımda oluşturduğumuz veri setine geri dönelim ve MSE hesaplamasını gerçekleştirelim;

  İsim    |    Boy    |   Kilo    |  Cinsiyet
________ _________ _________ __________
Ahmet 165 75 E (0)
Veli 175 76 E (0)
Nazan 154 45 K (1)
Elif 136 56 K (1)
Kamil 145 70 E (0)
Suzan 167 56 K (1)
... ... ... ...

Bu veri setinde, veriler üzerinden boy ve kiloya göre cinsiyet tahmini edilceğinden dolayı cinsiyetler Erkekler (E) “0” Kadınlar (K) “1” olacak şekilde değerler düzenlenebilir. Bu durumda sonucu ağ üzerindeki tahmin değeri 0'a yakın ise Erkek 1'e yakın ise Kadın olarak yorumlayabiliriz.

Ek olarak, verileri normalleştirmek için ufak bir dönüşüm yapılabilir. Bu işlem öğrenme süresini kısaltmak ve daha anlamlı sonuçlar elde etmek için faydalır. Boy değerleri için -160 kilo değerleri için -71 işlemlerini yapibiliriz. Buradaki amaç basitçe verilerimizin değerlerini azaltmak bir nevi standartlaştırmaktır (Farklı standartlaştırma veya dönüşüm metodları da tercih edilebilir).

  İsim    | Boy(-160) | Kilo(-71) |  Cinsiyet
________ _________ _________ __________
Ahmet 5 4 E (0)
Veli 15 5 E (0)
Nazan -6 -26 K (1)
Elif -24 -15 K (1)
Kamil -15 -6 E (0)
Suzan 7 -15 K (1)
... ... ... ...

MSE değerini hesaplamak için ilk önce ağımızın tahmin değerine ihityacımız var bu nedenle eğitimin ilk aşamasında, ilk gözlemimiz olan “Ahmet” in dönüştürülmüş boy ve kilo verilerini ağ üzerinde geçirelim;

Şekil 1 — İleri beslemeli ağ ile tahmin

Çıktı nöronunun sonucunun 0.7296 olarak elde edildiği yukarıdaki örnekte gösterilmektedir (Bu hesaplamaların neden bu şekilde yapıldığı hakkında bir bilginiz yok ise lütfen Bölüm 1'de yer alan yazımı okuyunuz). Ahmet’in gerçek (doğru) değeri bu kilo ve boy için Erkek yani “0”. Bu durumda tahmin değerinin doğru değerden oldukça uzak olduğunu açık bir şekilde gözlemlenebilir. Fakat bu farkın standartlaştırılmış bir metrik halinde elde edilmesi için Loss değeri hesaplanmalıdır. Loss değeri yani MSE değerini hesaplamak için ise aşağıda ki formülü kullanabiliriz.

“Ahmet” sadece 1 gözlem olduğu için MSE formülünde n = 1 olmalıdır ve doğru değer Ytrue = 0 , tahmin değeri Yprediction = 0.7296 olacaktır.

Evet artık “Ahmet” gözlemi için MSE Loss değerimizi L = 0.07311 olarak hesaplamış olduk.

Ağırlıklar ve Bias Değerinin Güncellenmesi

Ağın eğitilebilmesi için Loss miktarına göre Nöronlarda bulunan W ve b değerlerlerinin güncellenmesi ve ardında diğer gözlem girdilerinin ağ içeresinden geçirilip yeni tahmin değerleri ile tekrar güncelleme yapılması gerekmektedir. Bu işlem tahmin değeri ile gerçek değer arasındaki oran minimuma gelene kadar devam etmeliydi. İşte tam da bu sayede yapay sinir ağımızı eğitmiş oluyoruz. Ağırlıkların ayrı ayrı nörondan elde edilen değerlere göre güncellenebilmesi için Loss değerinin her bir W ve b değerine olan etkisinin hesaplanması gerekmektedir. Bu işlemi ise Loss değerinin W ve b değerlerine göre kısmı türevinin alınmasıyla gerçekleştirebiliriz. Yukarıdaki örneğimizde 3 adet nöron ve her bir nöronda 2 adet W 1 adet b bulunmaktaydı. Bu durumda Loss fonksiyosunu her bir ağırlık ve bias değeri için aşağıdaki gibi olmaktadır.

Peki, neden kısmı türev işlemi yapılmalı veya kısmı türev bize hangi sonucu veriyor? Kısmı türev çok değişkenli bir fonksiyonda bir değişkenin o fonskiyonu ne kadar etkilediğini elde etmek için kullanılmaktadır. Bu durumda bizim problemimizde kısmı türev, her bir ağırlık ve bias değerinin Loos değerimizi nasıl etkildeğini elde etmemize olanak sağlamaktadır. Bu durumda Loss fonksiyonun ağırlık ve bias değerlerine göre kısmı türevleri aşağıdaki gibi gösterilebilir.

Loss değerinin Ağırlık ve Bias değerlerine göre kısmi türevleri.

Bu durumda W1 in Loss’a olan etkisini hesaplama için; L’nin W1'e göre kısmı türevini aşağıdaki gibi oluşturabiliriz.

Bu eşitlik zincir kuralından gelmektedir. Detaylı bilgi edinmek için bu videoyu izleyebilirsiniz

Yukarıdaki eşitliği çözebilmemiz için ilk olarak L değerini hesapladığımız eşitlikler üzerinden kısmi türev işlemini gerçekleştirmemiz gerekmektedir. L eşitliğimiz aşağıdaki gibi hesaplanabilir.

MSE Loss eşitliği

Şimdi bu eşitlikten yola çıkarak L’nin Yprediction’a göre kısmi türevini hesaplayalım;

L’nin Yprediction’a göre türevi. Gerçekleştirilen türev işleminin nasıl yapıldığı hakkında fikriniz yoksa lütfen bu videoyu izleyiniz.

L’nin Yprediction’a göre kısmi türevini elde etmiş olduk. Şimdi Yprediction’nın W1'e göre kısmı türev işlemini yapmamız gerekmektedir. Bunun için tekrar Kısmi Türevde Zincir Kuralını kullanmamız gerekmektedir;

YPrediction’nın W1'e göre türevi zincir kuralından YPrediction’nın H1 nöronuna türeviyle, H1 nöronunun W1'e türevinin çarpamın eşittir. Bu durumda YPrediction’nın H1 nöronuna göre türevi ve H1 nöronunun W1'e göre trüvi yine zincir kuralından elde edilen sonuca göre yukarıda olduğu gibi hesaplanmaktadır. “f” fonksiyonu ise Sigmoid fonksiyonunu temsil etmektedir. “f üssü” ise sigmoid fonksiyonunu türevi anlamına gelmektedir. Şimdi sigmoid fonksiyonunun türevini alarak hesaplamalarda bu eşitliği kullanalım.

Sigmoid fonksiyonunun türevi

Evet, W1 ağırlık değerine Loss değerinin etkisini hepsaplamak için bütün formüllerimizi oluşturduk. Bu durumda W1 ağırlık değerine etkinin hesaplanması için gerek tüm eşitliklerimiz aşağıda yer almaktadır.

L’nin W1'e göre türevinin alınmasıyla oluşan eşitlikler.

W1'in Loss değerine olan etkisinin hesaplanmasının ardından ağırlıklığı bu oranda güncelenmesi gerekmektedir. Bu güncelleme işlemide “Learning Rate” yani öğrenme oranı düzeyinde gerçekleşmektedir. Etki hesaplamasında elde edilen sonuç öğrenme oranı ile çarpılarak güncelenekce olan ağırlık değerinden çıkartılır. Bu işlimin formülasyonu aşağıda yer almaktadır;

Ağırlık değerini öğrenme oranı ve türev sonucu ile günceleme

Not: Oluşturulan bu formülasyonlar sadece W1 ağırlık değerinin güncellemesi içindi. Bu formüller yine aynı teoriden yola çıkılarak Ağ’da yer olan bütün ağırlık ve bias değerleri için uygulanmalıdır.

Şimdi, bu formüller üzerinden, “Ahmet” gözleminin verileri Ağ’a girdikten sonra W1 ağırlılığının güncelleme işlemini yapalım. Yazının ilk başlarında “Ahmet” gözleminin H1,H2 ve O1 (yani tahmin) değerlerini hesaplamıştık.Bu değerler H1 = 0.993, H2 = 0.993 ve O1 = 0.7296 şeklindeydi. Bir diğer ihtiyaç duyacağımız değer de “Learning Rate” (öğrenme oranı) 0.015 olarak belirlensin. Aşağıda “Ahmet” gözlemi için Loss fonksiyonun W1'e göre türevinin nasıl hesaplanacağı gösterilmektedir.

Yapılan işlemler sonucunda dL/dW1 = 0.0100 olarak elde edilmiştir. Bu durumda artık W1 değerini nasıl güncelleyeceğimizi biliyoruz. Bunun için elde edilen değeri, öğrenme oranı ile çarpmalı ardından W1 değerinden çıkartmalıyız.

Son olarak yeni W1 ağırlık değerimizi elde etmiş olduk. Artık bir sonraki gözlem için W1 ağırlık değerimiz 0.99985 olarak kullanılmalıdır. Ayrıca unutulmamalıdır ki, w2, w3, w4, w5, w6, b1, b2 ve b3 için değerleri için de aynı işlemler yapılmalı ve bu değerler de güncellenmelidir.

Sonuç olarak yapılan işlemlerin bir gizli katmandaki bir nöron ve çıktı katmanındaki bir nöron için akış diyagramı aşağıda gösterilmektedir;

Yapay sinir ağlarında eğitim süreci…

Tüm Ağın (Neural Network) Python Üzerinde Geliştirilmesi

Artık bir ağın nasıl eğitildiğini öğrenmiş olduk, şimdi bu işlemleri Python üzerinde uygulamaya başlayalım. Sıfırdan oluşuturacağımız bu ağda yeni bir sınıf oluşturarak buna “Network” adını verelim. Oluşturulan bu sınıf belirli yöntemleri içerisinde barındırmalıdır;

  • Sigmoid Fonksiyonu — Nöron değerlerini 0 ile 1 arasında elde etmek için
  • Sigmoid Fonksiyonunun Türevli Hali — Ağırlıklandırma işleminde kullanmak amacıyla.
  • Feedforward — İleri besleme yöntemi ile nöron değerlerinin elde edilmesi
  • Eğitim — MSE değeri (Loss) minimumuma gelene kadar devam edecek eğitim yöntemi.

Öncelikle class’ımızı (sınıf) ve içerisindeki method’larımızı oluşturulım(yöntem);

Network metods

class’ın __init__ methodunda bütün ağırlıkları ve bias değerlerini rastgele olarak tanımlayabiliriz. İlk başta bu değerlerin rastgele oluşturulsade eğitim sürecinde elde edilen çıktı tahmin değerlerine göre güncellenerek en iyi tahmini yapan değerlere ulaşcaktır. Bunun için numpy kütüphanesinde yer alan “random.normal” methodunu kullanabiliriz. Bu method oratalaması 0 standart sapması 1 olan seriden bir adet rastgele değer vermektedir. Ağımız üzerinde 3 adet nöron bulunduğundan dolayı, her bir nöronda 2 adet ağırlık olmak üzere toplam 6 adet ağırlık değer ve her bir nöronda 1 adet bias olmak üzere toplam 3 adet bias değerini __init__ methodu içerisinde rastgele olarak oluşturalım;

Network class’ı __init__ methodu

Şimdi sigmoid hesaplamasını yacağımız methodumuzu oluşturalım; bu method nörondaki toplam değeri 0 ile 1 arasında standartlaştırmaktadır. Bu nedenle girdi olarak x, nörondaki toplam değeri temsil etmektedir;

Sigmoid fonksiyonu

Ardından ağırlık ve bias güncelleme eşitliklerinde kullanmak üzere sigmoid fonksiyonun türev’i olan methodu oluşturalım (yukarı kısımda sigmoid fonksiyonun türevini olarak bu eşitliği elde etmiştik);

Geliştirdiğimiz sinir ağının genel olarak nasıl eğitildiğini gözlemlemek adına her bir devirde veri setindeki toplam Loss’u hesaplamak için MSE metodunu oluşturabiliriz. Bu sayede tahmin edilen değerler ile gerçek değerler arasındaki farkı inceleyerek modlemizin tutarlığını ölçümleyebiliriz.

Şimdi ise feedforward methodu yani İleri Besleme yöntemini oluşturmamız gerekli. İleri besleme methodunda ağırlık değerleri ile girdiler çapılmakta ardından bias değerleri ile toplanarak sigmoid ile değeri standartlaştırılmış halde elde edilmekteydi (bkz. Şekil-1). Feedforward yöntemi son olarak o1 tahmin değerimizi elde etmekteyiz. Şimdi bu işlemi 3 nöron üzerinden gerçekleştirerek tahmin değerimizi elde edeceğimiz yöntemimizi kodlayalım;

Bütün yöntemlerin belirlenmesinden sonra “train” yöntemini kodlayamaya başlayabiliriz. “train” kısmında her bir ağırlığın Loss değerine göre günceleneceği değer belirlenmelidir. Bu bağlamda train metodunun içerisinde aşağıdaki değerlerin hesaplanması gerekmektedir;

  • Loss değerinin tahmin değerine göre türevi.
  • Tahmin değerinin hangi nöronun ağırlık değerine göre türev alıyorsa o nöronun toplam değerine göre türevi.
  • Hangi nöronun ağırlık değerine göre türev alınıyorsa, o nöronun değerinin ağırlık değerine türevi.
  • Hangi nöronun ağırlık değerine göre türev alınıyorsa, o nöronun değerinin “bias” değerine göre türevi.

Ayırıca eğitimin ne kadar tekrar edeceğini belirlemek ve her bir devirde ağırlık ve biasların hangi oranda güncelleneceğini belirlemek için “epoch” yani devir sayısı ve “learning rate” öğrenme ornaı belirlenmesi gerekmektedir. Bu örnekte epoch = 1000 ve learning_rate= 0.001 olarak belirleyebiliriz.

Train aşamasının hepsini tamamlamış olduk. Son olarak MSE metodunu kullanarak her bir devirde Loss değerini yazdıran bir kod ekleyelim. Bu kod devir for döngüsünün sonuna konulmalıdır.

Son aşama ile birlikte Network classımızdaki bütün metdoları tanımlamış olduk. Network class’nız aşağıdaki kod parçasında olduğu gibi görünmelidir.

Oluşturduğumuz Network üzerinden verilerimizi eğitmeye başlayabiliriz. Bu eğitimde boy , kilo ve cinsiyet verilerinin yer aldığı veri setini kullanalım;

Yukarıda yer alan kodu çalıştırdığınızda her bir devirde modelinizin Loss (MSE) değeri hesaplanır. Eğer bütün kodları doğru bir şekilde aktardıysanız aşağıdaki gibi bir çıktı göreceksiniz. Bu çıktı her bir devirde (epoch) hesaplanan Loss değerini göstermektedir. Burada ki amaç Loss değerini minimum olarak hesaplayabilmektir. Bu modeliniz gerçeğe çok yakın sonuç verdiğini gösterir. Devir (epoch) sayısını arttırarak sonuçlarını gözlemleyebilirsiniz.

Devir 9991 loss: 0.1736706
Devir 9992 loss: 0.1736711
Devir 9993 loss: 0.1736717
Devir 9994 loss: 0.1736722
Devir 9995 loss: 0.1736728
Devir 9996 loss: 0.1736733
Devir 9997 loss: 0.1736739
Devir 9998 loss: 0.1736744
Devir 9999 loss: 0.1736750

Evet, sonunda modelimizi geliştirdik! Şimdi sıra tahmin yapmakta. Örneğin X kişisinin cinsiyetini tahmin edeceğiz. X kişisini boyu 180 ve kilosu 80. Hatırlarsanız eğtim verisini normalleştirmek için boyların 160 eksiniği kilolarında 71 eksiğini alarak basit bir dönüşüm yapmıştık. Şimdi aynı dönüşümü X kişisi içinde yapmamız gerekmektedir. Bu durumda boy ve kilo sırasıyla 20 ve 9 olamalıdır;

Eğer tahmin sonucun 0.5'ten büyük ise 1'e daha yakın olduğu için “Kadın” küçük ise 0'a daha yakın olduğu için “Erkek” olduğunu söyleyebiliriz.

Bu çalışmada geliştirilen Python kodlarını github’dan indirebilirsiniz.

R üzerinde veri bilimi, istatistik ve makine öğrenmesi tekniklerini tüm detayları ile anlattığım, 50 Saat ve 300'den fazla ders içeriğinden oluşan Udemy eğitimine aşağıdaki bağlantıdan ulaşabilirsiniz.

--

--

Sergen Cansiz
Sergen Cansiz

Written by Sergen Cansiz

Data Scientist, Statistician, Python and R Developer

Responses (2)