Напишите функцию, возвращающую рецептивное поле стека свёрток по ядрам и шагам.
Дан список слоёв, описанных размером ядра и шагом. Вычислите рецептивное поле одного выходного элемента относительно входа сети.
Ограничения:
- слои упорядочены от входа к выходу; каждый элемент — пара (kernel, stride)
- без dilation, без ветвлений, эффекты паддинга не учитываем
- вернуть одно целое число, во входных пикселях
def receptive_field(layers):
"""layers: [(kernel, stride), ...] от входа к выходу. Возвращает int."""
...
Допишите реализацию.
Идём по слоям от входа к выходу, храня jump — произведение пройденных шагов. Стартуем с rf = 1, jump = 1; для каждого слоя делаем rf += (k − 1) × jump, затем jump ×= s. Вклад слоя — k − 1 пикселей, умноженных на накопленное прореживание.
- ✗Игнорируют шаг и просто перемножают размеры ядер
- ✗Прибавляют k вместо k − 1 на каждый слой
- ✗Применяют шаг текущего слоя до того, как учли вклад его ядра
- →Как меняется формула, если у слоя есть dilation?
- →Почему накопленный jump равен произведению всех предыдущих шагов?
Ключ — накапливать jump, произведение шагов всех уже пройденных слоёв. Вклад слоя в поле измеряется во входных пикселях, поэтому его нужно масштабировать на прореживание, накопленное ДО него.
def receptive_field(layers):
"""layers: [(kernel, stride), ...] от входа к выходу. Возвращает int."""
rf, jump = 1, 1
for kernel, stride in layers:
rf += (kernel - 1) * jump
jump *= stride
return rf
Порядок важен: сначала прибавляем вклад ядра, затем обновляем jump. Стек из трёх свёрток 3×3 с шагом 1 даёт 1 + 2 + 2 + 2 = 7. Если у второго слоя шаг 2, третий слой добавляет уже 2 × 2 = 4, и поле вырастает до 9.