Perceptronlar

Buraya kadar perceptronların basitçe nasıl çalıştığını anlatmaya çalıştım. Bu birimlerin nasıl öğrendiği konusuna henüz girmedim. Perceptronların girdi sayısına göre belirlenen boyuttaki bir uzayı iki parçaya ayırdığını gördük. Tek girdili bir perceptron tek boyutlu sayı doğrusunu iki parçaya ayırıyor. İki girdili bir perceptron da iki boyutlu koordinat sisteminin bir doğru ile iki parçaya ayırıyor. Eğer simulasyonu yapsaydık üç girdili bir perceptronun da üç boyutlu uzayı bir düzlem ile iki parçaya ayırdığını görecektik. İspatlamadan genel olarak N girdili bir perceptronun N boyutlu uzayı N-1 boyutlu bir düzlemle iki parçaya ayıracağını söyleyebiliriz. Eğer bias kullanmazsak ayırmak için kullanılan doğru ya da düzlem her zaman orijinden geçecek ama bias ile bu ayraç bu noktayla kısıtlı kalmayacaktır.

Şimdi bu basit perceptronları yanyana kullanarak ne tür problemleri çözebileceğimize bakmak istiyorum.

Tek bir perceptron ile verilen uzayı doğrusal bir şekilde iki parçaya ayırabildiğimizi gördük. Görsel açıdan kolaylık olsun diye aşağıdaki örneklerde iki boyutlu koordinat sistemini örnek olarak kullanacağım. Aynı fikirler çok daha yüksek boyutlu uzaylar için de geçerli olacak.

Birden fazla perceptron ile istediğimiz şekilde kapalı bir alanı tanımlayabiliriz. Örneğin üç tane perceptron ile aşağıdaki gibi yeşil alanı tanımlayabiliriz.

Açık yeşil alan üç perceptron tarafından tanımlanabilir.

Tanımlanabilen alanların orijinde olması gerekmemektedir. Ayrıca birden fazla alan da tanımlanabilir.

Yukarıdaki alanı üç perceptron ile şu şekilde elde ederiz.

Birinci perceptron düzlemi şu şekilde ikiye ayırmakta:

Birinci perceptron

Bu perceptron yeşil alandaki girdilerde aktifleşiyor ve kırmızı alandaki girdilerde aktifleşmiyor. Perceptronun ağırlık ve bias değerlerini grafikten okumak mümkün ama buna burada girmeyeceğim.

İkinci perceptronun grafiği de aşağıdaki şekilde.

İkinci perceptron

Bu perceptron da sadece yeşil alandaki girdilerde aktifleşiyor.

Son olarak da üçüncü perceptron:

Üçüncü perceptron

Bu perceptron da diğer ikisi gibi yeşil alandaki girdilerde aktifleşiyor. Sonuçta üç grafiği üstüste koyduğumuzda en üstteki grafiği elde ederiz. Yani üç perceptronun da aktifleştiği girdiler en üstteki grafikteki yeşil alandaki girdiler olacak. Böylece bu bölgeyi programda tanıma yöntemimiz de belli olmuş bulunuyor. Üç perceptronun da aktifleşmiş olması.

Bu mantığı istediğimiz kadar geliştirebiliriz ama kısa süre sonra bir problemle karşılaşırız. Oldukça karmaşık alanlar için çok fazla perceptrona ihtiyacımız olacak, çünkü tek bir perceptron sadece doğrusal bir parçalamaya imkan veriyor ve aranan alan çok kıvrımlı bir sınıra sahip olabilir. Ayrıca bu şekilde sadece sınıflama türü problemleri çözebileceğiz. Yani verilen girdi hangi sınıfa ait? Yeşil bölgeye mi yoksa kırmızı bölgeye mi?

İlerideki yazılarda perceptronlarımızda ufak değişiklikler yaparak daha başka problemleri de nasıl çözebileceğimize değineceğim.

Perceptron (Bias)

Bu yazıda tek girdili basit perceptron modelinde bahsettiğim bir zayıflığın nasıl giderilebileceğini göstereceğim. Bahsettiğim zayıflık bu perceptronun sayı doğrusunu hep 0 noktasından ikiye ayırmasıydı. Kullanacağım çözüm aslında biraz hile gibi gözüküyor çünkü kullanacağım perceptron artık tek bir girdiye sahip olmayacak.

Simulasyon sayfasında çözüm modeline bakarsak ilk bakışta bu perceptronun aslında iki girdili bir perceptron olduğunu görüyoruz ama arada küçük bir fark var. Alttaki girdinin değeri her zaman 1.0 kalmakta. Böylece iki girdili perceptron durumundaki gibi iki değişkenimiz yok, hala sadece bir değişkenimiz var ama bu ekstra terim artık karar eşiğini sağa ya da sola kaydırabilecek.

