Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Receptive Field в нейронных сетях
Receptive Field (рецептивное поле) — это размер области исходного входа (входного изображения или последовательности), которая влияет на выход определённого нейрона в слое нейронной сети. Это ключевой концепт для понимания того, как сверточные нейронные сети (CNN) обрабатывают информацию и какой контекст они видят на каждом уровне.
Как работает receptive field в CNN
Первый сверточный слой
При kernel size = 3x3:
- Receptive field = 3x3
- Каждый нейрон видит 9 пикселей входного изображения
import numpy as np
import matplotlib.pyplot as plt
# Пример: входное изображение 5x5, kernel 3x3
input_image = np.random.rand(5, 5)
print(f"Входное изображение (5x5)")
print(input_image)
# Сверка 3x3 фильтром, padding=0, stride=1
# Результат: 3x3 (каждый нейрон видит соответствующий 3x3 блок входа)
output_shape = (5 - 3) // 1 + 1 # 3x3
print(f"Output shape: {output_shape}x{output_shape}")
print(f"Receptive field: 3x3")
Несколько слоёв
Когда стакируешь несколько сверточных слоёв, receptive field растёт экспоненциально:
def calculate_receptive_field(kernel_size, stride=1, padding=0, n_layers=1):
"""
Вычисляет receptive field после n слоёв
RF_n = 1 + n * (kernel_size - 1) (при stride=1)
"""
rf = 1
for i in range(n_layers):
rf = rf + (kernel_size - 1) * (stride ** i)
return rf
# Примеры
print("3x3 kernel, stride=1:")
for layers in [1, 2, 3, 4, 5]:
rf = calculate_receptive_field(kernel_size=3, stride=1, n_layers=layers)
print(f" {layers} слоёв -> RF = {rf}x{rf}")
print("\n5x5 kernel, stride=1:")
for layers in [1, 2, 3, 4]:
rf = calculate_receptive_field(kernel_size=5, stride=1, n_layers=layers)
print(f" {layers} слоёв -> RF = {rf}x{rf}")
print("\n3x3 kernel, stride=2 (pooling):")
for layers in [1, 2, 3, 4, 5]:
rf = calculate_receptive_field(kernel_size=3, stride=2, n_layers=layers)
print(f" {layers} слоёв -> RF = {rf}x{rf}")
Результат:
3x3 kernel, stride=1:
1 слой -> RF = 3x3
2 слоя -> RF = 5x5
3 слоя -> RF = 7x7
4 слоя -> RF = 9x9
5 слоев -> RF = 11x11
5x5 kernel, stride=1:
1 слой -> RF = 5x5
2 слоя -> RF = 9x9
3 слоя -> RF = 13x13
4 слоя -> RF = 17x17
3x3 kernel, stride=2 (pooling):
1 слой -> RF = 3x3
2 слоя -> RF = 7x7
3 слоя -> RF = 15x15
4 слоя -> RF = 31x31
5 слоев -> RF = 63x63
Формула расчёта receptive field
RF(l) = RF(l-1) + (kernel_size - 1) * stride(l-1)
Где:
RF(l) — receptive field на слое l
kernel_size — размер ядра
stride — шаг свёртки
Пример расчёта VGG-подобной архитектуры
def compute_receptive_field_sequence(layers_config):
"""
layers_config: список кортежей (kernel_size, stride)
"""
rf = 1
cumulative_stride = 1
print(f"{'Слой':<20} {'Kernel':<10} {'Stride':<10} {'RF':<10}")
print("-" * 50)
for i, (kernel_size, stride) in enumerate(layers_config):
rf = rf + (kernel_size - 1) * cumulative_stride
cumulative_stride *= stride
print(f"Слой {i+1:<13} {kernel_size:<10} {stride:<10} {rf:<10}")
return rf
# VGG-подобная архитектура
config = [
(3, 1), # Conv 3x3
(3, 1), # Conv 3x3
(2, 2), # MaxPool 2x2
(3, 1), # Conv 3x3
(3, 1), # Conv 3x3
(2, 2), # MaxPool 2x2
]
final_rf = compute_receptive_field_sequence(config)
print(f"\nИтоговый receptive field: {final_rf}x{final_rf}")
Практическое значение receptive field
1. Размер входного изображения
# Если входное изображение 224x224 (ImageNet стандарт)
# А receptive field на последнем слое = 450x450
# Это значит модель может видеть больше, чем размер входа
# Это называется "over-complete receptive field"
input_size = 224
final_rf = 450
ratio = final_rf / input_size
print(f"Receptive field покрывает {ratio:.1f}x больше входа")
2. Для семантической сегментации
# Нужен достаточно большой RF для контекста
# Для распознавания объектов нужен RF, охватывающий весь объект
# U-Net для медицинской сегментации
# Обычно RF = 70-150 для 512x512 входа
print("U-Net обычно: RF = 70-150 для входа 512x512")
print("Ratio: 70/512 = 0.14 до 150/512 = 0.29")
3. Для обнаружения объектов (Object Detection)
# YOLO, Faster R-CNN требуют RF, охватывающий целый объект
# Но и должна быть информация о малых масштабах
# ResNet50 backbone
print("ResNet50:")
print(" После layer1: RF ≈ 71x71")
print(" После layer2: RF ≈ 231x231")
print(" После layer3: RF ≈ 471x471")
print(" После layer4: RF ≈ 1023x1023")
Атрусные свёртки (Dilated Convolutions)
Этот паттерн используется для быстрого увеличения RF:
# Обычная свёртка 3x3: RF = 3
# Атрусная свёртка 3x3 с dilation=2: RF = 5
# Атрусная свёртка 3x3 с dilation=4: RF = 7
def receptive_field_dilated(kernel_size, dilation):
return kernel_size + (kernel_size - 1) * (dilation - 1)
print("3x3 kernel с разными dilation:")
for d in [1, 2, 4, 8]:
rf = receptive_field_dilated(3, d)
print(f" dilation={d}: RF = {rf}x{rf}")
Проверка RF в PyTorch
import torch
from torchvision.models import resnet50
from torch_receptive_field import receptive_field
model = resnet50(pretrained=True)
model.eval()
# Вычисляем RF для выхода последнего слоя
rfs, rf_x, rf_y = receptive_field(model, (3, 224, 224))
print(f"ResNet50 RF: {rfs}x{rfs}")
Важные выводы
- Маленький RF — модель видит только локальные детали, может пропустить контекст
- Большой RF — модель может видеть глобальный контекст, лучше для понимания
- Оптимальный RF зависит от задачи:
- Классификация: RF должен быть ≥ размеру объекта
- Сегментация: RF должен быть больше объекта
- Обнаружение: зависит от диапазона размеров объектов
- Stride и pooling экспоненциально растят RF
- Атрусные свёртки эффективны для роста RF без потери разрешения
Понимание receptive field критично при проектировании архитектур CNN для конкретных задач компьютерного зрения.