Проект классификации изображений кухонных принадлежностей с использованием сверточных нейронных сетей

Представьте себе мир, в котором природа постановила, что ни одно существо не должно жить за счет воды и пищи! В этом мире сущность воды и пищи не имеет значения. Больше никаких криков «Джуди» за едой. Возможно, мы не стали бы утомлять этих проницательных профессоров добавлением слова «голод» в Оксфордский словарь. Каждое существо проживает жизнь за пределами ресторанов и баров. Мы бережем палец для шеф-повара Брауна, когда нет необходимости резать лук. Анархия, которая приходит с жизнью воды и пищи, похоронена. Это спасает наши уши от шума «мне суждено быть поваром». Все мирно живут вне столпотворения ароматов. Они могут жить только в нашем воображении. И воображение породило мир искусства.

Вернуться к жизни, дарованной нам существом, за пределами секунд, проведенных в духовном царстве. Жизнь, в которой деятельность, связанная с голодом и охлаждением, приносит триллионы долларов. Одно из таких действий превратилось в подвиды деятельности, в которых каждый интеграл работал над своим собственным проектом. Следуйте за мной, пока я поднимаю ваше видение до одной из неотъемлемых частей, которые я выполнил.

Введение в проект (здесь я изобразил ситуацию Джона, которая стимулирует инновации)

Вам может быть интересно, как Джон элегантно входит в картину проекта по науке о данных. Правильно, есть чему удивиться! Позвольте мне развеять ваши мысли и поставить вещи в правильном свете. Картина, которую Джон представляет, представляет собой вымышленный момент. Я увидел ситуацию, которая привела к инновациям. Эта ситуация представляет Джона в браке с проектом Data Science, который я собираюсь вам объяснить. Давайте перейдем к краткой истории Джона. Мир метавселенной в действии!

Человек, Джон.

Джон — молодой человек, который в детстве и пальцем не пошевелил, чтобы заняться «домашними делами». Обо всем позаботились домработницы его семьи. Эти действия его семьи сделали его «НЕ ВАШИМ ПАРНИЕМ», когда дело доходит до домашних дел. Плохо, что Джон плохо разбирается в кухонных предметах. Так Джон хочет прожить остаток своей жизни? Будут ли доступны технологии, которые восполнят пробел, когда Джон решит начать жить ОДНИМ? Эти вопросы требуют ответов.

В детстве люди воспринимали Джона как «НЕ ТАК ХОРОШО». Они пришли к выводу, что ничего не будет добавлено к его имени как его личное достижение, кроме его семейного наследства. Даже родители списали его со счетов. Живя своей беззаботной жизнью, эти тревожные ощущения передавались ему в уши. Сначала он думал, что это ничего не значит. Но со временем действия окружающих его людей перекалибровали его жизнь. Он поклялся отмежеваться от вещей, переданных ему родителями. Тем самым изменив дело своей жизни.

Много лет спустя, после долгих хлопот, Джон добился успеха. «Одна вещь, которую вы не можете отнять у нас, как у людей, — это наша решимость продемонстрировать изобилие успеха». Джон не исключение. Он решил купить просторный дом. Покажите его достижения людям, которые его списали со счетов. Его первыми покоренными умами будут его родители.

Джон решил купить свой дом в богатом районе. "Вы знаете, что покупка дома может быть классифицирована как удовлетворение для самого трудолюбивого человека, в зависимости от иерархии потребностей человека. Вы играете в доме от спальни нестандартного размера до красиво обставленной гостиной, до красивой, хорошо выложенной плиткой ванной комнаты и всех дополнений, которые идут с домом. Вы берете на себя обязательство наслаждаться дизайном интерьера дома. Вы наслаждаетесь безмятежной обстановкой, наслаждаясь внешним благоустройством, окружающим дом». В совокупности это был первый опыт Джона.

Избавившись от домашних развлечений, что дальше?

Щелкнуло, что ему нужно было наполнить свой круглый пустой шар (желудок) хорошей едой. В идеале он бы заказал еду. Но он не мог из-за своего окружения. Он вошел на кухню, чтобы выполнить обещание своему желудку. Затем наступает осознание его воспитания. Он не мог понять, для чего предназначен каждый материал/предмет на кухне. Его голод перешел в другую фазу. Кто придет на помощь Джону? Какое следующее действие он должен предпринять?

Следуйте за мной, пока я расскажу вам о его благодетеле (решателе проблем).

Джон и DataTalks

При отсутствии проблемы гарантирует отсутствие решения (что случается редко). В этом случае есть проблема, которую нужно решить. Джону, со своей стороны, пришлось бродить по Интернету, чтобы найти решение своего затруднительного положения. Затем он наткнулся на DataTalks.

