20 Mart 2017 Pazartesi

Matplotlib ile log analizi yapmak

Merhabalar; Bu blog yazımızda access.log dosyasımızdaki logları matplotlib kütüphanesini kullanarak grafiğini çıkaracağız. Dilerseniz bu log dosyasını indirebilir veya aynı formataki kendi log dosyanızı kullanabilirsiniz.
Matplotlib veriler üzerinde her türlü çizgi, histogram, bar, faz, dairesel ve daha nice grafik formatlarını sadece basit birkaç satır kod ile çıktı alabileceğimiz harika bir python kütüphanesidir. Nufus dağılımlarından, ülkedeki okuyan bilgisi, matematiksel bir denklemin grafiğinden, zararlı bir yazılımın dağılım hızı gibi aklınıza gelebilecek her türlü konuda rahatlıkla kullanabilirsiniz. İşin içine istatistiğin girdiği her konuda işinize ve ihtiyaçlarınıza fazlasıyla cevap verecektir. Günlük hayatta bir çok konuda uygulanabilir diyerek konunun girizgahını yapalım.
Yukarıda da bahsetmiş olduğumuz üzere biz bu yazımızda bir web sitesine ait access.log dosyasındaki belli bilgileri kullanarak matplotlib yardımıyla yazacağımız scripte herhangi bir access.log dosyasını vererek en çok request yapan ip adreslerini ve request değerlerini grafiğe dökeceğiz. Başlayalım!
Öncellikle aşağıdaki komut ile kütüphanemizi kuralım.
pip3 install matplotlib
Kodumuza kütüphanelerimizi dahil etmekle başlayalım.
from matplotlib import pyplot as plt #Grafikleri çizeceğimiz alan(plot)
from sys import argv #Dışarıdan argüman alacağımız için import ediyoruz.
En çok istekte bulunan n. kayda kadar listeleyeceğimiz için n argüman değerimizi ve log dosya adımızı dışardan alıyoruz.
logfile = argv[1]
n = int(argv[2])
access.log dosyamızın her bir satırı bir liste elemanı olacak şekilde log listemize atıyoruz.
with open(logfile, "r") as f:
 log = f.readlines()
Sonrasında access.log dosyamızdaki yalnızca ip sutununu alacak şekilde parse edelim ve ip değerlerimizi bir ip listesine atayalım.
ip = [i.split()[0] for i in log]
access.log dosyamızda tekrar eden ip adreslerini bire indirgiyoruz.(Tekrar durumundan önüne geçmek için)
uniq_ip = list()
[uniq_ip.append(i) for i in ip if i not in uniq_ip]
Şimdi ise her ip'den gelen toplam request sayısını bulalım. Yani frekansı.
freq = list()
[freq.append(ip.count(i)) for i in uniq_ip if i not in freq]
Request yapan ip'ler ve ip sayılarını bir liste içerisinde 2 elemanlı demetler şeklinde request sayısına göre büyükten küçüğe doğru sıralıyoruz.
eq = sorted(zip(freq, uniq_ip), reverse=True)
Şimdi plota çizeceğimiz eksen noktalarımızı belirleyelim.
y_axis  = [i[0] for i in eq] # y ekseni

# x ekseni. Her bir x noktasına bir y noktası denk geleceği için x ve y liste uzunluklarının eşit olmasına dikkat ediniz.
x_axis  = range(len(y_axis))

x_label = [i[1] for i in eq] # x eksenindeki etiket isimleri (ip adresleri)
y_axis değişkenimizde frekans sayıları, x_label değişkenimizde ise ip adresleri yer almaktadır.
# Grafiğimizi çizdik. marker ile x ve y ekseninin kesiştiği yere .(nokta) koyduk.
plt.plot(x_axis[:n], y_axis[:n], marker='.')

# x, y eksenindeki bilgi etiketlerini ve başlığı yazdırıyoruz.
plt.title(argv[1]+" File Analysis")
plt.ylabel("Total Request")
plt.xlabel("Ip Address")

# Grid ile x ve y ekseninde yatay ve dikey referans çizgilerini aktif ediyoruz.
plt.grid(True)

# X eksenimizdeki etiket alanında sayi görünmesi yerine ip adreslerini gösteriyoruz. 90 derece göndererek overlop olmasının önüne geçiyoruz.
plt.xticks(x_axis[:n], x_label[:n], rotation=90)

# y eksenimizi 50 birimlik referans çizgileri ile belirliyoruz. Daha fazla detay için küçük değer verilebilir.
plt.yticks(range(0,max(y_axis),50))

#Grafiğimizi gösteriyoruz.
plt.show()
Time to test :) En çok istek yapan ilk 10 ip'ye bakalım.
python3 log_analiz.py test_log 10
İlk paragrafta verdiğim örnek access log dosyasına bakalım.
python3 log_analiz.py access_log 30
Bu yazımızda matplotlib kütüphanesinin temel kullanımını güzel bir örnek ile anlatmış olduk. Sonraki yazılarımızda farklı grafik türlerini kullanarak örnekler yapacağız. Siz aynı örnek üzerinde request-time şeklinde grafik oluşturabilirsiniz. Tamamen size kalmış. Bir sonraki yazımızda ise dinamik grafik oluşturmayı göreceğiz. Ayrıca bu yazıda kullandığımız kodlara şuradan erişebilirsiniz. Sağlıcakla kalınız.

Kaynaklar:
http://matplotlib.org/api/pyplot_api.html

17 Mart 2017 Cuma

Merhabalar,
Bu yazıda Django'nun kendi user modelinden kalıtım alarak kendi user modelimizi oluşturmayı ve authentication modeli olarak oluşturduğumuz modeli göstermeyi basit bir şekilde anlatacağım. Bu yazıyı yazmamın sebebi gözlemlediğim kadarı ile insanlar user modeline extra fieldlar eklemek istediklerinde OneToOneField kullanarak extra bir model oluşturduklarını görmem. Bunu daha basit, temiz ve tavsiye edilen yöntem olan hali hazırda Django'da yazılmış AbstractUser sınıfından kalıtım alarak nasıl çözeriz hemen bahsedelim.

OneToOneField


OneToOneField bildiğiniz gibi iki modeli ilişkilendirmek için kullanıyoruz. ForeignKey'de 1'e n bir ilişki varken, örneğin bir(1) yazarın birden fazla(n) kitabı olabilir. OneToOneField'de ise 1'e 1 ilişki bulunmaktadır. OneToOneField'in bu durumda nasıl kullanıldığını örneklemek amacı ile stackoverflow.com'dan bu örneği aldım. Tam olarak demek istediğim haliyle kullanmış buradaki arkadaş. Ama biz bunu istemiyoruz. Biz istiyoruz ki siz en güzel ve temiz yöntemi kullanın.
from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    nim = models.CharField(max_length=10, blank=True)

    def __str__(self):
        return self.user.username
Örnekte gördüğümüz gibi arkadaş Django'nun var olan User modeline nim adında bir field daha eklemek istemiş. Bunun için ise Profile adında bir model oluşturmuş ve bunu Django User modeli ile OneToOneField ile bağlamış.

Custom Model


Şimdi aynı işlemi kalıtım alarak uygulayalım.
from django.contrib.auth.models import AbstractUser
from django.db import models

class Profile(AbstractUser):
    email = models.EmailField('email address', unique=True)
    nim = models.CharField(max_length=10, blank=True)

    def __str__(self):
        return self.username
Burada ben ekstradan email alanını tekil ve zorunlu hale getirdim. Bildiğiniz gibi default user modelinde bu alan tekil ve zorunlu değil. Son olarak yapmamız gereken ise settings.py dosyası içerisinde bu modelin authentication modeli olduğunu Django'ya bildirmek.
AUTH_USER_MODEL = 'app_name.Profile'
Bu işlemden sonra Django'nun sadece bizim oluşturduğumuz modele ait tabloyu veritabanında oluşturduğunu görebilirsiniz. Son olarak oluşturduğumuz modeli admin sayfasında görebilmek için register işlemini yapalım.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import Profile


admin.site.register(Profile, UserAdmin)
Faydalı olması dileğiyle. Kolay gelsin.

23 Ocak 2017 Pazartesi

PYTHON İLE BASİT BİR YSA UYGULAMASI

Gelişen teknolojiyle beraber dijitalleşen hayatlar sonucunda her geçen saniye binlerce veri kayıt altına alınmaktadır. Bu veriler; açık veya kapalı devre kameralardan alınan veriler, bir sunucu veya data centerın log kayıtları, bir gsm şireketinin ses kayıtları, bir sosyal medyadaki veriler diye uzayıp giden devasa veri yığınlarının da dahil olduğu uzunca bir liste. Dijital sahada bu kadar veri dururken bunların insan gücüyle analiz edilmesi neredeyse imkansız hale gelmiştir. Çünkü bu büyük veri yığının içerisinde gerekli olan anlamlı verileri çıkarmak yada bu verileri kullanarak anlamlı bir sonuç çıkarsama birçok insanın bile yapabileceği bir iş değildir. Bu problemlere çözüm olacak yöntem ise makinelerin de kendilerine özgü karar verme ve çıkarım yapabilme yeteneklerine sahip olmasıdır. Bu kadar veriler içerisinde anlamlı olan verileri ayıklamak veya bu verileri kullanarak bir çıkarsama yapabilmesi artık çağımızın bir zorunluluğu haline gelmiştir.

İşte bu noktadan sonra biyolojik olarak insan zekasının çalışma mantalitesinden esinlenerek yapay zeka tekniği geliştirilmeye başlandı ve hala ciddi çalışmalar ile devam etmektedir. Bu yazımızda yapay zekanın öğrenme tekniklerden biri olan yapay sinir ağı(YSA) mimarisini kullanarak python ile basit bir uygulama yapacağız. Bildiğiniz üzere python veri madenciliğinden, bilimsel çalışmalara, yapay zekadan siber güvenliğe kadar yelpazesi çok geniş olan bir dildir. Yapay sinir ağı konusunda çok ciddi kütüphaneleri de bulunmaktadır. Bunlardan bazıları coffe, theano, tensorflow, scikit, panda ve torch kütüphaneleridir.

Keras ise arkada tensorflow veya theano kütüphanesini kullanan bir arabirimdir. Biz ise keras ile arkada tensorflow kullanarak bir uygulama yapacağız. Tensorflow, google tarafından geliştirilmiş ve 2015 yılında bir kısmı public hale getirilen makina öğreniminde kullanılan ciddi bir kütüphanedir.

Ancak örnek uygulamamızı yazmaya geçmeden önce yapacağımız uygulamayı anlamak için yapay sinir ağı mimarisinin nasıl çalıştığını bilmemiz ve bu konudaki terminolojiye biraz hakim olmamız gerekmektedir. Bu sebeble kısa bir şekilde biraz değineceğiz. Ancak bu yazıyı konuya biraz hakim olduğunuzu ve yazacaklarımı hatırlamanız amacıyla yazdığımı belirtmek isterim.

Aşağıdaki resimde giriş ve ara katmanlar(hidden layers) olmak üzere üç katmanlı yapıya sahip bir yapay sinir ağı modeli görmektesiniz.


Yukarıdaki gördüğünüz her bir düğüm aslında bir yapay sinir hücresini temsil etmektedir. Ve bunlara perceptron denmektedir. Perceptronlar arasındaki çizgiler ise ağırlıkları temsil etmektedir. Ve bir perceptronun değeri; kendisinden bir önceki katmanda bulunan bütün perceptronlardaki değerin ilgili ağırlıklarıyla çarpıldıktan sonra bir toplam fonksiyonundan geçtikten sonra bulunan değerin bir aktivasyon fonksiyonundan geçmesi sonucu bir değere sahip olacaktır. Bu bulunan sonuç, bir sonraki katmana girdi olarak verilmektedir Anlatmak istediğimizi aşağıdaki resim açıkça izah etmektedir. Aşağıdaki resim, yukarıda gördüğünüz her düğüm içerisinde olan işlemleri göstermektedir.

