Derin Öğrenme (Deep Learning) - Bilgisayar Görmesi Örnekleri

Çiçek Fotoğrafları Tahmini- (Functional API Model Kullanarak)

Yayın tarihi :06-Mar-22
Bölüm kodlarını ve/veya veri setlerini indir.

Konu: 5 farklı çiçek grubuna ait resimler Derin Öğrenme modeli ile eğitilerek yeni girilen çiçek türünü tahmin etmek.

Veri seti: 5 farklı klasör içersinde 'papatya', 'karahindiba', 'gül', 'ayçiçeği' ve 'lale' çiçeklerine ait farklı boyutlarda toplamda 3670 adet fotoğrafın bulunduğu bir veri setidir.

Veri seti okuma işlemleri

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
import warnings
warnings.filterwarnings("ignore")

import glob
import pathlib
import PIL

from tensorflow.keras.models import Sequential,Model
from tensorflow.keras.layers import Dense,Dropout,BatchNormalization
from tensorflow.keras.utils import plot_model,image_dataset_from_directory
from tensorflow.keras.models import model_from_json
from tensorflow.keras.preprocessing import image
from tensorflow.data import AUTOTUNE
from tensorflow.keras.applications.efficientnet_v2 import EfficientNetV2B1

from tensorflow.compat.v1 import ConfigProto,InteractiveSession
config = ConfigProto()
config.gpu_options.allow_growth = True
session = InteractiveSession(config=config)

Veri setini aşağıda bulunan kod yardımı ile indirebilirsiniz.

dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
data_dir = tf.keras.utils.get_file(origin=dataset_url,
                                   fname='flower_photos',
                                   untar=True)
data_dir = pathlib.Path(data_dir)
print(data_dir)

Çıktı:

C:\Users\(Kullanıcı Adı)\.keras\datasets\flower_photos

 Yukarıdaki çıktıda da görüldüğü üzere veri seti ilgili adrese indirelecektir. İndirilen fotoğraf sayısını inceleyelim.

len(list(data_dir.glob("*/*.jpg")))

Çıktı:

3670
#Veri setinde bulunan "roses" klasöründen bir tane örnek fotoğraf
roses=list(data_dir.glob("roses/*"))
PIL.Image.open(str(roses[0]))

Çıktı:

#Veri setinde bulunan "sunflowers" klasöründen bir tane örnek fotoğraf
sunflowers=list(data_dir.glob("sunflowers/*"))
PIL.Image.open(str(sunflowers[0]))

Çıktı:

Veri seti için Train ve Test verilerini ayırma işlemi

batch_size=32
img_height=180
img_width=180

#Train veri seti
train_ds=image_dataset_from_directory(
    directory=data_dir, #dizin adı
    validation_split=0.2, #Test verisi boyutu
    subset="training", #eğitim mi test mi?
    seed=123,
    image_size=(img_height,img_width),
    batch_size=batch_size
)

#Test veri seti
test_ds=image_dataset_from_directory(
    directory=data_dir, #dizin adı
    validation_split=0.2, #Test verisi boyutu
    subset="validation", #eğitim mi test mi?
    seed=123,
    image_size=(img_height,img_width),
    batch_size=batch_size
)

Çıktı:

Found 3670 files belonging to 5 classes.
Using 2936 files for training.
Found 3670 files belonging to 5 classes.
Using 734 files for validation.

Yukarıdaki çıktıda görüldüğü üzere 3670 resimli 5 sınıftan oluşan veri setinde 2936 tane rasgele resim "train" için 734 tane resim ise "test" için kullanılacaktır.

#Verilerin bulunduğu klasörler(resimlerin sınıfları) listeleme işlemi
class_names=train_ds.class_names
print(class_names)

Çıktı:

['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']
#Train için ayrılan resimlerden birkaç tanesini görüntüleyelim
plt.figure(figsize=(15,10))

for image,label in train_ds.take(1):
    for i in range(25):
        ax=plt.subplot(5,5,i+1)
        plt.imshow(image[i].numpy().astype("uint8"))
        plt.xticks([])
        plt.yticks([])
        plt.title(class_names[label[i]])