DataTalks — сообщество данных для Data Scientist и Machine Learning Expert. Они решают проблемы. Они видят беременные данные и родовой раствор от данных плода.

До ситуации с Джоном DataTalk организовала конкурс среди своих экспертов на разработку продукта, задача которого заключалась бы в идентификации Kitchenware. Последствия этого соревнования будут означать решение затруднительного положения Джона. Все, что нужно сделать Джону, — это сфотографировать любую кухонную утварь и загрузить ее, после чего алгоритм, разработанный экспертом, идентифицирует предмет и придумывает имя.

Я являюсь одним из участников этого проекта DataTalks. Ниже приведены шаги, которые я предпринял для создания алгоритма, который послужит основой продукта, задуманного DataTalks.

Подробнее о конкурсе здесь….

Заявление о проекте

Этот проект направлен на создание модели, которая будет классифицировать изображения различных предметов кухонной утвари по шести классам:
"чашки", "стаканы", "тарелки", "ложки", "вилки" и "ножи".

В этом проекте я намереваюсь построить алгоритм с высокой точностью для идентификации любого из вышеперечисленных классов кухонной утвари.

Источник данных проекта

Данные (примеры изображений) были получены с помощью Толока. Подробнее о Толоке здесь. Данные проекта можно оценить здесь.

Обзор набора данных проекта

Этот набор данных содержит изображения различных кухонных принадлежностей.

train.csv — обучающий набор (идентификаторы изображений и классы)
test.csv — производительность модели будет оцениваться на этом тестовом файле. Он содержит только идентификаторы изображений. Модель предсказывает классы изображений, используя предоставленные идентификаторы изображений и изображения в формате jpeg. Полученный результат будет содержаться в CSV-файле в виде файла заявки, который будет отправлен для оценки и рейтинга модели среди остальных участников.
изображения — примеры изображений, на которых будет обучаться и тестироваться модель в формате JPEG.

Учебные материалы по моделированию

Поскольку проблема проекта больше фокусируется на глубоком обучении, я буду использовать следующие учебные ресурсы:

- TensorFlow
- Keras — построен на основе TensorFlow. Это помогает нам обучать и использовать нейронные сети. Это важно для данного проекта.

Рабочий процесс проекта

Поскольку этот вариант использования проекта — это классы изображений, для эффективного прогнозирования на основе рекомендаций исторического проекта будут обучены сверточные нейронные сети. Если после изучения производительности и знаний предварительно обученной модели в этом варианте использования проекта мы обнаружим, что модель также может быть полезна для проекта, таким образом сосредоточив внимание на переносе обучения.

Краткая справка о CNN

В треках Deep Learning есть несколько аспектов, разделенных на сегменты GO-TO в зависимости от конкретного варианта использования проекта. CNN — один из их аспектов. Сверточные нейронные сети — это тип нейронных сетей, которые в основном используются для классификации изображений. Он состоит из двух разных типов слоев, упакованных в виде треков знаний во время процессов сбора информации. Один из них — сверточные слои, а другой — плотные слои.

В этом проекте я больше сосредоточусь на плотных слоях, так как намерен использовать извлеченные сверточные слои из предварительно созданного приложения (модели) в Keras. . Предполагаемое извлечение сверточных слоев из готовой модели будет преобразовано в векторное представление. Это векторное представление будет использоваться в качестве входных данных для плотных слоев, которые я планирую обучать.

Ниже приведены шаги, которые я намерен предпринять:

Шаг 1 ==> Исследование образца изображения на предварительно построенной модели

Шаг 2 ==› Обучение и оценка базовой модели

Шаг 3==› Настройка гиперпараметров базовой модели

Шаг 4==› Увеличение данных

Шаг 5==› Обучение модели на большом размере изображения

Шаг 6==› Использование наиболее эффективной модели

Поскольку я утопил ваш аппетит широким обзором моих планов действий по этому проекту, позвольте мне перейти к собственно реализации проекта. Подписывайтесь на меня!

Шаг 1: Исследование образца изображения на готовых моделях

Будут выполняться следующие процессы:

  • Загрузите образец изображения для первоначального исследования.
  • Проверьте, подходит ли предварительно созданное приложение в Keras для целей этого проекта, выполнив следующие действия:
    › — Предоставьте загруженный пример изображения приложению
    › — Сделайте прогноз изображения с помощью приложения< br /> › — Проверить вывод своего прогноза, особенно прогноз класса
    › — Сделать вывод, соответствует ли он конкретному случаю проекта
    › — И если нет, перейти к следующему шагу

Для первоначального исследования и всего жизненного цикла проекта будет принята модель Xception. Поскольку из всех готовых моделей в Keras она имеет лучший показатель точности, имеет небольшой размер и эффективное время выполнения как на ЦП, так и на ГП.