Yandaki resimde Xi’ler bizim girdi değerlerimiz, Wi’ler ise ağırlıklarımızı ifade etmektedir. Her girdi kendi ağırlığıyla çarpıldıktan sonra çıkan değeri bir sonraki katmandaki bulunan perceptronlara aktarmaktadır ve bu perceptronda toplam fonksiyonundan geçtikten sonra çıkan değer aktivasyon fonksiyonuna göndererek ortaya nihai bir değer çıkacaktır. Ve varsa bu değer bir sonraki katmana aktarılarak bu döngü çıkışa varıncaya kadar böyle devam edecektir. Bu her değer için bu iterasyon yapılacaktır. Ve her iterasyonda uygun bir sonuç bulmak için ağırlıklar yeniden düzenlenecektir. Bu olaya epoch denilmektedir. Çünkü sonuçları etkileyen en önemli etkenlerden biri de ağırlık değerlerimizdir. En basit haliyle bir ysa modeli bu şekildedir. Şimdi ise verilerin bu model içerisinde nasıl işlenildiğine kısaca değinelim;

Elimizde bir dataset(veri kümesi) olur. Bu dataset bizim kullanacağımız teknik gereği birden fazla girdinin ama bir çıktının olacağı bir yapıya sahip olmalıdır. Örneğin; bir kullanıcının mouse hareketlerini, tıklama sayıları, girdiği siteleri, bu sitelerde kaldığı süre gibi çevresel değişkenleri alıp bu değerler sonunda bu kişinin bot mu? Insan mı? Değerini saklayan bir dataset düşünelim.

10 bin kullanıcıdan alınan değerler sonucunda bu kişilerin bot mu? Insan mı? Olduğu değerini tutan böyle bir datasetimizin olduğunu varsayalım. Bu değerlerimiz gerçek değerlerdir. Yani herhangi bir lab ortamında bot davranışlarını tuttuklarını ve binlerce insanın bilgisayar kullanırken ki aktivitelerini kayıt altına aldıklarını düşünelim. Çünkü bizim ysa modelimiz bu örneklerden bir çıkarım yaparak kendisine daha önce hiç gösterilmemiş bir örnek gösterildiğinde bunun bot mu? Insan mı? Olduğunu bu gerçek değerlerle kendisini eğiterek bulacaktır. Ama öncesinde tabi ki de sistemimizin öğrenme eğitimini tamamlaması gerekir.

Biz bu 10 bin veriden 9 bin tanesini ysa modelimize eğitim verisi olarak vereceğiz. Eğitim verileri, bir ysa modelini eğitmek için verilen verilerdir. Bizim bu örneğimizde ise girdi ve çıktı değerlerinin olduğu veriye verilen isimdir. Çünkü modelimiz girdi değerleri ile çıktı arasında bir matematiksel model oluşturmaya çalışacak. Bu model oluştururken ağırlıklar, aktivasyon fonksiyonu, ara katmanlar, katmanlardaki perceptron sayıları gibi değişkenler değiştirilip en uygun değer bulunmaya çalışılır. Ve modelimiz belirlediğimiz bir eşik değerine vardığında öğrenme sona erer. Öğrenme bitmesi ysa modelimizin girdi ve çıktılarımız arasında bir matematiksel model bulduğu anlamına gelmektedir. Sistem eğitimi tamamladıktan sonra test etmemiz gerekmektedir. Testi ise 10 bin veriden bir köşeye ayırdğımız bin adet veriyle yapacağız. Ancak burda önemli olan nokta şudur; Test verilerimizi verdiğimiz de sadece girdi değişkenlerimizi vereceğiz. Yani o kişinin bot mu? Insan mı? Olduğu değerini vermeyeceğiz aksine modelimiz bu değeri kendisi bulacak. Ve bulacağı bu değeri gerçek değer ile mukayese ederek sistemimizin yüzde kaç başarılı olduğunu hesaplayacağız. Örneğin yüzde 90 ve üzeri bir başarı bizim için kabul edilebilir bir değer ise modelimiz başarılı olmuştur demektir. Zaten hiçbir ysa modeli size %100 kesin sonuçla bir değer veremez. Her zaman bir hata payı vardır ve olmak zorundadır. Çünkü sistem kendisi verilen değerlerden bir sonuç çıkarmaktadır. Eğer yüzde 100 doğru cevap veriyorsa bir sistem o sistem öğrenmemiş ezber yapmıştır. Bu duruma overfitting de denilmektedir.

Ayrıca dikkat ettiyseniz tabloları kullanıyoruz bu da YSA’da özellikle matrisleri çok yoğun kullanacağımız anlamına gelir. Zaten uygulamamızı yaptığımızda numpy kütüphanesini de kullanacağımızı göreceksiniz. Unutmadan aslında yaptığımız anlatığımız bunca şeyin arkada nasıl çalıştığını ve öğrenme dediğimiz o olayın nasıl gerçekleştirildiğini çok güzel simüle eden tensorflow’un bu web uygulamasına kesinlikle bakınız. Parametrelerle oynayın, kurcalayın biraz işte ;)

Şimdi bir ysa modeli için bir kaç önemli hususu maddeler halinde verelim.
  • Herşeyden önce sistemimizi eğiteceğimiz bir datasetine sahip olmalıyız. Bunun için belli başlı dataset repoları var. Şu ve şu adreslere bakabilirsiniz.
  • Datasetinde bir sistemin öğrenmesi için yeterli sayıda veri bulunmalıdır. Az veri olursa sistem ezbere düşecektir.
  • Datasetimizdeki veriler makul olmalıdır. Çünkü sistem o verileri kullanarak öğrenme yapmaktadır.
  • Eksik ve yanlış verilerin olması sistemin öğrenmesini çok ciddi bir şekilde etkilemese de sistem belli bir seviyeden sonra öğrenemez.
  • Eğitim verilerinizi aynı zamanda test verisi olarak hiçbir zaman kullanmayınız. Alacağınız sonuçlar sağlıklı olmayacaktır. Sistemin daha önce hiç görmediği veriler ile test ediniz.

Bu kadar cümleden sonra işin hikaye kısmını bitirdik ve artık teknik kısma geçmek için hazırız. Bizim kullanacağımız dataset yaklaşık 800 insanın vucudundan alınmış yaklaşık 8 değer var yani girdiler. Bunlar; hamilelik sayısı, plazma glukoz konsantrasyonu, diastolic kan basıncı, deri kalınlığı, kullanılan insulin miktarı, vucut kitle indexi, diyabet soyağacı ve yaş değerleridir. Ve son sutunda ise 1 veya 0 değeri yer almakta. Eğer 1 ise kişinin şeker hastası(diabet) olduğu, 0 ise diabet hastası olmadığı anlamına gelmektedir. Buradan ufak bir parantez açayım. Datasetimizdeki her verinin numerik olması gerekmektedir. Çünkü bu değerler üzerinde matematiksel işlemler yapılmaktadır. Çıkışlar bile numerik olmalıdır en azından o şekilde ifade edilmelidir.
Öncellikle kullanacağımız kütüphaneleri varsa diğer projelerde kullandığımız kütüphaneleri etkilememesi için bir virtual environment kullanarak uygulamamızı diğer python kütüphanelerinde izole hale getireceğiz. Bunun için;
$sudo pip3 install virtualenv
Kurulum bitince ardından ;
$sudo virtualenv keras
diyerek keras adından bir izola ortam oluşturup;
source /bin/activate
diyerek izole ortamımızı aktif hale getirelim. Şimdi ihtiyaç duyacağımız kütüphanleri yükleyelim.
$sudo pip3 install numpy $sudo pip3 install tensorflow $sudo pip3 install keras

İşlem bittiğinde uygulamamız için gerekli herşey hazır demektedir. Artık python kodumuzu yazmaya başlayabiliriz. Öncellikle kullanacağımız paketleri import edelim.
#Kullanacağımız ysa modeli için.
from keras.models import Sequential

#YSA modelimizde katmanlar oluşturabilmek için.
from keras.layers import Dense

#Çıktımızı terminalden aldığımızda sonuçları renklendiriyoruz. Yanlışlar kırmızı, doğrular yeşil. Bunu kullanmasanızda olur yani.
from termcolor import cprint

#YSA matrislerle çalıştığı için numpy olmazsa olmaz.
import numpy
Datasetimizi yüklüyoruz.
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
numpy kütüphanesindeki loadtxt() metodumuz verilen ilk parametredeki dosya/string I delimiter(ayırıcı) ile split ederek bir matrise atamaktadır. Datesetimizi ayrıştırıyoruz. X, 8 adet girdimiz. Yani 600 satır ve 8 sutun. Y ise çıkışımız 600 satır 1 sutundan oluşmaktadır. Eğer bu parçalamayı anlamadıysanız lütfen şu konuya bakınız.
X = dataset[:600,0:8]
Y = dataset[:600,8]
Şimdi modelimizi oluşturup katmanlarımızı yerleştirelim. Modelimizden model adında bir nesne türettik.
model = Sequential()
Ve ilk katmanımızı modelimize add metodu ile dense tipindeki katmanımızı ekliyoruz. Parametrelerden 12 olanı ilk katmandaki perceptron sayısı. İnput dim bizim girdi değer sayımız. Hatırlarsanız 8 değerimiz vardı. Init parametremiz yapay sinir hücrelerimiz arasındaki ağırlıklarımızın rastgele verilmesi yerine belli bir algoritmaya göre vermektedir. Aktivation ise o katmanda kullandığımız aktivasyon fonksiyonumuz.
model.add(Dense(20, input_dim=8, init='uniform', activation='relu'))
#İkinci katmanımızda 12 yapay sinir hücresi. 
model.add(Dense(12, init='uniform', activation='relu'))

#Üçüncü katmanımızda 8 yapay hücremiz var.
model.add(Dense(8, init='uniform', activation='sigmoid'))

#Dördüncü katmanımızda 1 yapay hücremiz var. Yani çıkışımız.
model.add(Dense(1, init='uniform', activation='sigmoid')) 

#Modelimizi derliyoruz.
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
Modelimizi çalıştırıyoruz. İlk parametre girdilerimiz, ikincic parametre çıktığımız. 3. paramtre epoch değerimiz. Yani ağırlıkların yeniden düzenleyerek çözüme en yakın değeri buluncaya kadar yapacağı deneme sayısı. Batch size tek seferde alınacak veri sayısını ifade etmektedir. Verbose ise herhangi bir hata oluşması durumunda göstermemeisini istedik.
model.fit(X, Y, nb_epoch=150, batch_size=10,  verbose=2)
Modelimizin başarı yüzdesini hesaplıyoruz.
scores = model.evaluate(X, Y)
Ve son olarak modelimizin sonucunu ekrana basıyoruz.
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
Evet buraya kadar modelimiz verdiğimiz örnekleri kullanarak girdi ve çıktılar arasında ilişkisel olarak bir model buldu ve eğitim sona erdi. Bundan sonra sisteme test verilerimizi vererek ne kadar başarılı bir sonuç bulduğunu hesaplayacağız. Şimdi köşeye ayırdığımız 1000 değeri sistemimize vereceğiz ve ysa modelimizin bulduğu sonuçlar ile gerçek sonuçları karşılaştırıp ne kadar başarılı olduğunu görelim. Aşağıdaki kodlarıda yine aynı python dosyasına yazarak devam edelim.
#96 adet test verimizin sadece 8 girdisini sisteme veriyoruz.
test_verisi = dataset[600:696, 0:8]