\(o = sgn(i \cdot w + 1.0 \cdot w_{b}) = sgn(i \cdot w + w_{b}) \)

burada \(w \) yukarıdaki girdinin bağlı olduğu ağırlık değerini simgelerken, \(i \) de yukarıdaki girdi oluyor. \(w_{b} \) ise aşağıdaki sabit bias girdisinin ağırlık değeridir ve bu ağırlık öğrenme aşamasında tabii ki değişkendir. Yukarıdaki denklemde de görülebileceği gibi bu ağırlık değeri sign fonksiyonunu kendi değeri kadar sağa ya da sola kaydırır.

signum fonksiyonu
signum fonksiyonunun grafiği

Şimdi bu fonksiyonu bias terimi (\(w_{b} \)) ile görelim.

sign(x+2) fonksiyonunun grafiği

Simulasyonda bias terimiyle oynayarak aşağıdaki grafikte hangi girdi değerlerinin perceptronu aktifleştireceğini ve hangi değerlerin aktifleştirmeyeceğini görebiliriz. Bu sefer ayrımın 0 noktasında olmak zorunda olmadığına da dikkat edelim.

Perceptron (İki girdi)

Yapay zeka ağlarında tek girdili perceptronlardan daha karmaşık ne olabilir? Tabii ki iki girdili perceptronlar. Bu animasyonda da geçen yazıdaki aynı sistemi kullandım. Dolayısıyla bunları tekrar anlatmayacağım. Bu animasyondaki ağdaki tek fark birbirlerinden bağımsiz iki girdi ve iki ağırlık olduğundan iki değişik çarpan elde ediyoruz ve bunları toplayabiliyoruz artık. Bu sefer iki girdinin düzlem koordinat sisteminde ne yaptığına grafikte bakarsak orijinden geçen bir doğru ile bu düzlemi ikiye ayırdığını görüyoruz. Yeşil bölgedeki girdiler için bu perceptron aktifleşecek ve kırmızı bölgedeki girdiler içinse aktifleşmeyecek. Tek girdili bir perceptron sayı doğrusunu iki bölgeye ayırıyordu, iki girdili perceptron da düzlemi iki bölgeye ayırıyor. Bu ayrım belki pek net görünmese de doğrusal bir şekilde yapılıyor, çünkü herhangi bir andaki ağırlık değerleriyle yazabileceğimiz fonksiyon şu şekilde oluyor:

\(o = sign(w_{1}\cdot i_{1} + w_{2}\cdot i_{2}) \)

Bu durumda çıktının aktif (1) olması için sign fonksiyonunun girdisinin pozitif olması gerekir. Bu da

\( w_{1}\cdot i_{1} + w_{2}\cdot i_{2} > 0 \)

eşitsizliği anlamına gelir. Ağırlıklar için sabit \(W_{1} \) ve \(W_{2} \) değerlerini alırsak ve girdileri de x ve y diye adlandırırsak bu eşitsizlik liseden tanıdığımız doğru eşitsizliklerine denk olur.

\(W_{1} \cdot x + W_{2} \cdot y > 0 \)

Böylece tek bir perceptronun düzlemi doğrusal bir şekilde ikiye ayırdığını gördük. Bu doğru şimdilik her zaman orijinden geçiyor ama ileride buna da bir çözüm bulacağız. Yine de bu türde, yani iki girdili perceptronlar ile belki neler yapabileceğimizi hayalimizde biraz canlandırabiliriz. Örneğin iki tane perceptron ile iki değişik yarı düzlemin kesişimlerini tanıyabiliriz. Burada tanımaktan kast ettiğim şey bu iki perceptronun da bu kesişim alanında aktif olması ve diğer durumlarda en fazla birinin aktif olmasıdır.

Bir dahaki yazıda düzlemi perceptron ile orijinden geçmeyen bir doğruyla iki bölgeye ayıracağım. Şimdilik bu linkten iki girdili perceptronla oynayabilirsiniz.

Perceptron (Yapay sinir ağları)

Yapay sinir ağları, yapay zeka sayesinde bir süredir yine oldukça popüler konulardan biri oldu. Yaklaşık çeyrek asır önce üniversitede bu dersi almıştım ve hoşuma gitmişti. Sanki yeterince hobim yokmuş gibi bu alandaki yeniliklere göz atmaya karar verdim. Yapay zeka uygulamalarını programlamak için olası en kolay yolların matlab ya da tensorflow tabanlı kütüphaneler olduğunu gördüm. Bu arada biraz python da öğrenebilirim belki dedim ve tensorflow kendimi akımına bıraktım.

