Увеличение данных изображения для глубокого обучения

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

Фото Крис Лоутон on Unsplash

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

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

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

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

Типы увеличения данных изображения

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

Сначала я продемонстрирую различные методы увеличения изображения с помощью Python и Keras. Если вы хотите попробовать, убедитесь, что у вас установлены следующие программы и пакеты:

После установки Anaconda и TensorFlow создайте новый блокнот Jupyter.

Вертикальный сдвиг

Первая техника увеличения изображения, которую я хочу показать, это вертикальное смещение, вертикальное смещение случайным образом сдвигает изображение по вертикали вверх или вниз. В этом примере я буду использовать изображение с именем 747.jpg, расположенный в той же папке, что и мой Jupyter Notebook.

Источник изображения: https://commons.wikimedia.org/wiki/File:Qantas_Boeing_747-438ER_VH-OEI_at_LAX.jpg. Этот файл находится под лицензией Creative Commons Attribution-Share Alike 2.0 Generic лицензию.

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

Ассоциация ImageDataGenerator class от Keras генерирует пакеты данных изображения с увеличением данных в реальном времени.

#---импорт модулей---
импортировать numpy как np
импортировать matplotlib.pyplot как plt
из tensorflow.keras.preprocessing.image импортировать load_img
из tensorflow.keras.preprocessing.image импортировать img_to_array
из tensorflow.keras.preprocessing.image импортировать ImageDataGenerator
#---загрузить изображение---
image_filename = '747.jpg'
img = load_img (имя_файла_изображения)
#---преобразовать изображение в 3D-массив---
image_data = img_to_array(img)
#---преобразовать в четырехмерный массив из 4 элемента трехмерного массива, представляющего
# Изображение---
images_data = np.expand_dims (image_data, ось = 0)
#---создать генератор увеличения данных изображения---
datagen = ImageDataGenerator (width_shift_range = 0.2)
#---подготовить итератор; flow() принимает массив 4D и возвращает
# итератор, содержащий пакет изображений---
train_generator = datagen.flow (images_data, batch_size = 1)
ряды = 5
столбцы = 4
#---построить 5 строк и 4 столбца---
рис, оси = plt.subplots (строки, столбцы)
для r в диапазоне (строки):
для c в диапазоне (столбцы):
#---получить следующее изображение в пакете (одно изображение после пакета
# размер 1)---
image_batch = train_generator.next()

#---преобразовать в целые числа без знака для просмотра---
изображение = image_batch[0].astype('uint8')

#---показать изображение---
оси[r,c].imshow(изображение)
#---установить размер фигуры---
fig.set_size_inches(15,10)

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

Как видно из приведенного выше вывода, каждый раз, когда вы вызываете next() метод из train_generator объект, вы получаете изображение, которое слегка изменено. В приведенном выше фрагменте кода новое изображение, сдвинутое на 20 % в зависимости от высоты исходного изображения, возвращается каждый раз, когда вы вызываете метод next() Метод:

генератор данных = ImageDataGenerator(ширина_shift_range = 0.2)

Интересно, что для этой версии ImageDataGenerator (tensorflow.keras.preprocessing.image) класс, определяющий width_shift_range параметр смещает изображение по вертикали, а не по горизонтали (что характерно для более старыхImageDataGeneratorиз keras.preprocessing.image модуль). Точно так же, если вы хотите, чтобы изображение было смещено по горизонтали, вам нужно использовать height_shift_range параметр (см. следующий раздел).

Обратите внимание, что next() метод будет возвращать увеличенное изображение столько раз, сколько вы хотите. В приведенном выше фрагменте кода мы вызывали его 20 раз (5 строк и 4 столбца).

Горизонтальный сдвиг

Теперь вы можете попробовать сдвинуть изображение по горизонтали с помощью height_shift_range Параметр:

генератор данных = ImageDataGenerator(height_shift_range=0.2)
train_generator = datagen.flow (images_data, batch_size = 1)
ряды = 5
столбцы = 4
рис, оси = plt.subplots (строки, столбцы)
для r в диапазоне (строки):
для c в диапазоне (столбцы):
image_batch = train_generator.next()
изображение = image_batch[0].astype('uint8')
оси[r,c].imshow(изображение)
fig.set_size_inches(15,10)

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

Горизонтальный флип

Иногда имеет смысл отразить изображение по горизонтали. В случае самолета передняя часть самолета может быть обращена влево или вправо:

генератор данных = ImageDataGenerator(Horizontal_flip = Истина)
train_generator = datagen.flow (images_data, batch_size = 1)
ряды = 2
столбцы = 2
рис, оси = plt.subplots (строки, столбцы)
для r в диапазоне (строки):
для c в диапазоне (столбцы):
image_batch = train_generator.next()
изображение = image_batch[0].astype('uint8')
оси[r,c].imshow(изображение)
fig.set_size_inches(15,10)

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

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