#Sistemin verdiğimiz değerlerden yola çıkarak kişinin diyabet hastası olup olmadığını tahmin ediyor.
predictions = model.predict(test_verisi)
Buradan sonrası ise sonuçları ekrana basma olayı.
dogru = 0
yanlis = 0
toplam_veri = len(dataset[600:696,8])

for x, y in zip(predictions, dataset[600:696,8]):    
    x = int(numpy.round(x[0]))
    if int(x) == y:
        cprint("Tahmin: "+str(x)+" - Gerçek Değer: "+str(int(y)), "white", "on_green", attrs=['bold'])
        dogru += 1
    else:
        cprint("Tahmin: "+str(x)+" - Gerçek Değer: "+str(int(y)), "white", "on_red", attrs=['bold'])
        yanlis += 1

print("\n", "-"*150, "\nISTATISTIK:\nToplam ", toplam_veri, " Veri içersinde;\nDoğru Bilme Sayısı: ", dogru, "\nYanlış Bilme Sayısı: ",yanlis,
      "\nBaşarı Yüzdesi: ", str(int(100*dogru/toplam_veri))+"%", sep="") 

Eğer herhangi bir hata ile karşılaşmadan buraya kadar geldiyseniz artık python dosyanızı çalıştırabilirsiniz. Çalıştırdığınızda arkada tensorflow kütüphanesinin çalıştığına dair bir bilgilendirme mesajı da görebilirsiniz. Bendeki eğitim öğrenme yüzdesi:


Test verilerindeki başarı değeri ise;
Sonuç olarak; yapay zeka kendi başına çok derin ve ayrı bir yetkinlik isteyen konu. Daha değinmediğim birçok şey var. Ancak yazının başında da belirtiğim gibi zaten bu konuya en azından çalışma mantalitesi hakkında bilgi sahibi olduğunuzu varsayarak yazdım. Ağırlıkların neye göre hesaplandığı, eşik değerlerinin belirlenmesi, neye göre hangi aktivasyon fonksiyonunun kullanılacağı, regresyon, sınıflandırma baya birçok anlatılacak nokta var gördüğünüz üzere ancak benim burda yaptığım konuya yeteri kadar hakim olan birinin pythonda keras yardımıyla tensorflow kullanarak nasıl uygulama yapabileceğine dair giriş mahiyetinde bir örnekti. Artık her olasılık için bir kural tanımlama günümüz dünyasında yetersiz bir durumdur bu nedenle dev veriler karşısında kısmen de olsa mantıklı çıkarımlar yapacak sistemlere ihtiyacımız var. Geleceğin burda yattığı şüphesiz doğrudur. Hatta günümüzde bile farkında olmadan kullanmaya başladık bile. Karakter tanıma, yüz ve parmak izi tanıma, ses tanıma, dudak okuma diye gider. Anlamadığınız veya hatalı noktalar varsa lütfen yorum kısmında belirtiniz.
Sağlıcakla kalın.

Bu uygulamada kullandığımız bütün kodlara buradan erişebilirsiniz.
KAYNAKLAR:
https://archive.ics.uci.edu/ml/index.html
https://keras.io/
https://www.tensorflow.org/
http://machinelearningmastery.com/tutorial-first-neural-network-python-keras/

31 Ağustos 2015 Pazartesi

Django Translation

Merhaba, Djangoda translation işlemine bakacağız. Bunun için django ile birlikte gelen translation kütüphanesinin nasıl kullanıldığından bahsedeceğiz. Hemen işe koyulalım. İlk önce settings.py dosyası içerisinde ayarlamalar yapacağız. İlk önce MIDDLEWARE_CLASSES değişkenini düzenleyeceğiz.
MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)
Daha sonra yine settings.py dosyası içerisinde hangi dilleri kullanacağımızın listesini ve dil dosyalarının ana dizinini belirteceğiz.
from django.utils.translation import ugettext_lazy as _

LOCALE_PATHS = (os.path.join(BASE_DIR, "locale"),)

LANGUAGES = (
    ('tr', _('Turkish')),
    ('en', _('English')),
)
İki dil tanımlaması yaptık. Dikkatinizi çekmiştir, ugettext_lazy adında bir fonksiyon kullandık. İleride bu fonskiyonu açıklayacağız. Settings dosyasındaki ayarlarımız bu kadar. Şimdi isterseniz django aracılığı ile dil dosyalarımızı oluşturalım. Projemizin ana dizinine locale adında bir dizin oluşturuyoruz ve şu komutları çalıştırıyoruz.
django-admin.py makemessages -l tr
django-admin.py makemessages -l en
locale dizini altında django.po adındaki dosyalarımızın oluştuğunu göreceksiniz. Django bizim için bulduğu stringleri bile ekledi. Dosyanın en başında
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-01 02:57+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
Gibi bir ifade göreceksiniz. Bu dosyanın ayarlarını içermektedir. Kendinize göre düzenleyebilirsiniz. Ardından burada bilmemiz gereken;
msgid "Mesaj ID'si"
msgstr "Mesaj içeriği"
şeklinde bir yapı olduğudur. msgid ile gösterdiğimiz kısmı metnimizi çağırırken kullanacağız. Bu kısım her dil dosyasında aynı olmalıdır. msgstr kısmı ise dillere göre değişkenlik gösterecek kısımdır. Burada msgid kısmını yazarken de cümle kuruyormuş gibi yazabilirsiniz. Değişken tanımlar gibi hissetmenize gerek yoktur kendinizi. en ve tr dillerini tanımladığımız için locale dizini içerisinde en ve tr adında iki farklı dizin oluştu. Bu dizinler içerisinde ise django.po dosyası bulunmakta. Şimdi bir kaç tanımlama yapalım.
#tr dizini içerisindeki django.po
msgid "Test metni"
msgstr "Test metni"

#en dizini içerisindeki django.po
msgid "Test metni"
msgstr "Test text"
Dosyalarımı oluşturdaktan sonra sıra geldi compile işlemine bunun için projemizin ana dizininde şu komutu çalıştırıyoruz.
django-admin.py compilemessages
Bu komuttan sonra dil dosyalarımız compile edilecek ve aynı dizinler içerisinde django.mo dosyaları oluşacaktır. Dil dosyalarını oluşturma ve compile etme işlemi bu kadar. Şimdi bunları nasıl kullancağımıza bakalım. Örneğin views içerisinde bir değişkeninizin değerinin dil seçimine göre değişmesini istiyorsak, şu şekilde kullanabiliriz.
from django.utils.translation import ugettext as _
from django.http import HttpResponse

def my_view(request):
    output = _("Test metni")
    return HttpResponse(output)
Buradaki output değişkenine gelen değer dil seçimine göre Test metni veya Test text olacaktır. Birazdan dil seçiminin nasıl yapılacağını göstereceğiz. Şimdi aynı işlemi formlar için uygulayalım.
from django.utils.translation import ugettext_lazy as _
class RegistrationForm(UserCreationForm):
    username = CharField(label=_("Test metni"))
Gördüğünüz gibi kullanımı oldukça basit. Burada ugettext_lazy kullandığımıza dikkat edin.
from django.db import models
from django.utils.translation import ugettext_lazy as _

class MyThing(models.Model):
    name = models.CharField(help_text=_('This is the help text'))
Model dosyası içerisinde de bu şekilde kullanabilirsiniz. Metin alanı olarak kullanacağınız tüm alanlarda bu şekilde translate işlemi yapabilirsiniz. Modeller içerisindeki verbose_name, help_text formlar içerisindeki label, error_messages gibi. Template(şablon) içerisindeki kullanımını görelim.
{% load i18n %}
{% trans "This is the title." %}
{% trans myvar %}
Gördüğünüz gibi kullanımı gerçekten basit. Bu şekilde django bizim için değerleri dil dosyaları içerisinden çekecektir. Template içerisinde aktif olan file şu şekilde erişebilirsiniz.
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
Veya view içerisinde şu şekilde erişebilirsiniz.
from django.utils import translation
def cur_lang(language):
    cur_language = translation.get_language()
    ....
Ve son olarak bir dili aktif etmeyi görelim. Yukarıda metinlerimizi hep translate edicek şekilde çağırdık. Hangi dil aktif ise o dile göre metinler getirilicektir.
def language(request, lang_code):
    translation.activate(lang_code)
    request.session[translation.LANGUAGE_SESSION_KEY] = lang_code
    return HttpResponseRedirect('/')
Çok basit hali dil seçimi yapan bir view yazdık. Kullanıcıdan alınan lang_code değerini aktif ediyor ve ardından session ataması yaparak kalıcı hale getiriyoruz. Django'da translation işlemi en basit haliyle bu şekilde. Daha fazla bilgiye bu sayfadan erişebilirsiniz.
Kaynakça

6 Ağustos 2015 Perşembe

Django ile Database Taşıma

Projenizi sqlite database kullanarak hayata geçirdiniz ve bir süre sonra size sqlite yetmez oldu. Database'inizi mysql veya postgresql gibi databaselere taşımak istiyorsunuz. Bu işlemi yapmak django ile oldukça kolay. Zaten ORM yapısını kullandığınız için kodlarınızda herhangi bir değişiklik olmaz. Sadece settings.py dosyası içerisinde database konfigürasyonlarınızı değiştirmelisiniz. Bu yazının konusu sadece database içerisindeki dataları taşımak olduğu için bu konfigürasyon konularına değinmeyeceğiz. Yapmamız gereken ilk önce varolan projemizde aşağıdaki komutu çalıştırmaktır.
$ python manage.py dumpdata > dump.json
Bu komut ile database'in json formatında dumpını almış olduk. Ardından konfigürasyonumuzu değiştirdikten sonra artık database değişmiş oldu ve eski datalarımızı kaybettik. Örneğin sqlite database kullanırken mysql'e geçmek istedik. Konfigürasyonu mysql olarak ayarladıktan sonra aşağıdaki komutları sırası ile çalıştırıyoruz.
$ python manage.py migrate
$ python manage.py loaddata dump.json
İşte Django aracılığı ile database değişikliği yapmak bu kadar kolay.

10 Haziran 2015 Çarşamba

Celery, Python'da dağıtık iş kuyruğu oluşturmanızı sağlayan oldukça kullanışlı bir kütüphane. Bu yazımızda bu kütüphanenin basit bir şekilde django üzerinde nasıl kullanıldığından bahsedeceğiz. Ve tahmin ediyorum ki bu kütüphaneyi daha önce duymamış olan arkadaşar yazıdan sonra kullanmaya başlayacaktır. Size şöyle bir örnek ile açıklayalım. Örneğin sisteme kullanıcı kaydı alıyorsunuz ve kayıt alırken de her kullanıcı kayıt olduğunda sistem bana mail olarak bunu bildirsin dediniz. İşte bu noktada eğer kodunuz şu tarz ise;
kullanıcı verilerini al
doğruluğunu kontrol et
kaydet
mail at
sonuç dön
Bildiğiniz gibi mail atma işlemi biraz zaman alan bir işlem olduğu için bu yapıda kullanıcıyı sistemin mail atması için gereksiz yere bekletmiş olacaksınız ve kullanılabilirlik düşmüş olacaktır. İşte Celery tam bu noktada devreye gire bir kütüphane. Burada mail için bir kuyruk oluşturuyorsunuz ve mail atma işlemi ile artık Celery ilgileniyor. Siz kullanıcıya sonucu direk dönerken Celery arka tarafta mail atma işlemini tamamlıyor. Hemen django ile kullanımına geçelim.
Broker
İş kuyruğu olarak broker seçmemi gerekiyor. Yani bizim iş kuyruğu oluşturmamızı sağlayan asıl yapı olacak. Bunun için RabbitMQ veya Redis seçilebilir. Biz RabbitMQ kullanacağız. Kurulumu :
 sudo apt-get install rabbitmq-server
