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.
- SimpleRNN
- LSTM
- 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_dim : Katman çı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...