# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# + [markdown] id="view-in-github" colab_type="text"
# <a href="https://colab.research.google.com/github/farkoo/Cat-Dog-Classifier/blob/master/CatDogClassifier_Part_5.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>

# + [markdown] id="1g4Li6ngEF9d"
# # استفاده از شبکه‌های عصبی کانولوشنی و استفاده از شبکه‌های از پیش آموزش داده شده

# + [markdown] id="IRnk0Sq4KEld"
# ## آماده‌سازی داده‌های آموزشی ، اعتبارسنجی و تست 

# + [markdown] id="Y2hB_PdsKL7k"
# <div dir='rtl'>
# مشابه قسمت‌های قبلی لازم است داده‌ها را در ماشین مجازی آماده‌سازی کنیم.

# + colab={"base_uri": "https://localhost:8080/"} id="38ScwC7bewNw" outputId="77b6236a-40a8-403e-a960-622ab798b822" language="bash"
# git clone "https://github.com/MKasaei00/IUT-CI-HW3-cat-dog-classifier.git"

# + colab={"base_uri": "https://localhost:8080/"} id="UvNMNj1whfmG" outputId="dcab39b2-edb3-47d7-f3e7-762d988904f9"
# %cd IUT-CI-HW3-cat-dog-classifier

# + colab={"base_uri": "https://localhost:8080/"} id="Nb69RhJ5iDrW" outputId="2ff10b39-ba64-425b-95c9-2f5122471a37" language="bash"
# 7z x dataset/test_set.zip -odataset
# 7z x dataset/training_set.zip -odataset

# + id="hTd3JReGlT0r"
import numpy as np
import os
import cv2
from google.colab.patches import cv2_imshow
from keras.utils import np_utils
import matplotlib.pyplot as plt
import tensorflow as tf
import random
import math

# + [markdown] id="g7tavQwbKWpN"
# <div dir='rtl'>
#
# مسیر داده‌های آموزشی و تست را مشخص می‌کنیم.

# + id="NA3x7ObDlopB"
test_dir = 'dataset/test_set'
training_dir = 'dataset/training_set'


# + [markdown] id="AUk50IjIKfEz"
# <div dir='rtl'>
#
# با توجه به شبکه‌ی آماده‌ای که از وزن‌های اولیه‌ی آن استفاده می‌کنیم لازم است مقادیر ورودی بین -1 و +1 باشد.
#
# پس با توجه به مقادیر مختلف ممکن برای هر رنگ پیکسل (بین 0 تا 255) لازم است تمام اعداد را از وسط بازه کم کنیم و تقسیم بر نصف طول بازه کنیم تا درنهایت تمام مقادیر به مقادیر بین -1 و +1 تبدیل شوند.

# + id="5lNX7WfLln7S"
def load_data_from_directory(dir,width,height,classes):
  img_data = []
  img_label = []
  categories = os.listdir(dir)
  for category in categories:
    for file in os.listdir(os.path.join(dir,category)):
      img_path = os.path.join(dir,category,file)
      img = cv2.imread(img_path)
      
      img = cv2.resize(img,(width,height))
      img = (np.array(img).astype('float32') - 175.5) / 175.5
      
      img_data.append(img)
      img_label.append(category)

  img_onehot = np_utils.to_categorical([categories.index(label) for label in img_label],classes,dtype=np.ubyte)
  img_data = np.array(img_data)
  img_onehot = np.array(img_onehot)

  zip_list = list(zip(img_data, img_label, img_onehot))
  random.shuffle(zip_list)
  img_data, img_label, img_onehot = zip(*zip_list)
  return img_data , img_label, img_onehot


# + [markdown] id="y-jHkmO3LHrS"
# <div dir='rtl'>
#
# طول و عرض تصاویر متفاوت است و لازم است برای سازگاری با شبکه‌ی عصبی تمام تصاویر را به یک اندازه مشخص تبدیل کنیم.

# + id="cVb181xCZZbJ"
classes = 2
w = 150
h = 150

# + id="9kpvfOQ3mDqq"
train_x , train_label, train_onehot = load_data_from_directory(training_dir,w,h,classes)
test_x , test_label, test_onehot = load_data_from_directory(test_dir,w,h,classes)

# + id="0TV8o9GRwGPi"
test_label2 = []
for i, label in enumerate(test_label):
     test_label2.append(1) if (label == 'dogs') else test_label2.append(0)

# + id="v7XgBhICe2Y6"
train_x = np.asarray(train_x)
train_label = np.asarray(train_label)
train_onehot = np.asarray(train_onehot)

test_x = np.asarray(test_x)
test_label = np.asarray(test_label2)
test_onehot = np.asarray(test_onehot)

# + id="cYnCpcoumHxk"
# !rm -rf cleanData
# !mkdir cleanData
np.save('cleanData/train_x.npy',train_x)
np.save('cleanData/train_label.npy',train_label)
np.save('cleanData/train_onehot.npy',train_onehot)

np.save('cleanData/test_x.npy',test_x)
np.save('cleanData/test_label.npy',test_label)
np.save('cleanData/test_onehot.npy',test_onehot)