Eğer ubuntu kullanıyorsanız komut ile kurabilirsiniz. Kurulduktan sonra kendisi servis olarak ayağa kalkacaktır. Kurulum için ayrıntılı bilgiyi buradan ulaşabilirsiniz. Şimdi Celery kütüphanesini kuralım.
 
pip install celery
proje adında bir projemiz olduğunu düşünürsek görünümü şu şekilde olacaktır.
proje
├── manage.py
└── proje
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py
İlk önce yapmamız gereken projemizin ayar dizinine celery.py dosyası oluşturmak ve içerisine şu komutları yazmak.
proje/proje/celery.py
from __future__ import absolute_import

import os

from celery import Celery

#celery için django default settings dosyasını gösteriyoruz
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proje.settings')

from django.conf import settings

#celery app oluşturuyoruz
app = Celery('proje')

app.config_from_object('django.conf:settings')
#bu fonksiyon sayesinde projemizde her uygulama içerisindeki tasks.py içeriği celery tarafından yorumlanacaktır.
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)


@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))
Şimdi aynı dizindeki __init__.py dosyasını düzenlememiz gerekiyor.
proje/proje/__init__.py
from __future__ import absolute_import

from .celery import app as celery_app
Artık task oluşturabiliriz. Bunun için ilk önce bir uygulama oluşturalım. ve içerisine tasks.py adında tasklarımızı yazacağımız bir dosya oluşturalım.
#python2.7 manage.py startapp uygulama
#tree proje
../proje
├── manage.py
├── proje
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── settings.py
│   ├── settings.pyc
│   ├── urls.py
│   └── wsgi.py
└── uygulama
    ├── __init__.py
    ├── admin.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tasks.py
    ├── tests.py
    └── views.py
Şimdi tasks.py dosyasının içeriğini dolduralım.
from __future__ import absolute_import

from celery import shared_task


@shared_task
def mail_gonder():
    mail() # mail gonder fonksiyonu oldugu kabul edilmiştir.
Celery ile fonksiyon oluşturmak bu kadar basit. Bu fonksiyonu views.py dosyası içerisinde şu şekilde kullanabiliriz.
from uygulama.tasks import mail_gonder
def index(request)
    ....
    mail_gonder.delay()
    ....
Kullanımı da oldukça basittir. Burada fonksiyonu doğrudan adıyla değilde delay(/) fonskiyonu ile çağırdığımıza dikkat edin. Eğer doğrudan adı ile çağırırsanız, normal bir fonksiyondan bir farkı olmaz ve işlenmesi beklenir. Burada artık bu satır işlendiği anda fonksiyon iş kuyruğuna atılacak ve hiç bekleme yapmadan kod satırları işlenmeye devam edilecektir. Rabbitmq serverımız kurduk ve çalışır bir vaziyetteyse celeryi ayağa kaldırabiliriz demektir. Eğer RabbitMQ ayakta değilse ilk önce onu ayağa kaldırmalısınız.
service rabbitmq-server start
Daha sonra proje ana dizinine giderek Celery'i ayağa kaldırmalıyız.
celery -A proje worker -l info
Bu komutu verdikten sonra Celery ayağa kalkacak ve herşey kullanıma hazır demektir. Zaten komut çıktısını incelerseniz yazmış olduğunuz taskların kullanıma hazır olduğu çıktısını görebilirsiniz. index fonksiyonu çağrıldığı anda da komut satırında taskların düzgün bir şekilde düştüğünü izleyebilirsiniz. Tabi gördüğünüz gibi Celery'i komut satırında çalıştırdık. Bu durumun böyle olmaması ve her zaman çalışabilmesi için Supervisor'ı kullanacağız.
Supervisor
sudo pip install supervisor
Supervisor config dosyasını şu şekilde oluşturalım.
/etc/supervisor/config.d/proje.conf
[program:proje-celery]
command=celery --app=proje.celery:app worker --loglevel=INFO
directory=proje_path/proje
user=user_name
numprocs=1
stdout_logfile=/log_path/logs/celery-worker.log
stderr_logfile=/log_path/logs/celery-worker.log
autostart=true
autorestart=true
startsecs=10


stopwaitsecs = 600


killasgroup=true


priority=998
Supervisor işleme alması için şu komutları çalıştıralım.
# supervisorctl reread
# supervisorctl reload 
Artık her şey kullanıma hazır. Mail atmak istediğimiz zaman mail işlemi celery tarafından kuyruğu alınacaktır ve kuyrukta işlenecektir.
Kaynakça

27 Mart 2015 Cuma

Django FlatPages Kullanımı

flatpages Django'nun kendisi ile birlikte gelen dinamik sayfalar oluşturulmasını sağlayan bir uygulamadır. Bu yazımızda nasıl kullanıldığından bahsedeceğiz. Bunun için ilk önce uygulamayı projemize dahil etmemiz gerekiyor.
INSTALLED_APPS = (
    ....
    'django.contrib.sites',
    'django.contrib.flatpages',
)
Burada dikkat etmeniz gereken flatpages uygulaması sites uygulamasını kullandığı için sites uygulamasının da projeye dahil edilmiş olması gerekmektedir. Dikkat edilmesi gereken bir diğer nokta ise sites uygulaması için şu satırı settings.py dosyasını eklememiz gerektiğidir.
SITE_ID = 1
Bu işlemden sonra MIDDLEWARE_CLASSES'a şu satırı ekliyoruz.
MIDDLEWARE_CLASSES = (
     ....
    'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
)
Url yapılandırmamızı yapalım.
urlpatterns = patterns('',
    url(r'^admin/', include(admin.site.urls)),
    url(r'^pages/', include('django.contrib.flatpages.urls')),
)
flatpages uygulamasının url dosyasını içe aktarmış olduk. Bundan sonra yapmamız veritabanı oluşturarak admin panelinden bir sayfa oluşturmak.
python manage.py syncdb
Artık dinamik bir sayfa oluşturmaya hazırız. Admin panelini açtığınız zaman Flat pages alanını göreceksiniz. Tıklayarak yeni birtane oluşturalım. Oluşturduğumuz url'e /pages/lorem-ipsum/ diye gitmeye çalışırsak flatepages/default.html bulunmadı gibi bir hata alırız. Bunun için templates dizini altında flatepages/default.html oluşturuyoruz. Ve içerisine şunları yazıyoruz.
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>{{ flatpage.title }}</title>
</head>
<body>
{{ flatpage.content }}
</body>
</html>
Şimdi tekrardan http://localhost:8000/pages/lorem-ipsum/ adresine gitmeye çalışırsanız sayfanın açıldığını göreceksiniz. Sayfayı oluştururken template name alanını boş bıraktığımız flatepages/default.html şablonunu aramaktadır.
Bir başka kullanım yöntemi ise şu şekildedir. Url tanımlamasını şu şekilde yapabilmekteyiz.
urlpatterns = patterns('',
    ...
    url(r'/lorem-ipsum/$', 'django.contrib.flatpages.views.flatpage', kwargs={'url': '/lorem-ipsum/'}, name='lorem_ipsum'),
)
Daha önceki url tanımlamasını silerseniz. Bu url tanımlamasından sonra http://localhost:8000/lorem-ipsum/ adresi ile tarayıcıdan yine ulaşabilirsiniz. Admin panelinden Flat Plage girerken Advanced Options kısmındaki Template Name alanına eğer herhangi bir isim girerseniz artık bu sayfa girdiğiniz şablona yönlendirilecektir.
Url tanımlasını şu şekilde de yapabiliriz.
urlpatterns += patterns('django.contrib.flatpages.views',
    (r'^pages/(?P<url>.*/)$', 'flatpage'),
)
Aşağıdaki html çıktısı ile, flatpages sayfalarını listeleyebilirsiniz.
{% load flatpages %}
{% get_flatpages as flatpages %}
<ul>
    {% for page in flatpages %}
        <li><a href="{{ page.url }}">{{ page.title }}</a></li>
    {% endfor %}
</ul>
Kaynakça

16 Mart 2015 Pazartesi

Pdb ile Python Debugging

Pdb, Python scriptleri üzerinde debug işlemi yapabilmenize olanak sağlayan bir kütüphanedir. Bu yazıda çok basit bir şekilde kullanımından bahsedeceğiz.
Yazdığımız bir python scriptini debug etmek için komut satırından şu şekilde çalıştırabiliriz.
python -m pdb t.py 
Bu şekilde çalıştırıldığında script debug işlemi kodların en başından başlayacaktır.
Gördüğünüz gibi scripti çalıştırdığımızda bizi doğrudan pdb kabuğuna düşürdü. Burada artık debug işlemimize başlayabiliriz. Tabi bu işlem ile gördüğünüz gibi ilk satırdan itibaren debug işlemine başlamış olduk. Bu şekil de kullanmak yerine herhangi bir satırda bu işlemin başlamısını isteyebiliriz. Bunun için ise script içerisinde herhangi bir satıra şu kodu yazabiliriz.
import pdb; pdb.set_trace()
Bu kodu yazdığımız satıra kadar programımız yorumlanacak ve bu satırdan sonra bizi Pdb kabuğuna düşürecektir. Şimdi yazdığımız basit kodu şu hale getiriyoruz ve ardından komut satırından normal bir şekilde - pdb kullanmadan - çalıştırıyoruz.
def deneme(a):
 print "Bu bir fonksiyon"

