гитхаб, бумага

В недавней статье Google AI Обучение изменению размера изображений для задач компьютерного зрения авторы предложили новый способ изменения размера изображений перед их отправкой в ​​классификатор изображений. Обычно мы изменяем размер изображений до пространственного разрешения 224x224, используя какой-либо метод интерполяции (например, билинейный, бикубический), но что, если мы заменим фиксированный размер изменяемым размером? Именно на этот вопрос и призвана ответить данная статья.

Таким образом, мы хотим изучить модель, которая научится изменять размер изображений (например, размер входного изображения — 448x448, а размер выходного — 224x224, который будет передан классификатору изображений, например ResNet). Изображения с измененным размером не будут иметь такого же визуального качества, как исходное изображение, но вместо этого улучшит производительность задачи. Пример изображений, выводимых этой моделью, показан на рисунке 1, и, как мы видим, они явно не похожи на изображения из реальной жизни.

Зачем нам нужно изменять размер изображений?

Первым шагом почти в каждом конвейере обработки изображений является уменьшение изображения до фиксированного разрешения. Это можно сделать с помощью билиарной интерполяции, выборки ближайшего соседа (в случае сегментации изображения), обрезки изображения до желаемого разрешения.

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

Модель изменения размера

Предлагаемая модель Resizer используется для уменьшения масштаба изображений. Теперь из-за внутренних ограничений, описанных выше, мы также должны передавать изображения фиксированного размера в модель Resizer, что вначале может показаться нелогичным. Но вот конвейер с моделью ресайзера и без нее.

Модель без изменения размера

Original Image -> Downscale to 224x224 -> ResNet

Модель с изменением размера

Original Image -> Downscale to 448x448 -> Resizer to downscale to 224x224 -> ResNet

Как видно сверху, мы уменьшаем изображение до 448x448, что в 4 раза больше пикселей, чем 224x224. Это означает, что модель имеет в 4 раза больше информации для последующей задачи.

Примечание. Значение 448x448 является абсолютно произвольным, и вы можете уменьшить его до любого разрешения.

Предлагаемая модель изменения размера показана на рисунке 2.

Архитектура модели довольно проста, и код PyTorch для сети показан ниже (или вы можете проверить на github)

class ResBlock(nn.Module):
    def __init__(self, channel_size: int, negative_slope: float = 0.2):
       super().__init__()
       self.block = nn.Sequential(
            nn.Conv2d(channel_size, channel_size, kernel_size=3, padding=1,
                      bias=False),
            nn.BatchNorm2d(channel_size),
            nn.LeakyReLU(negative_slope, inplace=True),
            nn.Conv2d(channel_size, channel_size, kernel_size=3, padding=1,
                     bias=False),
            nn.BatchNorm2d(channel_size)
        )
    def forward(self, x):
        return x + self.block(x)
class Resizer(nn.Module):
    def __init__(self,
                 interpolate_mode: str = "bilinear",
                 input_image_size: int = 448,
                 output_image_size: int = 224,
                 num_kernels: int = 16,
                 num_resblocks: int = 2,
                 slope: float = 0.2,
                 in_channels: int = 3,
                 out_channels: int = 3):
    super().__init__()
    scale_factor = input_image_size / output_image_size
    n = num_kernels
    r = num_resblocks
    
    self.module1 = nn.Sequential(
        nn.Conv2d(3, n, kernel_size=7, padding=3),
        nn.LeakyReLU(slope, inplace=True),
        nn.Conv2d(n, n, kernel_size=1),
        nn.LeakyReLU(slope, inplace=True),
        nn.BatchNorm2d(n)
    )
    resblocks = []
    for i in range(r):
        resblocks.append(ResBlock(n, slope))
    self.resblocks = nn.Sequential(*resblocks)
    self.module3 = nn.Sequential(
        nn.Conv2d(n, n, kernel_size=3, padding=1, bias=False),
        nn.BatchNorm2d(n)
    )
    self.module4 = nn.Conv2d(n, out_channels, kernel_size=7,padding=3)
    
    self.interpolate = partial(F.interpolate,
                               scale_factor=scale_factor,
                               mode=interpolate_mode,
                               align_corners=False,
                               recompute_scale_factor=False)
def forward(self, x):
    residual = self.interpolate(x)
    
    out = self.module1(x)
    out_residual = self.interpolate(out)
  
    out = self.resblocks(out_residual)
    out = self.module3(out)
    out = out + out_residual
    out = self.module4(out)
    out = out + residual
    return out

Теперь мы можем напрямую передать выходные данные этой модели в качестве входных данных базовой модели (в данном случае ResNet-50) и выполнить классификацию изображений. Обе модели будут изучены совместно. Код для этого показан ниже

def forward(self, x):
    if self.resizer_model is not None:
        x = self.resizer_model(x)
    x = self.base_model(x)
    return x

Набор данных

Наборы данных Imagenette и Imagewoof используются для проверки производительности предлагаемой модели. Эти наборы данных содержат 10 классов, каждый из которых Imagenette является более простым набором данных, а Imagewoof содержит 10 самых сложных классов. Инструкции по загрузке наборов данных приведены в README.

Результаты модели с ResNet-50 в качестве базовой модели показаны ниже.

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

Инструкции по записи экспериментов приведены в README.

твиттер, линкедин, гитхаб

Первоначально опубликовано на https://kushajveersingh.github.io 17 сентября 2021 г.