Çıktı:

#32'li olarak gruplandırılan(bacth_size) Train verilerinin grup sayısı
print("Grup sayısı:{}".format(len(train_ds)))

#Train verilerindeki resim ve label boyutları
for image_batch,label_batch in train_ds.take(1):
    print("Resim boyutları:{}".format(image_batch.shape))
    print("Label boyutları:{}".format(label_batch.shape))

Çıktı:

Grup sayısı:92
Resim boyutları:(32, 180, 180, 3)
Label boyutları:(32,)
#32'li olarak gruplandırılan(bacth_size) Test verilerinin grup sayısı
print("Grup sayısı:{}".format(len(test_ds)))
#Test verilerindeki resim ve label boyutları
for image_batch,label_batch in test_ds.take(1):
    print("Resim boyutları:{}".format(image_batch.shape))
    print("Label boyutları:{}".format(label_batch.shape))

Çıktı:

Grup sayısı:23
Resim boyutları:(32, 180, 180, 3)
Label boyutları:(32,)

Model oluşturma ve model eğitme işlemleri

Bilgisayar CPU'sunun etkin bir şekilde kullanılabilmesi için aşağıdaki komutun eklenmesi gerekmetekdir.

autotune=AUTOTUNE

train_ds = train_ds.cache().prefetch(buffer_size=autotune)
test_ds = test_ds.cache().prefetch(buffer_size=autotune)

EfficientNetV2B1 ile ImageNet üzerinde önceden eğitilmiş ağırlıklarla yüklenen bir Keras görüntü sınıflandırma modeli döndürür. Bizde bu modeli başlangıç olarak kullanarak başarı oranımızı artıracağız. Modelin görselleştirilmesi aşamasında EfficientNetV2B1 ile modele eklenen katmanları görüntüleyebilirsiniz.

efficientNet =EfficientNetV2B1(
    include_top=False,
    input_shape=(180,180,3),
    pooling='avg',
    classes = 3, 
    weights='imagenet')
num_classes=len(class_names) #Çıktı boyutu

#Model ve katmanların eklenmesi
x=efficientNet.output
x=BatchNormalization()(x)
x=Dense(512,activation="relu")(x)
x=Dropout(rate=0.2)(x)
x=Dense(256,activation="relu")(x)
x=Dropout(rate=0.2)(x)
x=Dense(num_classes,activation="softmax")(x)
model=Model(efficientNet.input,x)
#Modelin görüntüsünü inceleyelim
plot_model(model,show_shapes=True)

Çıktı:

model.compile(
    optimizer="adam",
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"]    
)
model.fit(
    train_ds,
    validation_data=test_ds,
    epochs=3,
    verbose=1,
    batch_size=64
)

Çıktı:

Epoch 1/3
92/92 [==============================] - 981s 10s/step - loss: 0.5973 - accuracy: 0.8028 - val_loss: 0.3820 - val_accuracy: 0.9087
Epoch 2/3
92/92 [==============================] - 913s 10s/step - loss: 0.2865 - accuracy: 0.9067 - val_loss: 0.2496 - val_accuracy: 0.9264
Epoch 3/3
92/92 [==============================] - 930s 10s/step - loss: 0.1750 - accuracy: 0.9465 - val_loss: 0.2729 - val_accuracy: 0.9101

Kayıp değerleri(loss) ve başarı değerlerini(accuracy) train ve test verilerindeki durumlarına göre grafiksel olarak gözlemleyebiliriz. 

fig=plt.figure(figsize=(20,6))

#Accuracy Grafiklemesi
x1=fig.add_subplot(121)
x1.plot(model.history.history['accuracy'])
x1.plot(model.history.history['val_accuracy'])
x1.set_title('Model accuracy')
x1.set_ylabel('Accuracy')
x1.set_xlabel('Epoch')
x1.legend(['Train', 'Test'], loc='upper left')

#Loss Grafiklemesi
x2=fig.add_subplot(122)
x2.plot(model.history.history['loss'])
x2.plot(model.history.history['val_loss'])
x2.set_title('Model loss')
x2.set_ylabel('Loss')
x2.set_xlabel('Epoch')
x2.legend(['Train', 'Test'], loc='upper left')

