3 Aralık 2015 Perşembe

PHP ile Yapay Sinir Ağı (Denetimli Öğrenme Algoritması ile)



PHP ile Yapay Sinir Ağı Oluşturmak




Bu konuda internette Türkçe bilgi bulmak pek kolay değil. Bu makaleyi bu nedenle yazıyorum.

Bu makalede yapılanı anlamanız için yapay sinir ağlarının ne olduğunu biliyor olmanız gerekiyor. Yani burada "yapay sinir ağı nedir?" değil "PHP ile yapay sinir ağı nasıl oluşturulur?" meselesini inceleyeceğiz.

Sıfırdan yapay sinir ağı kodlamasını anlatmayacağım. Bunun için yazılmış ve paylaşıma sunulmuş bir class'ın nasıl kullanılacağını anlatacağım.

Öncelikle şu linkten, class_neuralnetwork.php dosyasını indirip sitemizin kök klasörüne taşıyoruz:
https://github.com/infostreams/neural-network

Öncelikle bir arayüz tasarlayalım. Bu arayüz sayesinde, eğitilmiş bir yapay sinir ağına veriler gönderip sonuçları okuyacağız.

Buyrun, index.php adlı dosyamız:
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="UTF-8">
  <title>YZ</title>
  <link rel="stylesheet" type="text/css" href="css.css" />
  <script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
  <script type="text/javascript" src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
  <script type="text/javascript" src="js.js"></script>
</head>
<body>
  <table id=arayuz cellpadding=0 cellspacing=50>
        <tr><td id="cevap"></td></tr>
  <tr>
  <td id="ileti_kutusu" height=50>
  <input type="text" id="kullanici" autocomplete="off" />
  <button id="btn_gonder">Gönder</button>
  </td>
  </tr>
  </table>
</body>
</html>

Gördüğünüz gibi sayfama bazı stil ve js dosyaları da çağırıyorum.

Buyrun, css.css adlı dosyamız:




* {margin:0; padding:0; }
html,body,table {height:100%;}
body { font-family:Verdana; }
#arayuz { text-align:center; vertical-align:middle;  width:100%; background-color:#ccc; }
#cevap { 
font-size:15px; 
letter-spacing:.5px; 
border:1px solid #333; 
box-shadow:0px 3px 6px #555 inset; 
background-color:#f3f3f3; 
border-radius:5px;
}
#kullanici {
width:50%;  height:20px; padding:10px; 
font-size:15px;  letter-spacing:.5px; 
outline:none; 
border-radius:5px; border:1px solid #777;
}
#btn_gonder {
width:100px; height:42px; 
font-size:15px; letter-spacing:.5px; text-shadow:0px 0px 2px #555; 
border-radius:5px; border:1px solid #333; box-shadow:0px -1px 10px #03c inset;
background-color:#09c; color:#fff; 
cursor:pointer; 
}
#btn_gonder:hover { background-color:#39f; box-shadow:0px -1px 10px #06d inset; }




Buyrun, js.js adlı dosyamız:



$(document).ready(function() {
  $('#btn_gonder').click(function() {
  if($('#kullanici').val()!="")
  $.ajax({
                type:'POST',
  url:'ysa_cevap.php',
  data:'kullanici='+$('#kullanici').val(),
  beforeSend :function() { 
                    $('#cevap').stop().animate({'background-color':'#aaa','color':'#555'},200); 
                },
  success:function(ajaxcevap){
  $('#cevap').html(ajaxcevap);
  $('#kullanici').attr('placeholder',$('#kullanici').val()).val("");
  $('#cevap').stop().animate({'background-color':'#f3f3f3','color':'#000'},200);
  }
  }) 
        else $('#cevap').stop().animate({'background-color':'#aaa','color':'#555'},200);
  });
});




Henüz yapay sinir ağıyla ilgili bi'şey yapmadık. Stil dosyamız sadece arayüzümüzün şeklini şemalini çıkarttı. JS dosyamız da index.php'deki Gönder butonuna tıklandığında AJAX metoduyla ysa_cevap.php'ye metin kutusundaki verileri gönderme işini yapmak için hazırlandı. AJAX metoduyla bu işi yapmak istedim çünkü hem PHP işleri index.php'den ayrı bir sayfada gerçekleşsin hem de sayfa her Gönder butonuna tıkladığımızda yeniden oluşturulmasın istedim.

Peki ysa_cevap.php dosyamızda ne var? Bu dosya, eğitilmiş yapay sinir ağına gönderilen verileri yapay sinir ağına işleterek, ekrana sinir ağının çıktısını veriyor. JS dosyamız da burada ekrana yazılan çıktıyı alıp index.php'deki kendi alanına bunu yazdırmakla görevli... 

Bakalım ysa_cevap.php dosyamızda neler var:



<?php
$k = (isset($_POST["kullanici"])) ? $_POST["kullanici"] : "";
if($k!="") {
      require_once("class_neuralnetwork.php");
      $n = new NeuralNetwork (2, 3, 1); // 2 giriş, 3 gizli, 1 çıkış nöronu
      $n->setVerbose(false); // hata verme
      $n->load("ysa.txt");
      $veri = str_split($k);
      $i=1;
      foreach($n->calculate($veri) as $eleman) { echo "<br />Sonuç $i: $eleman"; $i++; }
}
?>



1.satır: AJAX'ın bize POST ettiği (metin kutusundan alınan) değeri $k değişkenine attık.
2.satır: eğer $k değişkeni boş değilse
3.satır:     class_neuralnetwork.php dosyasını çağır.
4.satır:     $n adında, 2 giriş, 3 gizli, 1 çıkış nöronu bulunan bir ağ oluştur.
5.satır:     $n'de bir hata oluşursa bunu ekrana basma.
6.satır:     $n'nin değerleri ysa.txt'deki eğitilmiş ağın değerleri olsun.
7.satır:     $k'daki karakterleri birbirinden ayırıp dizi haline getir. Bu dizi $veri olsun.
9.satır:     $veri dizisini ağa gönderip işlet ve çıkış nöronlarından elde ettiğin verileri ekrana yaz.

Sürekli eğitilmiş ağ deyip duruyoruz da, bu ağı nerede eğitiyoruz? Nerede eğitip de ağın değerlerini ysa.txt adlı bir dosyaya kaydediyoruz? Bunun için, henüz herhangi bir arayüz kodlamadığım egitim.php adlı dosyam var. Buyrun:



<meta charset="UTF-8" />
<?php

require_once("class_neuralnetwork.php");

$n = new NeuralNetwork(2, 3, 1); // 2 giriş, 3 gizli, 1 çıkış nöronu

// Eğitim verileri
$n->addTestData(array(0, 0), array(1)); // 0 0 için 1 üreteceksin
$n->addTestData(array(0, 1), array(0)); // 0 1 için 0 üreteceksin
$n->addTestData(array(1, 0), array(0)); // 1 0 için 0 üreteceksin
$n->addTestData(array(1, 1), array(1)); // 1 1 için 1 üreteceksin

$maks = 10;

$i=0;
while(!($basarili = $n->train(1000, 0.02)) && ++$i<=$maks) echo "Eğitim $i: başarısız...<br />";

if ($basarili) {
    $epochs = $n->getEpoch();
    echo "Ağ, $i eğitim + $epochs iterasyon sonucu öğrendi.<hr />";
}

echo "<h2>Son Durum</h2>";
for ($i = 0; $i < count($n->trainInputs); $i ++) {
    echo "<br />$i. test seti: ";
    echo "istenen çıkış = (".implode(", ", $n->trainOutput[$i])."); ";
    echo "ağ çıkışı = (".implode(", ", $n->calculate($n->trainInputs[$i])).")\n";
}

echo "<hr />";
$n->save("ysa.txt");
echo "YSA bu şekliyle kaydedildi";
?>



Bu dosyamızda ağı eğitip ysa.txt adıyla kaydediyoruz. Bunu nasıl yapmışız bakalım:
1.satır: Türkçe karakterler sayfamda bozuk görünmesin
2.satır: class_neuralnetwork.php dosyamı çağır.
3.satır: $n adında, 2 giriş, 3 gizli, 1 çıkış nöronu bulunan bir ağ oluştur.
4,5,6,7.satır: Eğitim verilerin ve bunlara karşılık vermen gereken yanıtlar bunlar. (Eğer iki nöronundan da 1 veya iki nöronundan da 0 gelirse 1 döndürmelisin. Eğer iki nöronundan da farklı değer geliyorsa 0 döndürmelisin. -> XNOR kapısını öğretiyorum)
8.satır: Maksimum eğitim tekrarı sayım. 10 defa eğitilip de öğrenemezsen daha fazla uğraşma.
9.satır: Her eğitim için 1000 iterasyonla öğrenmeye çalış. Eğer 0.02'lik bir hata payıyla öğrenme gerçekleşirse daha fazla öğrenmeye çalışmayacak şekilde eğitime başla. Başarısız olan her eğitimi de ekrana bas ki görelim...
10.satır: Eğitim başarılı olmuşsa, son eğitiminde kaç iterasyon kullandığını al ve ekrana bas.
11.satır: "Son Durum" başlığı altına
12.satır: Eğitim seti sayısında (4,5,6,7.satırlarda 4 adet eğitim setimiz vardı) $i sayaçlı bir döngü aç
13.satır:     [$i]. eğitim seti:
14.satır:     istenen çıkış = ([$i.eğitim setinde istenen çıkışları aralarına virgül koyarak yaz]);
15.satır:     ağ çıkışı = ([$i.eğitim verilerini ağa işletim çıkışları al ve yine virgülle ayırarak yaz] ;
16.satır: <hr /> ile ekrana bir çizgi çek.
17.satır: $n ağını bu son haliyle ysa.txt adında kaydet.
18.satır: "YSA bu şekliyle kaydedildi" diye ekrana yaz (ki buraya kadar sorunsuz geldiysek bu yazıyı görebilelim ve mutlu olalım)

Yapacağınız olayı kısaca açıklayayım.
- İlk olarak egitim.php sayfasının kodlarını açarak, ihtiyacınıza göre bir ağ oluşturup bu ağı eğitiyorsunuz. Eğer istediğinizi öğrenebilmiş bir ağınız varsa bu ağ artık ysa.txt adında bir dosyada tutuluyor.
- Sonra ysa_cevap.php sayfasının kodlarını açarak, eğitimde oluşturduğunuz ağla aynı sayıda giriş, gizli ve çıkış nöron sayısına sahip bir ağ oluşturuyorsunuz.
- Nihayetinde index.php sayfasına girip metin kutusundan ağa 1'ler ve 0'lar gönderiyorsunuz.

Benim yaptığım kodlama tabii ki oldukça basit. Mesela bu ağ -1 ve 1 aralığında tüm değerleri alabiliyorken ben ağa bu metin kutusuyla sadece 1 ve 0 gönderiyorum. Siz elbette site kodlarını kendinize göre düzenleyip ağa küsüratlı ve/veya negatif bir değer de gönderebilirsiniz. AJAX'ı ortadan kaldırabilir veya geliştirebilirsiniz. Ağın eğitimi için kodlarla uğraşmak yerine bir arayüz tasarlayabilirsiniz... Gerisi size kalmış. Artık bu class_neuralnetwork.php'deki class'ı nasıl kullanacağınızı biliyorsunuz.

Yeni bir ağ oluşturabiliyorsunuz:
$n = new NeuralNetwork( [giriş nöron sayısı], [gizli nöron sayısı], [çıkış nöron sayısı]);

Ağa istediğiniz kadar eğitim verisi verebiliyorsunuz:
$n->addTestData( [giriş nöronlarına gönderilecek dizi], [çıkış nöronlarından istenen dizi]);
$n->addTestData( [giriş nöronlarına gönderilecek dizi], [çıkış nöronlarından istenen dizi]);
$n->addTestData( [giriş nöronlarına gönderilecek dizi], [çıkış nöronlarından istenen dizi]);
... ağa hangi veriler girince hangi çıkışların verilmesi gerekir, bu şekilde söyleyebiliyorsunuz.

Bir hata payı belirleyip, istediğiniz iterasyon sayısıyla ağı eğitimeye başlayabiliyorsunuz:
$n->train([iterasyon sayısı], [kabul edilebilir hata payı]);

Lazım olursa, eğitim için ağa gönderilen eğitim dizisini bulabiliyorsunuz:
$n->trainInputs[2]; // ağa verilen 2.eğitim setinde, giriş nöronlarına verilen dizi

Lazım olursa, eğitimde ağdan istediğiniz çıktı dizisini bulabiliyorsunuz:
$n->trainOutput[2]; // ağa verilen 2.eğitim setinde, çıkış nöronlarından istenilen dizi

Eğitimden sonra herhangi bir giriş vererek, öğrendiklerine göre işlem yapmasını isteyebiliyorsunuz:
$n->calculate( [çıkış almak için ağın giriş nöronlarına gönderilecek veri dizisi] );

Ağı bir txt dosyasına (ini dosyası falan da yapabilirsiniz) kaydedebiliyorsunuz:
$n->save("siniragi.txt"); veya $n->save("siniragi.ini");

Kaydettiğiniz bir ağı alıp, elinizdeki sinir ağınının değerlerini o kayıtlı ağ ile değiştirebiliyorsunuz:
$n = new NeuralNetwork( [giriş nöron sayısı], [gizli nöron sayısı], [çıkış nöron sayısı]);
$n->load("siniragi.txt"); veya $n->load("siniragi.ini");

Aslında tüm bunları sadece class_neuralnetwork.php dosyasında, class'ı hazırlayan kişinin yorum satırlarında sunduğu örneği inceleyerek kendiniz de çıkarabilirdiniz ama ben yine de Türkçe bir açıklaması bulunsun istediğim için bu makaleyi yazdım. Umuyorum ki siz de buradan hareketle işi daha ileriye taşıdıktan sonra kendi makalelerinizi oluşturursunuz ve bu konudaki Türkçe kaynaklar çoğalmış olur.

Ama lütfen bu yazdıklarımı aynen alıp başka sitelere (mesela forumlara) aynen kopyalamayın. Yani bunun üzerine kendinizce bi'şeyler katmadığınız sürece internete tekrar takrar koymayın. İlle de bu makaleyi örnek göstermek istiyorsanız bu sayfanın linkini verin, isteyenler sizin gibi buraya gelip okusunlar. Aksi halde bu paylaşımların bilgi kirliliğinden başka kimseye bir getirisi olmuyor. Benim size burada "Yapay Sinir Ağları nedir? Çalışma mantığı nedir?" diye açıklama yapmamamın da nedeni bu. Çünkü internette zaten bu konuyla ilgili sayısız kaynak bulmak mümkün. 

Ama tabii ki dediğim gibi, üzerine bi'şeyler katmak, yani geliştirmek şartıyla bu makaleyi istediğiniz gibi kullanabilirsiniz.

İyi günler dilerim... :)



< Önceki Makale (PHP'de PDO ile MySQL işlemleri için class)


4 yorum:

  1. Sizden biraz geç başlamış olabilirim ama paylaşmış olduğunuz içeriklerin ben dahil çoğu arkadaşın aklında oluşan sorulara bi nebze de olsa cevap olacağını düşünüyorum

    YanıtlaSil
  2. Biraz anlatım karışıklığı olmuş. Daha sade bir anlatımla başka biz yazı hazırlayabilir misiniz?

    Birde şu kendi kendine öğrenme isi var.

    YanıtlaSil
  3. Bu bir yapay zeka değil yalnız? Bu kadar basit bir mantığı yok maalesef :)

    YanıtlaSil
    Yanıtlar
    1. Yorumunuz için teşekkür ederim. Bu paylaşım, yapay zekanın bir kolu olan yapay sinir ağlarına örnektir. Bu, XNOR kapısını öğretmek gibi bir örnekle göz korkutmayan basit bir giriş sayılabilir. Elbette bir yapay sinir ağı oluşturmanın bir çok optimize edici kuralları vardır. Ancak temel mantık aslında bu kadar kolay. Ağın nöron dizilimini belirlersiniz. Giriş verilerini ve bunlara karşılık istediğiniz çıkış verilerini verirsiniz. Ağı belirlediğiniz kurallara göre eğitirsiniz.

      Sil

Site Haritası

CodeIgniter Yayınları 1. Merhaba Dünya : CodeIgniter'da Merhaba Dünya yazısını görün... 2. Template Sistemi : CodeIgniter ile sta...