Perceptron'un öğrenme sürecini gösteren grafik: giriş, ağırlık, yanlılık ve karar sınırının bir grafik üzerinde dinamik olarak ayarlanması.

Perceptron Nedir? Python ile En Küçük Yapay Zekayı İnşa Edin

Bir perceptron, inşa edebileceğiniz en küçük ‘beyindir’. Bir sayı içeri girer. Bir evet-ya da-hayır cevabı dışarı çıkar. İşte hepsi bu kadar.

Kulağa önemsiz gelecek kadar basit gelebilir. Ancak bu minik fikir, bugün çalışan her nöral ağın tohumudur. Bu yazıda, Python’da sıfırdan bir perceptron inşa edecek ve öğrenmesini tarayıcınızda canlı olarak izleyeceğiz. Ağır matematik yok, büyük kütüphaneler yok. Sadece bir ağırlık, bir yanlılık ve bir döngü.

Perceptron Nedir?

1958’de Frank Rosenblatt adında bir araştırmacı, perceptron adını verdiği bir makine inşa etti.

Bu, tek bir beyin hücresi olan bir nörondan ilham aldı. Bir nöron sinyalleri alır ve bu sinyaller yeterince güçlüyse ateşlenir. Rosenblatt bu fikri matematikte kopyaladı:

output = 1   if (w · x + b) > 0
         0   otherwise

Burada x girdi, w ağırlık ve b yanlılıktır. Bu kelimeler için henüz endişelenmeyin. Gerçek bir şey inşa ederek her biriyle tanışacağız.

Önce İnsan Gibi Düşünün

Bir makine bir şeye karar vermeden önce, bir insanın karar vermesini izleyelim. John Doe ile tanışın. Bir iş teklifi var ve tek bir soruyu yanıtlaması gerekiyor: kabul etmeli mi?

John yazı tura atmaz. O, durumları tartar. Bazı faktörler onun için diğerlerinden daha önemlidir.

Faktör (girdi)DeğerJohn’ın ne kadar önemsediği (ağırlık)
Ekstra ödemeyüksekçok
Aynı şehirde kalıyorhayır, taşınmalıçok

John her faktörü ne kadar önemsediğiyle çarpar, sonra her şeyi toplar. Eğer toplam yeterince yüksekse, evet der. Değilse, hayır der.

İşte bu bir perceptron. Faktörler girdilerdir. Ne kadar önemsediği ağırlıktır. Ve ‘yeterince yüksek’ ise kafasında taşıdığı bir eşiktir. Bu eşiği aklınızda tutun. Daha sonra ona bir ad vereceğiz: yanlılık (bias).

John Doe nasıl karar veriyor: her girdi bir ağırlıkla çarpılır, sonuçlar bir yanlılıkla toplanır ve toplam tek bir evet-ya da-hayır cevabı olur.

En Basit Olası Karar: Bu Sayı Pozitif mi?

Sorunu neredeyse hiçbir şey kalmayana kadar küçültelim. Bir girdi. Bir soru.

Bu sayı pozitif mi?

Hepsi bu kadar. Makineye bir sayı besleyin. Pozitif için ‘Doğru’ ve negatif için ‘Yanlış’ yanıtını vermelidir.

Makine tahminini şöyle yapar:

prediction = (weight * value + bias) > 0

Girdiyi ağırlıkla çarpın, yanlılığı ekleyin ve sonucun sıfırın üzerinde olup olmadığını kontrol edin. Eğer evetse, ‘Doğru’ tahmin eder. Hayırsa, ‘Yanlış’ tahmin eder. Bu küçük formül, sınıflandırıcı veya karar fonksiyonu olarak da adlandırılır.

Başlangıçta, ağırlık ve yanlılık sadece rastgele sayılardır. Bu yüzden makine kötü tahmin eder. Şimdi tek akıllıca kısım geliyor: hatalarından öğrenir.

if prediction != result:
    error = result - prediction      # True - False = 1, False - True = -1
    weight += learning_rate * error * value
    bias   += learning_rate * error

Tahmin yanlış olduğunda, ağırlığı ve yanlılığı doğru yöne doğru iteriz. Hata bize hangi yöne iteceğimizi söyler. Öğrenme oranı her itmenin ne kadar büyük olacağına karar verir. Bunu her örnek için yaparız, sonra tüm geçişi tekrar ederiz. Veri üzerindeki bir tam geçişe epoch denir. Epoch’ları tekrarlamak eğitimdir.