Примечание. Xception — это предварительно созданное приложение в Keras. Он был обучен на наборе данных Imagenet с 1000 классами изображений. Imagenet имеет различные комбинации различных видов объектов изображения. Таким образом, его можно использовать для классификации изображений общего назначения. Это повлияло на мое решение выбрать Xception для этого проекта.

Структура шага 1

#importing the libraries
import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt

import tensorflow as tf 
from tensorflow import keras 

from tensorflow.keras.preprocessing.image import load_img 
from tensorflow.keras.applications.xception import Xception
from tensorflow.keras.applications.xception import preprocess_input
from tensorflow.keras.applications.xception import decode_predictions
from tensorflow.keras.preprocessing.image import ImageDataGenerator

Тестирование изображения ниже в приложении Xception

# getting the file path 
path = 'data/images'
name = '0560.jpg'
fullname = f'{path}/{name}'

# load and resize
img = load_img(fullname, target_size=(299, 299))

# convert the image to a numpy array 
x = np.array(img)
# creating an array for the sample image 
X = np.array([x])
# preprocessing the input sample image
X = preprocess_input(X)

# initializing the xception model 
# (setting it's weights == imagenet), since it was on imagenet dataset 
model = Xception(weights='imagenet', input_shape=(299, 299, 3))

# making prediction on the sample preprocessed image 
pred = model.predict(X)

# decoding the model prediction 
decode_predictions(pred)

Глядя на результат прогнозов, мы видим, что прогноз модели довольно близок к классу образцов изображений. Однако сама модель прошла обучение на 1000 занятий, что выходит за рамки данного проекта. Мы намерены обучать модель с помощью отдельных 6 классов, которые не учитывались в исходной предварительно построенной модели.

С этой целью это означает, что мы не можем использовать модель Imagenet для этого проекта.

В дальнейшем я буду обучать другую модель с классами, которые нам нужны для конкретного случая проекта. Чтобы сделать этот процесс беспроблемным, в этом сценарии использования проекта будет применено переносное обучение.

Шаг 2. Обучение базовой модели

Обучение другой модели (базовой модели) на шести классах, на которых предварительно построенная модель не обучалась. Намерения для этого процесса следующие:

›› — Загрузка наборов данных проекта
›› — Разделение набора данных на наборы для обучения и проверки
›› — Повторное использование модели Xception
›› — Извлечение Сверточные слои Модель Xception
›› — Преобразование извлеченных CL в Векторное представление
›› — Предоставление `Векторного представления` в качестве входных данных для нового Плотные слои Я намерен обучать
›› — Обучать плотные слои, используя векторное представление
›› — Обучать модель, используя сопутствующие параметры обучения.

# load the training csv
# convert id column datatype to string 
df_train_full = pd.read_csv('data/train.csv', dtype={'Id': str})
# making another column (named filename)
## this contains the images file path using id's in the train csv 
df_train_full['filename'] = 'data/images/' + df_train_full['Id'] + '.jpg'

# splitting the dataset (80% train and 20% validation)
val_cutoff = int(len(df_train_full) * 0.8)
df_train = df_train_full[:val_cutoff] 
df_val = df_train_full[val_cutoff:]

# read and generate the train and validation data 
## Note: preprocessing_function parameter will be set to preprocess_input module
## used for Xception model
############## Training Data ####################
train_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)
train_gen = train_datagen.flow_from_dataframe(
    df_train,
    x_col='filename',
    y_col='label',
    target_size=(150, 150),
    batch_size=32,
)
############ Validation Data ####################
val_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)
val_gen = val_datagen.flow_from_dataframe(
    df_val,
    x_col='filename',
    y_col='label',
    target_size=(150, 150),
    batch_size=32,
)

Я хочу обучить и инициализировать базовую модель с сопутствующими параметрами.

Примечание:
- Xception – это приложение Keras, которое мы намерены внедрить.
 - Поскольку Xception был обучен на наборе данных Imagenet, параметр веса будет установлено значение «Imagenet»
— проект фокусируется на трансферном обучении, поэтому в модели Xception его плотные слои будут удалены путем установки параметра `include_top` как «False»
— Input_shape изображениям будет установлено значение `(150, 150, 3)`:- поможет быстрее обучить модель
- Чтобы модель не обучалась заново, для базовой модели будет установлено значение `False`
- Выходные данные сверточных слоев базовой модели будут преобразованы в векторное представление с использованием `Pooling`
- Затем для выходных данных плотных слоев (которые мы намереваемся тренировать) будет установлено значение 6 (поскольку классы проекта: 6) с использованием векторов преобразования в качестве входных данных

