2025, Oct 30 21:17

Обратный сдвиг тензора в PyTorch: roll с отрицательным смещением

Показываем, как выполнить обратный круговой сдвиг тензора в PyTorch с помощью roll: используйте отрицательное смещение по нужной оси. Примеры кода и пояснения.

При вращении элементов тензора в PyTorch с помощью roll легко подумать, что есть только одно направление. По умолчанию положительный сдвиг как будто толкает значения «вниз» или вправо. Но иногда нужна противоположная операция — сдвиг влево или вверх. Обращение через inverse — это другое: оно переворачивает всю последовательность, а не меняет направление кругового сдвига. Ниже — короткий и практичный способ прокрутить в обратную сторону без лишних шагов.

Постановка задачи

Допустим, у нас есть одномерный тензор:

import torch

vec = torch.tensor([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
shifted = vec.roll(1, 0)
print(shifted)

Это перемещает последний элемент в начало — фактически поворот вправо:

tensor([6., 1., 2., 3., 4., 5.])

Но цель — получить противоположный порядок:

[2.0, 3.0, 4.0, 5.0, 6.0, 1.0]

В некоторых пайплайнах после поворота последний элемент затем зануляют, но ключевой момент здесь — сменить направление самого roll.

Что происходит на самом деле

roll выполняет круговой сдвиг вдоль указанного измерения. Знак смещения определяет направление: положительное значение сдвигает в одну сторону, отрицательное — в другую. inverse полностью разворачивает последовательность, что не равно направленному сдвигу.

Решение

Используйте отрицательный сдвиг, чтобы прокрутить в противоположную сторону. Этого достаточно.

import torch

src = torch.tensor([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
rotated_left = src.roll(-1, 0)
print(rotated_left)

Результат:

tensor([2., 3., 4., 5., 6., 1.])

Официальная документация показывает тот же принцип для многомерных тензоров. Например, тензор 4x2, прокрученный вверх вдоль измерения 0 со сдвигом -1:

import torch

mat = torch.tensor([1, 2, 3, 4, 5, 6, 7, 8]).view(4, 2)
print(mat)
print(torch.roll(mat, -1, 0))

Результат:

tensor([[1, 2],
        [3, 4],
        [5, 6],
        [7, 8]])

tensor([[3, 4],
        [5, 6],
        [7, 8],
        [1, 2]])

Справка: https://docs.pytorch.org/docs/stable/generated/torch.roll.html

Почему это важно

Направление при преобразовании последовательностей — частый источник незаметных ошибок. Отрицательный сдвиг в roll делает намерение очевидным и избавляет от реверса или другого постобработчика. Этот нюанс легко упустить, когда бегло ищешь «поведение, похожее на pop», хотя такой сценарий прямо описан в документации.

Выводы

Если нужно прокрутить тензор PyTorch в обратном направлении, не переходите на inverse и не выдумывайте обходные пути. Вызовите roll с отрицательным сдвигом по нужному измерению. Так вы явно выражаете намерение, соблюдаете описанное в документации поведение и сохраняете операцию корректной и лаконичной.

Статья основана на вопросе на StackOverflow от FlumeRS и ответе от Aadvik.