print "Pdb'den once"
import pdb; pdb.set_trace()
print "Fonksiyon cagirilmadan once"
deneme(5)
print "Fonskiyon cagirildiktan sonra"
Gördüğünüz gibi program pdb satırına gelene kadar normal bir şekilde yorumlandı ve o satıra geldikten sonra bizi pdb kabuğuna düşürdü. Debug işlemi için yapmamız gereken bu kadar. Şimdi Pdb kabuğuna düştükten sonra neler yapabileceğimize bakalım. Daha önceden dikkatinizi çeti ise l ifadesini kullandım.
  • l(ist) : Yazdığımız kodu listelememizi sağlar.
  • w(here) : Programın olduğu satırı yazar.
  • c(ontinue : Programın kaldığı yerden yorumlanmaya devam etmesini sağlar.
  • b(reak) SatirNumarasi : Satır Numarasına Break Point koyar.
  • tbreak SatirNumarasi : Geçici olarak break point koyar. Birinci işlemden sonra break point silinir.
  • q(uit) : Debug işleminden çıkar.
  • c(lear) : Break pointleri temizlemek için kullanılır. Sorulan soruya y(es) cevabı verilirse break pointler silinir.
  • commands BreakPointNumarasi Girilen Break Point numarasına gidilirken istenilen komutlarında çalışmasını sağlar. Kullanılışı şu şekildedir. Command'ten çıkmak için end ifadesi kullanılır.
  • s(tep) : Bir sonraki satıra geçer.
  • n(ext) : Bir sonraki satıra geçer.
  • İkisi arasındaki fark; Step ile bir fonksiyona girildiği zaman adım adım işlerken n(ext) fonksiyonu işler ve çıkar.
  • j(ump) SatirNumarasi : Yazılan satır numarasına atlar.
  • a(rgs) : Varsayılan fonksiyonun argümanlarını verir.
  • p a : a değişkenin değerini ekrana yazdırır.
  • run : Debug edilen programı yeniden başlatır.

9 Mart 2015 Pazartesi

Django Virtualenv, Gunicorn, Nginx ve Supervisor

Merhabalar bu yazıda bir Virtualenv oluşturmayı, ardından oluşturduğumuz Virtualenv içerisinde bir django projesi oluşturmayı, oluşturmuş olduğumuz bu projemizi nasıl Gunicorn üzerinde koşturacağımızı. Koşturduğumuz bu projemizi Nginx ile nasıl konuşturacağımızı ve en son olarak Gunicorn'u yönetim işlemini nasıl Supervisor'a devredeceğimizden bahsedeceğiz.
Yazımıza geçmeden önce şu komutları sırası ile çalıştırarak sistemimiz güncelleyelim.
sudo apt-get update
sudo apt-get upgrade
Python Virtualenv
Pyton Virtualenv bize özel bir python çalışma alanı yaratır. Ve yüklediğimiz kütüphaneler sadece bu alana yüklenerek sistemin genelini etkilemez. Yaptığımız kurulumların sadece burada geçerli olmasını sağlıyoruz. Bunun ne gibi avantajları var derseniz. En basitinden tek bir sistem altında farklı Django sürümleri ile 1.6 ve 1.7 gibi geliştirilmiş projeleri rahat bir şekilde yayınlayabilirsiniz. İlk önce şu komutu vererek Virtualenv'yi sistemimize kuruyoruz.
sudo apt-get install python-virtualenv
Kurulum ardından kendimize özel bir Virtualenv oluşturalım.
virtualenv django-virt
Oluşturma işleminin ardından dizin içerisini inceleyebilirsiniz. Oluşturduğumuz dizin içerisine girelim ve aktif edelim.
cd django-virt/
source bin/activate
Bu işlemden sonra komut satırının başının değiştiğini göreceksiniz. Artık kuracağımız kütüphaneler bu virtualenv içerisine kurulacaktır.
(django-virt)massumo@ubuntu:~/django/django-virt$
Django Kurulumu
(django-virt)massumo@ubuntu:~/django/django-virt$ pip install django
komutunu çalıştırarak djangoyu oluşturmuş olduğumuz sanal çalışma alanımıza kuruyoruz.
Nginx Kurulumu
Sistemimize Nginx'i kuralım. Bunun için ilk önce aşağıdaki komutu çalıştırarak virtualenv içerisinden çıkalım. Ardından Nginx kurulumu için gerekli olan komutu verelim.
(django-virt)massumo@ubuntu:~/django/django-virt$ deactivate
sudo apt-get install nginx
Gunicorn Kurulumu
Gunicorn çok güçlü bir Python WSGI HTTP Server'dır. Şimdi tekrar virtualenv içerisine girerek Gunicorn'u kuracağız.
$ source bin/activate
(django-virt)massumo@ubuntu:~/django/django-virt$ pip install gunicorn
Django Projesi Oluşturmak
Gunicornu başarılı bir şekilde kurduktan sonra django projesi oluşturabiliriz.
(django-virt)massumo@ubuntu:~/django/django-virt$ django-admin.py startproject django_project
(django-virt)massumo@ubuntu:~/django/django-virt$ cd django_project
(django-virt)massumo@ubuntu:~/django/django-virt/django_project$ python manage.py runserver
Not : Burada komut satırlarının tamamını yazmamın sebebi sizin o an bulunduğumuz dizini ve çalışma alanınızı takip edebilmenizi kolaylaştırmaktır.
Projemiz başarılı bir şekilde ayağa kalktı. Şimdi projeyi Gunicorn ile ayağa kaldıralım.
(django-virt)massumo@ubuntu:~/django/django-virt/django_project$ gunicorn_django --workers=3 --bind localhost:8000
Eğer oluşturduğunuz django projesi 1.7 ve üzeri ise bu komutu çalıştırdığınız da şu şekilde bir hata alacaksınız.
...
    from django.core.management.validation import get_validation_errors
ImportError: No module named validation
Bu hatanın sebebi Django 1.7ile itibaren bazı sınıfların kaldırılması veya yerlerinin değiştirilmesi. Burada da aynı sorun söz konusu. Bu hatanın ortadan kalkması için yapmanız gereken virtualenv içerisine kurmuş olduğumuz gunicorn içerisindeki django_wsgi.py dosyasını düzenlemek. Bu dosyayı şuradan açın
/django-virt/lib/python2.7/site-packages/gunicorn/app/
Bu dizin altındaki django_wsgi.py dosyasını açın ve eski halinden yeni haline getirin.
##Eski hali 
...
##Bu satiri silin
from django.core.management.validation import get_validation_errors
...
def make_wsgi_application():
    # validate models
    s = StringIO()
    if get_validation_errors(s):
        s.seek(0)
        error = s.read()
        msg = "One or more models did not validate:\n%s" % error
        print(msg, file=sys.stderr)
        sys.stderr.flush()
        sys.exit(1)

    translation.activate(settings.LANGUAGE_CODE)
    if django14:
        return get_internal_wsgi_application()
    return WSGIHandler()
...

##Yeni Hali
...
def make_wsgi_application():
    # validate models
    s = StringIO()
    import django
    from django.core.management.base import BaseCommand
    django.setup()
    cmd = BaseCommand()
    import sys
    cmd.stdout, cmd.stderr = sys.stdout, sys.stderr
    cmd.check()
    translation.activate(settings.LANGUAGE_CODE)
    if django14:
        return get_internal_wsgi_application()
    return WSGIHandler()
...
Bu düzeltme işlemini yaptıktan sonra aynı komutu tekrar çalıştırıyoruz.
(django-virt)massumo@ubuntu:~/django/django-virt/django_project$ gunicorn_django --workers=3 --bind localhost:8000
Şimdi hatasız bir şekilde çalıştı. Tarayıcıdan localhost:8000 yazarak çalıştığını görebilirsiniz. Buradaki workers değerini değiştirebilirsiniz. Şimdi gunicorn için bir config dosyası için bir dosya oluşturalım. Ardından ayarlarımızı bu dosya içerisine yazarak bu dosya üzerinden projemizi koşturalım. Virtualenv'nin ana dizinine gunicorn_config.py adında bir dosya oluşturuyoruz ve içerisine şu satırları ekliyoruz.
command = '/home/massumo/django/django-virt/bin/gunicorn'
pythonpath = '/home/massumo/django/django-virt/django_project'
bind = '127.0.0.1:8000'
workers = 3
Bunun ardından bu dosya üzerinden projemizi şu şekilde çalıştırıyoruz.
(django-virt)massumo@ubuntu:~/django/django-virt$ gunicorn -c gunicorn_config.py django_project.wsgi
Projemiz sıkıntısız bir şekilde çalıştı.
Nginx Ayarlamaları
Nginx'i daha önce kurmuştuk. Şimdi ayarlamalarını yaparak projemizi Nginx üzerinde koşturacağız. İlk önce Nginx'i başlatalım.
#service nginx start
Daha sonra /etc/nginx/sites-available dizini içerisine girerek bir conf dosyası oluşturuyoruz.
#####Dosya adı 'myproject'
server {
        server_name localhost;
        access_log off;
 listen 80;
        location /static/ {
                alias /home/massumo/django-virt/django_project/static/;
        }

        location / {
                proxy_pass http://127.0.0.1:8000;
                proxy_set_header X-Forwarded-Host $server_name;
                proxy_set_header X-Real-IP $remote_addr;
                add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"';
        }
}
Burada dikkatinizi çekmiştir. Nginx bizim Gunicorn ile 8000 portta ayağa kaldırdığımız projeyi dinliyor. Eğer siz az önce komut satırından çalıştırdığımız projeyi CTRL+C vb bir işlem kapattıysanız. Nginx aracılığı ile projeyi koşturamazsınız. O yüzden onu kapatmadan başka bir terminal açarak bu işlemleri yapın. Yani burada nginx bir nevi tünelleme görevi görüyor. Bizim Gunicorn ile ayağa kaldırdığımız projeyi dinleyerek kullanıcıya gösteriyor. Şimdi işlemlerimize devam edelim.
Oluşturduğumuz config dosyasını /etc/nginx/sites-available dizini içerisinde oluşturduk. Oysa nginx ana config dosyası içerisinde aktarma işlemi yaparken /etc/nginx/sites-enabled dizini içerisindeki dosyaları aktarır. Bunu /etc/nginx/nginx.conf dosyasını inceleyerek görebilirsiniz. Bizde bundan dolayı oluşturduğumuz dosyayı ../sites-enabled dizini içerisine linkleyeceğiz. Bunun için siz de şu komutu çalıştırın.
massumo@ubuntu:/etc/nginx/sites-available$ sudo ln myproject ../sites-enabled/myproject
$sudo service nginx restart
Tarayıcıdan localhost yazarsanız projenin çalıştığını görebilirsiniz. Eğer bir hata oluşursa işlemlerinizi kontrol edin.
Supervisor Kurulumu ve Ayarlamaları
Buraya kadar projemizi gunicorn aracılığı ile nginx üzerinde koşturduk. Ama sizde fark etmişsinizdir ki burada bir eksik var. Projemizi terminalde gunicorn üzerinden şu komutla çalıştırmamız gerekiyor ki nginx üzerinden erişilebilsin.
/django-virt$ gunicorn -c gunicorn_config.py django_project.wsgi
Yani bizim bunun kontrolünü sürekli takip etmemiz gerekiyor. Eğer bilgisayarı kapatıp açarsak bu işlemi tekrar yapmamız gerekiyor. İşte bu kontrolleri bizim yerimize Supervisor yapacak. İlk önce kuralım. Virtaulenv içerisinden çıktıktan sonra şu komutu çaıştırın.
sudo apt-get install supervisor
Kurulumu yaptıktan sonra /etc/supervisor/conf.d dizinin açıyoruz ve config dosyası oluşturuyoruz.
##dosya adı 'django_project.conf'

[program:project]
command = /home/massumo/django/django-virt/bin/gunicorn -c /home/massumo/django/django-virt/gunicorn_config.py django_project.wsgi
Config dosyasını Supervisor'a göstermek için şu komutları sırası ile çalıştırın.
sudo supervisorctl reread
sudo supervisorctl update
İşlemlerimiz başarılı bir şekilde gerçekleşti. Artık tarayıcıdan gelerek gunicorn komutunu çalıştırmamıza gerek yok. Supervisor bu işlemi bizim için halledecek. Şuan bilgisayarınızı yeniden başlatsanız bile Nginx üzerinde koşan bir uygulama olması gerekmektedir. Tarayıcıdan http://localhost yazarak ulaşabilirsiniz.

23 Ocak 2015 Cuma

Django Admin Panel Resim Thumbnail

Django'da model içerisinde imagefield kullandığınız zaman admin panelinde form içerisinde bu resmi göremiyoruz. Sadece resmin adı görünmektedir. Bu yazıda bu resmi küçük bir şekilde nasıl görebiliriz ondan bahsedeceğiz. İlk önce model oluşturalım.
#models.py
from django.db import models

class Image(models.Model):
    name = models.CharField(max_length=255)
    image = models.ImageField(upload_to="image")

İlk önce listeleme sayfasında resimleri gösterelim. Bildiğiniz gibi admin sayfasında elemanları listelerken list_display özelliği ile istediğimiz alanları ve istediğimiz herhangi bir fonksiyondan dönen değeri yazdırabiliyoruz. Şimdi model içerisinde bir fonksiyon oluşrulım ve bu fonksiyon bize resmi döndürsün.
class Image(models.Model):
    name = models.CharField(max_length=255)
    image = models.ImageField(upload_to="image")

    def image_thumb(self):
        return '<img src="%s" height="200" width="300"/>' % (self.image.url)
    image_thumb.short_description = 'Resim'
    image_thumb.allow_tags = True
Daha sonra admin.py içerisine şu kodları yazıyoruz.
from django.contrib import admin

class ImageAdmin(admin.ModelAdmin):
    list_display = ['name', 'image_thumb']

admin.site.register(Image, ImageAdmin)
Artık model satıları listelenirken resimleri görebiliyoruz.
Bu işlemden sonra resmin içeriğini görmek için tıklarsanır şöyle bir çıktı alacaksınız.
Gördüğünüz gibi resim görünmemekte sadece resmin yolu görünmektedir. Şimdi burada da resmi gösterelim. Yapmamız gereken admin.py dosyasına şu kodları eklemek.
from django.contrib.admin.widgets import AdminFileWidget
from django.utils.safestring import mark_safe


class ImageWidget(AdminFileWidget):
    def render(self, name, value, attrs=None):
        output = []
        if value and hasattr(value, "url"):
            output.append(('<a target="_blank" href="%s">'
                           '<img src="%s" height="100" title="%s"/></a> '
                           % (value.url, value.url, value.name)))
        output.append(super(AdminFileWidget, self).render(name, value, attrs))
        return mark_safe(u''.join(output))
Burada özel bir widget ekliyoruz. Bu widget aldığı alan için bir geri değer döndürecek. Son olarak yapmamız gereken ise image alanımıza bu widgetı tanımlamak bunun için yine admin.py dosyasında az önce yazdığımız ImageAdmin sınıfını değiştirmek.
class ImageAdmin(admin.ModelAdmin):
    list_display = ['name', 'image_thumb']
    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'image':
            request = kwargs.pop("request", None)
            kwargs['widget'] = ImageWidget
            return db_field.formfield(**kwargs)
        return super(ImageAdmin, self).formfield_for_dbfield(db_field, **kwargs)


admin.site.register(Image, ImageAdmin)
Artık resmi düzenleme sayfasında da görebiliyoruz.
Siz burada kendinize göre biraz daha özelleştirebilirsiniz.

15 Ocak 2015 Perşembe

Django Google reCAPTCHA ve noCAPTCHA Kullanımı

Bu yazıda basit bir şekilde google'ın captcha uygulamalarını sitemize nasıl import edebileceğimizden bahsedeceğiz.
reCAPTCHA
İlk önce https://www.google.com/recaptcha/intro/index.html adresinden kendimiz için bir recaptcha oluşturuyoruz. Buradaki Get reCAPTCHA butonuna tıkladığınızda size Site key ve Secret key oluşturacaktır. Bunları projemizde kullanacağız.
Bu işlemi yaptıktan sonra https://github.com/praekelt/django-recaptcha adresinden uygulamayı indiriyoruz. İndirdikten sonra
cd Downloads/django-recaptcha-develop/
sudo python setup.py install
komutlarını sırası ile çalıştırıyoruz. Kurduktan sonra settings.py dosyasında INSTALLED_APPS değişkenine uygulamayı eklemeliyiz.
INSTALLED_APPS = (
.....
    'captcha',
)
Daha sonra şu satırları settings.py dosyasına ekliyoruz.
RECAPTCHA_PUBLIC_KEY = 'Googledan aldığınız Site Key'
RECAPTCHA_PRIVATE_KEY = 'Googledan aldığınız Secret Key'
RECAPTCHA_USE_SSL = True
Son satır reCAPTCHA'nın SSL kullanması ile ilgili. Eğer isterseniz bu satırı kaldırabilirsiniz. reCAPTCHA'yı kullanmak için artık her şey hazır. Şimdi basitçe kullanalım. İlk basit bir form oluşturuyoruz.
from django import forms
from captcha.fields import ReCaptchaField

class reCAPTCHAForm(forms.Form):
    captcha = ReCaptchaField()
Şimdi bu formu kullanalım. Basit bir view oluşturalım.
from django.shortcuts import render
from go.forms import reCAPTCHAForm
# Create your views here.
def go(request):
 if request.method == "POST":
     form = reCAPTCHAForm(request.POST)
     if form.is_valid():
  """ Form başarılı ise yapılacaklar """
 else:
     form = reCAPTCHAForm() 
 return render(request, 'index.html', locals())
Bu viewa ait olan index.html şablonun içeriği ise şu şekilde;
 
{% csrf_token %} {{ form }}
Artık kullanabilirsiniz. Ekran çıktımız şu şekilde olacaktır.


noCAPTCHA
noCAPTCHA'nın reCAPTCHA'dan neredeyse hiç bir farkı yok. Hemen ufak tefek değişikliklerden bahsedelim. Github sayfasını sizinle paylaşalım. https://github.com/ImaginaryLandscape/django-nocaptcha-recaptcha Bu sayfada kullanımı oldukça basit bir şekilde anlatılmış.
İlk önce kurulum yapıyoruz.
pip install django-nocaptcha-recaptcha
Daha sonra aynı şekilde INSTALLED_APPS'e ekliyoruz.
INSTALLED_APPS = (
....
    'nocaptcha_recaptcha',
)
settings.py dosyasına ayarlamaları ekliyoruz.
NORECAPTCHA_SITE_KEY = 'Googledan aldığınız Site Key'
NORECAPTCHA_SECRET_KEY = 'Googledan aldığınız Secret Key'
Form dosyasını şu şekilde değiştiriyoruz.
from django import forms
from nocaptcha_recaptcha.fields import NoReCaptchaField

class reCAPTCHAForm(forms.Form):
    captcha = NoReCaptchaField()
View dosyamız
from django.shortcuts import render
from go.forms import reCAPTCHAForm
# Create your views here.
def go(request):
 if request.method == "POST":
     form = reCAPTCHAForm(request.POST)
     if form.is_valid():
                """ Doğru ise yapılacaklar """
 else:
     form = reCAPTCHAForm() 
 return render(request, 'index.html', locals())
index.html şablon dosyamız


 
{% csrf_token %} {{ form }}
Burada dikkat etmeniz gereken ekstrandan Google'ın javascript dosyasını çağırıyor olmamız.

9 Ocak 2015 Cuma

Django hvad ile Model'de Çoklu Dil Desteği

Django ile uygulama yaparken bazen model dosyalarınızda çoklu dil desteği oluşturmak isteyebilirsiniz. 3.parti uygulama olarak hvad bunun için müthiş bir kolaylık sağlıyor. Uygulamanın github sayfasına buradan veya kendi dökümantasyonuna buradan ulaşabilirsiniz.
Biz bu yazıda basit bir örnek yaparak model dosyamızı nasıl çoklu dil desteği verebiliriz ve bunu web sitesinde seçim olarak nasıl gösterebiliriz buna bakacağız. İlk olarak basit bir şekilde uygulamayı kuralım.
pip install django-hvad
Ardında uygulamayı projemize dahil edelim.
INSTALLED_APPS = (
    ....
    'hvad',
)
Şimdi uygulamayı kullanabiliriz. İlk önce yapmamız gereken model oluşturmak. Model oluştururken bildiğiniz gibi djangonun kendi model sınıflarından kalıtım alıyoruz. Burada ise yapmamız gereken hvad uygulamasının sınıflarından kalıtım almak. Basit bir model oluşturalım.
from hvad.models import TranslatableModel, TranslatedFields,
class Images(TranslatableModel):
    image = models.ImageField()
    category = models.ForeignKey(Category)

    translations = TranslatedFields(
        title=models.CharField(max_length=200),
        description=models.TextField(),
    )

Burada gördüğünüz gibi bir model oluşturduk. Burada image alanı sabit olduğu için translation içerisine almadık sonuç olarak resim her zaman aynı. Ama title ve description alanları her dil için farklı olarak girilmesi gerektiğinden dolayı TraslatedField alanı içerisin aldık. Şimdi bu model oluşturduğumuza göre admin.py dosyası içerisinde ayarlamalarını yapmalıyız. admin.py dosyası şu şekilde olmalı.
from *.models import Images
from hvad.admin import TranslatableAdmin

class ImagesAdmin(TranslatableAdmin):
    def __init__(self, *args, **kwargs):
        super(ImagesAdmin, self).__init__(*args, **kwargs)
Bunları yaptıktan sonra admin sayfasından ekleme yapmaya çalışırsanız şu şekilde bir pencere ile karşılacaksınız.
Gördüğünüz gibi hemen hemen her dil için ekleme yapabiliyoruz. Burada TranslatedField alanı içerisine almadıklarımızı bir kere girmemiz yeterli aldıklarımızı için her dil için farklı olarak girmeliyiz. Burada bazı dilleri istemeyebilirsiniz. Bunun için istediğiniz dilleri şu şekilde settings.py dosyasına ekleyebilirsiniz.
LANGUAGES = (
    ('tr', 'Turkish'),
    ('en', 'English'),
)
Artık sadece Türkçe ve İngilizce sekmelerini göreceksiniz. Bu şekilde iki dile indirmiş olduk. Peki ekleme yaptıktan sonra bunları view dosyaları içerisinde dillere göre nasıl alacağız. Buda oldukça basit.
images = Images.objects.language('en').all()
Bu şekilde sadece ingilizce yazılan kısımlar gelecektir. Eğer siz bir kayıt eklerken sadece türkçe kısmını girer ve ingilizce kısmını boş bırakırsanız bu sorguda o kayıt gelmeyecektir. Burada language kısmı içerisini session değerinden çekerek kullanıcının seçtiği dile göre veritabanından sorgulama yapabilirsiniz. Bu yazıda çok basit bir şekilde hvad uygulamasının kullanımından bahsettik. Gerçekten de insanın işini çok kolaylaştıran bir uygulama. Daha fazla bilgiye kendi dökümantasyonundan oulaşabilirsiniz.
Kaynakça

10 Aralık 2014 Çarşamba

Numpy: Veri Dosyaları


Python programındaki anlık veriler fiziksel bellek üzerinde depolanır ve program sonlandırıldığında kaybolur. Bu yüzden verileri kalıcı hale getirmek ve daha önceden kaydedilmiş veri blokları programımızda kullanmak için dosyadan veri alışverişi yapma ihtiyacı duyarız. Veri dosya içerisinde yazılı metin olarak durduğundan biçimi, verinin nasıl okunup yazılmasını gerektiğini belirler. Bu bölümde Numpy kütüphanesinin dosya işlemleri için bize sunduğu fonksiyonlarıyla düzenli dosya okuyup yazmanın nasıl yapıldığını göreceğiz.

Hızlı okuyup yazma
Dizileri dosyaya yazdırmanın en basit yolu tofile komutunu kullanmaktır. Bu fonksiyon fiziksel hafızada depolandığı biçimiyle yani ikili(binary) olarak diziyi kaydeder. Bu yöntem hızlı olsa da veri dosyalarının taşınabilir olması istenen durumlar için tavsiye edilmez çünkü kayıt formatı mevcut donanıma ve işletim sistemine bağlıdır. Kaydedilen ikili dosyalar fromfile komutu ile okunabilir. 
>>> from numpy import *                      # Numpy kütühanesini ekliyoruz
>>> dizi = ndarray(shape(2,2), dtype='int')  # 2x2'li dizi oluşturup değer atıyoruz
>>> dizi[0,0] = 1; dizi[0,1] = 2; dizi[1,0] = 3; dizi[1,1] = 4;
>>> print(dizi)
[[1, 2]
[3, 4]]
>>> dizi.tofile('dizi.dat')
>>> dizi_kopya = fromfile('dizi.dat', dtype='int')
>>> print(dizi_kopya)
[1, 2, 3, 4]
dizi.dat dosyasını açmaya çalıştınızda ascii karakterlerden oluştuğunu göreceksiniz. Dosya ikili formatta olduğu için yalnızca yine Python kodu tarafından açılıp okunabilir. Ayrıca görüldüğü gibi dizimizin şekli korumayıp geri alındığında tek boyutlu dizi olarak elde edilmektedir. Bu sebeplerden ötürü kalıcı dosya kayıtları için yukarıda bu tip dosya okuyup yazma tercih edilmemektedir. Yerine daha işlevsel olan savetxt, loadtxt komutları kullanılır.

Metin biçiminde okuyup yazma
Metin veri dosyası istenilen biçimde şekillendirilebilir. Örneğin; birçok ölçüm cihazının yazılım arayüzü ölçüm değerlerini kaydettiği dosyada öncelikle ölçüme ait ortam parametrelerini verir ve ardından sütunlar halinde sonuçları sıralar. Başka bir örnek de HDF gibi yapısal veri dosya biçimleridir. Bu dosyalarda veri ait olduğu nesnenin sınıfın altında verilir. Benzer birçok örnek de verilebilir. İşte bu sebepten ötürü yazılımcılar genellikle farklı biçimleri de sorunsuzca okuyup yazmaya imkan tanıyacak fonksiyonlar ararlar. Python programlama dili, Numpy kütüphanesi sayesinde bize oldukça işlevsel olan loadtxt, savetxt komutlarını bize sunar.  İki komut benzer yapıda olup, adından da anlaşılacağı üzere biri dosyaya kaydetmeyi, diğeri de dosyadan veri okumayı sağlar. Öncelikle bir örnekle dizimizi farklı biçimlerde nasıl dosyaya yazdırabildiğimizi görelim ardından da bu dosyalardaki verileri okumaya çalışalım.
>>> dizi = random.radom(6)          # 6'lık dizi oluşturup rastgele değer atıyoruz
>>> matris = reshape(dizi, (3,2))   # diziyi matris biçiminde şekillendiriyoruz
>>> print(matris)                   # matrisi ekrana yazdırıyoruz
[[ 0.71822401, 0.59663587]
 [ 0.5858213 , 0.12121402]
 [ 0.32291168, 0.32205304]]
>>> # herbir iki sütun da farklı formatta olacak biçimde dosyaya yazdırıyoruz.
>>> savetxt('matris.txt', matris, fmt=['%.2','%.5f'], delimiter=',', newline='\n',\
... header='Dizi yazdiriliyor...', footer='Dizi yazdirildi.', comment='#')
Görüldüğü gibi tek bir komutla veri dosyamızdaki sütünların formatını belirleyip yorum satırları da ekleyerek yazdırabiliyoruz. Buradaki fmt veri sütunlarının formatını, delimiter sütunların hangi karakterle birbirinden ayrılacağını, newline satırların hangi karakterle ayrılacağını, header ve footer sırasıyla alt ve üst yorum cümlelerini, comment yorum cümlelerinin hangi karakterle başlayacağını belirtir. Şimdi dosyamız içindeki verilerin nasıl göründüğünü bakalım.
# Dizi yazdiriliyor...
0.72,0.59664
0.59,0.12121
0.32,0.32205
# Dizi yazdirildi.
Dosyamızı yazdırdıktan sonra benzer şekilde loadtxt komutu ile verileri otomatik olarak dizi nesnesine aktarabiliriz. Sadece değerler diziye aktarılacağı için yorum cümleleri göz ardı edilir.
>>> # matrisi geri al
>>> matris = loadtxt('matris.txt', dtype='float', comments='#', delimiter=',')
>>> print(matris)
[[0.72 0.59664]
 [0.59 0.12121]
 [0.32 0.32205]]
>>> # ilk iki sütunu ayrı ayrı dizilere al
>>> s1, s2 = loadtxt('matris.txt', dtype='float', comments='#', delimiter=','\
... usecols=(0,1), unpack=True) )
>>> print(s1)
[0.72 0.59 0.32]
>>> print(s2)
[0.59664 0.12121 0.32205]
Görüldüğü gibi Numpy kütüphanesinin sunduğu fonksiyonlar sayesinde verilerimizi; standart dosya açma, kapama işlemlerine ve döngü ile değerleri teker transfer etmeye gerek kalmadan kolayca okuyup yazabiliriz.

26 Ekim 2014 Pazar

Numpy: Matrisler ve Basit Lineer Cebir

Sayısal analiz kitaplarının muhtevasını incelediğinizde fark ederseniz; birçoğu ilk bölümlerde doğrusal denklem sistemleri yani lineer cebir konusunu ele alır. Lineer cebirin bu kadar önemli olmasının sebebi, sayısal hesaplamaların çoğunun nihayetinde matris ve vektörlerden oluşan  doğrusal denklemlere indirgeniyor olmasıdır. Derslerimizin şu ana kadar ki kısımlarında genel olarak tek boyutlu vektörlerden bahsettik. Şimdi matrisleri biraz ayrıntılı irdeleyip Numpy kütüphanesini kullanarak temel lineer cebir işlemleri nasıl yapabileceğimiz öğrenelim.  
Matrisler
Matrisleri vektörler gibi oluşturabiliriz. Ancak matrislere özgü fonksiyonlar da mevcuttur. Bunları eye, identity, diag fonskiyonları olarak sıralayabiliriz. eye, identity fonksiyonları birbirine çok benzer olup birim matris oluşturmaya yarar.
>>> from numpy import *    # Numpy kütüphanesini ön alan adı eki olmadan ekliyoruz
>>> print(identity(3))     # birim köşegen matris
[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]]
>>> print(eye(3))          # birim köşegen matris
[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]]
>>> print(eye(3, k=1))     # köşegenin bir üst çapraza birim vektör ekleme 
[[ 0.  1.  0.]
 [ 0.  0.  1.]
 [ 0.  0.  0.]]
>>> print(eye(3, k=-2))    # köşegenin iki alt çapraza birim vektör ekleme 
[[ 0.  0.  0.]
 [ 0.  0.  0.]
 [ 1.  0.  0.]]
diag ise oldukça işlevsel bir fonksiyondur ve girilen bir vektörden köşegen matris oluşturur. Bu komut sayesinde aynı zamanda bant matrisleri de çok kolay oluşturabiliriz.
>>> print(diag([2,3,4], k=0))       # [2,3,4] dizisinden köşegen matris
[[2 0 0]
 [0 3 0]
 [0 0 4]]
>>> print(diag([2,3,4], k=1))       # aynı diziden bir üst köşegen matris
[[0 2 0 0]
 [0 0 3 0]
 [0 0 0 4]
 [0 0 0 0]]
>>>
>>> # üçlü bant matris oluşturma
>>> print(diag(ones(4),k=-1) + diag(2*ones(5),k=0) + diag(ones(4), k=1))
[[ 2.  1.  0.  0.  0.]
 [ 1.  2.  1.  0.  0.]
 [ 0.  1.  2.  1.  0.]
 [ 0.  0.  1.  2.  1.]
 [ 0.  0.  0.  1.  2.]]

Lineer Cebire Giriş
Lineer cebir temel olarak matrislerin özelliklerini ve tek boyutlu vektörlerle olan işlemlerinin halidir. En genel halde bir lineer cebrik sistem A matris x ve b tek boyutlu vektör olmak üzere Ax=b şeklinde bir forma sahiptir. Bu sistemin çözülebilmesi için gerekli olan temel işleçler çarpım ve bölme işlemleridir. Matris-matris, matris-vektör çarpma/bölme işlemi bir önceki yazımızda anlattığımız vektörel aritmetikten farklı olup birebir elemanların çarpımı veya bölümüyle yapılmaz. O yüzden Numpy'de bu amaçla hususi fonksiyonlar tanımlanmıştır. Farkı anlamak için aşağıdaki örneklere göz atalım.
>>> A = ones((4,4))    # 1'lerden oluşan matris
>>> x = ones(4)        # 1'lerden oluşan vektör
>>> b = A*x            # matrisin her bir sütununun x ile vektörel çarpımı
>>> print(b)
[[ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]]
>>> b = dot(A,x)      # lineer cebir çarpımı
>>> print(b)
[ 4.  4.  4.  4.]
Görüldüğü gibi ' operatörü bizim istediğimiz manada lineer cebir çarpımını değil vektörel formdaki çarpım işlevini yerini getirir. Bu yüzden Numpy'de matris-vektör çarpımı için dot fonksiyonu tanımlanmıştır. Benzer şekilde lineer cebrik sistemin çözümü için bölme işlemine yani x=b/A ifadesini hesaplayabilmemiz lazım. Bu işlem için yine direkt bölme operatörünü kullanmak yerine linalg alt kütüphanesi içerisindeki inv komutuyla matrisin tersini bulup b vektörüyle çarpabiliriz. 
>>> A = random.random((4,4))     # rastgele kare A matrisi
>>> print(A)
[[ 0.69769186  0.79776825  0.09984681  0.21271922]
 [ 0.05979394  0.72758335  0.0570817   0.59825989]
 [ 0.61698744  0.29374527  0.82004994  0.41084264]
 [ 0.02961924  0.86964469  0.63311203  0.82975882]]
>>> b = random.random(4)         # rastgele b vektörü
>>> print(b)
[ 0.20801453  0.81169016  0.84603751  0.74985329]<
>>>
>>> x = dot(linalg.inv(A), b)    # Ax=b çözümü olarak x=A^-1*b
>>> print(dot(A,x))              # bulduğumuz çözümün sağlamasını yapıyoruz (Ax=b) 
[ 0.20801453  0.81169016  0.84603751  0.74985329]
Lineer sistemin çözümünü yukarıdaki gibi tersini alıp çarpmayla uğraşmak yerine linalg.solve komutunu kullanarak kısa yoldan gerçekleştirebiliriz.
>>> x = linalg.solve(A,b)
>>> print(dot(A,x))       # yine sağlamasını yapıp A*x=b olduğunu kontrol ediyoruz
[ 0.20801453  0.81169016  0.84603751  0.74985329]
Üniversitede lineer cebir almış olanlar bilirler matrisin determinantı ve öz değer/vektörlerini kağı kalemle bulmak oldukça meşakkatlidir. Numpy'nin lineer cebir paketi sayesinde tek bir komutla bu işlemlerimizi basitçe halledebiliriz.
>>> A = diag([2,3,4], k=0)
>>> print(A)             # köşegen A matrisi
[[2 0 0]
 [0 3 0]
 [0 0 4]]
>>> print(linalg.det(A)) # determinantı
24.0
>>> l, v = linalg.eig(A) # eig komutu öz değer ve öz vektörden oluşan iki döndürür
>>> print(l)             # öz değerler
[ 2.  3.  4.]
>>> print(v)             # öz vektörler yazdırılan matrisin sütunlarıdır
[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]]
Oldukça geniş bir konu lineer cebrik sistemlere ilişkin yazımızı, Scipy kütüphanesinin konuları arasında daha fazla değinmek üzere şimdilik bitiriyoruz.

21 Ekim 2014 Salı

Django Purge Pagination