# base model
base_model = Xception(
    weights='imagenet',
    include_top=False,
    input_shape=(150, 150, 3)
)
base_model.trainable = False
# input dependency
inputs = keras.Input(shape=(150, 150, 3))
base = base_model(inputs, training=False)
# converting the CL's to Vector representation
vectors = keras.layers.GlobalAveragePooling2D()(base) 
outputs = keras.layers.Dense(6)(vectors)
model = keras.Model(inputs, outputs)

######### Model Optimizer ############
# Using Adam optimizer with learning rate at 0.01 
optimizer = keras.optimizers.Adam(learning_rate=0.01)

######## Model Loss #########
# Using CategoricalCrossentropy
# Setting logits to True, since we want categorical result not probability
loss = keras.losses.CategoricalCrossentropy(from_logits=True)

######## Model Compiler #########
# Compiling the model with optimizer, loss, and metrics evaluation 
model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])

# fitting and training the model with 10 epoch 
history = model.fit(
    train_gen,
    epochs=10,
    validation_data=val_gen
)

Визуализация результата

# plotting the performance for each epoch 
plt.plot(history.history['accuracy'], label='train')
plt.plot(history.history['val_accuracy'], label='validation')
plt.legend()

Судя по приведенным выше изображениям, существует большой разрыв между точностью поезда и проверкой. Вы можете видеть, что производительность модели была наилучшей с 6 по 7 эпохи с соответствующим увеличением показателей val_loss. Самая низкая модель была в эпохе 5. Производительность модели все еще может быть улучшена для достижения вехи точности проекта, принимая во внимание вклад более низкого показателя val_loss. Используя эту информацию, полученную в результате работы базовой модели, мы выполним настройку гиперпараметров для некоторых параметров модели.

Шаг 3: Настройка гиперпараметров базовой модели

  • Поэкспериментируйте, регулируя скорость обучения с различными значениями скорости обучения (будет выбрана лучшая скорость обучения)
  • Поэкспериментируйте, добавив в сети внутренние плотные слои. Обратите внимание, что отсев будет введен в этом аспекте с другими значениями.
  • Проверка процессов для сохранения лучшей модели

Мы должны знать, что гипернастройка параметров не является воротами для того, чтобы плохая модель стала хорошей. Что он делает, так это улучшает свою производительность по сравнению с тем, когда никакая настройка не проводилась.

Экспериментирование скорости обучения модели с различными значениями по сравнению с производительностью модели для каждого значения скорости обучения (будет выбрана лучшая скорость обучения)

# defining a function 

def make_model(learning_rate=0.01):
  base_model = Xception(
      weights='imagenet', 
      include_top=False, 
      input_shape= (150, 150, 3)
  )

  base_model.trainable = False

  ################################################

  inputs = keras.Input(shape=(150, 150, 3))
  base = base_model(inputs, training=False)
  vectors = keras.layers.GlobalAveragePooling2D()(base)
  outputs = keras.layers.Dense(6)(vectors)
  model = keras.Model(inputs, outputs)

  ################################################

  optimizer = keras.optimizers.Adam(learning_rate=learning_rate)
  loss = keras.losses.CategoricalCrossentropy(from_logits=True)

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

  
  return model

# iterating over different values of learning rate 

scores = {}

for lr in [0.0001, 0.001, 0.01, 0.1]:
  print(lr)

  model = make_model(learning_rate=lr)
  history = model.fit(train_gen, epochs=10, validation_data=val_gen)
  scores[lr] = history.history

  print()
  print()

Визуальное представление производительности

На изображении мы видим, что скорость обучения, которая оказалась лучше всех экспериментальных скоростей обучения, составила «lr ==> 0,001». Однако `lr ==› 0,0001` можно отметить для более сложного обучения. Визуальное изображение точности проверки интерпретирует, что 0,001 л достигла максимальной и наилучшей производительности в «эпохе 4». Он также показал лучшие результаты, судя по его «оценкам потерь при проверке». Модель получила скачок по сравнению с предыдущей производительностью ранее обученной базовой модели.

С учетом этих эмпирических данных в дальнейшем скорость обучения будет установлена ​​на уровне «0,001». Безопасно ли откладывать наши эксперименты здесь? Нет, производительность модели еще можно улучшить. Давайте двигаться вперед!

Поэкспериментируйте, добавив в сети внутренние плотные слои

Идея заключается в том, чтобы добавить еще один слой (внутренний плотный слой) между входным векторным представлением и выходным плотным слоем. Что это делает, так это выполняет некоторую промежуточную обработку представления входного вектора, и выходные данные этого слоя будут переданы в выходной плотный слой.

Мы хотим, чтобы модель была более мощной и изучала некоторое внутреннее представление из предоставленного ввода (VR).

Задание:
 – Использование внутренних плотных слоев разных размеров (будет выбрана наилучшая комбинация)
 – Установка скорости обучения на `0,001`
