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

1. Прежде чем начать

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

Предпосылки

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

Что вы узнаете

  • Как улучшить компьютерное зрение и точность с помощью сверток

Что вы будете строить

  • Слои для улучшения вашей нейронной сети

Что вам понадобится

Вы можете найти код остальной кодлабы , работающей в Colab .

Вам также потребуется установленный TensorFlow и библиотеки, которые вы установили в предыдущей лаборатории кода.

2. Повысьте точность компьютерного зрения с помощью сверток

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

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

import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images/255.0
test_images=test_images/255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_accuracy*100))

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

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

Короче говоря, вы берете массив (обычно 3x3 или 5x5) и передаете его по изображению. Изменяя базовые пиксели на основе формулы в этой матрице, вы можете выполнять такие операции, как обнаружение краев . Например, обычно для обнаружения края определяется 3x3, где средняя ячейка имеет значение 8, а все ее соседи - -1. В этом случае для каждого пикселя вы должны умножить его значение на 8, а затем вычесть значение каждого соседа. Сделайте это для каждого пикселя, и вы получите новое изображение с улучшенными краями.

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

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

3. Попробуйте код

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

import tensorflow as tf
print(tf.__version__)
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images.reshape(60000, 28, 28, 1)
training_images=training_images / 255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images / 255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Conv2D(64, (3, 3), activation='relu', input_shape=(28, 28, 1)),
  tf.keras.layers.MaxPooling2D(2, 2),
  tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
  tf.keras.layers.MaxPooling2D(2,2),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.summary()
model.fit(training_images, training_labels, epochs=5)
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_accuracy*100))

Вероятно, он увеличился примерно до 93% на данных обучения и 91% на данных проверки.

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

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

Посмотрите еще раз на код и посмотрите, как шаг за шагом строились свертки.

4. Соберите данные

Первым шагом является сбор данных.

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

import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images.reshape(60000, 28, 28, 1)
training_images = training_images/255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images = test_images/255.0

5. Определите модель

Затем определите свою модель. Вместо входного слоя вверху вы добавите сверточный слой. Параметры:

  • Количество сверток, которые вы хотите сгенерировать. Значение, подобное 32, является хорошей отправной точкой.
  • Размер сверточной матрицы, в данном случае сетка 3x3.
  • Используемая функция активации, в данном случае используйте relu .
  • В первом слое форма входных данных.

Вы будете следовать за сверткой с максимальным объединяющим слоем, который предназначен для сжатия изображения при сохранении содержимого функций, которые были выделены сверткой. Указав (2,2) для максимального объединения, эффект заключается в уменьшении размера изображения в 4 раза. Он создает массив пикселей 2x2 и выбирает наибольшее значение пикселя, превращая 4 пикселя в 1. Он повторяется. это вычисление по всему изображению, и при этом вдвое уменьшается количество горизонтальных пикселей и вдвое уменьшается количество вертикальных пикселей.

Вы можете вызвать model.summary() , чтобы увидеть размер и форму сети. Обратите внимание, что после каждого максимального слоя пула размер изображения уменьшается следующим образом:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_2 (Conv2D)            (None, 26, 26, 64)        640       
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 13, 13, 64)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 11, 11, 64)        36928     
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 1600)              0         
_________________________________________________________________
dense_4 (Dense)              (None, 128)               204928    
_________________________________________________________________
dense_5 (Dense)              (None, 10)                1290      
=================================================================

Вот полный код CNN:

model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(2, 2),
#Add another convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2, 2),
#Now flatten the output. After this you'll just have the same DNN structure as the non convolutional version
tf.keras.layers.Flatten(),
#The same 128 dense layers, and 10 output layers as in the pre-convolution example:
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])

6. Скомпилируйте и обучите модель

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

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)
test_loss, test_acc = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_acc*100))

7. Визуализируйте свертки и объединение

Этот код показывает свертки графически. print (test_labels[:100]) показывает первые 100 меток в тестовом наборе, и вы можете видеть, что метки с индексами 0, 23 и 28 имеют одинаковое значение (9). Это все туфли. Взгляните на результат выполнения свертки для каждого из них, и вы увидите, что между ними появляются общие черты. Теперь, когда DNN обучается на этих данных, она работает с гораздо меньшим количеством информации и, возможно, находит общность между обувью на основе этой комбинации свертки и объединения.

print(test_labels[:100])
[9 2 1 1 6 1 4 6 5 7 4 5 7 3 4 1 2 4 8 0 2 5 7 9 1 4 6 0 9 3 8 8 3 3 8 0 7
 5 7 9 6 1 3 7 6 7 2 1 2 2 4 4 5 8 2 2 8 4 8 0 7 7 8 5 1 1 2 3 9 8 7 0 2 6
 2 3 1 2 8 4 1 8 5 9 5 0 3 2 0 6 5 3 6 7 1 8 0 1 4 2]

Теперь вы можете выбрать некоторые из соответствующих изображений для этих меток и отобразить, как они выглядят, проходя через извилины. Итак, в следующем коде FIRST_IMAGE , SECOND_IMAGE и THIRD_IMAGE — это все индексы для значения 9, ботильоны.

import matplotlib.pyplot as plt
f, axarr = plt.subplots(3,4)
FIRST_IMAGE=0
SECOND_IMAGE=23
THIRD_IMAGE=28
CONVOLUTION_NUMBER = 6
from tensorflow.keras import models
layer_outputs = [layer.output for layer in model.layers]
activation_model = tf.keras.models.Model(inputs = model.input, outputs = layer_outputs)
for x in range(0,4):
  f1 = activation_model.predict(test_images[FIRST_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[0,x].imshow(f1[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[0,x].grid(False)
  f2 = activation_model.predict(test_images[SECOND_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[1,x].imshow(f2[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[1,x].grid(False)
  f3 = activation_model.predict(test_images[THIRD_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[2,x].imshow(f3[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[2,x].grid(False)

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

6c9109bcc640a1ec.png

8. Упражнения

Упражнение 1

Попробуйте отредактировать свертки. Измените количество извилин с 32 на 16 или 64. Как это повлияет на точность и время обучения?

Упражнение 2

Удалите окончательную свертка. Как это влияет на точность или время обучения?

Упражнение 3

Добавьте больше сверток. Какое влияние это оказывает?

Упражнение 4

Удалите все свертки, кроме первого. Какое влияние это оказывает? Поэкспериментируйте с ним.

9. Поздравления

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