Вводное руководство по концепциям и моделям классификации изображений

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

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

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

Оттенки серого

Изображение в градациях серого — это изображение, в котором значение каждого пикселя представляет собой один образец, представляющий только количество света; то есть он несет только информацию об интенсивности. Изображения в оттенках серого, разновидность черно-белого или серого монохрома, состоят исключительно из оттенков серого. Контраст варьируется от черного при самой слабой интенсивности до белого при самой сильной. — Википедия

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

RGB

Изображение RGB, иногда называемое изображением в истинном цвете, хранится в виде массива данных размером m на n на 3, который определяет компоненты красного, зеленого и синего цветов для каждого отдельного пикселя. — Источник

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

Изображения RGB имеют три канала ([m x n x 3]), каждый из которых представляет значения интенсивности красного цвета, значения интенсивности зеленого цвета и значения интенсивности синего цвета соответственно. Обратите внимание, что существуют и другие форматы цветных изображений, но два наиболее распространенных формата — это RGB и BGR (обратный формат RGB, который чаще всего используется для изображений, снятых на старых устройствах).

Варианты использования классификации изображений

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

Здравоохранение

Индустрия здравоохранения давно стремится свести к минимуму человеческие ошибки при анализе различных форм медицинских данных. В последние годы это часто означало обращение за помощью к технологическим прорывам. Глубокое обучение имеет множество применений в сфере здравоохранения, но, в частности, классификация изображений оказалась полезной при интерпретации рентгеновских снимков и компьютерной томографии. Некоторые конкретные варианты использования включают: скрининг рака молочной железы, рентгенографический анализ легких COVID-19, сегментацию изображений сердца для расчета кровотока и многое другое.

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

Розничная торговля

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

Методы распознавания изображений и обнаружения объектов могут помочь потребительским брендам стандартизировать проверки магазинов и получать согласованные результаты по всем каналам продаж, что позволяет им уверенно принимать бизнес-решения на основе данных о полках. —КДнаггетс

И теперь, когда Amazon Go запущен, он поднял планку для других розничных продавцов, чтобы также включить классификацию изображений для покупок!

Безопасность

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

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

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

Автономное вождение

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

Автономное вождение требует надежного и точного обнаружения и распознавания окружающих объектов в реальных условиях движения. — Источник

Визуальный поиск

Вы видели Google Image Search, поисковую систему, которая использует предоставленные пользователями изображения в качестве входных данных и визуально ищет в Интернете похожие изображения в качестве выходных данных?

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

Платформы социальных сетей

Платформы социальных сетей также имеют классификацию изображений, встроенную в их технологию. Вы когда-нибудь загружали изображение в Facebook или Instagram и замечали, что платформа автоматически предлагает имена людей на изображении? Это распознавание лиц, подмножество идентификации изображений.

Распознавание изображений также может помочь маркетологам находить изображения конкретных брендов в социальных сетях для различных целей.

Фотографии, которыми люди делятся в социальных сетях, отражают поведение, желания и потребности потребителей, которые часто остаются незамеченными маркетологами. — Источник

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

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

ВГГ-16

ВГГ-16 предложили Карен Симонян и Андрей Зиссерман. В своей знаменитой статье они исследовали влияние глубины свертки на точность. Эта модель была обучена крупномасштабным настройкам распознавания изображений, и каждое изображение было пропущено через стек сверточных слоев.

Модель была представлена ​​на ILSVRC-2014 и обучена с использованием набора данных ImageNet. Размер входного изображения фиксируется на [224, 224, 3], и единственная выполняемая предварительная обработка заключается в вычитании среднего значения RGB из каждого пикселя. Модель состоит из нескольких сверточных слоев с небольшими фильтрами восприимчивого поля размера [3, 3] и одной конфигурации сверточных фильтров [1, 1], которые использовались для линейных преобразований. Шаг свертки (то есть сдвиг пикселя по входной матрице) фиксируется на один пиксель. Максимальное количество слоев объединения было включено для выполнения пространственного объединения. За стеком сверточных слоев следуют три полносвязных слоя; первые два из этих слоев имеют по 4096 каналов каждый, а последний — 1000 каналов. Последний и последний уровень в модели VGG использует слой активации softmax.

