Создайте модель компьютерного зрения с помощью TensorFlow

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

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

Предпосылки

  • Уверенное знание Python
  • Базовые навыки программирования

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

В этой лаборатории кода вы:

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

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

  • Нейронная сеть, которая идентифицирует предметы одежды

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

Если вы никогда не создавали нейронную сеть для компьютерного зрения с помощью TensorFlow, вы можете использовать Colaboratory — браузерную среду, содержащую все необходимые зависимости. Вы можете найти код остальной кодлабы , работающей в Colab .

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

2. Начните программировать

Сначала пройдитесь по исполняемой записной книжке Colab .

Начните с импорта TensorFlow.

import tensorflow as tf
print(tf.__version__)

Вы обучите нейронную сеть распознавать предметы одежды из общего набора данных под названием Fashion MNIST . Он содержит 70 000 предметов одежды в 10 различных категориях. Каждый предмет одежды находится в изображении в оттенках серого 28x28. Вы можете увидеть некоторые примеры здесь:

Метки, связанные с набором данных:

Этикетка

Описание

0

Футболка/топ

1

Брюки

2

Натяни

3

Платье

4

Пальто

5

Сандалии

6

Рубашка

7

кроссовки

8

Сумка

9

Ботильоны

Данные Fashion MNIST доступны в API tf.keras.datasets . Загрузите это так:

mnist = tf.keras.datasets.fashion_mnist

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

(training_images, training_labels), (test_images, test_labels) = mnist.load_data()

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

import matplotlib.pyplot as plt
plt.imshow(training_images[0])
print(training_labels[0])
print(training_images[0])

Печать данных для элемента 0 выглядит так:

Вы заметите, что все значения являются целыми числами от 0 до 255. При обучении нейронной сети проще обрабатывать все значения как от 0 до 1, этот процесс называется нормализацией . К счастью, Python предоставляет простой способ нормализовать подобный список без циклов.

training_images  = training_images / 255.0
test_images = test_images / 255.0

Вы также можете посмотреть на 42, другую загрузку, чем загрузчик с индексом 0.

Теперь вам может быть интересно, почему существует два набора данных — для обучения и тестирования.

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

3. Спроектируйте модель

Теперь спроектируйте модель. У вас получится три слоя. Просмотрите их один за другим и изучите различные типы слоев и параметры, используемые для каждого из них.

