CNN - Handwritten Digit Recognition

Kategori: Deep Learning , 10 Nisan 2020 , JanFranco


CNN kullaranak el yazısını tanıyabilen bir model geliştirip, train edeceğiz. Bunun için MNIST veri setini kullanacağız. MNIST veriseti keras kütühanesinde bulunan bir veriseti olduğundan sadece import etmemiz yeterli olacaktır:


from keras.datasets import mnist
Import ettiğimiz verisetini 4 parçaya ayırmalıyız. Train edeceğimiz kısım, train edeceğimiz kısmın labelları, test edeceğimiz kısım, test edeceğimiz kısmın labelları:


(x_train, y_train), (x_test, y_test) = mnist.load_data()
Boyutları görelim:


print("x_train shape = " + str(x_train.shape))
print("y_train shape = " + str(y_train.shape))
print("x_test shape = " + str(x_test.shape))
print("y_test shape = " + str(y_test.shape))

>>

x_train shape = (60000, 28, 28)
y_train shape = (60000,)
x_test shape = (10000, 28, 28)
y_test shape = (10000,)
Verisetinden bir kaç örnek resim görüntüleyelim:


import cv2
import numpy as np

for i in range(6):
  randomNum = np.random.randint(0, len(x_train))
  img = x_train[randomNum]
  cv2.imshow("Random Img", img)
  cv2.waitKey(0)
  
cv2.destroyAllWindows()
cv2 ve numpy kütüphanelerini import ettik. 6 resim bastıracağımız için range(6) fonksiyonunu kullanarak bir for döngüsü açtık. numpy kütüphanesindeki random methodunu kullanarak random bir sayı ürettik ve x_train dizisinde bu random sayının karşılık geldiği indexteki resmi, cv2 kütüphanesindeki imshow methodu ile gösterdik. Eğer Google CoLab üzerinde çalışıyorsak yukarıdaki imshow methodu çalışmayacaktır. Google CoLab için aşağıdaki kodları deneyebiliriz:


import numpy as np
from google.colab.patches import cv2_imshow

for i in range(6):
  randomNum = np.random.randint(0, len(x_train))
  img = x_train[randomNum]
  cv2_imshow(img)
İlk olarak gerekli methodları import edelim:


from keras.models import Sequential
from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D, Dropout
from keras.optimizers import SGD
Modeli oluşturalım:


model = Sequential()
Katmanları ekleyelim:


model.add(Conv2D(32, (3,3), activation='relu', input_shape=inputShape))
model.add(Conv2D(64, (3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))
Dropout methodu ile overfitting ihtimalinin önüne geçebiliriz. Compile edelim:


model.compile(loss='categorical_crossentropy', optimizer=SGD(0.01), metrics=['accuracy'])
Modeli bastıralım:


print(model.summary())

>>
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 26, 26, 32)        320       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 24, 24, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 12, 12, 64)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 12, 12, 64)        0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 9216)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 128)               1179776   
_________________________________________________________________
dense_2 (Dense)              (None, 10)                1290      
=================================================================
Total params: 1,199,882
Trainable params: 1,199,882
Non-trainable params: 0
_________________________________________________________________
None
CNN bizden 4. boyutu da istemektedir. Resimlerin nasıl saklandığını biliyoruz. Bu nedenle yeni boyutu (60000, 28, 28, 1) şeklinde ayarlayacağız. Renkli bir resim olsaydı (60000, 28, 28, 3) şeklinde ayarlayacaktık. İlk olarak satır ve sütun boyutlarını alalım:


rows = x_train[0].shape[0]
cols = x_train[1].shape[0]
reshape methodu ile boyutları ayarlayalım:


x_train = x_train.reshape(x_train.shape[0], rows, cols, 1)
x_test = x_test.reshape(x_test.shape[0], rows, cols, 1)
Modelimizin ilk katmanı için inputShape belirleyelim:


inputShape = (rows, cols, 1)
Algoritmada ağırlıklar, aktivasyon değerleri vs. float tipinde olacağından, biz de değerleri integer değerden float değere çevirmeliyiz:


x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
Daha iyi sonuç almak için normalizasyon işlemi yapabiliriz. Biliyoruz ki resmin pisek değerleri 0-256 arasındadır. 0-1 arasına sıkıştırmak için aşağıdaki işlem yeterlidir:


x_train /= 255
x_test /= 255
One-hot encoding işlemi yaparak preprocessingi tamamlıyoruz:


from keras.utils import np_utils

y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
Batch size ve epoch değerlerimizi tanımlayalım:


batchSize = 32
epochs = 1
fit methodu ile train işlemini başlatalım:


