20 Mart 2016 Pazar

Küçük lineer cebir numaraları (1)

A matris, x ve b ise vektörlerimizi gösteren değişkenler olsun.
$$\mathrm{Ax}\;=\;\mathrm b$$ Eşitliğinde A matrisi ile b vektörünün bilindiğini varsayalım. O halde x vektörünü şöyle bulabiliriz.
$$ \style{font-family:'Times New Roman'}{\style{font-size:14px}{\begin{array}{l}\mathrm{Ax}\;=\;\mathrm b\\\mathrm A^{-1\;}\mathrm{Ax}\;=\;\mathrm A^{-1}\mathrm b\\\mathrm{Ix}\;=\;\mathrm A^{-1}\mathrm b\\\mathrm x\;=\:\mathrm A^{-1}\mathrm b\\\end{array}}} $$ Burada I birim matristir. O halde x vektörünü bulabilmem için A matrisinin tersini bulup, bulduğum matrisi b vektörüyle çarpma işlemine tabi tutmalıyım. Örneğin A şöyle bir matris olsun:
$$ \mathrm A\;=\;\begin{bmatrix}1&-1&-1\\-1&\;\;\;2&\;\;\;3\\1&\;\;1&\;\;\;4\end{bmatrix} $$ b vektörü de şöyle olsun:
$$ \begin{bmatrix}0\\5\\12\end{bmatrix} $$ bu durumda A'nın tersi bir tanedir ve şöyledir:
$$ \mathrm A^{-1\;}\;=\;\begin{bmatrix}\;5&\;3&-1\\\;7&\;5&-2\\-3&-2&\;\;1\end{bmatrix} $$ Şimdi x vektörünü bulabilirim.
$$ \mathrm x\;=\;{\begin{bmatrix}\;5&\;3&-1\\\;7&\;5&-2\\-3&-2&\;\;1\end{bmatrix}}_{3\times3}\times\;\;\;{\begin{bmatrix}0\\5\\12\end{bmatrix}}_{3\times1}\;=\;\;\;{\begin{bmatrix}3\\1\\2\end{bmatrix}}_{3\times1} $$ olur.
Eğer bir matrisin tersiyle kendisinin çarpımının birim matrisi verdiğini bilmezsem, o halde x vektörünün satır sayısı kadar denklem kurmam ve bunları teker teker çözmem gerekecekti. x vektörünün çok büyük boyutlu olduğunu düşündüğümüzde bu işlem imkansıza yakın zorlukta olacaktır.

9 Mart 2016 Çarşamba

Caffe'ye yeni bir Python katmanı ekleme

Caffe'de temel hesaplama birimleri katmanlardır. Her katmanın kendine özgü görevleri vardır. Bir hesaplama yapmak isterseniz, o hesabın yapıldığı katmanı, oluşturmuş olduğunuz ağa (net) eklemeniz yeterlidir.
Caffe ile birlikte gelen makine öğrenmesinde kullanılabilecek birçok fonksiyon/katman mevcut. Ancak bazen sizin istediğiniz bir işi, var olan fonksiyonlar yerine getirmeyebilir. Ya da sizin probleminize özgü bir fonksiyon yazılması gerekebilir. Bu durumda yeni bir katman eklemekten başka çare yoktur.
Caffe'de yeni bir katman eklemek kolaydır. Hele bir de python katmanı eklenecekse bu daha da kolaydır.
Baştan itibaren bir python katmanı nasıl eklenir, sırasıyla yazalım:
1. /include/caffe/python_layer.hpp
python_layer.hpp başlık dosyasının gerekli dizinde olması gerekir, yoksa eğer kendimiz elle oluşturacağız. (url)
2. /src/caffe/layer_factory.cpp
bu dosyada python_layer için gerekli düzenlemeleri yapmamız gerekir. Eğer Caffe'yi son sürümde kullanıyorsanız değişiklik yapmaya gerek yok.
3. /src/caffe/layers/python_layer.cpp
dosyası (eğer yoksa) gösterilen dizinde oluşturulmalıdır. Bu dosya da son sürümle beraber geliyor. (url)
4. /src/caffe/proto/caffe.proto
protobuffer dosyası son sürümle beraber geldiği için değişiklik yapmaya gerek kalmıyor.
5. Makefile.config dosyasında
WITH_PYTHON_LAYER := 1 satırındaki yorum işleci kaldırılmalıdır.

