← Назад к вопросам

Что такое RoI Pooling и RoI Align? Для чего они нужны?

3.0 Senior🔥 131 комментариев
#Глубокое обучение

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое RoI Pooling и RoI Align? Для чего они нужны?

RoI Pooling и RoI Align это два ключевых механизма в архитектуре объектных детекторов, основанных на регионах (R-CNN семейство). Они решают проблему извлечения признаков из произвольно сформированных регионов изображения.

Контекст: почему нужны RoI операции

В детекторах типа Faster R-CNN процесс состоит из двух этапов:

  1. Region Proposal Network (RPN) генерирует кандидатов регионов (region proposals) произвольного размера и соотношения сторон
  2. Head network должна классифицировать эти регионы и уточнить их координаты

Проблема: CNN ожидает фиксированные размеры входа. Как обработать регионы разных размеров?

Решение: RoI Pooling и RoI Align.

RoI Pooling (Region of Interest Pooling)

Это старый и простой метод, введённый в Fast R-CNN (2015).

Как работает:

  1. На выходе CNN есть карта признаков (feature map) размера H x W x C
  2. Для каждого предложенного региона известны его координаты в исходном изображении
  3. RoI Pooling преобразует эти координаты в координаты на feature map (с учётом stride CNN)
  4. Регион на feature map делится на сетку P x Q (фиксированного размера)
  5. В каждой ячейке сетки применяется max pooling
  6. Результат: tensor размера P x Q x C (фиксированный!)
import torch
import torch.nn as nn

# Пример использования
feature_map = torch.randn(1, 256, 64, 64)  # batch=1, channels=256, H=64, W=64

# RoI с координатами (x1, y1, x2, y2) в пикселях исходного изображения
# Исходное изображение обычно 224x224 или 256x256
rois = torch.tensor([
    [0, 10, 20, 100, 200],  # batch_index, x1, y1, x2, y2
    [0, 50, 50, 150, 150],
])

roi_pool = nn.RoIPool(output_size=(7, 7), spatial_scale=1.0/32.0)
# spatial_scale = 1 / stride CNN
# Если CNN имеет stride 32 (уменьшает размер в 32 раза)

pooled = roi_pool(feature_map, rois)
print(pooled.shape)  # (2, 256, 7, 7) фиксированный размер!

Математически:

Для региона [x1, y1, x2, y2]:
1. Преобразуем в координаты feature map: [x1/stride, y1/stride, x2/stride, y2/stride]
2. Делим регион на P x Q ячеек
3. В каждой ячейке берём максимум

Проблемы RoI Pooling:

  1. Quantization loss из-за округления координат

    • Координаты преобразуются из float в int, что приводит к потере информации
    • Регионы смещаются из-за округления
  2. Неточное выравнивание (misalignment)

    • Регион на исходном изображении не соответствует региону на feature map
# Пример quantization loss
# Регион [10.3, 20.7, 100.5, 200.2] в изображении
# После преобразования на feature map (stride=32):
# [10.3/32, 20.7/32, 100.5/32, 200.2/32] = [0.32, 0.65, 3.14, 6.26]
# После округления: [0, 0, 3, 6] — потеря точности!

RoI Align

Это улучшенная версия, введённая в Mask R-CNN (2017), которая решает проблемы RoI Pooling.

Ключевые отличия:

  1. Использует биллинейную интерполяцию вместо округления
  2. Не округляет координаты — работает с float
  3. Правильное выравнивание (proper alignment)

Как работает:

import torch
import torch.nn as nn
from torchvision.ops import RoIAlign

feature_map = torch.randn(1, 256, 64, 64)

# RoI Align
rois = torch.tensor([
    [0, 10.3, 20.7, 100.5, 200.2],  # Можем использовать float координаты!
    [0, 50.2, 50.8, 150.1, 150.9],
])

roi_align = RoIAlign(output_size=(7, 7), spatial_scale=1.0/32.0, sampling_ratio=2)
# sampling_ratio: количество точек выборки в каждой ячейке
# Если sampling_ratio=-1, берётся адаптивное количество

aligned = roi_align(feature_map, rois)
print(aligned.shape)  # (2, 256, 7, 7) фиксированный размер

Математически (RoI Align):

Для каждой ячейки выходной сетки (например 7x7):
1. Вычисляем соответствующие координаты на feature map (используя float)
2. Берём несколько точек выборки (sampling points) в этой ячейке
3. Для каждой точки используем биллинейную интерполяцию для вычисления значения
4. Берём max (или average) от всех выборочных точек

Пример биллинейной интерполяции:

def bilinear_interpolate(feature_map, x, y):
    """
    feature_map: (H, W, C)
    x, y: координаты (могут быть float)
    """
    x1, y1 = int(x), int(y)
    x2, y2 = x1 + 1, y1 + 1
    
    # Веса
    wx = x - x1
    wy = y - y1
    
    # Биллинейная интерполяция
    value = (
        feature_map[y1, x1] * (1 - wx) * (1 - wy) +
        feature_map[y1, x2] * wx * (1 - wy) +
        feature_map[y2, x1] * (1 - wx) * wy +
        feature_map[y2, x2] * wx * wy
    )
    
    return value

Сравнение RoI Pooling vs RoI Align

АспектRoI PoolingRoI Align
ОкруглениеДа (int)Нет (float)
ИнтерполяцияНетБиллинейная
Квантизационная потеряЕстьМинимальная
ВыравниваниеНеточноеТочное
СкоростьБыстрееМедленнее (sampling)
КачествоХужеЛучше
ИспользованиеFast R-CNN, Faster R-CNNMask R-CNN, современные детекторы

Практическое влияние

На практике RoI Align улучшает результаты на 2-3% mAP (Mean Average Precision) на COCO dataset.

Это особенно заметно для малых объектов, где квантизационная потеря в RoI Pooling была критичной.

Использование в современных фреймворках

PyTorch:

from torchvision.ops import RoIPool, RoIAlign

# RoI Pooling
roi_pool = RoIPool(output_size=(7, 7), spatial_scale=0.0625)

# RoI Align (рекомендуется)
roi_align = RoIAlign(output_size=(7, 7), spatial_scale=0.0625, sampling_ratio=2)

TensorFlow:

from tensorflow.image import crop_and_resize

# crop_and_resize это эквивалент RoI Align
crops = crop_and_resize(
    image_tensor,
    boxes,  # нормализованные координаты
    box_indices,
    crop_size=(7, 7)
)

Экспертные заметки для собеседования

  1. RoI Pooling используется в Faster R-CNN, это старый стандарт
  2. RoI Align используется в Mask R-CNN и современных детекторах (YOLO, EfficientDet и др.)
  3. Основное улучшение это биллинейная интерполяция и float координаты, а не округление
  4. sampling_ratio в RoI Align — важный гиперпараметр. Чем больше, тем точнее, но медленнее
  5. В контексте Mask R-CNN RoI Align было критично для точного маскирования объектов

Если на собеседовании спросят о деталях, упомяни квантизационную потерю и объясни, почему биллинейная интерполяция это решение.

Что такое RoI Pooling и RoI Align? Для чего они нужны? | PrepBro