YZ01: Derin Öğrenme ile Resimdeki Objeyi Tanıma

YZ00: Yapay Zeka’ya Giriş

YZ01: Derin Öğrenme ile Resimdeki Objeyi Tanıma

Merhabalar. Bu yazıda görüntü işleme alanında sıklıkla kullanılan derin öğrenme (deep learning) algoritmalarından biri olan Konvolüsyon Nöral Ağı -bilinen adıyla Convolutional Neural Network (CNN)- ile bir resimde kedi mi köpek mi olduğunu anlayacak bir yapay zeka algoritmasını geliştirecek ve test edeceğiz. Bu ağdan yazının ilerleyen satırlarında CNN olarak bahsedeceğim.

Bir otonom insansız araç yapacak olsaydık, üreteceğimiz aracın etrafındaki nesneleri algılamasını isterdik. Bir resme bakmak, görmek ve algılamak arasında çok vardır. Bizim istediğimiz şey bilgisayarın görmesi ve algılamasıdır. Algılanmasını isteyeceğiniz şeylerden bir tanesi de sokaklarda yaşayan kedi ve köpeklerdir. Neden mi? Çünkü her iki hayvanın da farklı refleksleri vardır. Mesela kediler daha ürkek hayvanlardır. Eğer kamera ile videosunu ya da fotoğrafını çektiğimiz hayvanın hangisi olduğunu tespit edebilirsek ona göre arabanın uygun bir manevra yapmasını sağlayabiliriz.

Otobanda köpeklerin ezildiğine maalesef şahit olmuşsunuzdur. Sanıyorum ürkek oldukları için kediler otobanda karşıdan karşıya geçmeye pek çalışmıyorlar. Amacımız üreteceğimiz arabanın kedi mi köpek mi olduğunu tespit ederek, hem sokak hayvanlarına çarpmamak hem de aracımızın zarar görmesini engellemek.

Avustralya’da hayvanların karıştığı kazaların %80’i kangurular nedeniyle oluyormuş. Volvo firması da Avustralya’da kullanılmak üzere üreteceği sürücüsüz aracın kesinlikle kanguruları tespit etmesi gerektiğini düşünerek 2015 yılından beri kanguruları tespit edebilmek için resim ve video topluyor. [1]

Öncelikle belirteyim ki yaptığım tüm uygulamaların kodlarına GitHub’tan ulaşabilirsiniz. Kodları geliştirmeye ve iyileştirmeye yönelik fikirleriniz varsa buradan ya da GitHub’dan bildirebilirsiniz. Kodların anlaşılır olduğunu düşünüyorum. Zira olabildiğince açıklama eklemeye çalıştım. Hem bu yazıda hem de kodlarda anlaşılmayan bir şey olursa sormaktan çekinmeyin lütfen. Her türlü olumlu ya da olumsuz fikrinizi duymaktan memnun olurum. Tek isteğim olumsuz fikriniz varsa lütfen çözüm önerinizi de yazın.

GitHub’da Yapay Bot: https://github.com/yapaybot

Hadi başlayalım.

1. Adım: Verileri İndirme

Microsoft tarafından kullanıma sunulan kedi köpek fotoğrafları veritabanında 25 BİN’i (12.5 BİN kedi ve 12.5 BİN köpek) eğitim için ve 12.5 BİN’i test için olmak üzere 37.5 BİN kedi-köpek fotoğrafı bulunmaktadır.

