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

Существует множество различных руководств, в которых показано, как реализовать вашу собственную модель CNN с использованием различных нейросетевых библиотек (Keras, TensorFlow, PyTorch и т. Д.) С вашей собственной сетевой архитектурой. Однако нет исчерпывающего объяснения того, что происходит внутри сети и ее скрытых слоев.

В этом уроке я хотел бы показать, как легко визуализировать и управлять глубокими скрытыми слоями CNN и как их анализировать с помощью нейронных сетей ConX.

Распознавание изображений с помощью CNN и дальнейший анализ

В этом уроке я буду:

  1. Постройте модель CNN
  2. Модель поезда на наборе данных STL-10
  3. Визуализируйте сетевую архитектуру и вывод скрытых слоев

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

Что такое ConX?

ConX - это доступный и мощный способ создания и понимания нейронных сетей глубокого обучения. Он разработан на Python 3 и Keras 2.

Чтобы установить ConX:

Зайдите в свой терминал и введите:

pip install conx

Начиная

Импортировать пакеты

import numpy as np
import tensorflow as tf
import conx as cx

Импортировать набор данных

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

# url of the binary data
DATA_URL=‘http://ai.stanford.edu/~acoates/stl10/stl10_binary.tar.gz'
# path to the binary train file with image data
DATA_PATH = ‘./data/stl10_binary/train_X.bin’
# path to the binary train file with labels
LABEL_PATH = ‘./data/stl10_binary/train_y.bin’
# test to check if the whole dataset is read correctly
images = read_all_images(DATA_PATH)
labels = read_labels(LABEL_PATH)
print('Image shape: ', images.shape)  
print('Labels shape: ', labels.shape)  
Image shape: (5000, 96, 96, 3)
Labels shape: (5000,)

Таким образом, набор данных содержит 5000 изображений (96 x 96 пикселей и 3 цветовых каналов) с ярлыками, принадлежащими один из следующих 10 классов: самолет, птица, машина, кошка, олень, собака, лошадь, обезьяна, корабль, грузовик.

Предварительная обработка данных

Поскольку я хочу построить и проанализировать CNN с помощью модуля ConX, в первую очередь я подготовлю данные для сетевого ввода и вывода. В этом случае входом сети является изображение формы 96x96x3, а на выходе - горячий вектор формы 10x1, имеющий 1 на месте метки.

target = []
labels_array = np.zeros(10, dtype=int)
for label in labels:
    labels_array[label-1] = 1
    target.append(labels_array)   
    labels_array = np.zeros(10, dtype=int)

Давайте проверим изображение и цель для первого элемента в наборе данных:

plot_image(images[0])
print('Target: ', target[0])

Target: [0 1 0 0 0 0 0 0 0 0]

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

Модель CNN

Назначение сети

Первым делом я создаю сеть с ее названием:

net = cx.Network(‘STL-10ImageClasses’)
net.dataset.clear()

Создайте набор данных

Затем я могу загрузить набор данных в формате (изображение, цель) (строка 4 следующего кода). Позже он будет использоваться для обучения и тестирования модели CCN. Я использую только 1000 записей, чтобы ускорить процесс обучения, если хотите, можете использовать все 5000 изображений.

for i in range(0, 1000):
    inputs = images[i]
    targets = target[i]
    net.dataset.append(inputs, targets)

Затем я могу проверить информацию о сети, чтобы убедиться, что набор данных загружен правильно:

net.dataset.info()

Исследование набора данных

Также возможно изучить набор данных с помощью некоторых методов ConX:

  • просмотрите первое изображение в наборе данных:
cx.view(net.dataset.inputs[0])

  • просмотрите первые десять изображений в наборе данных:
cx.view(net.dataset.inputs[0:10], layout=(1,10))

  • просматривать только изображения «птиц» в наборе данных:
bird = [i for i in range(40) if net.dataset.targets[i][1] == 1]
cx.view([cx.array_to_image(v) for v in net.dataset.inputs[bird]])

Определение наборов данных для обучения и тестирования

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

net.dataset.split(300)
net.dataset.split() 
(700, 300)

Теперь у меня есть прямой доступ к обоим наборам данных:

print(len(net.dataset.inputs), 'total images')
print(len(net.dataset.train_inputs), 'images for training')
print(len(net.dataset.test_inputs), 'images for testing')
1000 total images
700 images for training
300 images for testing

Конструкция модели

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

Модуль conx.layers содержит код всех слоев. Чтобы добавить слои в модель, мы можем просто вызвать метод add.

Сначала я добавляю слой ввода с произвольным именем «input», где указываю размер изображения:

net.add(cx.Layer("input", (96,96,3)))

Теперь я построю простую модель CCN, которая содержит два сверточных слоя, за которыми следуют слой объединения, плоский слой и три скрытых слоя (включая один выходной слой).

После входного слоя должен быть добавлен сверточный слой. Это делается в третьей строке следующего кода; инструкция conx.layers.Conv2DLayer (name, * args, ** params) добавляет сверточный слой. Здесь можно указать количество фильтров, размер ядра, шаги, стороны заполнения и функцию активации.

net.add(cx.Conv2DLayer(“conv2D_1”, 32, (5,5), strides=1, padding=’same’, activation=”relu”),
cx.Conv2DLayer(“conv2D_2”, 32, (5,5), strides=1, padding=’same’, activation=”relu”))

Для обоих слоев я использовал:

  • название: ‘conv2D_1’ (или conv2D_2)
  • фильтр, размерность выходного пространства: 32
  • размер_ядра: (5, 5)
  • шагов: 1
  • отступ: такой же
  • функция активации: relu

Давайте теперь добавим слой объединения:

net.add(cx.MaxPool2DLayer("maxpool_1", (2,2), strides=2, padding='same', dropout=0.25))

Я указал для слоя:

  • name: ‘maxpool_1’
  • pool_size: (2, 2)
  • шагов: 2
  • отступ: такой же
  • выпадение (доля единиц, которые нужно отбросить при линейном преобразовании входных данных): 0,25

В конце добавляется сплющенный слой. Этот вид слоя не требует никаких параметров:

net.add(cx.FlattenLayer("flat"))

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

net.add(cx.Layer("hidden", 512, activation='relu', vshape=(16, 32), dropout=0.5),
cx.Layer("hidden2", 50, activation='relu', vshape=(10, 5), dropout=0.5),
cx.Layer("output", 10, activation='softmax'))
  • размер: 512 (это потому, что 16 x 32 = 512)
  • vshape: (16, 32) (визуальная форма, как будет представлен слой)
  • функция активации: relu

Все слои добавляются по порядку; таким образом, все они должны быть связаны вместе.

net.connect()

Одна из самых мощных возможностей ConX - это визуализация. Таким образом, построенную сеть можно представить:

net.picture()

Начиная снизу, мы можем наблюдать за всеми добавленными слоями: input, conv2D_1, conv2D_2, maxpool_1, flat, hidden, hidden2, output.

Когда сеть спроектирована, следующим шагом является ее компиляция:

net.compile(error='categorical_crossentropy', optimizer='rmsprop', lr=0.0001, decay=1e-6)
  • функция потерь: «категориальная_ кроссентропия» (требуется при использовании softmax в качестве функции активации выходного слоя)

Визуализация сети

Теперь сеть готова к обучению:

net.train(100, batch_size=100, record=1)
  • эпоха: 100
  • batch_size: 100

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

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

net.dashboard()

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

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

net.propagate_to_features(“conv2D_1”, net.dataset.inputs[1], scale=2)

В ConX доступно множество других полезных методов; вы можете найти их все на официальной странице сайта: Начало работы с ConX.

Информация: