4.2. Набор данных для классификации изображений¶
Набор данных MNIST широко используется для классификации изображений, однако он слишком прост в качестве бенчмарка. Мы будем использовать аналогичный, но более сложный набор данных Fashion-MNIST.
Одним из наиболее широко используемых наборов данных для классификации изображений является набор данных MNIST https://en.wikipedia.org/wiki/MNIST_database (LeCun et al., 1998) с рукописными цифрами. На момент его выпуска в 1990-х годах он представлял собой серьезное испытание для большинства алгоритмов машинного обучения, состоя из 60 000 изображений разрешением \(28 \times 28\) пикселей (а также тестового набора из 10 000 изображений). Для понимания масштаба: в 1995 году Sun SPARCStation 5 с впечатляющими 64 МБ оперативной памяти и производительностью 5 MFLOPs считался передовым оборудованием для машинного обучения в Bell Laboratories компании AT&T. Достижение высокой точности распознавания цифр было ключевым компонентом автоматизации сортировки писем в USPS в 1990-х годах. Глубокие сети, такие как LeNet-5 (LeCun et al., 1995), машины опорных векторов с инвариантностью (Schölkopf et al., 1996) и классификаторы касательного расстояния (Simard et al., 1998), все могли достигать уровня ошибок ниже 1%.
На протяжении более чем десятилетия MNIST служил основной точкой отсчёта для сравнения алгоритмов машинного обучения. Хотя он хорошо справлялся с ролью бенчмарка, даже простые модели по современным стандартам достигают точности классификации выше 95%, что делает его непригодным для различения сильных и слабых моделей. Более того, этот набор данных позволяет достигать очень высоких уровней точности, что не типично для многих задач классификации. Это сместило фокус алгоритмических разработок в сторону конкретных семейств алгоритмов, способных использовать преимущества чистых наборов данных, таких как методы активного множества и алгоритмы активного множества, ориентированные на поиск границы. Сегодня MNIST служит скорее проверкой на адекватность, чем бенчмарком. ImageNet (Deng et al., 2009) представляет собой гораздо более актуальную задачу. К сожалению, ImageNet слишком велик для многих примеров и иллюстраций в этой книге, так как обучение на нём заняло бы слишком много времени, чтобы примеры оставались интерактивными. В качестве замены мы сосредоточим наше обсуждение в следующих разделах на качественно схожем, но гораздо меньшем наборе данных Fashion-MNIST (Xiao et al., 2017), который был выпущен в 2017 году. Он содержит изображения 10 категорий одежды при разрешении \(28 \times 28\) пикселей.
%matplotlib inline
import time
import torch
import torchvision
from torchvision import transforms
from d2l import torch as d2l
d2l.use_svg_display()
4.2.1. Загрузка набора данных¶
Поскольку набор данных Fashion-MNIST настолько полезен, все основные фреймворки предоставляют его предварительно обработанные версии. Мы можем скачать его и загрузить в память с помощью встроенных средств фреймворка.
class FashionMNIST(d2l.DataModule): #@save
"""The Fashion-MNIST dataset."""
def __init__(self, batch_size=64, resize=(28, 28)):
super().__init__()
self.save_hyperparameters()
trans = transforms.Compose([transforms.Resize(resize),
transforms.ToTensor()])
self.train = torchvision.datasets.FashionMNIST(
root=self.root, train=True, transform=trans, download=True)
self.val = torchvision.datasets.FashionMNIST(
root=self.root, train=False, transform=trans, download=True)
Набор данных Fashion-MNIST состоит из изображений 10 категорий, по 6000 изображений в обучающей выборке и по 1000 в тестовой выборке для каждой категории. Тестовая выборка используется для оценки производительности модели (её нельзя использовать для обучения). Следовательно, обучающая выборка и тестовая выборка содержат 60 000 и 10 000 изображений соответственно.
data = FashionMNIST(resize=(32, 32))
len(data.train), len(data.val)
Изображения являются черно-белыми и имеют разрешение \(32 \times 32\) пикселей. Это аналогично исходному набору данных MNIST, который состоял из бинарных черно-белых изображений. Обратите внимание, однако, что большинство современных изображений имеют три канала (красный, зеленый, синий), а гиперспектральные изображения могут содержать более 100 каналов (сенсор HyMap имеет 126 каналов). По соглашению мы храним изображение в виде тензора \(c \times h \times w\), где \(c\) — количество цветовых каналов, \(h\) — высота, а \(w\) — ширина.
data.train[0][0].shape
Категории Fashion-MNIST имеют понятные для человека названия. Следующий вспомогательный метод обеспечивает преобразование между числовыми метками и их названиями.
@d2l.add_to_class(FashionMNIST) #@save
def text_labels(self, indices):
"""Return text labels."""
labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return [labels[int(i)] for i in indices]
4.2.2. Чтение мини-батча¶
Чтобы упростить чтение из обучающей и тестовой выборок, мы используем
встроенный итератор данных, а не создаём его с нуля. Напомним, что на
каждой итерации итератор данных считывает мини-батч данных размером
batch_size. Для итератора обучающих данных мы также случайным
образом перемешиваем примеры.
@d2l.add_to_class(FashionMNIST) #@save
def get_dataloader(self, train):
data = self.train if train else self.val
return torch.utils.data.DataLoader(data, self.batch_size, shuffle=train,
num_workers=self.num_workers)
Чтобы понять, как это работает, загрузим мини-батч изображений, вызвав
метод train_dataloader. Он содержит 64 изображения.
X, y = next(iter(data.train_dataloader()))
print(X.shape, X.dtype, y.shape, y.dtype)
Рассмотрим время, необходимое для чтения изображений. Несмотря на то что это встроенный загрузчик, он работает не молниеносно. Тем не менее, этого достаточно, поскольку обработка изображений с помощью глубокой сети занимает значительно больше времени. Таким образом, обучение сети не будет ограничено скоростью ввода-вывода.
tic = time.time()
for X, y in data.train_dataloader():
continue
f'{time.time() - tic:.2f} sec'
4.2.3. Визуализация¶
Мы будем часто использовать набор данных Fashion-MNIST. Для визуализации
изображений и соответствующих меток можно воспользоваться
вспомогательной функцией show_images. Не вдаваясь в детали
реализации, мы просто покажем интерфейс ниже: для таких вспомогательных
функций нам достаточно знать, как вызывать d2l.show_images, а не то,
как именно она работает.
def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5): #@save
"""Plot a list of images."""
raise NotImplementedError
Давайте применим это на практике. В целом, полезно визуализировать и исследовать данные, на которых выполняется обучение. Люди отлично умеют замечать аномалии, и благодаря этому визуализация служит дополнительной защитой от ошибок и неточностей в проектировании экспериментов. Ниже представлены изображения и соответствующие им метки (в текстовом виде) для первых нескольких примеров в наборе данных для обучения.
@d2l.add_to_class(FashionMNIST) #@save
def visualize(self, batch, nrows=1, ncols=8, labels=[]):
X, y = batch
if not labels:
labels = self.text_labels(y)
d2l.show_images(X.squeeze(1), nrows, ncols, titles=labels)
batch = next(iter(data.val_dataloader()))
data.visualize(batch)
Теперь мы готовы приступить к работе с набором данных Fashion-MNIST в следующих разделах.
4.2.4. Итоги¶
Теперь у нас есть несколько более реалистичный набор данных для использования в классификации. Fashion-MNIST — это набор данных для классификации одежды, состоящий из изображений, представляющих 10 категорий. Мы будем использовать этот набор данных в последующих разделах и главах для оценки различных архитектур сетей, от простой линейной модели до продвинутых остаточных сетей. Как это обычно делается с изображениями, мы считываем их в виде тензора формы (размер батча, количество каналов, высота, ширина). На данный момент у нас имеется только один канал, поскольку изображения являются черно-белыми (на приведённой выше визуализации используется псевдоцветовая палитра для улучшения видимости).
Наконец, итераторы данных ⟦are a key component⟧ являются ключевым компонентом для обеспечения высокой производительности. ⟦For instance,⟧ Например, мы можем использовать графические процессоры для эффективной декомпрессии изображений, транскодирования видео или других операций предварительной обработки. ⟦Whenever possible, you should rely on well-implemented data iterators that exploit high-performance computing to avoid slowing down your training loop.⟧ По возможности следует использовать хорошо реализованные итераторы данных, которые используют возможности высокопроизводительных вычислений, чтобы не замедлять цикл обучения.
4.2.5. Упражнения¶
Влияет ли уменьшение
batch_size(например, до 1) на производительность чтения?Производительность итератора данных имеет важное значение. Как вы думаете, текущая реализация достаточно быстра? Изучите различные варианты её улучшения. Используйте системный профилировщик, чтобы выявить узкие места.
Ознакомьтесь с онлайн-документацией по API фреймворка. Какие ещё наборы данных доступны?