İlk önce yapay zeka uygulamalarında kullanabileceğimiz çok çeşitli verisetlerinin bulunduğu Kaggle (https://www.kaggle.com/c/dogs-vs-cats) isimli siteden fotoğrafları indirelim. Önce Data sekmesine sonra da test1.zip ve train.zip linklerine tıklayarak ve Download butonuna basarak dosyaları indiriyoruz. Dosya adlarından da anlaşılacağı üzere 543 MB boyutundaki train.zip içerisindeki fotoğrafları ağımızı eğitmek için, 271 MB boyutundaki test1.zip içerisindeki fotoğrafları oluşturduğumuz modeli test etmek için kullanacağız. İndirdiğimiz her iki zip dosyasını da bir klasörde zip’ten çıkarıyoruz.

GitHub’tan indireceğimiz kedikopek.py dosyasının “train” ve “test”klasörleri ile aynı klasörde olmasına dikkat ediyoruz. Nihai olarak klasör yapısı yandaki gibi olmalıdır.

2. Adım: Kullanılacak Algoritmanın Belirlenmesi 

Başarı her zaman ayrıntıda gizlidir. Bir resimdeki tüm ayrıntılara dikkat etmeden resmin ne içerdiğini anlayamayız. Peki bilgisayarın bütün ayrıntıları algılamasını nasıl sağlayabiliriz. CNN yani Convolutional Neural Network bunun için biçilmiş kaftandır.

Her resim, piksel denilen ufak noktalardan oluşur. Her bir pikselin rengi, RGB (Red Green Blue) renk sisteminde kırmızı, yeşil ve mavi renklerden ne kadar içerdiğine bağlı olarak değişir. Bir pikselin rengi, 0 ile 255 arasında bu üç rengin karışımından oluşur. Örneğin bir pikselin içeriği Kırmızı=0, Yeşil=0 ve Mavi=255 ise rengi mavi olarak görülür. Şu sayfadan istediğiniz üç renk karışımına karşılık gelen rengin ne olduğunu görebilirsiniz.

Piksellerin sahip olduğu renk değerlerinden dolayı, resimler bilgisayarda sayısal değerler halinde tutulur. Piksellerin sahip olduğu bu sayısal değerlere (piksel yoğunluklarına) bakarak resimde nasıl bir şekil yani patern olduğunu bilgisayarın anlamasını sağlayabiliriz.

Genellikle görüntü işleme alanında kullanılan CNN temelde şu katmanlardan oluşur:

  • Konvolüsyon Katmanı: Resmin her pikseline belirlediğiniz boyutta ve sayıda filtre ile bakmamızı sağlar. Adının konvolüsyon olması, matematikteki matris konvolüsyon çarpımından gelmektedir. Bu katman ile resimde yüzlerce farklı minik patern bulunur. Anlaşılması daha kolay olması açısından, bu katmanda her biri 5×5 piksel boyutundaki bir alana bakan ve işi konvolüsyon çarpımı yapmak olan 32 işçi olduğunu düşünebiliriz. Bu durumda filtre boyutumuz 5×5 ve filtre sayımız da 32 olmuş olur.
  • Havuzlama (Pooling) Katmanı: Konvolüsyon katmanında yüzlerce patern bulunur ama bunlar sınırlı bir alanı içerir. Hem paternin geri kalanını tespit etmek hem de sayıyı azaltmak için havuzlama yapılır. Burada genelde max pooling yöntemi kullanılır. Bu yönteme göre konvolüsyon katmanında bulunan paternler üzerinde, belirli bir boyuttaki filtrede (matris) sayı olarak büyük olan değerler yeni bir matrise taşınır.
  • Tam Bağlantılı (Fully Connected) Katman: Nihai amacımız resimdeki yüzlerce katmanı bulmak değil resmin hangi sınıfa ait olduğunu bulmaktır. Bu örnekte iki sınıf vardır. Bu yüzden iki bit ile bu sınıfları tespit edebiliriz. Sonuç olarak ağın çıkışından iki sayı alabilirsek resmin hangi sınıfa ait olduğunu tespit ederiz. Bir sınıfa 0 1 ve diğer sınıfa da 1 0 dersek çıkan sonuca göre kedi mi köpek mi olduğunu anlayabiliriz. Bu katmanın yaptığı iş tam olarak budur. Çıkış sayısını belirli bir sayıya azaltır.
  • Dropout Katmanı: Aşırı öğrenmeyi (overfitting) engellemek için kullanılan bir katmandır.

Kedi köpek algılamak için öncelikle resimdeki hayvanın şekli yani silueti ve rengi tespit edilir. Piksellerin değişimi bize bu bilgiyi verecektir. Daha sonra kulak, burun, ağız, kuyruk gibi uzuvların şekillerinin tespiti yapılır. Çok daha karmaşık ağ yapıları kullanırsanız köpeğin ayırt edici özelliklerini tespit edebilirsiniz.

3. Adım: Python, Tensorflow ve PyCharm Kurulumu

Aşağıdaki kodları çalıştırabilmek için Python ve Tensorflow‘un bilgisayarınızda kurulu olması gerekmekte. Kurulumda dikkat edilmesi gereken en önemli nokta TensorFlow’u kurabilmek için Python’un 3.5.2 sürümünün yüklü olması gerekiyor. Daha yeni Python sürümleri şimdilik TensorFlow tarafından desteklenmiyor. Kurulum konusunda problem yaşarsanız önce Google’da aratın yine de çözüm bulamazsanız yorum yazarak destek isteyebilirsiniz. Python kodlarını yazmak için bir tane de derleyici programa ihtiyacımız var. Ücretsiz PyCharm programını tavsiye ederim.

  1. Python Kurulumu: https://www.python.org/downloads/release/python-352/
  2. TensorFlow Kurulumu: https://www.tensorflow.org/install/install_windows
  3. PyCharm Kurulumu: https://www.jetbrains.com/pycharm/download

4. Adım: KODLAMA
Kodların aralarına açıklama satırları ekledim için kod için detaylı bir açıklama yapmayacağım. Python ile kütüphane yüklemek için pip komutunu kullanabilirsiniz.
Örneğin numpy kütüphanesini yüklemek için python konsolundan

 pip install numpy

komutunu yazıyoruz.

import cv2
import numpy as np
import os
from random import shuffle
from tqdm import tqdm
import tensorflow as tf
import matplotlib.pyplot as plt
import tflearn
from tflearn.layers.conv import conv_2d, max_pool_2d
from tflearn.layers.core import input_data, dropout, fully_connected
from tflearn.layers.estimator import regression

# "train" isimli klasörde yer alan resimleri eğitimde kullanacağız
EGITIM_KLASORU = 'train'

# "test" isimli klasörde yer alan resimleri testte kullanacağız
TEST_KLASORU = 'test'

# eğitim ve test için kullanılan resimleri aynı boyuta (50x50 piksel) getireceğiz.
RESIM_BOYUTU = 50

# öğrenme oranını 0.001 olarak tanımlayalım.
OGRENME_ORANI = 1e-3

# oluşturacağımız modele bir isim verelim.
MODEL_ADI = 'kedi-kopek-ayirici'

### DOSYA ADLARINDAN ETİKET BİLGİLERİNİN ALINMASI ###

# etiket_olustur isminde bir fonksiyon tanımlayalım.
# bu fonksiyon ile dosya adlarında yer alan "cat" ya da "dog" etiketlerini algılayacağız.
# fonksiyon dosya adı "cat" ise [1 0], "dog" ise [0 1] çıkışını verir.

def etiket_olustur(resim_adi):
 obje_turu = resim_adi.split('.')[-3] # dosya adında bulunan "cat" ya da "dog" kelimesini al
 if obje_turu == 'cat':
 return np.array([1, 0])
 elif obje_turu == 'dog':
 return np.array([0, 1])

### RESİMLERİN MATRİS HALİNE DÖNÜŞTÜRÜLMESİ ###

# train klasöründeki resimlerden eğitimde kullanılabilecek şekilde eğitim verisi oluştur.
# oluşturulan eğitim verisi "egitim_verisi.npy" isimli dosyaya yazılır.
# fonksiyon içerisinde verilerin karıştırılması (shuffle) sağlanır.
# resimler gri olarak okunup 50x50 piksel olacak şekilde yeniden boyutlandırılır.

def egitim_verisi_olustur():
 olusturulan_egitim_verisi = []
 for img in tqdm(os.listdir(EGITIM_KLASORU)):
 dosya_yolu = os.path.join(EGITIM_KLASORU, img)
 resim_verisi = cv2.imread(dosya_yolu, cv2.IMREAD_GRAYSCALE)
 resim_verisi = cv2.resize(resim_verisi, (RESIM_BOYUTU, RESIM_BOYUTU))
 olusturulan_egitim_verisi.append([np.array(resim_verisi), etiket_olustur(img)])
 shuffle(olusturulan_egitim_verisi)
 np.save('egitim_verisi.npy', olusturulan_egitim_verisi)
 return olusturulan_egitim_verisi

# test klasöründeki resimlerden eğitimde kullanılabilecek şekilde test verisi oluştur.
# oluşturulan test verisi "test_verisi.npy" isimli dosyaya yazılır
# fonksiyon içerisinde verilerin karıştırılması (shuffle) sağlanır.
# resimler gri olarak okunup 50x50 piksel olacak şekilde yeniden boyutlandırılır.

def test_verisi_olustur():
 olusturulan_test_verisi = []
 for img in tqdm(os.listdir(TEST_KLASORU)):
 dosya_yolu = os.path.join(TEST_KLASORU, img)
 resim_no = img.split('.')[0]
 resim_verisi = cv2.imread(dosya_yolu, cv2.IMREAD_GRAYSCALE)
 resim_verisi = cv2.resize(resim_verisi, (RESIM_BOYUTU, RESIM_BOYUTU))
 olusturulan_test_verisi.append([np.array(resim_verisi), resim_no])
 shuffle(olusturulan_test_verisi)
 np.save('test_verisi.npy', olusturulan_test_verisi)
 return olusturulan_test_verisi

# "egitim_verisi.npy" ve "test_verisi.npy" dosyaları daha önce oluşturulmadıysa:
# egitim_verisi = egitim_verisi_olustur()
# test_verisi = test_verisi_olustur()

# "egitim_verisi.npy" ve "test_verisi.npy" dosyaları oluşturulduysa:
egitim_verisi = np.load('egitim_verisi.npy')
test_verisi = np.load('test_verisi.npy')

# ağımızı eğitirken 500 adet resmi eğitimi test etmek için kullanacağız.
egitim = egitim_verisi[:-500]
test = egitim_verisi[-500:]

X_egitim = np.array([i[0] for i in egitim]).reshape(-1, RESIM_BOYUTU, RESIM_BOYUTU, 1)
y_egitim = [i[1] for i in egitim]
X_test = np.array([i[0] for i in test]).reshape(-1, RESIM_BOYUTU, RESIM_BOYUTU, 1)
y_test = [i[1] for i in test]

### MİMARİNİN OLUŞTURULMASI ###

tf.reset_default_graph()

# ağımızın girişinin boyutlarının ne olacağını tanımlayalım
convnet = input_data(shape=[None, RESIM_BOYUTU, RESIM_BOYUTU, 1], name='input')

# 32 adet 5x5 boyutunda filtrelerden oluşan ve relu aktivasyonlu konvolüsyon katmanı
convnet = conv_2d(convnet, 32, 5, activation='relu')

# 5x5 boyutunda filtelerden oluşan max_pool katmanı
convnet = max_pool_2d(convnet, 5)

convnet = conv_2d(convnet, 64, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)

convnet = conv_2d(convnet, 128, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)

convnet = conv_2d(convnet, 64, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)

convnet = conv_2d(convnet, 32, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)

# 1024 birimden oluşan tam bağlantılı ve relu aktivasyonlu katman
convnet = fully_connected(convnet, 1024, activation='relu')

# aşırı öğrenmeyi yani ezberlemeyi (overfitting) engellemek için dropout katmanı
convnet = dropout(convnet, 0.8)

# 2 birimli ve softmax aktivasyonlu tam bağlantılı katman
convnet = fully_connected(convnet, 2, activation='softmax')

# oluşturulan mimariyi, öğrenme oranını, optimizasyon türünü, kayıp fonksiyonunu ve dosya isimlerinden aldığımız hedef değerlerini
# kullanarak ağı oluşturalım.
convnet = regression(convnet, optimizer='adam', learning_rate=OGRENME_ORANI, loss='categorical_crossentropy',
 name='targets')

# OLUŞTURULAN MİMARİ İLE DEEP LEARNING NETWORK (DNN) MODELİ OLUŞTURULMASI
model = tflearn.DNN(convnet, tensorboard_dir='log', tensorboard_verbose=0)

# VERİLERLE EĞİTİM YAPILMASI
model.fit({'input': X_egitim}, {'targets': y_egitim}, n_epoch=10,
 validation_set=({'input': X_test}, {'targets': y_test}),
 snapshot_step=500, show_metric=True, run_id=MODEL_ADI)

### OLUŞTURULAN DERİN AĞ MODELİNİN TEST VERİLERİ ÜZERİNDE DENENMESİ

fig = plt.figure(figsize=(16, 12))

for no, veri in enumerate(test_verisi[:16]):

 resim_no = veri[1]
 resim_verisi = veri[0]

 y = fig.add_subplot(4, 4, no + 1)
 orig = resim_verisi
 veri = resim_verisi.reshape(RESIM_BOYUTU, RESIM_BOYUTU, 1)
 ag_cikisi = model.predict([veri])[0]

 if np.argmax(ag_cikisi) == 1:
 str_label = 'Köpek'
 else:
 str_label = 'Kedi'

 y.imshow(orig, cmap='gray')
 plt.title(str_label)
 y.axes.get_xaxis().set_visible(False)
 y.axes.get_yaxis().set_visible(False)
plt.show() 

Kodlara GitHub’tan da ulaşabilirsiniz: https://github.com/yapaybot/derin-ogrenme-ile-kedi-kopek-ayrimi

Sonuç olarak aşağıdakine benzer bir tablo ile karşılaşacağız. Ne dersiniz hiç de fena değil bence 🙂

[1] http://www.bbc.com/news/technology-40416606

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Google fotoğrafı

Google hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Connecting to %s