Как использовать PyTorch для простого создания остаточной сети

Автопилот
Как использовать PyTorch для простого создания остаточной сети

Автор: Та-ин Чен, аспирант кафедры машинного обучения Оксфордского университета, известный технологический блоггер на Medium.

Переводчик: Сун Сянь

图源:UnsplashМногие приложения компьютерного зрения, такие как модное автономное вождение и распознавание лиц, стали возможными благодаря глубоким нейронным сетям. Однако многие могут не знать, что революционные достижения в области компьютерного зрения в последние годы были обусловлены особым типом сетевой архитектуры, так называемой остаточной сетью (ResNet). На самом деле, многие передовые достижения ИИ, которые мы видели, были бы невозможны без изобретения остаточных блоков. Именно эта простая и элегантная концепция остаточных блоков позволяет нам иметь действительно «глубокие» сети.

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

Вырожденная проблема: чем больше слоев, тем мощнее?

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

Проблема деградации не кажется нам интуитивной. Само собой разумеется, что если у нас есть две сети с одинаковым количеством слоев и добавить перед второй сетьюxслой, худший случай должен быть доxСлой выводит карту идентичности, что дает одинаковую конечную производительность для обеих сетей. Возможная догадка состоит в том, что сеть с большим количеством слоев работает плохо, потому что карта идентичности игнорируется сетью. Таким образом, в начале 2010-х годов такие сети, как VGG-16, обычно ограничивались примерно 10–20 уровнями.

Остаточная архитектура

Остаточные сети обеспечивают простое и понятное решение проблемы деградации, описанной выше. Остаточные сети могут создавать ярлык, называемый пропускным соединением, который принимает исходный ввод в сеть и пропускает его через несколько сложенных слоев для окончательного объединения с выходными функциями.图1 简单的残差块(source:https://arxiv.org/abs/1512.03385)Как показано на рисунке 1, предположим, что ввод для входа в слой стека — это x, а слой стека в середине — это функция F, тогда окончательный выход y равен

y=F(x)+x\

\

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

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

вычислительная среда

библиотека

Мы будем использовать PyTorch (включая torchvision) для построения остаточной сети, следующий код импортирует все необходимые нам библиотеки:

"""
The following is an import of PyTorch libraries.
"""
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision
from torchvision import datasets, transforms
from torchvision.utils import save_image
import matplotlib.pyplot as plt
import numpy as np
import random

набор данных

Чтобы продемонстрировать мощь остаточных сетей, мы будем использовать для тестирования два набора данных: более простой набор данных MINST (содержащий 60 000 изображений рукописных арабских цифр от 0 до 9) и более сложный набор данных CIFAR-10.

Ссылка для скачивания следующая: 1.MNISTнабор данных 2.CIFAR-10набор данных

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

аппаратные требования

Вообще говоря, хотя мы можем использовать ЦП для обучения нейронной сети, на самом деле лучшим выбором является графический процессор, поскольку он может значительно повысить скорость обучения. Остаточная сеть, которую вам предстоит создать в этой статье, относительно проста, и могут работать как ЦП, так и ГП, но в практических приложениях появятся более сложные сети (такие как ResNet-152), а ГП, как правило, лучше. Мы можем использовать следующий код, чтобы проверить, можно ли обучить нашу машину с помощью GPU:

"""
Determine if any GPUs are available
"""
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

Построить остаточные блоки

Здесь мы опишем, как создать простейший остаточный блок в сверточной нейронной сети, у которого входная и выходная размерности одинаковы. Код ниже объединяет nn.Module PyTorch для создания остаточных блоков.

"""
Define an nn.Module class for a simple residual block with equal dimensions
"""
class ResBlock(nn.Module):
​
    """
    Initialize a residual block with two convolutions followed by batchnorm layers
    """
    def __init__(self, in_size:int, hidden_size:int, out_size:int):
        super().__init__()
        self.conv1 = nn.Conv2d(in_size, hidden_size, 3, padding=1)
        self.conv2 = nn.Conv2d(hidden_size, out_size, 3, padding=1)
        self.batchnorm1 = nn.BatchNorm2d(hidden_size)
        self.batchnorm2 = nn.BatchNorm2d(out_size)
​
    def convblock(self, x):
        x = F.relu(self.batchnorm1(self.conv1(x)))
        x = F.relu(self.batchnorm2(self.conv2(x)))
        return x
​
    """
    Combine output with the original input
    """
    def forward(self, x): return x + self.convblock(x) # skip connection

Используйте существующую модель ResNet

На самом деле существует множество сетей, использующих остаточные структуры, которые после обучения на больших наборах данных, таких как ImageNet, работают настолько хорошо, что мы можем использовать эти существующие модели, не изобретая велосипед. Torchvision предоставляет в своей библиотеке готовые модели контрольных точек и архитектур для таких сетей, как ResNet-34, ResNet-50 и ResNet-152. Мы можем получить приведенную выше модель с помощью следующего кода:

"""
Creates a pretrained on ImageNet Resnet34
"""
resnet = torchvision.models.resnet34(pretrained=True)

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

результат

После 50 циклов обучения созданная нами сеть может легко достичь точности около 99% в наборе данных MNIST, а ResNet-34 и ResNet-152 могут достичь 90% в наборе данных CIFAR-10. Согласно He Kaiming et al.оригинальная бумага, мы также можем видеть, что остаточная структура работает значительно лучше, чем VGG в наборе данных ImageNet, а также сильнее, чем сеть с таким же количеством слоев, но без остаточной структуры.

Эпилог

Остаточная структура Хэ Юминга и др. можно назвать одним из самых выдающихся изобретений в области нейронных сетей в направлении компьютерного зрения за последнее время. Сегодня почти все сети (даже те, что не относятся к сверточным сетям) в большей или меньшей степени используют остаточную блочную структуру, чтобы поддерживать хорошую производительность даже после наложения большого количества слоев. Этот простой и элегантный подход создает бесчисленные возможности для совершенствующихся машин в понимании человеческого мира.