Bu değişikliklerin etkinleşmesi için caffe'yi yeniden derlemek gerekiyor. Bunun için caffe dizininde sırasıyla
make pycaffe 
make all 
make test 
make runtest
komutları verilmelidir.
Buraya kadar anlattıklarım python katmanı oluşturmak için altyapıyı kurmak içindi. Şimdi python katmanı oluşturmaya başlayabiliriz.
İşe örnek bir prototxt oluşturmakla başlayalım:
"Ekle10.prototxt"
name: 'Ekle10'
input: 'data'
input_shape {
  dim: 1
  dim: 1
  dim: 1
  dim: 1
}

layer {
  name: "ekle10"
  type: "Python"
  bottom: "data"
  top: "ekle10_output"
  python_param {
    module: "Ekle10Modul"
    layer: "Ekle10Layer"
  }
  loss_weight: 1
}
Bu oluşturduğumuz prototxt iki tane katmandan oluşuyor. İlki bir adet 4-Boyutlu tensor. Bu tensor sadece bir değer içerecek.
İkinci katman ise birinci katmandan gelen değere 10 ekleyip çıkışa verecek.
Oluşturduğumuz ağ (net) aşağıda görülüyor.
Verilen girdiye 10 ekleyen katmanı şimdi yazabiliriz:
"Ekle10Modul.py"
import caffe

class Ekle10Layer(caffe.Layer):
    #Girdiye 10 ekleyen python katmanı.
    def setup(self, bottom, top):
        pass  

    #girdi boyutlarını caffe'nin kendi 
    #boyutlarına uydurmamız gerekiyor.

    def reshape(self, bottom, top):
        top[0].reshape(bottom[0].num, bottom[0].channels,
                bottom[0].height, bottom[0].width)

    #Sadece forward işlemi yapılacak.
    def forward(self, bottom, top):
        top[0].data[...] = bottom[0].data + 10 

    #Gradient hesabı olmayacağı için 
    #backward yapmaya da gerek yok.
    def backward(self, top, propagate_down, bottom):
        pass
python katmanının kodunu da yazdığımıza ($PYTHONPATH içinde olmasına dikkat edin) göre doğru çalışıp çalışmadığını kontrol edelim:
import caffe
import numpy as np
net = caffe.Net('Ekle10.prototxt', caffe.TEST)
input1 = np.array([[[[100]]]])
net.blobs['data'].data[...] = input1
net.forward()
net.blobs['ekle10_output'].data[0][0][0][0]
Bunun sonucunda verilen 100 değerine 10 eklenmiş olarak 110.0 değerini (float32) elde ederiz.
Bu yazıda, baştan sona Caffe için bir python katmanı oluşturduk. Bunun için önce alt yapı değişikliklerini gerçekleştirdik. Bundan sonra istenilen görevi yapan python katmanı yazdık. En son aşamada ise yazdığımız katmanın düzgün çalışıp çalışmadığını kontrol ettik. Gerçekten de oluşturduğumuz katman kendisinden istenilen görevi, basit şekilde gelen veriye 10 ekleme, yaptığını gördük.

29 Ocak 2016 Cuma

Marvin Minsky'nin anısına!

Geçen gün kaybettiğimiz Marvin Minsky'nin anısına, 2008'de yazdığı "Matematiği zor kılan nedir" başlıklı yazısının bir kısmını dilim döndüğünce çevirmek istedim. Minsky, Ali Nesin'in de birçok kez dile getirdiği gibi, Matematik eğitiminin eksiğini, konuya örneklerden başlanmasına ve sistemin yaratıcılığı köreltmesine bağlıyor. Bu yazının sonunda yaratıcılığa nasıl engel olunuyorun cevabı da var.
Matematiği zor kılan nedir?
Neden birçok öğrenci Matematiği zor bulurlar? Öyle sanıyorum ki bu, derse önce örnek ve aritmetik alıştırmalarından başlamaktan kaynaklanıyor. Dolayısıyla yaratıcılığı körüklemekten çok hata yapmayı engellemeye odaklanmaktan ortaya çıkıyor. Birçok öğrencinin bu olumsuz vurgudan ötürü Aritmetiği sevmediğini ve sonrasında teknoloji kokan her şeye karşı gönülsüz hale geldiğini düşünüyorum. Hatta daha uzun dönemli olarak sembolik temsillere karşı bir gönülsüzlüğe neden olduğuna inanıyorum.

Anekdot: Günün birinde çarpım tablosunu öğrenmede sorunu olan çocuğu için bir aile benden yardım istedi. Çocuk bunun çok büyük bir iş olduğundan şikayet ettiğinde ona diyagonal simetriyi açıklamaya çalışıyordum.
Ancak, çocuğun daha büyük bir şikayeti vardı: "Geçen sene toplama tablosunu öğrendim ve çok sıkıcıydı. Bu sene daha zor bir şeyi öğrenmek zorundayım. Anladım ki bunu bu sene öğrenirsem önümüzdeki seneler daha da zor olanlarını öğrenenmek zorunda kalacağım ve bu saçma şeylerin sonu gelmeyecek."