plt.show()

Çıktı:

Modelin başarı yüzdesini gözlemleyelim;

_, accuracy=model.evaluate(test_ds)
print('Accuracy: %.2f' % (accuracy*100))

Çıktı:

23/23 [==============================] - 42s 2s/step - loss: 0.2729 - accuracy: 0.9101
Accuracy: 91.01

Sonuç olarak; Derin Öğrenme Functional API modeline önceden ağırlıkları hesaplanmış EfficientNetV2B1 eklenmesi sonucunda %91.01 oranında başarı elde edilmiş oldu. (Aynı veri setini bir önceki örnekte Sequential API modeli ile eğitmiştik ve başarı sonucu %51.01 olarak bulunmuştu.).Bu model için başarı oranı artırılmak istenebilir, bunun için birkaç adım denenebilir, bu adımlardan bazıları yüksek bilgisayar gücü gerektirebilecektir. Bunlar;

  • Veri seti temizlemesi daha iyi yapılabilir.
  • Model katmanlarına "Dropout" katmanları da eklenebilir.
  • Model gizli katmanları artırılabilir.
  • Gizli katmanlardaki nöron sayısı artırılabilir.
  • Model fit işleminde epoch değeri artırılabilir.

Model kaydetme, okuma ve tahminleme işlemleri

#Model kayıt işlemi
model_json=model.to_json()
with open("modelFlowerFunctional.json", "w") as json_file:
    json_file.write(model_json)

#Model ağırlıkları kayıt işlemi
model.save_weights("modelFlowerFunctional.h5")

print("Model ve ağırlıkları dosya konumuna kaydedildi.")

Çıktı:

Model ve ağırlıkları dosya konumuna kaydedildi.
#Modeli yükle
json_file = open('modelFlowerFunctional.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)

# Model ağırlıklarını yükle
loaded_model.load_weights("modelFlowerFunctional.h5")

print("Model ve ağırlıkları dosya konumundan okundu.")

Çıktı:

Model ve ağırlıkları dosya konumundan okundu.
class_names=['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']
def predictImage(img_path):
    #Resim 180x180 boyutlarında ve kendi rengi ile okunur.
    img = image.load_img(img_path, target_size=(180,180))
  
    #Okunan resim matrise çevrilir.
    img_array = image.img_to_array(img)
    img_batch = np.expand_dims(img_array, axis=0)
    
    #Tahminleme işlemi uygulanır
    pred=loaded_model.predict(img_batch)
    
    #Grafikleme yapılır.
    labels=class_names
    fig=plt.figure(figsize=(15,4))

    x1=fig.add_subplot(121)
    x1.imshow(img)
    x1.set_title("Yüklenen Fotoğraf")
    x1.set_xticks([])
    x1.set_yticks([])

    x2=fig.add_subplot(122)
    x2.bar(labels,pred[0])
    x2.set_title("Tahmin Değeri")
    
    ratio=np.round(pred[0][np.argmax(pred[0])]*100,2)
    type_=class_names[np.argmax(pred[0])]
 
    
    return "%{} oranında '{}' olarak tahmin edilmiştir.".format(ratio,type_)

Bir kaç tane çiçek fotoğrafı yükleyelim ve tahminleme işlemi sonrasında yüklenen fotoğrafların türünü gözlemleyelim.

predictImage("img7.png")

Çıktı:

"%99.75 oranında 'sunflowers' olarak tahmin edilmiştir."

predictImage("img8.jpg")

Çıktı:

"%91.96 oranında 'roses' olarak tahmin edilmiştir."

predictImage("img9.jpg")

Çıktı:

"%100.0 oranında 'dandelion' olarak tahmin edilmiştir."

3 fotoğraf denemesinde de başarılı bir şekilde tahminleme yapılmış oldu. 

Paylaş:

Yorum Yap (*Yorumunuza kod eklemek isterseniz Kod Parçacığı Ekle butonuna tıklayarak ekleyebilirsiniz.)

Yorumlar

Henüz hiç yorum yapılmamış, ilk yorum yapan sen ol.