Классификация изображений CNN в TensorFlow с шагами и примерами
⚡ Умное резюме
Сверточные нейронные сети сканируют изображение с помощью небольших фильтров, а не присваивают каждому пикселю одинаковый вес, поэтому они доминируют в компьютерном зрении. В этом пошаговом руководстве объясняется каждый слой, а затем классифицируются цифры из набора данных MNIST с помощью TensorFlow.
Что такое сверточная нейронная сеть?
Сверточная нейронная сетьСверточные нейронные сети (CNN) — это широко распространенный метод в приложениях компьютерного зрения. Это класс глубоких нейронных сетей, используемых для анализа визуальных изображений. Этот тип архитектуры наиболее эффективен для распознавания объектов на изображениях или видео. Он используется в таких приложениях, как распознавание изображений или видео, обработка естественного языка и рекомендательные системы.
Archiструктура сверточной нейронной сети
Вспомните Facebook: несколько лет назад после того, как вы загрузили изображение в свой профиль, вас попросили вручную добавить имя к лицу на изображении. В настоящее время Facebook использует confnet, чтобы автоматически отмечать вашего друга на фотографии.
Сверточную нейронную сеть для классификации изображений не очень сложно понять. Входное изображение обрабатывается на этапе свертки, а затем ему присваивается метка.
Типичную архитектуру сверточной нейронной сети можно кратко описать на рисунке ниже. Сначала в сеть подается изображение; это называется входным изображением. Затем входное изображение проходит через ряд этапов; это сверточная часть сети. Наконец, нейронная сеть может предсказать цифру на изображении.