Теперь, когда у вас есть общее представление об архитектуре VGG-16, давайте обучим модель на этом наборе данных классификации цветов от Kaggle.

Сначала мы загрузим набор данных и пометим изображения:

! pip install -q kaggle
from google.colab import files
#Upload kaggle.json - access key file
files.upload()
! mkdir ~/.kaggle
! cp kaggle.json ~/.kaggle/
! kaggle datasets download -d alxmamaev/flowers-recognition
! unzip flowers-recognition.zip -d flowers-recognition
from tqdm import tqdm
import os
import cv2
import numpy as np
X=[]
Z=[]
IMG_SIZE=224
FLOWER_DAISY_DIR='/content/flowers-recognition/flowers/daisy'
FLOWER_SUNFLOWER_DIR='/content/flowers-recognition/flowers/sunflower'
FLOWER_TULIP_DIR='/content/flowers-recognition/flowers/tulip'
FLOWER_DANDI_DIR='/content/flowers-recognition/flowers/dandelion'
FLOWER_ROSE_DIR='/content/flowers-recognition/flowers/rose'
def assign_label(img,flower_type):
    return flower_type
def collect_train_data(flower_type,DIR):
    for img in tqdm(os.listdir(DIR)):
        label=assign_label(img,flower_type)
        path = os.path.join(DIR,img)
        img = cv2.imread(path,cv2.IMREAD_COLOR)
        img = cv2.resize(img, (IMG_SIZE,IMG_SIZE))
        
        X.append(np.array(img))
        Z.append(str(label))
collect_train_data('Daisy',FLOWER_DAISY_DIR)
collect_train_data('Sunflower',FLOWER_SUNFLOWER_DIR)
collect_train_data('Tulip',FLOWER_TULIP_DIR)
collect_train_data('Dandelion',FLOWER_DANDI_DIR)
collect_train_data('Rose',FLOWER_ROSE_DIR)

Далее мы закодируем метки и разделим данные на наборы для обучения и тестирования:

import random
import numpy as np
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
le=LabelEncoder()
Y=le.fit_transform(Z)
Y=to_categorical(Y, 5)
X=np.array(X)
X= X/255
X_train, X_test, Y_train, Y_test= train_test_split(X,
                                                   Y, 
                                                   test_size= 0.2, 
                                                   random_state= 42)

Теперь загрузим предварительно обученную модель VGG-16:

import tensorflow as tf
import keras

vgg16_model=tf.keras.applications.vgg16.VGG16(include_top=False,
                                            input_shape=(224,224,3), 
                                            pooling='avg')
vgg16_model.summary()

Теперь мы будем использовать концепции трансферного обучения и добавим последние слои модели:

from keras.utils.np_utils import to_categorical
from keras.optimizers import RMSprop
from keras.models import Sequential
from keras.layers import Conv2D, MaxPool2D, Flatten,Dense, Dropout
from keras.callbacks import ReduceLROnPlateau
from keras.preprocessing.image import ImageDataGenerator
model=Sequential()
model.add(vgg16_model)
model.add(Dense(256, activation='relu'))
model.add(Dense(5, activation='softmax'))
model.summary()
for layer in vgg16_model.layers[:15]:
    layer.trainable=False
for layer in vgg16_model.layers[15:]:
    layer.trainable=True

Теперь давайте скомпилируем модель и обучим ее:

model.compile(optimizer=Adam(learning_rate=1e-4),
              loss='categorical_crossentropy',
              metrics=['accuracy'])
datagen = ImageDataGenerator(
        rotation_range=10,  
        zoom_range = 0.1, 
        width_shift_range=0.2,
        height_shift_range=0.2,  
        horizontal_flip=True)