- Добавить функцию активации (в данном случае `RELU`(Выпрямленная линейная единица)) во внутренний слой. Это обработает выходные данные плотного вектора.
 – Экспериментируйте с регуляризацией и отсевом.

В исследовании использовались различные методы для определения наилучшего подхода к улучшению производительности модели. Чтобы избежать длинной заметки и трудоемкой статьи, эти процессы не будут выделены здесь. Чтобы получить полное представление об этих процессах, щелкните здесь в блокноте проекта, чтобы получить общее представление о процессах настройки гиперпараметров проекта.

Ниже приведены результаты экспериментов по добавлению внутренних плотных слоев вместе с сопровождающими их параметрами после долгих исследований.

# defining a function 

def make_model(learning_rate=0.0001, droprate=0.2):
  base_model = Xception(weights='imagenet', 
                        include_top=False, 
                        input_shape= (150, 150, 3))

  base_model.trainable = False

  ############## Vector Representation ###########################

  inputs = keras.Input(shape=(150, 150, 3))
  base = base_model(inputs, training=False)
  vectors = keras.layers.GlobalAveragePooling2D()(base)

  ############## Inner Dense Layer #################

  first_inner = keras.layers.Dense(units=256, activation='relu')(vectors)
  first_drop = keras.layers.Dropout(droprate)(first_inner)
  second_inner = keras.layers.Dense(units=128, activation='relu')(first_drop)
  second_drop = keras.layers.Dropout(droprate)(second_inner)

  ############## Output ##################

  outputs = keras.layers.Dense(6)(second_drop)
  model = keras.Model(inputs, outputs)

  ################################################

  optimizer = keras.optimizers.Adam(learning_rate=learning_rate)
  loss = keras.losses.CategoricalCrossentropy(from_logits=True)

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

  
  return model
# training the model
model = make_model()
history = model.fit(
    train_gen, 
    epochs=20, 
    validation_data=val_gen)

Визуальное представление производительности

# plotting the performance for each epoch 
plt.plot(history.history['accuracy'], label='train')
plt.plot(history.history['val_accuracy'], label='validation')
plt.legend()

Повторные исследования внутренних плотных слоев показывают в их сводных отчетах небольшое улучшение производительности модели. Тем не менее, по-прежнему существует большой разрыв между точностью обучающих и проверочных наборов. Теперь вопрос в том, можно ли улучшить эти характеристики и повысить точность обучения и проверки? Этот вопрос требует ответа. Одной из таких технологий, которую мы можем использовать, является Увеличение данных. Может ли большее количество данных улучшить производительность модели? Давайте исследуем это!

Шаг 4: Увеличение данных

Идея Data Augmentation состоит в том, чтобы создать больше вариантов данных из существующего набора данных. Это определит, поможет ли создание дополнительных данных из существующего набора данных улучшить производительность модели.

Когда вы проверите ноутбук проекта, вы увидите, что мы развернули настройку гиперпараметров отсева при регуляризации модели, чтобы избежать переобучения модели. Другой метод, который можно использовать вместо исключения, – Увеличение данных. Это позволяет избежать случаев, когда модель будет видеть похожие изображения во время обучения, а также побеждает случаи, когда модель запоминает.

Чтобы сделать это, я буду следовать приведенным ниже рекомендациям по преобразованию изображения:
- Flip ==› горизонтальное, вертикальное отражение или и то, и другое.
- Вращение
- Сдвиг ==› вверх, вниз, вправо и влево
- Сдвиг
- Масштаб (приближение/отдаление)

Методы увеличения, которые будут использоваться, будут основаны на сценарии использования изображения для этого проекта.

После долгих исследований каждого метода увеличения я обнаружил, что следующие параметры и сопровождающие их аргументы улучшили производительность модели:

rotate_range = 30
shear_range = 20
width_shift_range = 10
height_shift_range = 10
zoom_range = 0,1

Загляните в блокнот, для всестороннего понимания процессов.

# defining a function 

def make_model(learning_rate=0.0001, droprate=0.2):
  base_model = Xception(weights='imagenet', 
                        include_top=False, 
                        input_shape= (150, 150, 3))

  base_model.trainable = False

  ############## Vector Representation ###########################

  inputs = keras.Input(shape=(150, 150, 3))
  base = base_model(inputs, training=False)
  vectors = keras.layers.GlobalAveragePooling2D()(base)

  ############## Inner/Hidden Dense Layer #################

  first_inner = keras.layers.Dense(units=256, activation='relu')(vectors)
  first_drop = keras.layers.Dropout(droprate)(first_inner)
  second_inner = keras.layers.Dense(units=128, activation='relu')(first_drop)
  second_drop = keras.layers.Dropout(droprate)(second_inner)

  ############## Output ##################

  outputs = keras.layers.Dense(6)(second_drop)
  model = keras.Model(inputs, outputs)

  ################################################

  optimizer = keras.optimizers.Adam(learning_rate=learning_rate)
  loss = keras.losses.CategoricalCrossentropy(from_logits=True)

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

  
  return model