Bu tam makineyi aşağıda görebilirsiniz. ‘Eğit’ tuşuna basın ve öğrenmesini izleyin. Her yeşil nokta pozitif bir sayıdır (Doğru), her kırmızı nokta negatiftir (Yanlış) ve mavi kesikli çizgi, makinenin onları ayırmaya karar verdiği yerdir.

Hemen yerine oturur. Okumaya bakın: sınır tam olarak 0 civarına iner ve yanlılık da 0‘a yakın bir yere yerleşir.

Bu bir tesadüf değil. Bu problem için yanlılığa hiç ihtiyacımız yoktu. Bu garip, çünkü yanlılığın önemli olması gerekiyordu. Neden önemli olduğunu görmek için daha zor bir soruya ihtiyacımız var.

Karar Sınırı Nedir?

Bu mavi çizginin bir adı var: karar sınırı. Makinenin ‘Yanlış’ demekten ‘Doğru’ demeye geçtiği tam noktadır.

Bunu hesaplayabiliriz. Sınır, w · x + b = 0 olduğunda durur. x için çözün:

decision_boundary = -bias / weight

‘Bu sayı pozitif mi’ sorusu için sınır 0’da olmalıdır. Ve öyledir. Şimdi doğru cevabın sıfırda olmadığı zaman ne olduğuna bakın.

Yanlılık Neden Gerekli? Öğrenci Başarı Örneği

Yeni bir problem. Aynı makine. Ona 0’dan 100’e kadar sınav puanları veriyoruz ve soruyoruz:

Öğrenci geçti mi?

Kural basit: 50 veya daha yüksek bir puan geçmiştir. Bu yüzden karar sınırı 0’da değil, 50‘de olmalıdır.

Hadi önceki sorunu çözdüğümüz gibi, sadece ağırlığı kullanarak çözmeye çalışalım. Aşağıdaki demoda, ‘Yanlılık kullan’ seçeneğini kapatın ve ‘Eğit’ tuşuna basın.

Doğruluk oranına dikkat edin. Yaklaşık yüzde 50’ye tırmanır ve sonra takılı kalır. Ne kadar uzun süre eğitirseniz eğitin, daha iyi yapamaz.

İşte nedeni. Yanlılık olmadan, formül sadece ağırlık * puan şeklindedir. Her sınav puanı pozitif bir sayıdır. Bu yüzden ağırlık pozitifse, makine her öğrenciyi geçmiş olarak kabul eder. Ağırlık negatifse, herkesi başarısız sayar. Sınır 0’a sabitlenir ve hareket edemez. Sıfırdan geçmeye zorlanan bir çizgi, ’50 altını’ ’50 ve üstünden’ ayıramaz.

Şimdi ‘Yanlılık kullan’ seçeneğini tekrar açın ve ‘Eğit’ tuşuna tekrar basın. Doğruluk oranı yüzde 100’e kadar çıkar ve sınır kayarak 50 civarına park eder.

Yanlılığın tüm görevi budur. Ağırlık eğimi ayarlar. Yanlılık, çizginin cevabın gerçekte olduğu yere oturabilmesi için sınırı sola veya sağa hareket ettirir. Hatırlayın: decision_boundary = -bias / weight. Bir yanlılık ile sınır herhangi bir şey olabilir. Olmadan, sonsuza dek sıfırda takılı kalır.

Unutulmaması gereken tek cümle: Girdileriniz sıfırdan uzakta olduğunda, çizgiyi onlara taşımak için bir yanlılığa ihtiyacınız vardır.

Perceptron Nasıl Öğrenir? Çağlar (Epochs) ve Öğrenme Oranı (Learning Rate)

Eğitim sırasında iki kadran gördünüz: çağlar ve öğrenme oranı.

Bir epoch (çağ), tüm veri üzerinde bir tam geçiş demektir. Makine nadiren her şeyi tek bir geçişte doğru yapar, bu yüzden tekrar tekrar geçeriz. Daha fazla çağ, hataları düzeltmek için daha fazla şans demektir. Bu yüzden eğitim devam ettikçe doğruluk oranı artar.

Öğrenme oranı, her düzeltmenin boyutudur. Koddaki learning_rate çarpanıdır:

weight += learning_rate * error * value

Küçük adımlar dikkatlidir ancak yavaştır. Büyük adımlar hızlıdır ancak aşırıya kaçıp etrafa sıçrayabilir. Bunu iyi seçmek, sanatın bir parçasıdır. Burada 0.1 kullandık, bu da kararlı kalmak için yeterince naziktir.