model = tf.keras.models.Sequential([tf.keras.layers.Flatten(), 
                                    tf.keras.layers.Dense(128, activation=tf.nn.relu), 
                                    tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
  • Sequential определяет последовательность слоев в нейронной сети.
  • Flatten берет квадрат и превращает его в одномерный вектор.
  • Dense добавляет слой нейронов.
  • Функции Activation сообщают каждому слою нейронов, что делать. Вариантов много, но пока используйте эти:
  • Relu фактически означает, что если X больше 0, вернуть X, иначе вернуть 0. Он передает только значения 0 или выше на следующий уровень в сети.
  • Softmax берет набор значений и эффективно выбирает самое большое из них. Например, если выходные данные последнего слоя выглядят как [0,1, 0,1, 0,05, 0,1, 9,5, 0,1, 0,05, 0,05, 0,05], то это избавляет вас от необходимости сортировать по наибольшему значению — он возвращает [0, 0,0,0,1,0,0,0,0].

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

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

Обратите внимание на использование metrics= в качестве параметра, который позволяет TensorFlow сообщать о точности обучения, сверяя прогнозируемые результаты с известными ответами (метками).

model.compile(optimizer = tf.keras.optimizers.Adam(),
              loss = 'sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(training_images, training_labels, epochs=5)

При model.fit вы увидите потери и точность:

Epoch 1/5
60000/60000 [=======] - 6s 101us/sample - loss: 0.4964 - acc: 0.8247
Epoch 2/5
60000/60000 [=======] - 5s 86us/sample - loss: 0.3720 - acc: 0.8656
Epoch 3/5
60000/60000 [=======] - 5s 85us/sample - loss: 0.3335 - acc: 0.8780
Epoch 4/5
60000/60000 [=======] - 6s 103us/sample - loss: 0.3134 - acc: 0.8844
Epoch 5/5
60000/60000 [=======] - 6s 94us/sample - loss: 0.2931 - acc: 0.8926

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

5. Протестируйте модель

Как модель будет работать с данными, которых она не видела? Вот почему у вас есть тестовый набор . Вы вызываете model.evaluate и передаете два набора, и он сообщает о потерях для каждого из них. Попробуйте:

model.evaluate(test_images, test_labels)

И вот результат:

10000/10000 [=====] - 1s 56us/sample - loss: 0.3365 - acc: 0.8789
[0.33648381242752073, 0.8789]

Этот пример вернул точность 0,8789, что означает точность около 88%. (У вас могут быть немного другие значения.)

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

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

6. Исследовательские упражнения

Упражнение 1

Для этого первого упражнения запустите следующий код:

classifications = model.predict(test_images)
print(classifications[0])

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

Попробуйте запустить print(test_labels[0]) , и вы получите 9. Помогает ли это понять, почему список выглядит именно так?

Результатом модели является список из 10 чисел. Эти числа представляют собой вероятность того, что классифицируемое значение является соответствующей меткой. Например, первое значение в списке — это вероятность того, что одежда относится к классу 0, а следующее — 1. Обратите внимание, что все они имеют очень низкие вероятности, кроме одной. Кроме того, из-за Softmax все вероятности в списке в сумме равны 1,0.

Список и метки основаны на 0, поэтому ботильоны с меткой 9 означают, что это 10-й из 10 классов. Список, в котором 10-й элемент имеет наибольшее значение, означает, что нейронная сеть предсказала, что классифицируемый ею элемент, скорее всего, является ботильонами.

Упражнение 2

Посмотрите на слои в вашей модели. Поэкспериментируйте с различными значениями для плотного слоя с 512 нейронами.

Какие разные результаты вы получаете по потерям и времени обучения? Как вы думаете, почему это так?

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

Упражнение 3

Что произойдет, если вы удалите слой Flatten() . Как вы думаете, почему это так?

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

Вместо того, чтобы писать весь код, добавьте слой Flatten() в начале. Когда позже массивы будут загружены в модель, они будут автоматически сведены для вас.

Упражнение 4

Рассмотрим конечные (выходные) слои. Почему их 10? Что произойдет, если у вас будет другая сумма, чем 10?

Попробуйте обучить сеть с 5. Вы получите сообщение об ошибке , как только обнаружите неожиданное значение. Еще одно эмпирическое правило: количество нейронов в последнем слое должно соответствовать количеству классов, для которых вы классифицируете. В данном случае это цифры от 0 до 9, поэтому их 10, и, следовательно, у вас должно быть 10 нейронов в последнем слое.

Упражнение 5

Учитывайте влияние дополнительных слоев в сети. Что произойдет, если вы добавите еще один слой между слоем с 512 и последним слоем с 10?

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

Упражнение 6

Перед обучением вы нормализовали данные, переходя от значений от 0 до 255 к значениям от 0 до 1. Как повлияет удаление этого? Вот полный код, чтобы попробовать (обратите внимание, что две строки, нормализующие данные, закомментированы).

Как вы думаете, почему вы получаете разные результаты? Здесь есть отличный ответ на Stack Overflow.

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/255.0
#test_images=test_images/255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
model.fit(training_images, training_labels, epochs=5)
model.evaluate(test_images, test_labels)
classifications = model.predict(test_images)
print(classifications[0])
print(test_labels[0])

7. Исследуйте обратные вызовы

Ранее, когда вы тренировались для дополнительных эпох, у вас была проблема, из-за которой ваш проигрыш мог измениться. Возможно, вам потребовалось некоторое время, чтобы дождаться, пока обучение сделает это, и вы, возможно, подумали, что было бы неплохо, если бы вы могли остановить обучение, когда достигнете желаемого значения, например точности 95%. Если вы достигнете этого после 3 эпох, зачем сидеть и ждать, пока она закончится гораздо больше эпох?

Как и в любой другой программе, у вас есть обратные вызовы! Посмотрите их в действии:

import tensorflow as tf

class myCallback(tf.keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs={}):
    if(logs.get('accuracy')>0.95):
      print("\nReached 95% accuracy so cancelling training!")
      self.model.stop_training = True

callbacks = myCallback()
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(512, activation=tf.nn.relu),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5, callbacks=[callbacks])

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

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