Django'da sayfalama için kullanabileceğimiz uygulama olan purge-pagination'dan bahsedeceğiz. Django'nun sayfalama yapısı bizim tam olarak işimizi görmediği için bu sayfalama uygulamasını kullanabiliriz. Genelde sayfa sayısının çok fazla olduğu yerlerde tüm sayfalar gösterilmektense baştan bir kaç sayfa bulunulan sayfa ve sondan bir kaç sayfa gösterilerek güzel bir görüntü oluşması sağlanır. Purge Pagination bu işi halletmemizi sağlıyor. Kurmak için
pip install django-pure-pagination
Uygulamayı kurduktan sonra projemize eklememiz gerekiyor. Bunun için;
INSTALLED_APPS = (
    ...
    'pure_pagination',
)
Uygulamayı yükledikten sonra settings.py içerisinde ayarlamalarını yapabiliriz.
PAGINATION_SETTINGS = {
    'PAGE_RANGE_DISPLAYED': 10,
    'MARGIN_PAGES_DISPLAYED': 2,
}
Buradaki PAGE_RANGE_DISPLAYED ayarı ortada kaç tane sayfa göstericeğini belirtiyor. MARGIN_PAGES_DISPLAYED ise başta ve sonra kaç sayfa olacağını gösteriyor. Yani sayfalama başta 2 sayfa...ortada 10 sayfa...sonda 2 sayfa şeklinde olacak.
Uygulamayı eklediğimize göre kullanabiliriz. Django'nun kendi Pagination yapısı ile kullanımı hemen hemen aynı. Django'da Pagination metodlarınışu şekilde yürklüyoruz.
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
Purge Pagination'da ise sadece uygulama değişiyor. Metodlar ve kullanımları aynı.
from pure_pagination import Paginator, EmptyPage, PageNotAnInteger
View içerisinde şu şekilde kullanabiliriz.
tum_yazilar = Yazilar.objects.filter(onay=1)
yazi_sayfalari = Paginator(tum_yazilar, 10, request=request) 
yazilar = yazi_sayfalari.page(page)
Son olarak ise template içerisinde sayfaları şu şekilde gösterebiliriz.
        {% if yazilar.has_previous or yazilar.has_next %}
            {% load i18n %}
            
    {% if yazilar.has_previous %}
  • {% else %}
  • ‹‹
  • {% endif %} {% for page in yazilar.pages %} {% if page %} {% ifequal page yazilar.number %}
  • {{ page }}
  • {% else %}
  • {{ page }}
  • {% endifequal %} {% else %}
  • ...
  • {% endif %} {% endfor %} {% if yazilar.has_next %}
  • {% else %}
  • ››
  • {% endif %}
{% endif %}
Artık sayfalamamız şuna benzer bir şekilde görünecektir. Sizin temanıza göre stili değişir. Fakat sayfa sayısı bu şekilde olacaktır. Burada resmi uygulamanın github hesabından aldık.
Kaynakça

6 Ekim 2014 Pazartesi

Numpy: Vektörleştirme ve Dilimleme


Bilimsel hesaplamalarda ekseriyetle büyük veri kümeleri üzerinden işlem yapılır. Klasik programlamada, bu türden hesaplamalar liste halindeki sayısal değerlerin döngü içerisinde birer birer çağrılmasıyla yapılır. Ancak günümüzde ise mümkün mertebe döngü kullanımından kaçınılmaktadır. Hatta büyük firmalar tarafından bu amaca yönelik optimize edilmiş program arayüzleri ve kütüphaneler ticari olarak geliştirilmektedir (Matlab, Intel MKL). Bu yazımızda da Python'un Numpy kütüphanesi sayesinde dizi halindeki sayısal veriler üzerinden nasıl hızlı ve basit işlemlerimizi gerçekleştirebileceğimizden bahsedeceğiz. 

Vektörleştirme

Girişte de bahsettiğimiz gibi bir matematiksel işlemi çoğunlukla dizi halindeki verinin tüm elemanları üzerinden gerçekleştirmek isteriz. Bu durumda işlemi for döngüsü içerisinde dizinin herbir elemanı için teker teker yapmak yerine Numpy kütüphanesi sayesinde tek değer üzerinden işlem yapıyormuş gibi gerçekleştirebiliriz. Şimdi aşağıdaki örnekte, polinom ve trigonometri ifadeleri içeren bir hesaplamayı hem döngü ile hem de vektörel formda yapıp karşılaştıralım.
>>> import time as tm   # süre tutma için gerekli olan modül
>>> import numpy as np  # Numpy kütüphanesi 'np' ön adıyla ekliyoruz
>>>
>>> N = 10000               # dizinin eleman uzunluğu
>>> x = np.random.random(N) # argüman dizisi
>>> y = np.zeros_like(x)    # sonuç dizisi
>>> 
>>> t0 = tm.clock()         # kronometre başlangıcı
>>> 
>>> # döngü ile hesap
>>> for i in np.arange(N):
...     y[i] = x[i]**2 + 3*x[i] - x[i]/5 + np.sin(x[i])
>>> t1 = tm.clock()
>>> 
>>> # vektörel hesap
>>> y = x**2 + 3*x - x/5 + np.sin(x)
>>> t2 = tm.clock()
>>> 
>>> print("Döngü ile hesaplama: %5.2f ms" %((t1-t0)*1E3))
>>> print("Vektörel hesaplama: %5.2f ms" %((t2-t1)*1E3))
Döngü ile hesaplama: 106.15 ms
Vektörel hesaplama:  0.67 ms
Görüldüğü gibi vektörel hesaplamayla basit bir hesaplamada bile en az 100 kat daha hızlı işlem yapılabilmektedir. Ayrıca kod metnimiz daha sade ve anlaşılır hale gelmiştir.
Numpy kendi dizi yapıları için temel aritmetik işlemleri (+,-,x,/) ve standart math/cmath kütüphanelerindeki fonksiyonları vektörel formda sağlamaktadır. Eğer harici fonksiyonlar da aynı verimlilikle hesap yapabilmek için vektörleştirmek istenirse bu, vectorize fonksiyonu kullanarak sağlanabilir. 
>>> from math import sqrt           # standart kütüphanedeki kök alma fonksiyonu
>>> def afunc(x):
...    if x<0:
...        return sqrt(-x) + x**2
...    else:
...        return sqrt(x) + x**2
>>> 
>>> afunc_v = np.vectorize(afunc)   # fonksiyonu vektörel hale getiriyoruz
>>> 
>>> N = 10000                       # dizinin eleman uzunluğu
>>> x = np.random.uniform(-1,+1,N)  # argüman dizisi
>>> y = np.zeros_like(x)            # sonuç dizisi
>>> 
>>> t0 = tm.clock()                 # kronometre başlangıcı
>>> 
>>> # döngü ile hesap
>>> for i in np.arange(N):
...    y[i] = afunc(x[i])
>>> t1 = tm.clock()
>>> 
>>> # vektörel hesap
>>> y = afunc_v(x)
>>> t2 = tm.clock()
>>> 
>>> print("Döngü ile hesaplama: %5.2f ms" %((t1-t0)*1E3))
>>> print("Vektörel hesaplama: %5.2f ms" %((t2-t1)*1E3))
Döngü ile hesaplama: 45.30 ms
Vektörel hesaplama:  10.99 ms
Eğer harici fonksiyonumuz sadece temel aritmetik işleçler ve standart kütüphanedeki fonksiyonları içeriyorsa yukarıdaki gibi vektörleştirmeye gerek kalmadan fonksiyonun direk kendisiyle çalışılabilir.

Dilimleme
Önceki konu başlığında tüm dizi elemanları üzerinden nasıl hızlı işlem yapabileceğimizden bahsettik. Ancak bazı durumlarda dizinin tamamıyla değil de belli kısımlarıyla işlem yapmak isteyebiliriz. Mesela; dizinin yarıdan sonrası, çift indisli elemanları gibi... Dilimleme operatörü de işte dizilerdeki elemanlara bu açıdan erişmemizi sağlar. Kullanılışı köşeli parantez içerisindeki iki nokta üst üste işaretleriyle sağlanır [ilk:son:adım]. Parantez içerisindeki tüm değerler tam sayı olmalıdır. Python'daki standart indisleme kuralları geçerlidir. Yani; son indisteki değer aralığa dahil değildir ve adım aralığı geriye doğru ilerlemek için negatif değer alabilir. Aşağıdaki kısa örneklerle kullanışını açıklamaya çalışalım.
>>> N = 10
>>> dizi = np.arange(N, dtype='int')
>>> print(dizi[::])         # dizinin tüm elemanları
[0 1 2 3 4 5 6 7 8 9]
>>> print(dizi[0:N/2:2])    # dizinin yarısına kadar 2'şer aralıklarla
[0 2 4]
>>> print(dizi[::-1])       # tersten geriye doğru birer adımlama
[9 8 7 6 5 4 3 2 1 0]
Dilimleme tekniği özellikle iteratif işlem gerektiren algoritmaların programlanmasında çok önemlidir. Şimdi bize nasıl bir kolaylık sağladığını iyice görmek açısından gerçekçi bir örnek yapalım. Bilindiği gibi analitik türevi mümkün olmayan fonksiyonların ilgili aralıktaki örnek değerleri üzerinden sayısal türevi sonlu farklar yöntemiyle belli doğrulukta hesaplanabilmektedir. Algortimayla alakalı detaylı bilgiyi http://tr.wikipedia.org/wiki/Sonlu_fark referansına bırakıp nasıl kodlandığına bakalım. Karşılaştırmayı mümkün kılmak için analitik türevini bildiğimiz sin fonksiyonunun türevini sayısal olarak üç farklı sonlu fark formülüyle aşağıdaki gibi hesaplıyoruz.
>>> # adım aralığı bilgisini de alacak şekilde eş aralıklı örnekleme
>>> N = 10  # örnekleme sayısı
>>> x, dx = np.linspace(0,+np.pi,N,retstep=True) # [0,+pi]
>>> 
>>> # test fonksiyonu ve analitik türevi
>>> y = np.sin(x)
>>> yp_analitik = np.cos(x)
>>> 
>>> # sonlu farklar
>>> yp_merkezi = ( y[2:N]-y[0:N-2] )/(2*dx) # merkezi fark
>>> yp_ileri = ( y[1:N]-y[0:N-1] )/dx       # ileri fark
>>> yp_geri = ( y[1:N]-y[0:N-1] )/dx        # geri fark
Görüldüğü gibi her bir sonlu fark hesabını dilimleme operatörü sayesinde birer satırda gerçekleştirebildik. Not olarak belirtmek gerekir ki, ileri ve geri fark ifadeleri birbirine eşit görünmekle birlikte açı dizisinde (x) karşılık geldiği noktalar farklıdır.
Yazımızı, bulduğumuz sonuçları görselleştirip, çıktılarını inceleyerek bitirelim. Aşağıdaki kodda Matplotlib kütüphanesi kullanılarak analitik türevle birlikte sayısal türevler tek bir grafik üzerinde gösterilmek istenmiştir. İleri ve geri fark sonuçları ise birbirleriyle benzer hata oranıyla analitik değere iyi bir biçimde yakınsamaktadır. Ancak beklediğimiz gibi, merkezi fark yöntemiyle hesaplanan türev diğer ikisinden daha az yanılmayla sonuca yaklaşmıştır. Örnekleme sayısını arttıracak olsaydık sayısal türev değerleri giderek daha fazla analitik değere benzeyecek, grafik eğrileri üzerinde ayırt edilemez hale gelecekti.
>>> import matplotlib.pyplot as plt # matplotlib kütüphanesini çizdiricisi
>>> 
>>> fig = plt.figure()              # yeni grafik ekranı
>>> 
>>> plt.plot(x,yp_analitik, color='blue', label='analitik')
>>> plt.plot(x[1:N-1],yp_merkezi, color='red', label='merkezi')
>>> plt.plot(x[0:N-1],yp_ileri, color='yellow', label='ileri')
>>> plt.plot(x[1:N],yp_geri, color='green', label='geri')
>>> plt.legend(loc='upper right')
>>> plt.title('Sinüs Fonksiyonunun Türevi')
>>> plt.xlabel('x')
>>> plt.ylabel('y\'(x)')
>>> plt.grid()
>>> plt.xlim(0,+np.pi)
>>> plt.ylim(-1,1)
>>> plt.show()

Kaynaklar:
[1] Langtangen H. P., Python Scripting for Computational Science, Springer, 2007