# + id="mpcwCHVPmI1z"
train_label = np.load('cleanData/train_onehot.npy')
train_x = np.load('cleanData/train_x.npy')

test_x = np.load('cleanData/test_x.npy')
test_label = np.load('cleanData/test_onehot.npy')
test_vec = np.load('cleanData/test_label.npy')

# + [markdown] id="grFcBFEmLVFs"
# <div dir='rtl'>
# برای آموزش شبکه‌ی عصبی و برای نهایت استفاده از داده‌های در دسترس ۹۹ درصد داده‌های آموزشی را برای آموزش شبکه و فقط از یک درصد برای ازریابی و validation استفاده می‌کنیم.
#
# هم‌چنین داده‌های تست تعیین شده پس از آموزش کامل شبکه برای ارزیابی عملکرد شبکه استفاده می‌کنیم.

# + id="7FLzp06qGu1b"
from sklearn.model_selection import train_test_split
train_X, valid_X, train_Label, valid_Label = train_test_split(train_x, train_label, test_size = 0.01, random_state = 13)

# + colab={"base_uri": "https://localhost:8080/"} id="T2PZ3NEiWrJa" outputId="974e4565-a7ac-4289-bc3b-c669a50b304b"
train_X.shape, valid_X.shape

# + [markdown] id="q82TKEMcse8U"
# # استفاده از وزن‌های آماده و ساختار شبکه‌ی Inception V3

# + [markdown] id="YQuEAh7mMBGL"
# <div dir='rtl'>
#
#
# ابتدا کتابخانه 
# keras
# و ماژول‌های مورد نیاز را تعریف می‌کنیم.

# + id="ytLgdToaMHU8"
from keras.applications.inception_v3 import InceptionV3
from keras.models import Model
from keras.layers import *
from keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.optimizers import *


# + [markdown] id="iOafOGXaMK_j"
# <div dir='rtl'>
#
# تابع زیر مشابه قسمت‌های قبل وظیفه‌ی تعریف مدل و آماده‌سازی داده‌ها ، آموزش شبکه و در نهایت ارزیابی با داده‌های تست را دارد.
#
# در ابتدا شبکه‌ی 
# inceptionv3
# بارگذاری می‌شود و این لایه را غیر قابل آموزش و ثابت تعریف می‌کنیم پس از آن لایه‌های اضافی و قابل آموزش خود را به شبکه‌ اضافه می‌کنیم.
#
# برای آموزش بهتر شبکه از تغییرات منطقی و ممکن در داده‌ها مانند چرخش و زوم و .. استفاده می‌کنیم.
#
# در نهایت مدل را آموزش می‌دهیم و نموداری از 
# accuracy
# در 
# epoch 
# های مختلف براساس داده‌های آموزشی و داده‌های آموزشی و ارزیابی رسم می‌کنیم.
#
# در آخرین مرحله داده‌های تست را با استفاده از مدل پیش‌بینی کرده نتایج را به صورت کامل گزارش می‌کنیم.
#

# + id="jfKUyZ6VzqZB"
def train_model(config):
  input = Input((150, 150, 3))
  net = InceptionV3(include_top = False, weights = 'imagenet')(input)
  net = Conv2D(2, 3,padding='same',activation='relu')(net)
  net = GlobalAveragePooling2D()(net)
  output = Activation('softmax')(net)

  model = Model(inputs = input, outputs = output)
  #Freezing InceptionV3.
  model.layers[1].trainable=False
  model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc'])
  model.summary()


  train_datagen = ImageDataGenerator(
        rotation_range=config['aug_rotation'],
        width_shift_range=config['aug_shift_w'],
        height_shift_range=config['aug_shift_h'],
        shear_range=config['aug_shear'],
        zoom_range=config['aug_zoom'],
        horizontal_flip=config['aug_horizontal_flip'],
        fill_mode='nearest'
  )

  train_generator = train_datagen.flow(train_X, train_Label, batch_size = config['batch'])

  validation_datagen = ImageDataGenerator()
  validation_generator = validation_datagen.flow(valid_X,valid_Label,config['batch'])

  history = model.fit(train_generator,
                                validation_data=validation_generator,
                                epochs = config['epochs'],
                                batch_size=config['batch'],
                                steps_per_epoch=math.ceil(7920/config['batch']),
                                validation_steps = math.ceil(80/config['batch'])
                                )
  
  plt.plot(history.history['acc'])
  plt.plot(history.history['val_acc'])
  plt.title('Model Accuracy')
  plt.ylabel('accuracy')
  plt.xlabel('epoch')
  plt.legend(['train','validation'],loc='lower right')
  plt.show()

  test_eval = model.evaluate(test_x, test_label, verbose = 0)
  print('Test loss: ', test_eval[0])
  print('Test accuracy: ', test_eval[1])
  print('\n\n')
  
  predictes_classes = model.predict(test_x)
  predicted_classes = np.argmax(np.round(predictes_classes), axis = 1)

  from sklearn.metrics import classification_report
  target_names = ["Class {}".format(i) for i in range(classes)]
  print(classification_report(test_vec, predicted_classes, target_names = target_names))

  return model