Изображение состоит из массива пикселей, имеющих высоту и ширину. Изображение в оттенках серого имеет только один канал, в то время как цветное изображение имеет три канала (по одному для красного, зеленого и синего). Каналы накладываются друг на друга. В этом уроке вы будете использовать изображение в оттенках серого с одним каналом. Каждый пиксель имеет значение от 0 до 255, отражающее интенсивность цвета. Например, пиксель со значением 0 будет показывать белый цвет, а пиксель со значением, близким к 255, будет темнее.
Давайте посмотрим на изображение, хранящееся в Набор данных MNISTНа рисунке ниже показано, как представить изображение слева в матричном формате. Обратите внимание, что исходная матрица стандартизирована и имеет значения от 0 до 1. Для более темных цветов значение в матрице составляет примерно 0.9, а для белых пикселей — 0.
Сверточная операция
Наиболее важным компонентом модели является сверточный слой. Цель этой части — уменьшить размер изображения для ускорения вычислений весов и улучшения обобщающей способности.
На этапе свертки сеть сохраняет основные характеристики изображения и исключает ненужный шум. Например, модель учится узнавать слона по картинке с горой на заднем плане. Если вы используете традиционную нейронную сеть, модель присвоит вес всем пикселям, в том числе горным, что не является существенным и может ввести сеть в заблуждение.
Вместо этого Keras Сверточная нейронная сеть будет использовать математический метод для...tracВыделяются только наиболее важные пиксели. Эта математическая операция называется сверткой. Этот метод позволяет сети изучать все более сложные признаки на каждом слое. Свертка делит матрицу на небольшие части, чтобы изучить наиболее важные элементы в каждой части.
Компоненты сверточной нейронной сети (ConvNet или CNN)
Сверточная нейронная сеть состоит из четырех компонентов:
- Свертка
- Нелинейность (ReLU)
- Poolinг или субвыборка
- Классификация (полносвязный уровень)
Свертка
Цель свертки состоит в том, чтобыtracЭто означает, что нейронная сеть будет изучать определенные закономерности на изображении и сможет распознавать их по всему изображению.
Свертка — это поэлементное умножение. Концепция проста для понимания. Компьютер сканирует часть изображения, обычно размером 3×3, и умножает её на фильтр. Результат поэлементного умножения называется картой признаков. Этот шаг повторяется до тех пор, пока не будет отсканировано всё изображение. Следует отметить, что после свертки размер изображения уменьшается.
На приведенной ниже диаграмме показано, как один фрагмент изображения умножается на фильтр для получения одной ячейки карты признаков.
Приведённая ниже анимация демонстрирует, как одна и та же свёртка применяется ко всему изображению.
Существует множество доступных фильтров. Ниже мы перечислили некоторые из них. Вы можете видеть, что каждый фильтр имеет определенное назначение. Обратите внимание, что на рисунке ниже ядро является синонимом фильтра.
Арифметика свертки
На этапе свертки фильтр применяется к небольшому массиву пикселей внутри изображения. Фильтр перемещается вдоль входного изображения, имея форму примерно 3×3 или 5×5. Это означает, что сеть будет сдвигать эти окна по всему входному изображению и вычислять свертку. Анимация ниже демонстрирует, как работает свертка. Размер фрагмента составляет 3×3, а выходная матрица является результатом поэлементной операции между матрицей изображения и фильтром.
Вы заметили, что ширина и высота вывода может отличаться от ширины и высоты ввода. Это происходит из-за пограничного эффекта.
Эффект границы
Изображение содержит карту признаков размером 5×5 и фильтр 3×3. В центре находится только одно окно, через которое фильтр может обрабатывать сетку 3×3. Выходная карта признаков уменьшается на два фрагмента по каждой оси, оставляя размер 3×3.
Чтобы получить выходные размеры, совпадающие с входными, необходимо добавить отступы. Отступы заключаются в добавлении нужного количества строк и столбцов с каждой стороны матрицы. Это позволит свертке центрировать каждый входной фрагмент. На изображении ниже входная и выходная матрицы имеют одинаковые размеры, 5×5.
Когда вы определяете сеть, свернутые объекты контролируются тремя параметрами:
Глубина: Он определяет количество фильтров, применяемых во время свертки. В предыдущем примере вы видели глубину 1, что означает использование только одного фильтра. В большинстве случаев используется более одного фильтра. Анимация ниже показывает операции, выполняемые в ситуации с тремя фильтрами.
Шаг: Он определяет величину «пиксельного скачка» между двумя срезами. Если шаг равен 1, окно будет перемещаться на расстояние, равное одному пикселю. Если шаг равен двум, окно будет перемещаться на 2 пикселя. Увеличение шага приведет к уменьшению размера карт признаков. На двух диаграммах ниже сравниваются шаг, равный 1, и шаг, равный 2.
Пример шага 1
шаг 2
Нулевое заполнение: Операция заполнения (padding) заключается в добавлении соответствующего количества строк и столбцов с каждой стороны входных карт признаков. В этом случае выходные данные имеют ту же размерность, что и входные.
Нелинейность (ReLU)
В конце операции свертки выходные данные подвергаются воздействию функции активации, обеспечивающей нелинейность. Обычно в сверточных сетях используется функция активации ReLU. Все пиксели с отрицательным значением заменяются нулями.
Pooling Operaпроизводство
Этот шаг легко понять. Цель пулинга — уменьшить размерность входного изображения. Эти шаги выполняются для снижения вычислительной сложности операции. Уменьшение размерности приводит к тому, что сети приходится вычислять меньше весов, что предотвращает переобучение.
На этом этапе необходимо определить размер и шаг. Стандартный способ объединения входного изображения — использование максимального значения карты признаков. Посмотрите на картинку ниже. Объединение будет проверять четыре подматрицы карты признаков 4×4 и возвращать максимальное значение. Объединение берет максимальное значение массива 2×2, а затем сдвигает это окно на два пикселя. Например, первая подматрица — [3,1,3,2], поэтому объединение вернет максимальное значение, равное 3.
Существует еще одна операция объединения, например среднее значение.
Эта операция значительно уменьшает размер карты объектов.
Полностью связанные слои
Последний шаг состоит в построении традиционного искусственная нейронная сеть как вы это делали в предыдущем уроке. Вы соединяете все нейроны предыдущего слоя со следующим слоем. Вы используете функцию активации softmax для классификации числа на входном изображении.
Резюме:
Сверточная нейронная сеть TensorFlow компилирует различные слои перед тем, как сделать предсказание. Нейронная сеть имеет:
- Сверточный слой
- Функция активации ReLU
- Poolinг-слой
- Плотно связанный слой
Сверточные слои применяют различные фильтры к подобласти изображения. Функция активации ReLU добавляет нелинейность, а слои пулинга уменьшают размерность карт признаков.
Все эти слои extracизвлекается важная информация из изображений. Наконец, карты признаков подаются на полносвязный слой с функцией softmax для выполнения прогнозирования.
Обучайте CNN с помощью TensorFlow
Теперь, когда вы знакомы с основными компонентами сверточной сети, вы готовы создать свою собственную. TensorFlow. Мы будем использовать набор данных MNIST для классификации изображений CNN.
Подготовка данных такая же, как и в предыдущем уроке. Вы можете запустить коды и сразу перейти к архитектуре CNN.
Вы выполните следующие шаги для классификации изображений с использованием CNN:
- Шаг 1. Загрузите набор данных
- Шаг 2: Входной слой
- Шаг 3: Сверточный слой
- Шаг 4: Poolinг-слой
- Шаг 5: Второй сверточный слой и Poolinг Слой
- Шаг 6: Плотный слой
- Шаг 7: Логит-слой
Примечание к версии: Приведенные ниже примеры предназначены для TensorFlow 1.x. В TensorFlow 2 пространство имен tf.layers и tf.estimator.inputs.numpy_input_fn больше не существуют; их эквивалентами являются tf.keras.layers.Conv2D, Max.PoolinСлои g2D, Dense и Dropout объединены в объект tf.keras.Model и обучены с помощью model.fit(). Ознакомьтесь с этапами работы каждого слоя, а затем сопоставьте их с API Keras.
Шаг 1. Загрузите набор данных
Набор данных MNIST доступен через scikit-learn. Пожалуйста, скачайте его и сохраните в папке «Загрузки». Вы можете загрузить его с помощью функции fetch_mldata('MNIST original').
Примечание к версии: Сайт mldata.org закрыт, а функция fetch_mldata() удалена в scikit-learn 0.22. На любой текущей установке загрузите те же цифры с помощью fetch_openml Вместо этого используется fetch_openml('mnist_784', version=1). Остальная часть конвейера остается без изменений.
Создайте набор поездов/тестов
Необходимо разделить набор данных с помощью функции train_test_split.
Масштабируйте функции
Наконец, вы можете масштабировать признаки с помощью MinMaxScaler, как показано в приведенном ниже примере классификации изображений с использованием TensorFlow CNN.
import numpy as np import tensorflow as tf from sklearn.datasets import fetch_mldata #Change USERNAME by the username of your machine ## Windows USER mnist = fetch_mldata('C:\\Users\\USERNAME\\Downloads\\MNIST original') ## Mac User mnist = fetch_mldata('/Users/USERNAME/Downloads/MNIST original') print(mnist.data.shape) print(mnist.target.shape) from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(mnist.data, mnist.target, test_size=0.2, random_state=42) y_train = y_train.astype(int) y_test = y_test.astype(int) batch_size =len(X_train) print(X_train.shape, y_train.shape,y_test.shape ) ## resclae from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() # Train X_train_scaled = scaler.fit_transform(X_train.astype(np.float64)) # test X_test_scaled = scaler.fit_transform(X_test.astype(np.float64)) feature_columns = [tf.feature_column.numeric_column('x', shape=X_train_scaled.shape[1:])] X_train_scaled.shape[1:]
Дайте определение CNN
Сверточная нейронная сеть (CNN) использует фильтры на исходных пикселях изображения для изучения детальных закономерностей, в отличие от глобальных закономерностей, изучаемых традиционной нейронной сетью. Для построения CNN необходимо определить:
- Сверточный слой: Применяет n количество фильтров к карте признаков. После свертки необходимо использовать функцию активации ReLU для добавления нелинейности в сеть.
- Pooling-слой: Следующий шаг после свертки — уменьшение размерности карты признаков. Цель состоит в том, чтобы уменьшить размерность карты признаков, предотвратить переобучение и повысить скорость вычислений. Максимальное пулинг — это традиционный метод, который делит карты признаков на подобласти (обычно размером 2×2) и сохраняет только максимальные значения.
- Полностью связанные слои: все нейроны предыдущих слоев подключены к следующим слоям. CNN будет классифицировать метку в соответствии с признаками сверточных слоев и уменьшенными с помощью слоя объединения.
Архитектура CNN
- Сверточный слой: Применяет 14 фильтров 5×5 (например,trac(подобласти размером 5×5 пикселей), с функцией активации ReLU.
- Pooling Layer: выполняет максимальное объединение с фильтром 2×2 и шагом 2 (что указывает на то, что объединенные регионы не перекрываются)
- Сверточный слой: применяет 36 фильтров 5×5 с функцией активации ReLU.
- Pooling Слой № 2: снова выполняет максимальное объединение с фильтром 2×2 и шагом 2
- 1,764 нейрона с коэффициентом регуляризации отсева 0.4 (вероятность 0.4, что какой-либо элемент будет отброшен во время обучения)
- Плотный слой (логитовый слой): 10 нейронов, по одному на каждый целевой класс цифр (0–9).
Для создания CNN можно использовать три важных модуля:
- конв2д(). Создает двумерный сверточный слой с количеством фильтров, размером ядра фильтра, заполнением и функцией активации в качестве аргументов.
- max_pooling2d(). Создает двумерный слой пула с использованием алгоритма максимального пула.
- плотный(). Создает плотный слой со скрытыми слоями и блоками.
Вам нужно будет определить функцию для построения сверточной нейронной сети (CNN). Давайте подробно рассмотрим, как построить каждый строительный блок перед обертыванием.ping Всё вместе в рамках одной функции.
Шаг 2: Входной слой
def cnn_model_fn(features, labels, mode): input_layer = tf.reshape(tensor = features["x"],shape =[-1, 28, 28, 1])
Вам нужно определить тензор с формой данных. Для этого вы можете использовать модуль tf.reshape. В этом модуле вам необходимо объявить тензор для изменения формы и форму тензора. Первый аргумент — это характеристики данных, которые определены в аргументе функции.
Изображение имеет высоту, ширину и канал. Набор данных MNIST представляет собой монохромное изображение размером 28×28 пикселей. Мы устанавливаем размер пакета равным -1 в аргументе формы, чтобы он принимал форму features[“x”]. Преимущество заключается в том, что размер пакета можно использовать в качестве гиперпараметра для настройки. Если размер пакета установлен равным 7, то тензор будет обрабатывать 5,488 значений (28*28*7).
Шаг 3: Сверточный слой
# first Convolutional Layer conv1 = tf.layers.conv2d( inputs=input_layer, filters=14, kernel_size=[5, 5], padding="same", activation=tf.nn.relu)
Первый сверточный слой имеет 14 фильтров с размером ядра 5×5 и одинаковым заполнением. Одинаковое заполнение означает, что как выходной, так и входной тензоры должны иметь одинаковую высоту и ширину. TensorFlow добавит нули к строкам и столбцам, чтобы обеспечить одинаковый размер.
Вы используете функцию активации ReLU. Размер выходных данных будет [28, 28, 14].
Шаг 4: Poolinг-слой
Следующим шагом после свертки является вычисление пулинга. Вычисление пулинга уменьшит размерность данных. Вы можете использовать модуль max_pooling2d с размером 2×2 и шагом 2. В качестве входных данных используется предыдущий слой. Размер выходных данных будет [batch_size, 14, 14, 14].
# first Pooling Layer
pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)
Шаг 5: Второй сверточный слой и Poolinг Слой
Второй сверточный слой применяет 36 фильтров, в результате чего размер выходного изображения составляет [batch_size, 14, 14, 36]. Слой пулинга использует то же окно 2×2 и шаг 2, что и раньше, поэтому он уменьшает каждую пространственную ось вдвое, и форма выходного изображения становится [batch_size, 7, 7, 36].
conv2 = tf.layers.conv2d(
inputs=pool1,
filters=36,
kernel_size=[5, 5],
padding="same",
activation=tf.nn.relu)
pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)
Шаг 6: Плотный слой
Затем необходимо определить полносвязный слой. Перед соединением с полносвязным слоем карту признаков необходимо выровнять. Для этого можно использовать модуль reshape с размером 7*7*36.
Плотный слой будет соединять 1,764 нейрона. Вы добавляете функцию активации ReLU. Кроме того, вы добавляете регуляризацию Dropout с коэффициентом 0.3, что означает, что 30 процентов активаций будут установлены в 0. Обратите внимание, что Dropout происходит только на этапе обучения. Функция cnn_model_fn имеет аргумент mode, позволяющий указать, нужно ли обучать или оценивать модель, как показано в приведенном ниже примере классификации изображений с помощью CNN в TensorFlow.
pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 36])
dense = tf.layers.dense(inputs=pool2_flat, units=7 * 7 * 36, activation=tf.nn.relu)
dropout = tf.layers.dropout(
inputs=dense, rate=0.3, training=mode == tf.estimator.ModeKeys.TRAIN)
Шаг 7: Логит-слой
Наконец, в примере классификации изображений TensorFlow вы можете определить последний слой с предсказаниями модели. Форма выходных данных равна размеру пакета и 10, общему количеству целевых классов.
# Logits Layer
logits = tf.layers.dense(inputs=dropout, units=10)
Вы можете создать словарь, содержащий классы и вероятность каждого класса. Функция tf.argmax() возвращает индекс наибольшего значения в слое логитов. Функция softmax возвращает вероятность каждого класса.
predictions = {
# Generate predictions
"classes": tf.argmax(input=logits, axis=1),
"probabilities": tf.nn.softmax(logits, name="softmax_tensor") }
Вам нужно возвращать словарь прогнозов только тогда, когда в режиме установлено значение "прогнозирование". Добавьте этот код для отображения прогнозов.
if mode == tf.estimator.ModeKeys.PREDICT: return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)
Следующий шаг — вычисление функции потерь модели. В предыдущем уроке вы узнали, что функцией потерь для многоклассовой модели является кросс-энтропия. Функция потерь легко вычисляется с помощью следующего кода:
# Calculate Loss (for both TRAIN and EVAL modes)
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
Заключительный этап примера TensorFlow CNN — оптимизация модели, то есть поиск оптимальных значений весов. Для этого используется оптимизатор градиентного спуска с шагом обучения 0.001. Цель — минимизировать функцию потерь.
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
train_op = optimizer.minimize(
loss=loss,
global_step=tf.train.get_global_step())
Вы завершили работу с CNN. Однако вы хотите отобразить показатели производительности в режиме оценки. Показателем производительности для многоклассовой модели является точность. TensorFlow оснащен модулем точности, который принимает два аргумента: метки и прогнозируемые значения.
eval_metric_ops = {
"accuracy": tf.metrics.accuracy(labels=labels, predictions=predictions["classes"])}
return tf.estimator.EstimatorSpec(mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)
Вот и все. Вы создали свою первую CNN и готовы обернуть все в функцию, чтобы использовать ее для обучения и оценки модели.
def cnn_model_fn(features, labels, mode): """Model function for CNN.""" # Input Layer input_layer = tf.reshape(features["x"], [-1, 28, 28, 1]) # Convolutional Layer conv1 = tf.layers.conv2d( inputs=input_layer, filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu) # Pooling Layer pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2) # Convolutional Layer #2 and Pooling Layer conv2 = tf.layers.conv2d( inputs=pool1, filters=36, kernel_size=[5, 5], padding="same", activation=tf.nn.relu) pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2) # Dense Layer pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 36]) dense = tf.layers.dense(inputs=pool2_flat, units=7 * 7 * 36, activation=tf.nn.relu) dropout = tf.layers.dropout( inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN) # Logits Layer logits = tf.layers.dense(inputs=dropout, units=10) predictions = { # Generate predictions (for PREDICT and EVAL mode) "classes": tf.argmax(input=logits, axis=1), "probabilities": tf.nn.softmax(logits, name="softmax_tensor") } if mode == tf.estimator.ModeKeys.PREDICT: return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions) # Calculate Loss loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits) # Configure the Training Op (for TRAIN mode) if mode == tf.estimator.ModeKeys.TRAIN: optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001) train_op = optimizer.minimize( loss=loss, global_step=tf.train.get_global_step()) return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op) # Add evaluation metrics Evaluation mode eval_metric_ops = { "accuracy": tf.metrics.accuracy( labels=labels, predictions=predictions["classes"])} return tf.estimator.EstimatorSpec( mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)
Примечание к собранной функции: В приведенной выше версии с обернутыми данными первый сверточный слой имеет 32 фильтра, а значение Dropout — 0.4, в то время как в пошаговых примерах используются 14 фильтров и значение 0.3. Оба варианта работают, но выбирают одну пару значений и сохраняют ее согласованность, чтобы отображаемые фигуры соответствовали таблице слоев.
Действия, описанные ниже, аналогичны предыдущим урокам.
Прежде всего, вы определяете оценщик с помощью модели CNN для классификации изображений.
# Create the Estimator mnist_classifier = tf.estimator.Estimator( model_fn=cnn_model_fn, model_dir="train/mnist_convnet_model")
Обучение сверточной нейронной сети занимает много времени, поэтому необходимо создать механизм логирования для сохранения значений слоя softmax каждые 50 итераций.
# Set up logging for predictions tensors_to_log = {"probabilities": "softmax_tensor"} logging_hook = tf.train.LoggingTensorHook(tensors=tensors_to_log, every_n_iter=50)
Вы готовы оценить модель. Установите размер пакета равным 100 и перемешайте данные. Обратите внимание, что мы установили количество шагов обучения равным 16 000, что может занять много времени. Наберитесь терпения.
# Train the model train_input_fn = tf.estimator.inputs.numpy_input_fn( x={"x": X_train_scaled}, y=y_train, batch_size=100, num_epochs=None, shuffle=True) mnist_classifier.train( input_fn=train_input_fn, steps=16000, hooks=[logging_hook])
Теперь, когда модель обучена, вы можете оценить её и распечатать результаты.
# Evaluate the model and print results eval_input_fn = tf.estimator.inputs.numpy_input_fn( x={"x": X_test_scaled}, y=y_test, num_epochs=1, shuffle=False) eval_results = mnist_classifier.evaluate(input_fn=eval_input_fn) print(eval_results)
В результате оценки выводится восстановленная контрольная точка, шаг, на котором она остановилась, и итоговый словарь метрик.
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Starting evaluation at 2018-08-05-12:52:41 INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from train/mnist_convnet_model/model.ckpt-15652 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Finished evaluation at 2018-08-05-12:52:56 INFO:tensorflow:Saving dict for global step 15652: accuracy = 0.9589286, global_step = 15652, loss = 0.13894269 {'accuracy': 0.9689286, 'loss': 0.13894269, 'global_step': 15652}
При текущей архитектуре оценочный словарь показывает точность 0.9689286, что составляет примерно 97%. Вы можете изменить архитектуру, размер пакета и количество итераций, чтобы повысить точность. Сверточная нейронная сеть показала гораздо лучшие результаты, чем искусственная нейронная сеть или логистическая регрессия: в руководстве по искусственным нейронным сетям ваша точность составила 96%, что ниже, чем у сверточной нейронной сети (CNN). Производительность CNN впечатляет при работе с большим набором изображений, как с точки зрения скорости вычислений, так и точности.