Çocuk Matematiği sonu gelmeyen şeyler olarak görüyordu, sürekli alıştırmalar, örnekler... Onu, bundan sonra başka tabloların olmayacağına ikna etmek gerçekten zor oldu.
Bu sorunun üstesinden gelebilmek için bir iskambil destesi hazırladım. Bunların ön yüzünde çarpılacak iki sayı ve arkasında da cevapları vardı. Her defasında bir kart çekilecek, cevabı tahmin edilecek ve eğer doğruysa kart desteden ayrılacaktı. Destenin azalmasına bakarak bir insanın gelişim sürecini gösteren bir tür oyuna benziyordu. Sonunda çocuk heyecanla "bu deste" dedi, "gerçekten akıllı bir öğretim makinesi! Benim bildiklerimi hatırlatıyor, sadece bilmediklerimi soruyor bu yüzden de zaman kazanıyorum."

Ancak daha ciddi problemse çocuğun öğrendiği bu konunun sonucunun ne olacağına dair bir fikri yoktu. Matematik ileride nasıl işine yarayacaktı? Bunu başarmak için hedefleri ya da hırsı ne olmalıydı?

Anekdot: 6 yaşındaki çocuğa 15 ile 15'in toplamını sordum, hemen 30 dedi. Bunu hemen nasıl cevapladığını sordum, "herkes 16 ile 16'nın toplamının 32 oldunu bilir. Bu yüzden her birinden 1 çıkarttım ve sonucu buldum."

Bildiğimiz öğretmenin cevabı şöyle olur: "Cevabın doğru ancak yöntemin yanlış: Önce 5'leri toplayıp 10 bulmalıydın, daha sonra 0'ı yazıp elde 1 diyeceksin, en sonunda da toplama eldeyi katacaksın."

Çoğu yetişkinle yarışabilecek düzeyde 2'nin katlarıyla işlem yapıp yakınsamayla sonucu bulması, çocuğu özel kılacak yerde geleneksel tarzın kurbanı yapıveriyor.

23 Ocak 2016 Cumartesi

Başarılarını bir kenara yaz!

Tim Peterson'un yazısına Hacker News'da denk geldim. Kısaca alıntılamak istedim.
Ne yapıyorsanız yapın, başarılarınızı bir yerlere yazın. Hepsini ve her daim. Kendi kendinizin tarihçisi olmalısınız. Hiç kimse sizin ne yaptığınızı hatırlamaz. Siz yazmazsanız siz de hatırlamazsınız. O yüzden ne yaptığınızı yazın, tarihinizi kendiniz oluşturun. Bunu yaptığınızda hem ne yaptığınızı daha iyi hatırlayacak, hem de geleceğe dair daha kesin hedefler koyabileceksiniz.
Tim Peterson moleküler biyolojide postdoc yapıyormuş.

7 Ocak 2016 Perşembe

Telepati: Ne düşündüğünü anlıyorum

Japon Kyushu Teknoloji Enstitüsü araştırmacıları, insan henüz konuşmaya başlamadan, onların beyin dalgalarını okuyan ve kelimeleri çözen bir bilgisayar geliştirdiler.
Araştırmacılar bu telepatik bilgisayarla, insan beynindeki elektriksel aktivitelerin oluşma şeklinin, sesli veya içeriden konuşma anında aynı olduğunu keşfettiler.

Bu şu demek aslında:
İnsanların beyin dalgalarından, onların konuşmadan bile ne demek istediklerini tahmin edebiliyorlar. Peki bu nasıl oluyor?
Şöyle: İnsanların konuşurken beyinlerinde oluşan elektriksel dalgaların şekillerini kaydediyorlar. Bunun için erkek, kadın ve çocuklardan oluşan 12'şerli kişilere belli birkaç kelimeyi söylemeleri ve daha sonra bu kelimeleri sadece düşünmeleri isteniyor. Her iki durumda da oluşan beyin dalgalarını kaydediyorlar. Bu dalgalardan o kişilerin kelimeleri söylerken ve düşünürken birbirine benzer şekiller çıkardıklarını tespit ediyorlar.

Bu beyin dalgalarının benzerliklerinden yararlanarak, insanların konuşmadan sadece düşünerek ne söylemek istediklerini tahmin etmeye çalışıyorlar. Geliştirdikleri sistem, yüzde 30 civarında bir kesinlikle çok basit kelimeleri tahmin edebiliyor. Daha ötesi Japonca tek karakterli denemelerde ise yüzde 90'a varan bir kesinlikle hangi karakterin o anda düşünüldüğü belirlenebiliyor.
Bu çalışmayı yapan araştırmacılar, böyle bir sistemin konuşma yeteneğini kaybetmiş kişilerde kullanılabileceğini belirtiyorlar.