# investigating with different droprates 

scores = {}
for droprate in [0.0, 0.2]:
  print(droprate)
  model = make_model(
      learning_rate=learning_rate, 
      droprate=droprate)
  history = model.fit(
      all_train_gen, 
      epochs=20, 
      validation_data=val_gen)
  scores[droprate] = history.history
  print()
  print()

Визуальное представление производительности

plt.figure(figsize = [9, 7])

# droprate 0.0
plt.subplot(2, 1, 1)
hist = scores[0.00]
droprate = 0.0
plt.plot(hist['val_accuracy'], label=('val=%s' % droprate))
plt.plot(hist['accuracy'], label=('train=%s' % droprate))
plt.title('Training Vs Validation Accuracy for Droprate 0.0')
plt.legend();


# droprate 0.2
plt.subplot(2, 1, 2)
hist = scores[0.20]
droprate = 0.2
plt.plot(hist['val_accuracy'], label=('val=%s' % droprate))
plt.plot(hist['accuracy'], label=('train=%s' % droprate))
plt.title('Training Vs Validation Accuracy for Droprate 0.2')
plt.legend();

Приведенный выше случай показывает, что модель не является стабильной, судя по ее производительности для обоих коэффициентов выпадения при 0 и 0,2. Можем ли мы еще улучшить производительность? Давайте обучим большую модель с большим размером изображения.

Шаг 5: Обучение модели на больших размерах изображений

Когда мы начали обучать модель, мы обучили ее размеру входного изображения 150 x 150. Нашей основной целью при выборе размера изображения было обучение более быстрой модели. После обучения и настройки гиперпараметров мы так и не достигли поставленной цели. Что мы можем сделать, чтобы достичь этого? Я решил обучить гораздо более медленную модель, почти удвоив время обучения по сравнению с ранее обученной моделью.

Эта модель будет обучаться на изображении размером 299 x 299.

TO-DO:
 – Обучение без увеличения данных.
 – Обучение с добавлением данных.
 – Проверка наиболее эффективной модели.

Обучение без увеличения данных

input_size = 299
############## Data Augmentation Training Data ####################
large_train_datagen = ImageDataGenerator(
    preprocessing_function=preprocess_input
    )
larger_train_gen = large_train_datagen.flow_from_dataframe(
    df_train,
    x_col='filename',
    y_col='label',
    target_size=(input_size, input_size),
    batch_size=32,
)
############ Validation Data ####################
val_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)
val_gen = val_datagen.flow_from_dataframe(
    df_val,
    x_col='filename',
    y_col='label',
    target_size=(input_size, input_size),
    batch_size=32,
)
# defining a function 
def make_model(input_size = 299, learning_rate=0.0001, droprate=0.2):
  base_model = Xception(weights='imagenet', 
                        include_top=False, 
                        input_shape= (input_size, input_size, 3))

  base_model.trainable = False
  ############## Vector Representation ###########################
  inputs = keras.Input(shape=(input_size, input_size, 3))
  base = base_model(inputs, training=False)
  vectors = keras.layers.GlobalAveragePooling2D()(base)
  ############## Inner/Hidden Dense Layer #################
  first_inner = keras.layers.Dense(units=256, activation='relu')(vectors)
  first_drop = keras.layers.Dropout(droprate)(first_inner)
  second_inner = keras.layers.Dense(units=128, activation='relu')(first_drop)
  second_drop = keras.layers.Dropout(droprate)(second_inner)
  ############## Output ##################
  outputs = keras.layers.Dense(6)(second_drop)
  model = keras.Model(inputs, outputs)
  ################################################
  optimizer = keras.optimizers.Adam(learning_rate=learning_rate)
  loss = keras.losses.CategoricalCrossentropy(from_logits=True)

  model.compile(optimizer=optimizer, 
                loss=loss, 
                metrics=['accuracy']) 
  return model

# investigating with different droprates 
scores = {}

for droprate in [0.0, 0.2]:
  print(droprate)

  model = make_model(
      input_size = input_size, 
      droprate=droprate)
  history = model.fit(
      larger_train_gen, 
      epochs=20, 
      validation_data=val_gen)
  scores[droprate] = history.history
  print()
  print()

Визуальные представления производительности (точность и потери)