# + [markdown] id="Kc7Na087NuXS"
# <div dir='rtl'>
#
# حال از تابع تعریف شده و ضرایب مناسب برای آگمنتیشن و تغییر داده‌های ورودی جهت آموزش شبکه استفاده می‌کنیم.

# + colab={"base_uri": "https://localhost:8080/", "height": 1000} id="K4yJen86a6gq" outputId="05931a86-809f-4f58-af4b-c4c52480a1ba"
model = train_model({
    'in_drop_out':0,
    'batch':256,
    'epochs':10,
    'aug_rotation':180,
    'aug_shift_w':0.10,
    'aug_shift_h':0.10,
    'aug_shear':0.10,
    'aug_zoom':0.10,
    'aug_horizontal_flip':True
})


# + [markdown] id="xV8mN7lwOLW8"
# <div dir='rtl'>
#
#
# با مدل آموزش داده شده‌ی بالا توانستیم دقت ۹۵ درصد روی داده‌های تست به دست‌ آوریم.
#
# حال می‌خواهیم قسمت‌های آموزش‌پذیر مدل را بیش‌تر کنیم و پس تابع آموزش را دوباره تعریف می‌کنیم.

# + id="zckVVs2bq-wq"
def train_model(config):
  input = Input((150, 150, 3))
  net = InceptionV3(include_top = False, weights = 'imagenet')(input)
  net = Conv2D(2, 3,padding='same',activation='relu')(net)
  net = Conv2D(2, 3,padding='same',activation='relu')(net)
  net = GlobalAveragePooling2D()(net)
  output = Activation('softmax')(net)

  model = Model(inputs = input, outputs = output)
  #Freezing InceptionV3.
  model.layers[1].trainable=False
  model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc'])
  model.summary()


  train_datagen = ImageDataGenerator(
        rotation_range=config['aug_rotation'],
        width_shift_range=config['aug_shift_w'],
        height_shift_range=config['aug_shift_h'],
        shear_range=config['aug_shear'],
        zoom_range=config['aug_zoom'],
        horizontal_flip=config['aug_horizontal_flip'],
        fill_mode='nearest'
  )

  train_generator = train_datagen.flow(train_X, train_Label, batch_size = config['batch'])

  validation_datagen = ImageDataGenerator()
  validation_generator = validation_datagen.flow(valid_X,valid_Label,config['batch'])

  history = model.fit(train_generator,
                                validation_data=validation_generator,
                                epochs = config['epochs'],
                                batch_size=config['batch'],
                                steps_per_epoch=math.ceil(7920/config['batch']),
                                validation_steps = math.ceil(80/config['batch'])
                                )
  
  plt.plot(history.history['acc'])
  plt.plot(history.history['val_acc'])
  plt.title('Model Accuracy')
  plt.ylabel('accuracy')
  plt.xlabel('epoch')
  plt.legend(['train','validation'],loc='lower right')
  plt.show()

  test_eval = model.evaluate(test_x, test_label, verbose = 0)
  print('Test loss: ', test_eval[0])
  print('Test accuracy: ', test_eval[1])
  print('\n\n')
  
  predictes_classes = model.predict(test_x)
  predicted_classes = np.argmax(np.round(predictes_classes), axis = 1)

  from sklearn.metrics import classification_report
  target_names = ["Class {}".format(i) for i in range(classes)]
  print(classification_report(test_vec, predicted_classes, target_names = target_names))

  return model

# + [markdown] id="E6MzFU8tO9wC"
# <div dir='rtl'>
#
# در این مرحله چون تعداد متغیر‌های قابل‌اموزش مدل بیش‌تر شده بهتر است تعداد
# epoch
# های یادگیری را بیش‌تر کنیم تا شبکه زمان بیش‌تری برای ارزیابی و تطبیق شبکه با داده‌ها داشته باشد.

# + colab={"base_uri": "https://localhost:8080/", "height": 1000} id="WYOAroOrrA6B" outputId="6e97de0e-2699-4f6e-aa5b-97b98a121e12"
model = train_model({
    'in_drop_out':0,
    'batch':256,
    'epochs':30,
    'aug_rotation':180,
    'aug_shift_w':0.10,
    'aug_shift_h':0.10,
    'aug_shear':0.10,
    'aug_zoom':0.10,
    'aug_horizontal_flip':True
})

# + [markdown] id="ZW8K3Ad3PtPI"
# ## نتیجه نهایی

# + [markdown] id="YApBEmTFPvzh"
# <div dir='rtl'>
#
# در این بخش توانستیم تصاویر سگ و گربه را با استفاده از شبکه‌های عصبی کانولوشنی و وزن‌های از پیش آموزش داده شده با دقت خیلی خوبی تفکیک کرده و مدل مناسبی با صحت روی داده‌های تست 96 درصد ارائه کنیم.

StarcoderdataJupyterScriptsDedupFiltered