Bu ikinci öğrenme aşamasında yaptıklarım üzerine yazılar yazmayı düşünüyorum. Sistem olarak Ubuntu 19.04 altında python 3.7 ve pip3 kullanıyorum. Editör olarak eclipse ve PyDev eklentisini (7.3 versiyonu) kullanıyorum. Bu sistemlerin kurulumu için internette bir sürü kaynak olduğundan bunlara şimdi girmeyeceğim.

İlk yazımda yapay sinir ağlarının temel taşlarından olan perceptron modeli üzerine bir animasyon göstermek istedim. Animasyonları mümkün olduğunca HTML 5 ile programlamak istiyorum. İlk animasyonda perceptron modelinin en basit halini programladım. Sadece bir girdisi ve tek bir ağırlık değeri var. Dolayısıyla hesaplamaları da oldukça kolay. Umarım anlaşılması da kolaydır. Bir sonraki animasyonda birden fazla girdisi olan perceptron programlayacağım.

Perceptron için basit bir blok diyagram

Perceptron kabaca birden fazla girdisi ve bir çıktısı olan bir nöron modelidir. Perceptrona gelen girdiler önce her girdiye ait olan ağırlık değerleriyle çarpılır ve sonra bu çarpımlar toplanır. Bu toplamlar belli bir değerin üzerindeyse bu perceptron aktifleşir, değilse aktifleşmez.

Şimdi animasyonla biraz oynayalım. Girdi değeri bu animasyon için -1 ile 1 aralığında seçilebiliyor. Ağırlık değeri de -10 ile 10 arasında seçilebiliyor. Ardından başlat düğmesine basıldığında yapılan hesaplamalar ekranda gösteriliyor. En sonunda perceptron etkinleşmişse yeşil, etkinleşmemişse kırmızı oluyor. Etkinleşme için bu animasyonda signum fonksiyonunu kullandım. Yani toplamın sonucu sıfırdan büyükse bu fonksiyon 1 değerini veriyor. Diğer her durumda da 0 değerini.

Animasyonun altında bir sayı doğrusu üzerinde seçilmiş ağırlık değeri için hangi girdilerde perceptronun etkinleşeceğini (yeşil renkli kısım) ve hangi girdi değerleri için etkinleşmeyeceğini (kırmızı renkli bölge) çizdirdim. Bu gösterim için JSXGraph kütüphanesini kullandım. Bu şekilden de anlaşıldığı gibi eğer ağırlık değeri pozitif ise, pozitif girdiler için etkinleşme olacak, negatif değerlerde perceptronun çıktısı 0 olacak. Eğer ağırlık değeri negatif ise bu sefer perceptron negatif girdiler için etkinleşecek ve pozitif girdiler için 0 çıktısını verecek. Bunu matematiksel olarak da görmek kolay. Yukarıdaki diyagramda sadece bir tek girdi ve tek ağırlık olduğunu var sayalım. Animasyonda kullandığım f fonksiyonu şu şekildedir.

math-sgn-function-in-cpp How to Implement The Sgn Function in C++? c / c++ math programming languages

O zaman çıktı fonksiyonunu şu şekilde yazabiliriz:

\(o = sign(i\cdot{w}) \)

Eğer girdi (i) sıfırsa ya da ağırlık (w) sıfırsa, çıktı 0 olacaktır ( o = sign(0) ). Bunun dışındaki durumlar için ise aşağıdaki şekilde olacaktır.

\(o = sign((w > 0) \cdot{( i < 0)}) = sign(< 0) = -1 \)

\(o = sign((w > 0) \cdot{( i > 0)}) = sign(> 0) = 1 \)

\(o = sign((w < 0) \cdot{( i < 0)}) = sign(> 0) = 1 \)

\(o = sign((w < 0) \cdot{( i > 0)}) = sign(< 0) = -1 \)

Yukarıda w > 0, pozitif ağırlık değerleri, i > 0 da pozitif girdi değerleri anlamına geliyor. sign(>0) da sign fonksiyonunun girdisinin pozitif olduğu anlamına geliyor. Aynı şekilde < işaretini de bu değerlerin negatif olduğu durumlar için kullandım.

Yani bu basit perceptron ağırlığın sıfır olmadığı durumda sayı doğrusunu hep sıfır noktasında ikiye bölüyor. Sıfırın bir tarafı için -1 değerini üretirken, diğer tarafı için de 1 çıktısını üretiyor. Bu şekliyle oldukça sıkıcı bir zeka birimine benziyor ama ileride bu aksaklıkların üstesinden gelmenin yollarına bakacağız.