5 Ocak 2016 Salı

Yorumlanan ve Derlenen Diller

Bilindiği gibi, bilgisayarlar dijital makineler olduklarından sadece tek bir dilden anlarlar, o da makine dilidir. Makine dili sadece 0 ve 1'lerden oluşan ve insanların anlayamacağı kodlardan oluşur. Bu yüzden insanlar, kendi bildikleri yüksek seviyeli bir dilde programlarını yazarlar. Bilgisayarlar, yazılan bu programları kendi anlayacakları dile çevirmek için derleyici denilen özel yazılımları kullanırlar. Derleyici yazılımları kendisine girdi olarak gelen yüksek seviyeli dilde yazılmış kodu, bilgisayarların anlayabileceği makine koduna çevirirler. Yorumlanan ve derlenen diller ayrımı da işte burada ortaya çıkıyor.
Derlenen dillerde yazılmış bir program bir kere makine koduna çevirilir ve bir "çalıştırılabilen kod" ortaya çıkar. Buna bilgisayar bilimlerinde "executable code" deniyor. Bu kod ortaya çıktıktan sonra çalıştırılabilir ve istenen işi yapar. Bir kere çalıştırılabilir kod oluştuktan sonra bütün çalıştırma işlemlerinde bu kod çalışır.
Yorumlanan dillerde yazılmış bir program ise çalıştırılma işleminin her defasında makine diline çevrilir ve daha sonra istenen işi yapar. Burada her runtime anında iki işlem (çevirme ve çalıştırma) ardarda yapılır.
Derlenen diller için C, C++ veya kısmi olarak Java'yı örnek olarak verebiliriz. Yorumlanan diller içinse Python, JS gibi dilleri örnek gösterebiliriz.
Derlenen ve yorumlanan dillerin birbirine karşı üstünlükleri vardır. Örneğin yukarıda bahsettiğimiz, bir kere derle ve onu kullan özelliğinden dolayı derlenen diller, yorumlanan dillere göre hızlıdır. Çünkü yorumlanan dillerde ardarda iki işlem yapılır, bu da programın çalışmasının yavaşlamasına neden olur. Aslına bakılırsa, işlemcilerin gelişen saat performansları böyle üstünlükleri ortadan kaldırmaktadır. Hızlı işlemcilerle birlikte, derlenen ve yorumlanan diller arasındaki bu hız farkı artık önemsenmeyecek noktalara gelmiştir. Ancak gömülü sistemler gibi sınırlı kaynaklara sahip işlemcilerde bu üstünlük hala anlamlıdır. Raspbery Pi, Arduino gibi nispeten düşük özellikli mikrodenetleyicilerde bu fark hala devam etmektedir. Bu yüzden bu dillerin (derlenen, yorumlanan) hangisini kullanacağınızın kararı, hangi platformu kullanacağınıza bağlı olarak değişir.
Ayrıca yorumlanan dillerin, derlenen dillere göre runtime anına daha fazla adapte olabilme üstünlükleri vardır. Örneğin derlenen dillerde bir tamsayı değişken kullanmak isterseniz, önce bu değişkeni tanımlamak/deklare etmek gerekir.
int x;
gibi bir ifadeyi programın üstünde bir yerlerde tanımlamış olmanız gerekir.
Ancak Python gibi bir dilde bu tamsayıyı tanımlamadan istediğiniz herhangi bir yerde kullanabilirsiniz. Derleyici (Yorumlayıcı) kullanılan değişkenin, kendisine refere edilen değerine bakarak tamsayı, kayan noktalı sayı vb. olduğuna kendisi karar verir.

2 Ocak 2016 Cumartesi

Derin Sular

Bugün 2016'nın ikinci günü. Bu sene yeni bir bloga başlıyorum. Bu kararıma sebep olan Twitter'daki Vala Afsar'ın şu tweeti oldu:
"2016'nın 2. günü. Şunları yapmak için önünüzde tam 365 gün var: kodlama, blog yazma, yeni bir yetenek öğrenme, topluluğa konuşma yapma."
Bu blogda yazmayı planladıklarım ise; makine öğrenmesi, sinir ağları, derin öğrenme ile alakalı okumalarımın yanısıra ayrıca; arduino programlama, javascript gibi konu başlıklarında olacak.
Bu yazdıklarıma ek olarak çeşitli teknoloji konularında, özellikle STEAM konularında yazmayı da istiyorum. Umarım düşündüklerimi uygulayabilir ve menzile ulaşabilirim.
Güzel günler diliyorum.