Вертикальный флип

Точно так же, как горизонтальное отражение, вы также можете выполнить вертикальное отражение:

генератор данных = ImageDataGenerator(vertical_flip = Истина)
train_generator = datagen.flow (images_data, batch_size = 1)
ряды = 2
столбцы = 2
рис, оси = plt.subplots (строки, столбцы)
для r в диапазоне (строки):
для c в диапазоне (столбцы):
image_batch = train_generator.next()
изображение = image_batch[0].astype('uint8')
оси[r,c].imshow(изображение)
fig.set_size_inches(15,10)

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

Вращение

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

генератор данных = ImageDataGenerator(диапазон_вращения = 50)
train_generator = datagen.flow(images_data)
ряды = 5
столбцы = 4
рис, оси = plt.subplots (строки, столбцы)
для r в диапазоне (строки):
для c в диапазоне (столбцы):
image_batch = train_generator.next()
изображение = image_batch[0].astype('uint8')
оси[r,c].imshow(изображение)
fig.set_size_inches(15,10)

При вращении выходные данные показывают самолеты в различных положениях — имитируя положение взлета и посадки:

яркость

Еще одна техника увеличения — регулировка яркости изображения. Следующий фрагмент кода задает диапазон значений сдвига яркости:

генератор данных = ImageDataGenerator(яркость_диапазон = [0.15,2.0])
train_generator = datagen.flow (images_data, batch_size = 1)
ряды = 5
столбцы = 4
рис, оси = plt.subplots (строки, столбцы)
для r в диапазоне (строки):
для c в диапазоне (столбцы):
image_batch = train_generator.next()
изображение = image_batch[0].astype('uint8')
оси[r,c].imshow(изображение)
fig.set_size_inches(15,10)

Вывод содержит серию изображений разной яркости:

Масштабирование

Вы также можете увеличивать или уменьшать изображения:

генератор данных = ImageDataGenerator(Zoom_range=[5,0.5])
train_generator = datagen.flow (images_data, batch_size = 1)
ряды = 5
столбцы = 4
рис, оси = plt.subplots (строки, столбцы)
для r в диапазоне (строки):
для c в диапазоне (столбцы):
image_batch = train_generator.next()
изображение = image_batch[0].astype('uint8')
оси[r,c].imshow(изображение)
fig.set_size_inches(15,10)

Вывод показывает изображение в различных коэффициентах масштабирования:

Обратите внимание, что масштабирование изображений изменит соотношение сторон изображений.

Объединение всех аугментаций

Конечно, все различные методы увеличения, которые я обсуждал до сих пор, можно комбинировать:

генератор данных = ImageDataGenerator(ширина_сдвига_диапазон = 0.2,
height_shift_range=0.2,
horizontal_flip = Верно,
диапазон_вращения=50,
диапазон_яркости = [0.15,2.0],
Zoom_range=[5,0.5]
)
train_generator = datagen.flow (images_data, batch_size = 1)ряды = 8
столбцы = 8
рис, оси = plt.subplots (строки, столбцы)
для r в диапазоне (строки):
для c в диапазоне (столбцы):
image_batch = train_generator.next()
изображение = image_batch[0].astype('uint8')
оси[r,c].imshow(изображение)
fig.set_size_inches(15,10)

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

Вывод теперь показывает изображение с различными примененными дополнениями:

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

Фрукты
|__банан
|__банан1.jpg
|__банан2.jpg
|__банан3.jpg
|__ ...
|__дуриан
|__durian1.jpg
|__durian2.jpg
|__durian3.jpg
|__ ...
|__апельсин
|__orange1.jpg
|__orange2.jpg
|__orange3.jpg
|__ ...
|__клубника
|__strawberry1.jpg
|__strawberry2.jpg
|__strawberry3.jpg
|__ ...

Каждая подпапка содержит набор изображений. Например, банан папка содержит ряд изображений, названных банан1.jpg, банан2.jpg, и так далее. Имена подпапок будут служить метками для различных изображений. Это означает, что все файлы под банан папка содержит изображения бананов и так далее.

Чтобы загрузить серию изображений с диска, вы теперь вызываете flow_from_directory() метод ImageDataGenerator экземпляр вместо flow() метод (для загрузки изображений из памяти):

train_datagen = ImageDataGenerator(
horizontal_flip = Верно,
vertical_flip = Верно,
диапазон_вращения=50,
)
размер_пакета = 8поезд_генератор = train_datagen.flow_from_directory(
'./Фрукты',
целевой_размер = (224,224 XNUMX),
color_mode = 'rgb',
batch_size = размер_пакета,
class_mode = 'категориальный',
перемешать = верно)

Заметьте, что я установил batch_size до 8. Вскоре вы увидите использование размера пакета.

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