plt.figure(figsize = [9, 7])
# droprate 0.0
plt.subplot(2, 1, 1)
hist = scores[0.00]
droprate = 0.0
plt.plot(hist['val_accuracy'], label=('val=%s' % droprate))
plt.plot(hist['accuracy'], label=('train=%s' % droprate))
plt.title('Training Vs Validation Accuracy for Droprate 0.0')
plt.legend();
# droprate 0.2
plt.subplot(2, 1, 2)
hist = scores[0.20]
droprate = 0.2
plt.plot(hist['val_accuracy'], label=('val=%s' % droprate))
plt.plot(hist['accuracy'], label=('train=%s' % droprate))
plt.title('Training Vs Validation Accuracy for Droprate 0.2')
plt.legend();

# Loss Score 
plt.figure(figsize = [12, 10])
# droprate 0.0
plt.subplot(2, 1, 1)
hist = scores[0.00]
droprate = 0.0
plt.plot(hist['val_loss'], label=('val=%s' % droprate))
plt.plot(hist['loss'], label=('train=%s' % droprate))
plt.title('Training Vs Validation Loss for Droprate 0.0')
plt.legend();
# droprate 0.2
plt.subplot(2, 1, 2)
hist = scores[0.20]
droprate = 0.2
plt.plot(hist['val_loss'], label=('val=%s' % droprate))
plt.plot(hist['loss'], label=('train=%s' % droprate))
plt.title('Training Vs Validation Loss for Droprate 0.2')
plt.legend();

В отличие от случая, когда модель использовала размер входного изображения (150 x 150), модель учится и работает лучше всего при обучении на изображении большего размера. Сравнивая его производительность как при обучении, так и при проверке, мы можем согласиться с тем, что разрыв между точностью обучения и проверки меньше при частоте отбрасывания 0,2%. Это также дает нам стабильно низкие потери при проверке. Благодаря этим результатам, веха для этого проекта была достигнута.

Давайте посмотрим, сможем ли мы увидеть улучшение производительности модели, добавив к ее обучению дополнение данных.

Обучение дополнению данных

input_size = 299
############## Data Augmentation Training Data ####################
large_train_datagen = ImageDataGenerator(
    preprocessing_function=preprocess_input, 
    rotation_range = 30,
    shear_range = 20,
    width_shift_range = 10,
    height_shift_range = 10,
    zoom_range = 0.1
    )
larger_train_gen = large_train_datagen.flow_from_dataframe(
    df_train,
    x_col='filename',
    y_col='label',
    target_size=(input_size, input_size),
    batch_size=32,
)
############ Validation Data ####################
val_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)
val_gen = val_datagen.flow_from_dataframe(
    df_val,
    x_col='filename',
    y_col='label',
    target_size=(input_size, input_size),
    batch_size=32,
)
# defining a function 
def make_model(input_size = 299, learning_rate=0.0001, droprate=0.2):
  base_model = Xception(weights='imagenet', 
                        include_top=False, 
                        input_shape= (input_size, input_size, 3))

  base_model.trainable = False
  ############## Vector Representation ###########################
  inputs = keras.Input(shape=(input_size, input_size, 3))
  base = base_model(inputs, training=False)
  vectors = keras.layers.GlobalAveragePooling2D()(base)
  ############## Inner/Hidden Dense Layer #################
  first_inner = keras.layers.Dense(units=256, activation='relu')(vectors)
  first_drop = keras.layers.Dropout(droprate)(first_inner)
  second_inner = keras.layers.Dense(units=128, activation='relu')(first_drop)
  second_drop = keras.layers.Dropout(droprate)(second_inner)
  ############## Output ##################
  outputs = keras.layers.Dense(6)(second_drop)
  model = keras.Model(inputs, outputs)
  ################################################
  optimizer = keras.optimizers.Adam(learning_rate=learning_rate)
  loss = keras.losses.CategoricalCrossentropy(from_logits=True)

  model.compile(optimizer=optimizer, 
                loss=loss, 
                metrics=['accuracy']) 
  return model

# investigating with different droprates 
scores = {}
# saving the model (version 2(299))
checkpoint = keras.callbacks.ModelCheckpoint(
    'xception_v2_299_{epoch:02d}_{val_accuracy:.3f}.h5',
    save_best_only=True,
    monitor = 'val_accuracy',
    mode = 'max'
    )
for droprate in [0.0, 0.2]:
  print(droprate)

  model = make_model(
      input_size = input_size, 
      droprate=droprate)
  history = model.fit(
      larger_train_gen, 
      epochs=20, 
      validation_data=val_gen,
      callbacks = [checkpoint])
  scores[droprate] = history.history

  print()
  print()