history = model.fit(x_train, y_train, batch_size=batchSize, epochs=epochs, verbose=1, validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print("Test loss = ", score[0])
print("Test accuracy = ", score[1])

>>

Train on 60000 samples, validate on 10000 samples
Epoch 1/10
60000/60000 [==============================] - 9s 146us/step - loss: 0.5850 - acc: 0.8185 - val_loss: 0.2071 - val_acc: 0.9361
Epoch 2/10
60000/60000 [==============================] - 8s 141us/step - loss: 0.2989 - acc: 0.9087 - val_loss: 0.1455 - val_acc: 0.9575
Epoch 3/10
60000/60000 [==============================] - 9s 143us/step - loss: 0.2304 - acc: 0.9308 - val_loss: 0.1075 - val_acc: 0.9674
Epoch 4/10
60000/60000 [==============================] - 9s 144us/step - loss: 0.1775 - acc: 0.9460 - val_loss: 0.0837 - val_acc: 0.9743
Epoch 5/10
60000/60000 [==============================] - 8s 141us/step - loss: 0.1437 - acc: 0.9558 - val_loss: 0.0703 - val_acc: 0.9778
Epoch 6/10
60000/60000 [==============================] - 8s 141us/step - loss: 0.1248 - acc: 0.9618 - val_loss: 0.0602 - val_acc: 0.9807
Epoch 7/10
60000/60000 [==============================] - 8s 140us/step - loss: 0.1074 - acc: 0.9675 - val_loss: 0.0523 - val_acc: 0.9834
Epoch 8/10
60000/60000 [==============================] - 8s 141us/step - loss: 0.0972 - acc: 0.9710 - val_loss: 0.0482 - val_acc: 0.9844
Epoch 9/10
60000/60000 [==============================] - 8s 140us/step - loss: 0.0883 - acc: 0.9739 - val_loss: 0.0473 - val_acc: 0.9850
Epoch 10/10
60000/60000 [==============================] - 8s 139us/step - loss: 0.0839 - acc: 0.9742 - val_loss: 0.0432 - val_acc: 0.9860
Test loss =  0.04319153501094552
Test accuracy =  0.986
Modelimizi eğittik ve loss, accuracy gibi değerleri elde ettik. Bu değerleri kullanarak grafikleri çizelim:


import matplotlib.pyplot as plt

history_dict = history.history

loss_values = history_dict['loss']
val_loss_values = history_dict['val_loss']
epochs = range(1, len(loss_values) + 1)

line1 = plt.plot(epochs, val_loss_values, label="Validation Loss")
line2 = plt.plot(epochs, loss_values, label="Training Loss")
plt.setp(line1, linewidth=2.0, marker='+', markersize=10.0)
plt.setp(line2, linewidth=2.0, marker='4', markersize=10.0)
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.grid(True)
plt.legend()
plt.show()
Loss değerleri için grafiğimizi çizdirdik. Accuracy değerleri için de çizdirelim:


import matplotlib.pyplot as plt

history_dict = history.history

acc_values = history_dict['acc']
val_acc_values = history_dict['val_acc']
epochs = range(1, len(loss_values) + 1)

line1 = plt.plot(epochs, val_acc_values, label="Validation Accuracy")
line2 = plt.plot(epochs, acc_values, label="Training Accuracy")
plt.setp(line1, linewidth=2.0, marker='+', markersize=10.0)
plt.setp(line2, linewidth=2.0, marker='4', markersize=10.0)
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.grid(True)
plt.legend()
plt.show()
Modellerimizi daha sonra tekrar kullanmak üzere kaydedebiliriz. Her defasında yeniden train etmemize gerek yoktur:


model.save("simple_mnist_model.h5")
Kaydettiğimiz modeli yükleyelim:


from keras.models import load_model

classifier = load_model("simple_mnist_model.h5")
İşlemi tamamladık. Tüm kodları bir arada görmek istersek:


import numpy as np
import matplotlib.pyplot as plt
from google.colab.patches import cv2_imshow

from keras.datasets import mnist
from keras.utils import np_utils
from keras.optimizers import SGD
from keras.models import Sequential
from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D, Dropout

(x_train, y_train), (x_test, y_test) = mnist.load_data()
print("x_train shape = " + str(x_train.shape))
print("y_train shape = " + str(y_train.shape))
print("x_test shape = " + str(x_test.shape))
print("y_test shape = " + str(y_test.shape))

for i in range(6):
  randomNum = np.random.randint(0, len(x_train))
  img = x_train[randomNum]
  cv2_imshow(img)

rows = x_train[0].shape[0]
cols = x_train[1].shape[0]

x_train = x_train.reshape(x_train.shape[0], rows, cols, 1)
x_test = x_test.reshape(x_test.shape[0], rows, cols, 1)

inputShape = (rows, cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')

x_train /= 255
x_test /= 255

y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)

model = Sequential()

model.add(Conv2D(32, (3,3), activation='relu', input_shape=inputShape))
model.add(Conv2D(64, (3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer=SGD(0.01), metrics=['accuracy'])

print(model.summary())

batchSize = 32
epochs = 10

history = model.fit(x_train, y_train, batch_size=batchSize, epochs=epochs, verbose=1, validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print("Test loss = ", score[0])
print("Test accuracy = ", score[1])

history_dict = history.history

loss_values = history_dict['loss']
val_loss_values = history_dict['val_loss']
epochs = range(1, len(loss_values) + 1)

line1 = plt.plot(epochs, val_loss_values, label="Validation Loss")
line2 = plt.plot(epochs, loss_values, label="Training Loss")
plt.setp(line1, linewidth=2.0, marker='+', markersize=10.0)
plt.setp(line2, linewidth=2.0, marker='4', markersize=10.0)
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.grid(True)
plt.legend()
plt.show()

history_dict = history.history

acc_values = history_dict['acc']
val_acc_values = history_dict['val_acc']
epochs = range(1, len(loss_values) + 1)

line1 = plt.plot(epochs, val_acc_values, label="Validation Accuracy")
line2 = plt.plot(epochs, acc_values, label="Training Accuracy")
plt.setp(line1, linewidth=2.0, marker='+', markersize=10.0)
plt.setp(line2, linewidth=2.0, marker='4', markersize=10.0)
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.grid(True)
plt.legend()
plt.show()


Sonraki Yazı: CNN Visualization
Yorumlar

Henüz bir yorum bulunmuyor.
Yorum bırakın