class_dictionary = train_generator.class_indices#---создать словарь меток---
class_dictionary = { значение: ключ для ключа, значение в
class_dictionary.items()}
#---преобразовать словарь в список---
class_list = [значение для _, значение в class_dictionary.items()]
печать (класс_список)

Вы увидите следующий результат:

Найдено 54 изображения, принадлежащих к 4 классам.
['банан', 'дуриан', 'апельсин', 'клубника']

Всего в 54 папках 4 изображения. Так же class_list переменная содержит список фруктов.

Теперь я распечатаю набор увеличенных изображений, созданных ImageDataGenerator сорт. Я произвольно установлю строки равными 10, и для каждой строки я хочу распечатать пакет возвращенных изображений (в этом примере это 8):

ряды = 10рис., оси = plt.subplots(rows,batch_size)для r в диапазоне (строки):    
#---получить пакет дополненных изображений---
image_batch = train_generator.next()
#---получить количество возвращенных изображений---
images_count = image_batch[0].shape[0]

для c в диапазоне (images_count):
#---преобразовать в целые числа без знака для просмотра---
изображение = image_batch[0][c].astype('uint8')

#---отобразить изображение---
оси[r,c].imshow(изображение)

#---отобразить метку изображения---
оси[r,c].title.set_text(
class_list[np.argmax(image_batch[1][c])])
#---скрывает галочки x и y---
оси[r,c].set_xticks([])
оси[r,c].set_yticks([])
fig.set_size_inches(15,18)

С batch_size теперь установлен на 8 (а не на 1), train_generator.next() метод вернет вам партия из восьми дополненных изображений каждый раз, когда вы это называете. Количество возвращаемых изображений основано на batch_size который вы установили ранее в flow_from_directory() Метод:

train_generator = train_datagen.flow_from_directory(
'./Фрукты',
целевой_размер = (224,224 XNUMX),
color_mode = 'rgb',
batch_size = размер_пакета, # размер_пакета = 8
class_mode = 'категориальный',
перемешать = верно)

Значение image_batch переменная (возвращается функцией next() method) представляет собой кортеж из двух элементов:

  • Первый элемент (image_batch[0]) представляет собой массив размер партии изображения (четырехмерный массив)
  • Второй элемент (image_batch[1]) содержит метки для изображений

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

Обратите внимание, что в седьмой строке есть две пустые диаграммы без изображений. Напомним, что в наборе изображений всего 54 изображения, и поскольку каждый пакет возвращает 8 изображений (в строке), первые семь строк будут отображать в общей сложности 54 изображения (8 × 6 + 6). Следующий рисунок дает понять:

Обратите внимание, что вы можете установить rows на любой номер и ImageDataGenerator class будет продолжать генерировать для вас новые дополненные изображения.

Построение модели с использованием трансферного обучения

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

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

из модели импорта tensorflow.keras.models
из tensorflow.keras.applications импортировать VGG16
из tensorflow.keras.layers импортировать Dense, GlobalAveragePooling2D
#---количество фруктов---
NO_CLASSES = макс (train_generator.class_indices.values()) + 1
#---загрузить модель VGG16 в качестве базовой модели для обучения---
base_model = VGG16 (include_top = False, input_shape = (224, 224, 3))
#---добавляем собственные слои---
х = базовая_модель.выход
x = GlobalAveragePooling2D()(x)
x = Dense(1024,activation='relu')(x) # добавляем плотные слои, чтобы
# что модель может
# узнать больше сложного
# функции и
# классифицировать лучше
# Результаты.
x = Dense(1024,activation='relu')(x) # плотный слой 2
x = Dense(512,activation='relu')(x) # плотный слой 3
preds = плотный (NO_CLASSES,
активации='softmax')(x) # последний слой с
# активация софтмакс
#---создать новую модель с исходной базовой моделью
# ввод и вывод новой модели ---
модель = Модель (входы = base_model.input, выходы = преды)
#---не тренировать первые 19 слоев - 0..18---
для слоя в model.layers[:19]:
слой.trainable=Ложь
#---обучаем остальные слои - 19 и далее---
для слоя в model.layers[19:]:
слой.trainable=Истина

#---скомпилируем модель---
model.compile (оптимизатор = 'Адам',
потеря = 'categorical_crossentropy',
метрики = ['точность'])

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

Использование сгенерированных изображений для обучения

Чтобы использовать дополненные изображения для обучения, пройдите train_generator в fit() метод модели:

#---обучить модель---
Step_size_train = train_generator.n // train_generator.batch_size
модель.фит(поезд_генератор,
шаги_per_epoch=step_size_train,
эпох=15)

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

количество изображений/размер пакета

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

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

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

Увеличение данных изображения для глубокого обучения, переизданное из источника https://towardsdatascience.com/image-data-augmentation-for-deep-learning-77a87fabd2bf?source=rss—-7f60cf5620c9—4 через https://towardsdatascience.com/feed

<!–

->

Отметка времени:

Больше от Блокчейн-консультанты