Veriler Neden Normalleştirilir?

Geçme örneğinde sessiz bir sorun gizli. Güncelleme satırına tekrar bakın:

weight += learning_rate * error * value

Düzeltme value ile çarpılır. Sınav puanları için value 100 kadar büyük olabilir. Bu yüzden tek bir yanlış tahmin, ağırlığı büyük miktarda değiştirebilir. Makine hala öğrenir, ancak pürüzsüzce yerleşmek yerine sarsılır.

Çözüm normalizasyondur: eğitimden önce girdileri küçük, düzenli bir aralığa küçültün. En basit versiyon, her puanı mümkün olan en büyük puana bölmektir, böylece 0’dan 100’e 0’dan 1’e dönüşür.

Aşağıdaki demoda, önce normalizasyon kapalıyken ‘Eğit’ tuşuna basın ve doğruluk çizgisinin yukarı çıkarken etrafta zıplamasını izleyin. Sonra ‘Verileri normalleştir’ seçeneğini açın, sıfırlayın ve tekrar eğitin. Aynı makine, aynı cevap, ancak çağların çok daha kısa bir kısmında oraya ulaşır ve tırmanış pürüzsüzdür.

Dürüst bir not. Bunun gibi tek bir girdiyle, normalizasyon çoğunlukla size hız ve sakinlik kazandırır. Girdileriniz çok farklı ölçeklerde yaşadığında vazgeçilmez hale gelir. John Doe’yu düşünün: maaşı binlerce dolarla ölçülüyordu, ancak ‘aynı şehir’ sadece 0 veya 1’di. Normalizasyon olmadan, dolarlar diğer her şeyi bastırırdı ve makine temelde şehri görmezden gelirdi. İkisini de aynı ölçeğe koymak, her faktörün adil bir söz hakkı almasını sağlar. (Maksimuma bölmek kolay versiyondur; yaygın bir genel yöntem, ortalamayı çıkarmak ve yayılıma bölmektir, buna standardizasyon denir.)

Python’da Tam Bir Perceptron

‘Bu sayı pozitif mi’ için hiçbir şey gizlenmeden tam program aşağıdadır. Tek oturuşta okunabilecek kadar kısadır.

import random

learning_rate = 0.1
EPOCHS = 100

weight = random.uniform(-1, 1)
bias   = random.uniform(-1, 1)

# positive numbers are True, negative numbers are False
data  = [(i * 0.1, True)  for i in range(1, 501)]
data += [(i * 0.1, False) for i in range(-500, 0)]
random.shuffle(data)

for epoch in range(EPOCHS):
    for value, result in data:
        prediction = (weight * value + bias) > 0
        if prediction != result:
            error = result - prediction          # +1 or -1
            weight += learning_rate * error * value
            bias   += learning_rate * error

decision_boundary = -bias / weight
print(f"weight = {weight:.3f}")
print(f"bias   = {bias:.3f}")
print(f"decision boundary = {decision_boundary:.3f}")

Bunu öğrenci-geçme makinesine dönüştürmek için iki şeyi değiştirirsiniz: veriyi result = score >= 50 ile sınav puanları yaparsınız ve eğer yanlılık eksikliğinin acısını hissetmek isterseniz, yanlılığı 0’da dondurursunuz. Diğer her şey aynı kalır.

Sırada Ne Var?

Şimdi çalışan bir perceptron inşa ettiniz. Bir girdi alır, onu tartır, bir yanlılık ekler ve karar verir. Hatalarından öğrenir, her seferinde bir çağ.

Tek bir nöron sadece bir düz çizgi çizebilir. Sihir, onları istiflediğinizde başlar: bir nöronun çıktısı bir sonrakinin girdisi olur. Yeterince katmanlı bir araya getirdiğinizde, tek bir çizgiden çok daha karmaşık şekilleri öğrenebilen bir nöral ağ elde edersiniz. Ama o nöronların her biri, az önce izlediğiniz şeyi yapıyor. Bir ağırlık, bir yanlılık, bir karar.

Benim Kanada’da nasıl kod yazmaya başladığıma dair teknik olmayan hikayeyi okumak isterseniz, buraya yazdım: The Outsider Who Shipped Anyway.

Bunu benimle inşa ettiğiniz için teşekkürler. Şimdi sayıları değiştirin ve onu bozun. Öğrenmenin en hızlı yolu budur.

Comments

No comments yet. Why don’t you start the discussion?

    Bir yanıt yazın

    E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir