Pazartesi, Mart 13, 2017

Semantik Bölütleme ve FCN

Resimde nelerin olduğu dışında,  konumlarınıda öğrenmemizi gerektiren pek çok durum vardır. Mesela otonom araç etrafındaki nesneleri konumları ile tanıya bilmelidir ki çarpışma olmaksızın hareket edebilsin. Resimde konum belirlemenin iki şekli var.
  • Kutu içerisine alma
  • Semantik Bölütleme - Sematic Segmentation -
Biz bu yazımızda semantik bölütleme üzerine bir örnek gösterceğiz.  Resimde semantik bölütleme dediğimizde kast edilen, Resimdeki her pikselin neye ait olduğunu ayırabilmektir.



Yukarda resimde görüldüğü gibi köpeğe, kediye, ve kanepeye ait pikseller ayrıştırılmış. Peki Nasıl yapılıyor ?

Görüntü sınıflandırma için CNN yapsından bahsetmiştik.  ( bakınız )


Yıllardır görüntü bazlı problemler için CNN in eline su dökebilecek bir metod çıkmadı. Ağ yapılarında düzenlemeler, yeniliklerle , kendi kendiyle yarıştı.  Ağın genel yapısı yukarda gördüğünüz gibidir.  Kabaca giriş resmi üzerinde uygulanan konvolüsyon katmanları  ile öznitelik çıkarma, sondaki YSA katmanları ile çıkarılmış özniteliklerden sınıflandırmayı öğrenme işlemi yapılmaktaydı. Semantik bölütleme içinde bu yapıdan faydalanıldı.



Yukarda görüdüğünüz şekilde bir ağ yapısı oluşturuldu. CNN den farklı olarak, baştan sona  konvolüsyon katmanları kullanıldı.  Bu yeni tip Ağ yapısıda Fully Convolutional Networks olarak adlandırıldı. YSA yerine geçen katmanlarla, ağın çıkışı ebatları girişiyle aynı hale getirildi. Ek olarak ayrıştıracağı sınıf sayısı kadar kanala sahip bir matris üretildi. Mesela 5 sınıfa ait bir bölütleme işlemi yaptığımızı varsayalım

HxWx3 ( RGB )   ----->  FCN  ----->   HxWx5

Çıktıyı iki şekilde düşünebiliriz. 

Giriş resminin hep pikseli için sınıflandırma sonuç vektörü. yani HxW tane 5 lik vektör
Her sınıf için piksellerin o sınıfa ait olma ihtimalini gösterer Matrisler

İşin teferruatları ve terorisi için aşağıdaki makaleleri incelemenizi tavsiye ediyoruz
  1. Fully Convolutional Networks for Semantic Segmentation 2015
  2. Fully Convolutional Networks for Semantic Segmentation 2016
Makelelerinde tarihlerinden anlaşılacağı gibi çok yeni konular.  Medikal görüntülerden uydu görüntülerine, IHA görüntülerine, Radar görüntülerine, vs  vs .. kullanılabilecek uygulama alanı çok geniş bir metod.

Makalelerde geçen  FCN-32s, FCN-16s ve FCN-8s  tabirlerinin sizin ne ifade ettiğini



  yukardaki resimle gösterelim. Bölütleme kesinliği sondaki sayı ile ters orantılı. Gerçek bölütleme sonucuna en uygun sonuçlar FCN-8s ile elde ediliyor.


Gelelim bizim uygulamamıza. FCN ağ yapısının caffe kütüphanesi ile uygulanmış olduğu açık kaynak kodlu proje sayası var.

http://fcn.berkeleyvision.org

Bu sayfa sizi bir github sayfasına yönlenidir. Orada  değişik veri setleri ve için değişik ağ yapılara ve modellere ulaşabilirsiniz

Biz örneğimiz için  'fcn8s-heavy-pascal'  model tanım ve  ağırlık dosyalarını indirdik
  • fcn8s-heavy-pascal.prototxt
  • fcn8s-heavy-pascal.caffemodel
Bir ipython dosyası yazdık. Bu model 500x500 ebatında renkli resim alıp 20 sınıf + 1 Arka plan  olmak üzre 21 sınıflı 500x500x21 lik bir matris çıktısı veriyor. bir    Sonuçlar şöyle




Bisiklet sınıfı için  ihtimal  görüntüsü


Bölütleme sonucuda
Bisiklet için


Köpek İçin




gibi görünmektedir. Sonuç olarak bıyık filtrresinin !  :)  çıkardığı aksilik dışında gayet iyi çalışıyor.

Kodun içine elimizden geldiğince açıklama satırlarıda koyduğumuzdan burda ek açıklama yapmaya gerek duymadık.   Kod için bakınız

https://github.com/birolkuyumcu/ddm_blog_examples/tree/master/fcn-caffe

 Yinede anlaşılmayan yerler varsa, yada bu konularda görüş ve önerileriniz varsa iletişime geçebilirsiniz.

Cuma, Mart 03, 2017

Keras'a Giriş - 2 ( LSTM )

Ocak ayında ilk yazısını yayınladığımız  Keras 'a  Giriş  dizisine devam ediyoruz.

İlk yazımızda Kerasın kurulumunu, ve  ana kullanım fonksiyonlarını anlatmıştık.  Hali hazırda Kerasın içinde pek çok değişik katman bulunmaktadır. Katmanlarla ilgili kısımı okuyarak bunlara aşina olabilirsiniz. Katmanları bir birine ekleyerek kendi probleminize göre envai çeşit yapıyı tasarlayabilirsiniz.

Biz bu yazımızda Keras üzerinde  LSTM ile zaman serisi tahmini yapan bir uygulama geliştireceğiz.

LSTM nedir ?

Büyük soru, başta kendim olmak üzere kafamızı çok karıştırmadan mümkün mertebe sade anlatmaya çalışalım.

Açıklamaya RNN yani Recurrent Neural Networks  ile başlamamız gerekiyor. Tarihi çok eskilere giden bir YSA yapısı. Aslında anlaması çok da kolay.



YSA yapımızda verdiğimiz verilerin saklı katmandan ürettiği çıktış sinyalini başa alıp bir sonraki giriş de giriş değerlerinden biri olarak kullanıyoruz.

Bu ne işimize yarıyor diye soracak olursanız pek çok durumda verilerimiz de bir sıralılık bağlantısı vardır. sadece girdiklerimiz değil bir önceki durumda çıkışa etki ediyordur. Bu tip Sıralılık örüntüsü  - Sequence pattern - içeren durumlar için bu tip YSA yapıları daha başarılı bir modelleme imkanı sağlamaktadır.

Peki yıllardır bilinen bu yapı niye populer olamamış ?  Bu sorunun cevabı olarak meşhuuur  Vanishing gradient problem çıkıyor karşımıza. YSA eğitiminde giriş verileriyle çıkış değerleri hesaplanır. Hesaplanmış çıkış değerleri ile gerçek değerler karşılaştırılır ve farklılık bize bir  meyil  - gradient - Bu meyile göre geriye doğru ağ ağırlık değerlerinde güncelleme yapılır. Ağımız çok karmaşıksa geriye doğru meyil değerleri sıfırlanır. Meyil olmazsada güncelleme olmaz ve eğitilmeside durmuş olur. RNN yapısında da zaman içinde geriye doğru bağlılık var. Ağımızı eğitim açısında çok karmaşık hale getiriryor.


Bu problemin çözümü için LSTM - Long short-term memory - denen bir yapı kurulmuş.


Yukardaki akıllara ziyan  şemadan da anlaşılacağı üzere çok kompleks bir sistem. Yapıda kabaca RNN hücresine birde hafıza eşlik ediyor. Bu hafıza ile bir önceki zamandan gelen bilgi alınabiliyor , bir sonrakine iletilebiliyor. Neyi alıp neyi almayacağına eğitim ile karar veriyor. Konunun teferruatları için, Ve illede iç yüzünü öğreneceğim diyenler için bir kaç link verip geçiyorum

1)  Deep Learning Lecture 12: Recurrent Neural Nets and LSTMs
2) Understanding LSTM Networks
3) The Unreasonable Effectiveness of Recurrent Neural Networks

Keras da RNN katmanlar 

Hali hazırda Keras kütüphanesinde 3 çeşit  RNN katmanı var.
  1. SimpleRNN
  2. LSTM
  3. GRU
ilki zaten adından anlaşılıyor. LSTM den yukarda bahsettik . sonuncusu GRU - Gated Recurrent Unit - daha LSTM benzeri yeni bir sistem

Biz LSTM i kullanacağız. ondan bahsedelim

LSTM ler  genel anlamda sequence zaman sıralı şekilde gelen veriler üzerinden çalışırlar.

keras.layers.recurrent.LSTM(output_dim,
                                              batch_input_shape=(nb_samples, timesteps, input_dim),
                                              return_sequences=False,....)
eğer LSTM ilk katmansa batch_input_shape  verilmesi gerekiyor ve dökümanda geçen şekli
  
  • nb_samples : veri sayımız, None diyede  verebiliyoruz. 
  • timesteps :  LSTM e vereceğimiz veriler zaman bazında değişen aynı türdeki veriler  kaç birim zamanlık veri verilecek burda onu belirtmemiz gerekiyror 
  • input_dim :  giriş verimizin boyutu. 
  • return_sequences Kendinden sonraki katman Yine Bir LSTM olacaksa True  yapılacak
  • output_dimKatman çıkış boyutu ve LSTM birim sayısı.  Ağın çıkışı , eğer kendinden sonraki katman Yine Bir LSTM olacaksa  (nb_samples, timesteps, output_dim)  , olmayacaksa  (nb_samples, , output_dim) olur.
Şimdi biraz burda durup, input_dim giriş veri boyutuna biraz açıklık getirelim.  Sequence üzerinden çalışan bir sistem. Bizim bugün anlatacağımız önnekdeki gibi tek bir sayısal değerin değişimi var ise  giriş veri boyutu bir dir. Fakat pek ala zaman içinde değişien bir vektör de modellenebilir. budurumda vektörün uzunluğu giriş boyutumuz olur. Mesela bir metin üzerinde çalıştığımızı varsayın. biri birini takip eden harfler de bir sequence olur. Harfi bir vektöre çevirmek gerekir. vektör uzunluğuda metindeki alfabe büyüklüğü olur.

Olmaz ama soran olursa diye buraya yazayım peşin peşin, pek çok değişik kaynakda pek çok değişik notasyon var. Kullanımında benim tercihim bu şekilde oldu.

Uygulama

Keras da LSTM uygulamamız için bir zaman serisi verisi seçtik.

Daily maximum temperatures in Melbourne, Australia, 1981-1990

Avusturalya Melbornda 10 yıllık bir sürede ( 1981-1990 )  günlük olarak ölçülmüş en yüksek sıcaklıkları gösteriyor.

Yukardaki grafikden de anlaşılacağı üzre oldukça gürültülü bir sin fonksiyonu 

Bizde son 5 günün en sıcaklık değerlerini kullanarak yarınki en yüksek sıcaklık değerini hesaplattırmaya çalışacağız. uygulamızda

önce verimizi pandas ile  yüklüyoruz



tarih ve en yükseklik sıcaklığı tutan iki sutun var tarih bize lazım değil sadece en yüksek sıcaklık değerleriniz çekiyoruz.

YSA eğitimlerinde verileri ölçeklendirmek genellikle faydalı olur. bizde  ( 0 , 1 ) arası bir ölçeklendirme işlemi uyguluyoruz.

Bu veri üzerinde kayan pencere metoduyla ağımızı eğitmek için  veris seti oluşturuyoruz

Önce giriş ve çıkış verilerimizi oluşturuyoruz X ve Y olarak


ilk kutuda kayan pencere metoduyla  giriş ve çıkışları seçip X ve Y adında iki listeye atıyoruz.
ikinci  kutuda  listeleri Martise dönüştürüyoruz.
Üçüncü kutuda giriş verimizi LSTM in istediği formata çevrimek için bir dönüşüm yapıyoruz
çünkü öncesinde giriş matris ebadı  (nb_samples, timesteps) şeklinde bir giriş veri boyutunu 1 olarak verip (nb_samples, timesteps , 1 ) ebadına dönüştürüyoruz.

3645 adet verimiz var. Biz 3200 'ünü eğitim için kullanıyoruz geri kalanınıda test için bırakıyoruz.


Evet sıra geldi Ağımızı oluşturmaya


İki LSTM katmanı oluşturuyoruz ilki giriş katmanı çıkışı 64 kendinden sonra yine bir LSTM katmanına bağlanacağından return_sequence  değişkenine True değerini veriyoruz.
LSTM katmanı sonrasında  0.2 lik bir Dropout katmanı koyuyoruz. Dropout en basit ifade ile sistemin ezberlemesini önlemeye çalışan bir katmandır. biraz detay isterseniz daha önceki yazılarımda kısaca bahsetmiştim ordan bakabilirsiniz.

İkinci LSTM katmanının 32 çıkışı var yine peşine Dropout katmanı kondu. Perşinede Çıkış katmanı olarak normal bir YSA katmanı -Dense-  kullanıyoruz. Bir çıkış yani takip eden günün en yüksek sıcaklığı olduğundan çıkışı 1 .

model sınıfının summary fonksiyonu ile  modelimizin yapısını ve katmanların çıkış ebatlarını parametre sayılarını görebiliyoruz.



Bir katmanın girişi kendinden öncekinin çıkışı olduğunda girişleri göstermesine gerek olmuyor.

Eğitime başlatıyoruz. 



Eğitim sonunda  Test verisinden başlangıcını rastgele seçeceğimiz  100 adet veri seçiyoruz. Bu veri için  Gerçek değer. Tahmin edilen değer. Bir de sadece seçtiğimiz aralığın başlangıç değerini alıp ileriye doğru zincirleme tahmin hesaplattırarak  grafikler çizdiriyoruz.


Grafik den görüklerimizi yorumlayalım.
  • Tahmin ve gerçek değer arasında Müthiş bir sayısal yakınlık yok.
  • Sayısal doğruluk gibi bir bekleti bu tip bir zaman serisi için pekde mümkün değildi
  • Fakat Grafiklerdeki inişve çıkışlar parelellikler içeriyor.  Sequence learning kavramı hatırlayın
  • Zincirleme ileriye doğru tahmin ilk başta çalışsada sonrasında bir rakama sabitleniyor.
  • Bu da beklediğimiz bir durum bakınız  kaos teorisi

Ipython dosyasına ve veriye burdan ulaşabilirsiniz.

https://github.com/birolkuyumcu/high_temp_lstm

Bundan sonra tavsiyem,  ağın yapısı , parametreleri, hatta pencere ebatları ile oynayarak ne şekilde sonuçlara ulaşılabiliyor görmenizdir.

Eleştiri, öneri yada sorularınız olursa bekleriz...