plt.figure(figsize = [9, 7])
# droprate 0.0
plt.subplot(2, 1, 1)
hist = scores[0.00]
droprate = 0.0
plt.plot(hist['val_accuracy'], label=('val=%s' % droprate))
plt.plot(hist['accuracy'], label=('train=%s' % droprate))
plt.title('Training Vs Validation Accuracy for Droprate 0.0')
plt.legend();
# droprate 0.2
plt.subplot(2, 1, 2)
hist = scores[0.20]
droprate = 0.2
plt.plot(hist['val_accuracy'], label=('val=%s' % droprate))
plt.plot(hist['accuracy'], label=('train=%s' % droprate))
plt.title('Training Vs Validation Accuracy for Droprate 0.2')
plt.legend();

# Loss Score 
plt.figure(figsize = [12, 10])
# droprate 0.0
plt.subplot(2, 1, 1)
hist = scores[0.00]
droprate = 0.0
plt.plot(hist['val_loss'], label=('val=%s' % droprate))
plt.plot(hist['loss'], label=('train=%s' % droprate))
plt.title('Training Vs Validation Loss for Droprate 0.0')
plt.legend();
# droprate 0.2
plt.subplot(2, 1, 2)
hist = scores[0.20]
droprate = 0.2
plt.plot(hist['val_loss'], label=('val=%s' % droprate))
plt.plot(hist['loss'], label=('train=%s' % droprate))
plt.title('Training Vs Validation Loss for Droprate 0.2')
plt.legend();

Визуальные представления производительности (точность и потери)

Это подтверждает, что использование изображения размером 299 x 299 в сочетании с некоторыми методами увеличения данных повышает производительность модели. Модель, которую я буду развертывать, будет моделью с точностью проверки 0,967, оценкой потерь при проверке 0,1101 и вероятностью отбрасывания 0,0 в эпоху 15. При использовании этой модели при сравнении оценки точности обучения и проверки мы видим, что модель не учится намного быстрее на обучающих данных, чем на наборе данных проверки. Таким образом, делая оценки более близкими по рангу.

Теперь, когда мы построили модель с высокой точностью, что дальше? Давайте проверим модель!

Шаг 6: Использование/тестирование наиболее эффективной модели

TO-DO:

  • Загрузка модели
  • Оценка модели на некоторых изображениях
  • Получение прогнозов
# Loading the model 
model = keras.models.load_model('xception_v2_299_15_0.967.h5')
# getting the file path of the sample images for testing
path = 'data/images'
glass = '0560.jpg'
plate = '0014.jpg'
knife = '0013.jpg'
cup = '0009.jpg'
spoon = '0005.jpg'
fork = '0036.jpg'

glasspath = f'{path}/{glass}'
platepath = f'{path}/{plate}'
knifepath = f'{path}/{knife}'
cuppath = f'{path}/{cup}'
spoonpath = f'{path}/{spoon}'
forkpath = f'{path}/{fork}'

# loading and resizing the images
glass_img = load_img(glasspath, target_size=(299, 299))
plate_img = load_img(platepath, target_size=(299, 299))
knife_img = load_img(knifepath, target_size=(299, 299))
cup_img = load_img(cuppath, target_size=(299, 299))
spoon_img = load_img(spoonpath, target_size=(299, 299))
fork_img = load_img(forkpath, target_size=(299, 299))

# image preprocessing

# glass image
x1 = np.array(glass_img)
X1 = np.array([x1])
X1 = preprocess_input(X1)
# plate image
x2 = np.array(plate_img)
X2 = np.array([x2])
X2 = preprocess_input(X2)
# knife image
x3 = np.array(knife_img)
X3 = np.array([x3])
X3 = preprocess_input(X3)
# cup image
x4 = np.array(cup_img)
X4 = np.array([x4])
X4 = preprocess_input(X4)
# spoon image
x5 = np.array(spoon_img)
X5 = np.array([x5])
X5 = preprocess_input(X5)
# fork image
x6 = np.array(fork_img)
X6 = np.array([x6])
X6 = preprocess_input(X6)

Прогнозы модели

# getting the image classes 
classes = ['cup', 'forks', 'glass', 'knife', 'plate', 'spoon']

Судя по всем предсказаниям модели, она 100 % точна. Мы можем быть уверены, что теперь модель может быть развернута.

Теперь, когда мы создали рабочую модель, точность прогнозирования которой составляет 96 %, что дальше?

Мы только что закончили первую фазу рабочего процесса проекта. Модель, созданная без развертывания в рабочей среде, также бесполезна. На этом этапе, если модель не развернута, Джону следует просто принять свою веру, потому что решения пока нет. Было бы не так уж плохо, если бы Джон постился один день, а на следующий день он смог бы найти альтернативу своему голоду.

Однако в интересах забора воды из сухой скважины рабочий процесс этого проекта перейдет к следующему этапу. Создание решения на основе этой модели будет выгодно как поставщику решения, так и получателю решения в зависимости от деловой и финансовой хватки поставщика решения.

Чтобы узнать больше о процессах развертывания модели, нажмите здесь.