datagen.fit(X_train)
history=model.fit(datagen.flow(X_train,Y_train,batch_size=120),
                              epochs=5,
                              validation_data=(X_test,Y_test),
                              verbose=1,
                              steps_per_epoch=X_train.shape[0]//120)

Есть много способов улучшить точность модели отсюда. Но теперь, когда мы узнали, насколько просто начать работу с моделью классификации изображений, давайте попробуем еще несколько!

Реснет50

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

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

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

ResNet50 — это более глубокая версия ResNet. Для каждой функции невязки использовался стек из 3 сверточных слоев — 1x1, 3x3 и 1x1.

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

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

  • Размер первого слоя свертки составляет 7x7 с 64 различными каналами и шагом в два.
  • Следующий слой свертки состоит из слоя максимального объединения, за которым следуют три прохода трех ядер, каждое из которых имеет размер (1, 1, 64), (3, 3, 64) и (1, 1, 256) соответственно.
  • Следующий слой свертки состоит из четырех повторений трех ядер размеров (1, 1, 128), (3, 3, 128) и (1, 1, 512) соответственно.
  • Следующий слой свертки состоит из шести повторений трех ядер размеров (1, 1, 256), (3, 3, 256) и (1, 1, 1024) соответственно.
  • Следующий слой свертки состоит из трех повторений трех ядер размеров (1, 1, 512), (3, 3, 512) и (1, 1, 2048) соответственно.
  • За сверточными слоями следует средний объединяющий слой.
  • Последний слой — полносвязный (плотный) слой, содержащий 1000 узлов.

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

from tensorflow.keras.applications.resnet50 import ResNet50
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,BatchNormalization,Flatten
from tensorflow.keras.preprocessing.image import ImageDataGenerator
model = Sequential()
model.add(ResNet50(include_top= False, pooling= 'avg'))
model.add(Flatten())
model.add(BatchNormalization())
model.add(Dense(256, activation= 'relu'))
model.add(BatchNormalization())
model.add(Dense(256, activation= 'relu'))
model.add(BatchNormalization())
model.add(Dense(5, activation= 'softmax'))
model.layers[0].trainable = False
# Compile model
vmodel.compile(optimizer=Adam(learning_rate= 0.001), 
               loss= 'categorical_crossentropy', 
               metrics= ['accuracy'])
datagen = ImageDataGenerator(
               rotation_range= 10, 
               zoom_range= 0.1,
               width_shift_range= 0.1,
               height_shift_range= 0.1)
datagen.fit(X_train)
history= model.fit(datagen.flow(X_train, Y_train, batch_size= 32),
                   epochs= 20,
                   validation_data= (X_test, Y_test),
                   verbose= 1,
                   steps_per_epoch= 100)

Подскажите инженерную плюс Комету плюс Градио? На выходе получается потрясающее искусство, созданное искусственным интеллектом! Присмотритесь повнимательнее к нашему проекту публичного ведения журналов, чтобы увидеть некоторые удивительные творения, появившиеся в результате этого забавного эксперимента.

НачалоV3

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

В третьей версии авторы включили всю структуру V2, а также следующие атрибуты и обновления:

  1. Регуляризация сглаживания меток (LSR): LSR полезна на начальном этапе, поскольку модели могут быть слишком уверенными, если есть небольшие ошибки теста.
  2. RMSProp.RMSprop — это оптимизатор на основе градиента, то есть он может помочь ускорить оптимизацию для определения правильных градиентов. Он использует адаптивную скорость обучения, которая меняется со временем и в зависимости от данных.
  3. Факторизированная свертка 7x7. Традиционная свертка 7x7 была разбита на три слоя свертки 3x3 для V3.
  4. Вспомогательная пакетная нормализация.При использовании BN-Auxiliary полностью связанный слой вспомогательного классификатора также подвергается пакетной нормализации и действует как регуляризация.

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

Посмотрим, насколько эффективно эта модель будет работать с нашими данными:

from tensorflow.keras import layers
from tensorflow.keras import Model
from tensorflow.keras.optimizers import RMSprop
import tensorflow as tf
inception_model=tf.keras.applications.InceptionV3(include_top=False,
                                            input_shape=(224,224,3))
for layer in inception_model.layers:
    layer.trainable=False
x = inception_model.output
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(1024)(x)
x = layers.BatchNormalization()(x)
x = layers.Activation('relu')(x)
x = layers.Dense(5, activation= 'softmax')(x)
model = tf.keras.Model(inception_model.input, x)
model.compile(optimizer= RMSprop(lr= 0.001),
              loss= 'categorical_crossentropy',
              metrics= ['accuracy'])
datagen = ImageDataGenerator(
                rotation_range= 10, 
                zoom_range= 0.1,
                width_shift_range= 0.1,
                height_shift_range= 0.1)

В приведенной выше модели мы добавили несколько вещей перед ее компиляцией:

  1. Глобальный средний объединяющий слой;
  2. Полностью связанный слой с 1024 скрытыми единицами;
  3. Вспомогательный классификатор пакетной нормализации, за которым следует слой активации;
  4. Финальный полносвязный слой с функцией активации Softmax;
  5. Оптимизатор RMSProp.
history= model.fit(datagen.flow(X_train,Y_train,batch_size= 24),
                                epochs= 5,
                                validation_data= (X_test, Y_test),
                                verbose= 1,
                                steps_per_epoch= 100)

Эффективная сеть

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

В этом методе составного масштабирования размеры масштабируются с постоянным соотношением (т. Е. С использованием набора фиксированных коэффициентов). Так, например, если мы хотим увеличить вычислительные ресурсы на 2 ^ N, то размерность будет увеличена как: ширина 𝞪 ^ N, глубина 𝞫 ^ N, размер изображения 𝜸 ^ N. Здесь 𝞪, 𝞫, 𝜸 — постоянные коэффициенты, которые можно определить с помощью поиска по малой сетке.

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

  1. Глубина. Это наиболее часто масштабируемое измерение во многих CNN. Мотивация масштабирования глубины состоит в том, чтобы захватить более богатые и более сложные функции. Однако более глубокие сети трудно тестировать из-за проблем с исчезающим градиентом.
  2. Ширина.Многие модели небольшого размера сосредоточены на захвате мелких функций путем масштабирования ширины сети (что также облегчает их обучение). Однако, фиксируя детализированные функции, эти модели, как правило, пропускают некоторые функции более высокого уровня.
  3. Разрешение:CNN могут захватывать более мелкие шаблоны, когда им передаются изображения с более высоким разрешением. Масштабирование разрешения сети может повысить точность, но за счет некоторой общей производительности и вычислительных затрат.

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

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

import tensorflow as tf
!pip install -q efficientnet
import efficientnet.keras as efn
from tensorflow.keras import layers
from tensorflow.keras import Model
from tensorflow.keras.optimizers import RMSprop
base_model = efn.EfficientNetB3(input_shape = (224, 224, 3), 
                                include_top = False)

for layer in base_model.layers:
    layer.trainable=False

x = base_model.output
x = layers.Flatten()(x)
x = layers.Dense(1024, activation="relu")(x)
x = layers.Dropout(0.5)(x)
x = layers.Dense(5, activation='softmax')(x)

model = tf.keras.Model(base_model.input,x)

model.compile(optimizer=RMSprop(lr=0.001),loss='categorical_crossentropy',metrics=['accuracy'])

datagen = ImageDataGenerator(
    rotation_range=10, 
    zoom_range = 0.1,
    width_shift_range=0.1,
    height_shift_range=0.1)
history= model.fit(datagen.flow(X_train, Y_train, batch_size= 24),
                   epochs= 5,
                   validation_data= (X_test, Y_test),
                   verbose= 1,
                   steps_per_epoch= 100)

Последние мысли

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

Примечание редактора. Heartbeat — это интернет-издание и сообщество, созданное участниками и посвященное предоставлению лучших образовательных ресурсов для специалистов по науке о данных, машинному обучению и глубокому обучению. Мы стремимся поддерживать и вдохновлять разработчиков и инженеров из всех слоев общества.

Независимая от редакции, Heartbeat спонсируется и публикуется Comet, платформой MLOps, которая позволяет специалистам по данным и командам машинного обучения отслеживать, сравнивать, объяснять и оптимизировать свои эксперименты. Мы платим нашим авторам и не продаем рекламу.

Если вы хотите внести свой вклад, перейдите к нашему призыву к участию. Вы также можете подписаться на получение наших еженедельных информационных бюллетеней (Еженедельник глубокого обучения и Информационный бюллетень Comet), присоединиться к нам в Slack и следить за Comet в Twitter и LinkedIn, чтобы получать ресурсы, события и многое другое, что поможет вам быстрее создавать лучшие модели машинного обучения.