‘python’ etiketi için arşiv.
Çizimlerle merkezi limit teoremi
Merkezi limit teoremi (MLT) der ki; bağımsız ve aynı dağılım gösteren rassal değişkenlerin toplamları yaklaşık olarak normal dağılım gösterir. Ne kadar çok değişken toplanırsa, normal dağılıma o kadar çok yaklaşılır. Yazıda örnek Python kodu ile konuşacağım, matematiksel tanım ve ispat için vikipedi makalesine bakabilirsiniz.
Alttaki kodda başta verilen dağılımlardan birini seçerek MLT'nin illüstrasyonunu görebilirsiniz. Seçilen dağılımdan bağımsız olarak toplamlar hep normal dağılıma yakınsamakta.
Python'da bilimsel programlama ortamı
Python ile bilimsel programlama yapmaya çabaladığım günlerde hep MATLAB'da olduğu gibi bir IDE (Tümleşik Geliştirme Ortamı) olsun istemiştim. Hata ayıklama yapabileyim, otomatik tamamlaması olsun, javadoc gibi güzel bir yardım hizmeti olsun, değişkenleri çalışma esnasında gözlemleyebileyim, vb.
Yakın zamanda Spyder'ı keşfettim. Aradığım özelliklerin tümünü destekliyor. Tabii ki gücü altta yatan Python kütüphanelerine dayanıyor. MATLAB'e alternatif bir aracım da olsun, Python ile bilimsel kod yazayım derseniz mutlaka bakmanızı öneririm.
OpenCV 2.2, Python ve Numpy/Scipy
OpenCV 2.2 çıktı. Yeni gelişmelerden ilgimi en çok çeken Python arabiriminin durumu. Artık C++ arabiriminde olduğu gibi Python arabiriminde de değişkenler fonksiyonlar tarafından otomatik oluşturulabiliyor. Yani, fonksiyonun çıktısının atanacağı değişken için önce hafızada yer açmak gerekmiyor. Örneğin
import cv
a=cv.imread("lena.jpg",0)
b=cv.canny(a, 50, 100, apertureSize=3)
cv.imshow("test",b)
cv.waitKey(0)
kodundaki a ve b değişkenleri bildiğimiz numpy dizileri olarak oluşturuluyor. Böylece numpy/scipy gücünü OpenCV içine katabiliyorsunuz.
Not: Yayınlanma haberine Derindelimavi'den ulaştım.
Web arabiriminde formül ve kod kullanarak dokümantasyon oluşturma
Yeni bir konuya giriyorum; genelinde tensör matematiği ve özelinde bunun videodan bilgi çıkarmak için kullanımı. Sıfırdan başlayacağım desem pek yalan olmaz. Aldım, başladım ağırından okumaya. Multilineer cebir bir nevi. Onu anlamak için iyi bir nümerik ve lineer cebir bilgisi gerekiyor. Onları anlamak için başka şeyler derken gövde dallara, dallar yapraklara... Çoğu yaprağı biliyorum zaten. Dalları da çıkmak kolay ama hafızada tutmak zor. Çalışırken anlaşılıyor, sonra ne nerdeydi, bu nasıldı falan derken zaman ölüyor. Malum beyin bedava ama zaman öyle değil! Velhasıl-ı kelâm bunları nasıl etsem de bir havuzda toplasam diye kafa yormaktayım. İstediğim dokümantasyon şuna benzer olsun,
- Kaynak kod ile doğrudan çalışayım. Yani editör kullanma imkanım olsun, mysql'de falan tutulmasın. Ben kaynak kodları svn deposunda tutar, ona bir de Trac koyar kendi kendimi yönetirim.
- İçine LaTeX yazılabilsin ki formülleri güzelce gösterebilsin.
- LaTeX kodları için
\newcommandkullanabileyim. - İçine örnek kod eklersem (c, matlab veya python) onları allayıp pullayıp gösterebilsin.
- Arama özelliği olsun.
- İndeks olsun.
- Sayfalara yorum girilebilsin.
- Değişiklikleri yapınca tek tık ile tüm projeyi güncelleyebileyim.
Maksadım her ihtiyacım olduğunda kullanabileceğim bir elkitabını peyderpey oluşturmak. Bunu webden hocam ile de paylaşmak. Sonra lazım olduğunda buradaki bilgileri kopyalayıp yapıştırarak daha derli doplu yayınlar üretmek. Sizin de ilginizi çekerse buyrun bir tarama...
Dinamik programlamaya giriş
Alttaki yazı Jesse Farmer'ın "Introduction to Dynamic Programming" adlı yazısının çevirisidir. Burada, yazarın izniyle yayınlanmaktadır.
Dinamik programlama, örtüşen altproblemler (overlapping subproblems) ve eniyi altyapı (optimal substructure) özelliklerini gösteren geniş bir yelpazedeki arama ve eniyileme (optimizasyon) problemlerini verimli bir biçimde çözmek için kullanılan bir yöntemdir. Size bazı basit örnekler aracılığıyla bu özellikleri göstermeye çalışacağım ve bir alıştırma ile bitireceğim. Mutlu kodlamalar!
Örtüşen altproblemler
Tekrar tekrar kullanılan altproblemlere bölünebilen bir problem için, örtüşen altproblemlere sahiptir denir. Özyineleme (recursion) ile yakından ilişkilidir. Farkı görmek için (Python ile) şu şekilde tanımlanan faktöryel fonksiyonunu düşünün:
def factorial(n):
if n == 0: return 1
return n*factorial(n-1)
Görüldüğü gibi factorial(n) probleminin hesabı factorial(n-1) altprobleminin hesabına bağımlıdır. Bu problem örtüşen altproblemler özelliğini göstermez çünkü factorial, n'den daha küçük her pozitif tamsayı için bir kez çağrılır.
Nümerik işlemler ve bilgisayarla görmek için Python
Uzun süredir nümerik hesaplarım için IPython kabuğu ile Python'ın numpy modülünü kullanıyorum ve çok memnunum. Hele Opencv'nin güzel sürümündeki (svn'deki sürümü oluyor) matris yapısını numpy dizisine (ndarray) çevirebilince işlem kolaylığı ve çokluğu arttı, daha da şık oldu.
Bunun ne faydası var konusunda bir fikir vereyim. Opencv, içinde birçok bilgisayarla görme algoritmasını barındıran muhteşem bir açık kaynak kütüphane. Numpy, Matlab'ın Python muadili. Numpy neredeyse standart oldu ve tüm nümerik kütüphaneler onu destekliyor. Benim kullandığım en temel kütüphaneler grafik kütüphaneleri (matplotlib gibi) de Numpy destekli. Numpy'ın en güçlü yanı, dilimleme ("slicing") operatörü. Matlab kullananlar bunu bilir ve sever. Ayrıca işleri vektörlemek de mümkün. Kullanımı çok esnek. Opencv'de hazır fonksiyonları kullanmak çok kolay ama resimlerden istatistik falan toplayacaksanız işiniz Numpy sözdiziminde olduğu kadar kolay değil. Böyle bir çevirme işlemiyle ikisinin gücü birleşiyor. Bu arada, tüm bahsettiğim kütüphaneler platformdan bağımsız.
Şu anlık yalnızca float32 ve uint8 veri türlerini çevirdim.
def opencv2numpy(matIn):
"""Convert opencv matrix to numpy matrix (supports 1 and 3 channels currently)"""
if matIn[0].type == cv.CV_8UC1 or matIn[0].type == cv.CV_8UC3:
dtype = 'uint8'
elif matIn[0].type == cv.CV_32FC1 or matIn[0].type == cv.CV_32FC3:
dtype = 'float32'
else:
print "No support except float32 and uint8 yet"
return 0
if matIn[0].type == cv.CV_8UC3 or matIn[0].type == cv.CV_32FC3:
matOut = np.fromstring(matIn.tostring(), dtype=dtype).reshape(matIn.height, matIn.width, 3)
else:
matOut = np.fromstring(matIn.tostring(), dtype=dtype).reshape(matIn.height, matIn.width)
return matOut
def numpy2opencv(matIn):
if matIn.ndim == 3 and matIn.shape[2] == 3:
nChannels = 3
else:
nChannels = 1
h,w = matIn.shape[0], matIn.shape[1]
if matIn.dtype == "uint8":
if nChannels == 1:
dtype = cv.CV_8UC1
else:
dtype = cv.CV_8UC3
elif matIn.dtype == "float32":
if nChannels == 1:
dtype = cv.CV_32FC1
else:
dtype = cv.CV_32FC3
else:
print "No support except float32 and uint8 yet"
return 0
matOut = cv.CreateMatHeader(h, w, dtype)
if nChannels == 1:
cv.SetData(matOut, matIn.data, w*matIn.itemsize)
else:
cv.SetData(matOut, matIn.data, w*4*matIn.itemsize)
return matOut
Güncel işimi görmesi için yazdığımdan hataları olabilir, biraz da verimsiz oldu. Örneğin bir tarafa iyiyken, diğer tarafa verimsiz çeviriyor. Fakat benim için şu an bu öncelik konusu değil. "Exception" fırlatmam lazım ama hariçten gazel okumak zor geldi, işimi görüyor.
Kullanırsanız, genellerseniz veya geliştirirseniz lütfen benimle de paylaşın.
Güncelleme:
Opencv Python arayüzünde zaten hazırmış bu kod. Hem diğer veritipleri için de genellenmiş. Yenisi dönüşümler şöyle:
def cv2array(im):
depth2dtype = {
cv.IPL_DEPTH_8U: 'uint8',
cv.IPL_DEPTH_8S: 'int8',
cv.IPL_DEPTH_16U: 'uint16',
cv.IPL_DEPTH_16S: 'int16',
cv.IPL_DEPTH_32S: 'int32',
cv.IPL_DEPTH_32F: 'float32',
cv.IPL_DEPTH_64F: 'float64',
}
arrdtype=im.depth
a = np.fromstring( im.tostring(),
dtype=depth2dtype[im.depth],
count=im.width*im.height*im.nChannels)
a.shape = (im.height,im.width,im.nChannels)
return a
def array2cv(a):
dtype2depth = {
'uint8': cv.IPL_DEPTH_8U,
'int8': cv.IPL_DEPTH_8S,
'uint16': cv.IPL_DEPTH_16U,
'int16': cv.IPL_DEPTH_16S,
'int32': cv.IPL_DEPTH_32S,
'float32': cv.IPL_DEPTH_32F,
'float64': cv.IPL_DEPTH_64F,
}
try:
nChannels = a.shape[2]
except:
nChannels = 1
cv_im = cv.CreateImageHeader((a.shape[1], a.shape[0]),
dtype2depth[str(a.dtype)],
nChannels)
cv.SetData(cv_im, a.tostring(),
a.dtype.itemsize*nChannels*a.shape[1])
return cv_im
Python ile PCA (Temel Bileşenler Analizi)
Bu yazı temel bileşenler analizinin Python ile kodlanması üzerinedir. Temel bileşenler analizi hakkında detaylı teorik bilgi için tıklayınız.
Uzun süre önce MATLAB ile PCA kodunu paylaşmıştım. Python kullanarak biraz daha geliştirdim. PCA bilgisi için önceki yazıya bakabilirsiniz. Farklı olarak özvektör sayısı yerine varyansın toplam varyansa oranını parametre olarak alıyorum. 1.0 demek tüm varyansın dahil olması demek oluyor. Literatürde, genelde 0.98 veya 0.95 değerleri seçiliyor.
import numpy as np
def pca(samples, percentage=None):
"""
Perform Principal Component Analysis
Calculate the eigenvectors V (each as a column) and eigenvalues D of the
given samples which is a matrix involving a sample point in each row.
If #samples is less than #dimensions, it uses the faster PCA calculation.
Refer to the corresponding part in the thesis (Ari2008) for details."""
nSamples, nDim = samples.shape
meanSample = samples.mean(0)
# Subtract the mean from all samples to align them to origin
samples = samples - meanSample
# For faster calculation, use the transposed matrix of samples
if nDim > nSamples:
samples = samples.T
# Find the covariance of the distribution
C = np.dot(samples.T, samples) / (nSamples * 1.0)
# Find the eigenvectors (V) and eigenvalues (D) of the samples
# Recall that C*V = V*D and each column of V is an eigenvector
D,V = np.linalg.eigh(C)
# We need the eigenvalues sorted from higher to lower
indices = list(index for index, item in \
sorted(enumerate(D), key=lambda item: item[1]))
indices = np.flipud(indices)
D = D[indices]
V = V[:,indices]
# If faster calculation is done, we need to create the eigenvectors from the
# found ones and normalize them. The eigenvalues remain the same.
if nDim > nSamples:
V = np.dot(samples,V)
for i in range(nSamples):
normV = np.linalg.norm(V[:,i])
V[:,i] = V[:,i] / normV
V = V.T
# Compute the required # of dimensions acquiring the given
# variance percentage
if percentage is not None:
totalVariances = [sum(D[0:i]) for i in range(len(D))]
totalVariances = totalVariances / totalVariances[-1]
nEnoughComponents = len(totalVariances)
for i,val in enumerate(totalVariances):
if val > percentage:
nEnoughComponents = i+1
break
V = V[0:nEnoughComponents,:]
D = D[0:nEnoughComponents]
return V,D
Kullanırsanız ve/veya geliştirirseniz lütfen benimle de paylaşın.
Sınırlı hafızaya rastgele müzik seçimi
Benim şirin bir mp3çalarım var fakat 1GB hafızaya sahip. Sık sık dinlediğim albümler var ama bazen değişik şeyler dinleyeyim istiyorum. Radyosu olmadığı için, müzik arşivimde dolaşıp şarkılar seçiyorum ve mp3çalara atıyorum. Bu işlemi elle yapmaktan sıkıldım, tüm şarkıları atacak yeterli hafıza da yok. Ben de Python ile bir klasörden rastgele mp3 dosyaları seçip başka klasöre atayım istedim ve alttaki kısa kod ile bu işi kısmen hallettim.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, random, time, shutil
if __name__ == "__main__":
kaynakKlasor = u'/home/ismail/Music'
hedefKlasor = u'/media/MUZIKCALAR/Music/' + time.ctime()[4:10] + '/'
enCokDosyaSayisi = 160
kaynakKlasor = kaynakKlasor.encode('utf-8')
tumDosyalar = []
#altDosyalar = []
for root, dirs, files in os.walk(kaynakKlasor):
for f in files:
if f.endswith('.mp3'):
tumDosyalar.append(os.path.join(root, f))
#if root != kaynakKlasor: # Alt klasordeyim
# altDosyalar.append(os.path.join(root, f))
random.seed()
random.shuffle(tumDosyalar)
print "Toplam dosya sayisi: " + str(len(tumDosyalar))
if os.path.exists(hedefKlasor):
shutil.rmtree(hedefKlasor)
print "Onceki icerik silindi"
os.mkdir(hedefKlasor)
for i in range(enCokDosyaSayisi):
shutil.copy2(tumDosyalar[i], hedefKlasor + str(i) + " " + os.path.split(tumDosyalar[i])[-1])
print "(" + str(i+1) + "/" + str(enCokDosyaSayisi) + ") " + os.path.split(tumDosyalar[i])[-1]
Üstteki örnek, kaynaktan hedefe en çok 160 mp3 dosyası gönderebiliyor, hafıza yetmezse duruyor.
Bunu bir süre önce kendim için yazmıştım. Kardeşim de kullanmak istedi. Windows kullanıyor. Python'ı kurduk ve nasıl kullanacağını anlattım. Lisede okuyor ve dil bölümünde. Programlama bilmiyor fakat 5 dakikada kabaca nasıl çalıştığını anladı ve kendi işi için kullanabiliyor.
Koş yılan koş
PyCon 2009’da verilen konuşmalardan biri “Profiling” üstüne, yani yazılan programın dinamik analizi üstüne, özellikle de hız konusunda.Bu konuyu özet geçecek olursak şöyle:
Knuth amca bize diyor ki; kodu yazarken erkenden optimizasyona girmeyin, küçücük yerleri optimize etmekle uğraşmayın, muhtemelen size gerekecek hız artışını %3 gibi bir kısmı gözden geçirerek yaparsınız, önemli olan burayı bulabilmek. Python kodlarken de bu iş için gelişmiş araçlar mevcut ve kullanımları çok kolay. Örneğin bir fonksiyonu çalıştıracak olalım ve analizini yapacak olalım. Ben bu iş için cProfile kullanıyorum (Ubuntu’da python-profiler paketi ile kolayca yüklenebilir). Fonksiyonu analiz edeceğim kodu şöyle yaptım:
import cProfile
# ... başka fonksiyonlar buraya ...
#
# def fonksiyonum():
# ...
if __name__ == "__main__":
command = """fonksiyonum()"""
cProfile.runctx( command, globals(), locals(), filename="sonuclar.profile" )
Bunu yapınca kod normal hali ile çalışıyor ve istatistikler sonuclar.profile isimli dosyaya yazılıyor. Bu dosyayı okumak için de runSnakeRun kullanıyorum. Komut satırında
runsnake sonuclar.profile
yazınca arayüz geliyor ve nerede ne kadar zaman harcandığı gözlemlenebiliyor.
Programın nerelerde takıldığı gayet kolay gözlemlenebiliyor. Örneğin benim fonksiyonumun toplam zamanının %62’si resim yüklemeye, %13′ü de onlara ilgin bükme (“affine warping”) uygumaya gidiyormuş. Bir resmi 0.04 gibi bir saniyede işleyebiliyorum ki bu da saniyede 25 kare eder, şu anlık pek derdim olmasa da gerçek zamanlı sayılır. Daha iyi bir bilgisayarda yapsam daha da hızlanır.
Yani, kıssadan hisse şu: düzgün analizler yapmadan boşuna takla atmaya gerek yok. Analiz sonucunda baktık ki yazılan Python kodu cidden sıkıntılı, o zaman ilk hamlede alttaki linkteki ipuçlarını kullanmak, olmuyorsa da o kısmı Cython, vb. ile yazmak gerek.
Konuyla ilgili Python performans ipuçlarını okuyabilirsiniz.
"Küçük iyileştirmelerin %97’sini unutmak gerek. Erken eniyilendirme tüm kötülüklerin anasıdır."
— D. Knuth
Varşova’da Python kışokulu
8–12 Şubat 2010 tarihlerinde, Varşova’da, ileri seviye, bilimsel Python kışokulu düzenlenecek. Katılım ücretsiz, yalnızca yol, barınma ve yemek masrafları katılımcıya ait. Üniversitede iseniz, bilimsel programlama olduğu için fondan yararlanılabilir sanırım.
Ben Eylül’de Berlin’de düzenlenen yazokuluna katılmıştım. Varşova’daki ile konu olarak örtüştüğü için ona başvurmayacağım ama kısaca yazokulundaki gözlemlerimi yazayım:
Organizasyon sinirbilimcilerin organizasyonu gibi gözükmesine rağmen katılımcılar farklı alanlardan gelmişti. Ekonomisti, fizikçisi, mühendisi, kimyacısı, biyoloğu, meraklı herkes… Katılımcıların büyük kısmı Python bilmesine rağmen hiç bilmeyenler de vardı. Hatta ve hatta nesne-tabanlı programlama bilmeyen ve vektörel programlama konusunda fikri olmayanlar bile vardı! Yani, ben bilmiyorum, zaten kabul etmezler fikri tamamen yanlış, onun için diyorum. Bilmeyenler veya bilgisini tazelemek isteyenler için ilk gün (0. gün) hızlandırılmış bir kurs oluyor. Tüm dersler önce anlatım (2–2,5 saat) ve ardından alıştırmalar (~1,5 saat) şeklinde ilerliyor ve günde bunlardan iki set oluyor. Bir hayli yoğun bir program. Yazılım mühendisliği, kod tasarımı üstüne yaklaşımlar (“design patterns”), Python ile bilimsel programlama (MATLAB gibi kullanabilme [numpy, matplotlib, scipy]), kodu paralel çalıştırabilme, birim test yazma, hız analizi (“profiling”) öne çıkan başlıklar.
Tüm konuları hazmedemiyor insan ama çok iyi bir izlenim bırakıyor. Sadece dinlemiyorsun, elleri de zoraki kirletiyorsun. Bir de alıştırmaları zorunlu olarak 2 kişilik gruplarda yapıyorsun. Amaç birlikte çalışabilmeyi de zorlamak. İki kişinin bilgilerini paylaşmasını sağlamak. Bana farklı günlerde, ne yazık ki (!) çok bilen bir Fransız ve İtalyan arkadaş denk geldi ve onlara vektörel programlamayı anlatırken alıştırmalar güme gitti. Çok ilginçtir bu kazanım, daha sonra değineceğim. İtalyan arkadaşı çok sevdim, inanılmaz sıcak bir adamdı ama diğeri beni çok sevdiğinden ikinci gün sattı :)
Son iki gün yoğun bir şekilde 6 kişilik gruplar halinde bir projede çalıştık: Pacman! Pacman oyunu için her grup 2 adet oyuncu yazdı ve yazokulu sonunda oyuncuları kapıştırdık. Biz 4. olduk, ama beş takım vardı :) Yani çok büyük performans gösterdik anlayacağınız.
Benim kazancıma geleyim. Ben anlatılan çoğu şeyi biliyordum ama çok önemli bir şey farkettim. Bizim grup 6 kişi, biri ilk gün hastalandı, gitti. Kaldık 5 kişi. Bir İtalyan var (ilk bahsettiğimden farklı), eleman canavar. Onunla frekanslar tuttu, projeyi nasıl yaparız diye tartışıyoruz. Bir de benim ikili gruplardan partnerim olan Fransız var ki grubu hiç dinlemiyor. Hadi girişelim, ben şurayı yazacam falan, aceleye getiriyor işi. Ben kendimi görece grup çalışmasına yatkın biri olarak tanımlardım hep. 3 gün boyunca arada benim teller koptu, kendimi dışarı attım, sakinleşip yazmaya çalıştım. İşin ucunda bir şey olacağı yok ama strese sokuyorlar, geriyorlar ortamı falan. Of dedim of, ama kendimin bu konularda ne kadar tecrübesiz olduğunu gördüm. Yani kızsam kaybederiz, adamın dediği her şeye uymak da ters, birlikte kod yazarken de politik olmak gerekiyor onu farkettim. Litvanyalı bir kız vardı, onla partner olduk, birlikte projenin bize düşen ayağını yaptık. Sonunda iyi kötü işin içinden çıktık. Ben de kodlamanın ötesinde bir şey edinmiş oldum. Zaten organizatörlerde gördüğüm birlikte çalışabilme kültürü beni hayrete düşürdü. Hepsi birbirine saygılı ve paylaşımcı. Bizde pek az bulunan özellikler bunlar bence (hele bir de Boğaziçi’ndeyseniz, ÖSS sonucuyla ömrünü tamamlayan, çok fazla küçük dağ yaratıcısı ile yaşamaya alışmanız lazım).
Konferansta çalışmanın dışında yemekler de tertip edildi ve değişik insanlarla tanışma fırsatı doğdu. Çoğu doktora öğrencisi veya doktora sonrası araştırmacı. Çok iyi programlama biliyorlar genel de. Hepsinin dahil olduğu açık kaynak bir proje var ve mümkün olduğunca kendi aralarında alışveriş yapmaya çalışıyorlar. Çok teknik bir konuşma, bir an paylaşım üstüne güzel bir sohbete dönüşebiliyor. Açıkçası bunları görmek benim çok hoşuma gitti. Konferansta tanıştığım EPFL’den bir araştırmacı beni Freiburg’a sinirbilimcilerin başka bir Python çalıştayına çağırdı. O da 2 hafta kadar önceydi, oraya katıldım. Başka bir elemandan şimdiye kadar okuduğum en iyi programlama kitabını öğrenmiş oldum: The Pragmatic Programmer. Birlikte iş yaptığımız için insanlarla daha yakından tanıştık. Python bilgisi dışında bana kattığı farklı güzel şeyler oldu. Berlin’i de unutmamak gerek.
Vel hasıl-ı kelam, bilimsel Python programlama öğrenmeye meraklıysanız; sadece teknik olmasın, biraz da yazılıma dair bakış açıları öğreneyim derseniz birebir. Ayrıntılı bilgi programda var. Sinirbilim kardeşi bir alanda iseniz kullandığınız açık kaynak modüllerin yazarları orada olabilir, bakmak lazım. Bu arada, Varşova’nın soğuğu da cabası!

