Именованные тензоры
Именованные тензоры позволяют пользователям явно задавать имена размерностям тензора. В большинстве случаев операции, принимающие параметры размерности, будут принимать имена размерностей, избегая необходимости отслеживать размерности по положению. Кроме того, именованные тензоры используют имена для автоматической проверки правильности использования API во время выполнения, обеспечивая дополнительную безопасность. Имена также могут использоваться для перестановки размерностей, например, для поддержки «расширения по имени», а не «расширения по положению».
Предупреждение
API именованных тензоров является экспериментальной функцией и может быть изменён.
Создание именованных тензоров
Функции-фабрики теперь принимают новый names аргумент, который связывает имя с каждой размерностью.
>>> torch.zeros(2, 3, names=('N', 'C'))
tensor([[0., 0., 0.],
[0., 0., 0.]], names=('N', 'C'))
Именованные размерности, как и обычные размерности тензора, упорядочены. tensor.names[i] — это имя размерности i тензора tensor.
Следующие функции-фабрики поддерживают именованные тензоры:
Именованные размерности
См. names для ограничений на имена тензоров.
Используйте names для доступа к именам размерностей тензора и rename() для переименования именованных размерностей.
>>> imgs = torch.randn(1, 2, 2, 3 , names=('N', 'C', 'H', 'W'))
>>> imgs.names
('N', 'C', 'H', 'W')
>>> renamed_imgs = imgs.rename(H='height', W='width')
>>> renamed_imgs.names
('N', 'C', 'height', 'width)
Именованные тензоры могут сосуществовать с неуказанными тензорами; именованные тензоры являются экземплярами torch.Tensor. У неуказанных тензоров None-именованные размерности. Именованные тензоры не требуют именования всех размерностей.
>>> imgs = torch.randn(1, 2, 2, 3 , names=(None, 'C', 'H', 'W')) >>> imgs.names (None, 'C', 'H', 'W')
Семантика распространения имен
Именованные тензоры используют имена для автоматической проверки правильности вызова API во время выполнения. Это происходит в процессе, называемом выведением имен. Более формально, выведение имен состоит из следующих двух шагов:
- Проверка имен: оператор может выполнять автоматические проверки во время выполнения, проверяющие, что определённые имена размерностей совпадают.
- Распространение имен: выведение имен распространяет имена на выходные тензоры.
Все операции, которые поддерживают именованные тензоры, распространяют имена.
>>> x = torch.randn(3, 3, names=('N', 'C'))
>>> x.abs().names
('N', 'C')
Семантика соответствия
Два имени совпадают, если они равны (равенство строк) или если по крайней мере одно из них None. Значения None фактически являются специальным именем «подстановочного знака».
unify(A, B) определяет, какое из имён A и B распространять на выходе. Она возвращает более конкретное из двух имён, если они совпадают. Если имена не совпадают, возвращается ошибка.
Примечание
На практике при работе с именованными тензорами следует избегать именования размерностей, так как их обработка может быть сложной. Рекомендуется преобразовать все неуказанные размерности в именованные размерности с помощью refine_names().
Основные правила вывода имен
Посмотрим, как match и unify используются в выводе имен в случае сложения двух одномерных тензоров без трансляции.
x = torch.randn(3, names=('X',))
y = torch.randn(3)
z = torch.randn(3, names=('Z',))
Проверка имен: проверяется, что имена двух тензоров совпадают.
Для следующих примеров:
>>> # x + y # match('X', None) is True
>>> # x + z # match('X', 'Z') is False
>>> # x + x # match('X', 'X') is True
>>> x + z
Error when attempting to broadcast dims ['X'] and dims ['Z']: dim 'X' and dim 'Z' are at the same position from the right but do not match.
Распространение имен: унифицируются имена, чтобы выбрать имя для распространения. В случае x + y, выбирается unify('X', None) = 'X', поскольку 'X' более конкретное, чем None.
>>> (x + y).names
('X',)
>>> (x + x).names
('X',)
Полный список правил вывода имен см. в Обзор операторов именованных тензоров. Вот две общие операции, которые могут быть полезны для рассмотрения:
- Бинарные арифметические операции: Объединяет имена из входов
- Операции матричного умножения: Исключает размерности
Явное выравнивание по именам
Используйте align_as() или align_to() для выравнивания размерностей тензора по имени в заданном порядке. Это полезно для выполнения «расширения по именам».
# This function is agnostic to the dimension ordering of `input`,
# as long as it has a `C` dimension somewhere.
def scale_channels(input, scale):
scale = scale.refine_names('C')
return input * scale.align_as(input)
>>> num_channels = 3
>>> scale = torch.randn(num_channels, names=('C',))
>>> imgs = torch.rand(3, 3, 3, num_channels, names=('N', 'H', 'W', 'C'))
>>> more_imgs = torch.rand(3, num_channels, 3, 3, names=('N', 'C', 'H', 'W'))
>>> videos = torch.randn(3, num_channels, 3, 3, 3, names=('N', 'C', 'H', 'W', 'D')
>>> scale_channels(imgs, scale)
>>> scale_channels(more_imgs, scale)
>>> scale_channels(videos, scale)
Управление размерностями
Используйте align_to() для перестановки большого количества размерностей без упоминания всех из них, как это требуется в permute().
>>> tensor = torch.randn(2, 2, 2, 2, 2, 2)
>>> named_tensor = tensor.refine_names('A', 'B', 'C', 'D', 'E', 'F')
# Move the F (dim 5) and E dimension (dim 4) to the front while keeping
# the rest in the same order
>>> tensor.permute(5, 4, 0, 1, 2, 3)
>>> named_tensor.align_to('F', 'E', ...)
Используйте flatten() и unflatten() для уплощения и восстановления размерностей соответственно. Эти методы более подробны, чем view() и reshape(), но имеют более ясный смысл для человека, читающего код.
>>> imgs = torch.randn(32, 3, 128, 128)
>>> named_imgs = imgs.refine_names('N', 'C', 'H', 'W')
>>> flat_imgs = imgs.view(32, -1)
>>> named_flat_imgs = named_imgs.flatten(['C', 'H', 'W'], 'features')
>>> named_flat_imgs.names
('N', 'features')
>>> unflattened_imgs = imgs.view(32, 3, 128, 128)
>>> unflattened_named_imgs = named_flat_imgs.unflatten(
'features', [('C', 3), ('H', 128), ('W', 128)])
Поддержка Autograd
Autograd в настоящее время ограниченно поддерживает именованные тензоры: autograd игнорирует имена всех тензоров. Вычисление градиента всё ещё верно, но мы теряем безопасность, предоставляемую именами.
>>> x = torch.randn(3, names=('D',))
>>> weight = torch.randn(3, names=('D',), requires_grad=True)
>>> loss = (x - weight).abs()
>>> grad_loss = torch.randn(3)
>>> loss.backward(grad_loss)
>>> weight.grad # Unnamed for now. Will be named in the future
tensor([-1.8107, -0.6357, 0.0783])
>>> weight.grad.zero_()
>>> grad_loss = grad_loss.refine_names('C')
>>> loss = (x - weight).abs()
# Ideally we'd check that the names of loss and grad_loss match but we don't yet.
>>> loss.backward(grad_loss)
>>> weight.grad
tensor([-1.8107, -0.6357, 0.0783])
Поддерживаемые операции и подсистемы
Операторы
См. Обзор операторов именованных тензоров для полного списка поддерживаемых операций torch и тензоров. Мы пока не поддерживаем следующие операции, не охваченные ссылкой:
- индексирование, расширенное индексирование.
Для torch.nn.functional операторов мы поддерживаем следующее:
Подсистемы
Поддерживается Autograd, см. Поддержка Autograd. Поскольку градиенты в настоящее время не именованные, оптимизаторы могут работать, но не протестированы.
Модули NN в настоящее время не поддерживаются. Это может привести к следующему при вызове модулей с именованными тензорными входами:
- Параметры модуля NN не именованные, поэтому выходы могут быть частично именованными.
- Функции forward модулей NN не поддерживают именованные тензоры и будут выводить соответствующую ошибку.
Мы также не поддерживаем следующие подсистемы, хотя некоторые из них могут работать «из коробки»:
- распределения
- сериализация (
torch.load(),torch.save()) - многопоточность
- JIT
- распределённый режим
- ONNX
Если какой-либо из этих аспектов важен для вашего случая использования, пожалуйста, поищите, была ли уже создана проблема, а если нет, создайте её.
Ссылка на API именованных тензоров
В этом разделе представлена документация для API, специфичных для именованных тензоров. Для получения подробной справки о том, как имена распространяются через другие операторы PyTorch, см. Область применения операторов именованных тензоров.
- classtorch.Tensor
-
-
names -
Хранит имена для каждой из размерностей этого тензора.
names[idx]соответствует имени размерности тензораidx. Имена — это либо строка, если размерность именованная, либоNoneесли размерность неименованная.Имена размерностей могут содержать символы или символ подчеркивания. Кроме того, имя размерности должно быть допустимым именем переменной Python (то есть не начинаться с подчеркивания).
Тензоры не могут иметь две именованные размерности с одинаковым именем.
Предупреждение
API именованных тензоров находится в стадии эксперимента и может быть изменено.
-
rename(*names, **rename_map)[source] -
Переименовывает имена размерностей
self.Существует два основных способа использования:
self.rename(**rename_map)возвращает представление тензора с переименованными размерностями, как указано в отображенииrename_map.self.rename(*names)возвращает представление тензора, переименовывая все размерности позиционно, используяnames. Для удаления имён тензора используйтеself.rename(None).Нельзя одновременно указывать как позиционные аргументы
names, так и ключевые аргументыrename_map.Примеры:
>>> imgs = torch.rand(2, 3, 5, 7, names=('N', 'C', 'H', 'W')) >>> renamed_imgs = imgs.rename(N='batch', C='channels') >>> renamed_imgs.names ('batch', 'channels', 'H', 'W') >>> renamed_imgs = imgs.rename(None) >>> renamed_imgs.names (None, None, None, None) >>> renamed_imgs = imgs.rename('batch', 'channel', 'height', 'width') >>> renamed_imgs.names ('batch', 'channel', 'height', 'width')Предупреждение
API именованных тензоров находится в стадии эксперимента и может быть изменено.
-
rename_(*names, **rename_map)[source] -
Вместо
rename()используется методrename().
-
refine_names(*names)[source] -
Уточняет имена размерностей
selfв соответствии сnames.Уточнение — это частный случай переименования, который «поднимает» неименованные размерности. Неименованная
Noneразмерность может быть уточнена с любым именем; именованная размерность может быть уточнена только с тем же именем.Поскольку именованные тензоры могут сосуществовать с неименованными тензорами, уточнение имён является отличным способом написания кода, учитывающего именованные тензоры, который работает как с именованными, так и с неименованными тензорами.
namesможет содержать не более одной многоточие (...). Многоточие расширяется жадно; оно расширяется на месте, чтобы заполнитьnamesдо той же длины, что иself.dim(), используя имена из соответствующих индексовself.names.Python 2 не поддерживает многоточие, но можно использовать строковую литерал вместо этого (
'...').- Параметры:
-
names (итерируемый из str) – Желаемые имена выходного тензора. Может содержать не более одной многоточие.
Примеры:
>>> imgs = torch.randn(32, 3, 128, 128) >>> named_imgs = imgs.refine_names('N', 'C', 'H', 'W') >>> named_imgs.names ('N', 'C', 'H', 'W') >>> tensor = torch.randn(2, 3, 5, 7, 11) >>> tensor = tensor.refine_names('A', ..., 'B', 'C') >>> tensor.names ('A', None, None, 'B', 'C')Предупреждение
API именованных тензоров находится в стадии эксперимента и может быть изменено.
-
align_as(other) → Tensor -
Переупорядочивает размерности тензора
selfв соответствии с порядком размерностей в тензореother, добавляя размерности с размером 1 для любых новых имён.Эта операция полезна для явного вещания по именам (см. примеры).
Все размерности
selfдолжны быть именованы, чтобы использовать этот метод. Результирующий тензор является представлением исходного тензора.Все имена размерностей
selfдолжны присутствовать вother.names.otherможет содержать именованные размерности, которые не находятся вself.names; выходной тензор имеет размерность размером 1 для каждого из этих новых имён.Чтобы выровнять тензор по определённому порядку, используйте
align_to().Примеры:
# Example 1: Applying a mask >>> mask = torch.randint(2, [127, 128], dtype=torch.bool).refine_names('W', 'H') >>> imgs = torch.randn(32, 128, 127, 3, names=('N', 'H', 'W', 'C')) >>> imgs.masked_fill_(mask.align_as(imgs), 0) # Example 2: Applying a per-channel-scale >>> def scale_channels(input, scale): >>> scale = scale.refine_names('C') >>> return input * scale.align_as(input) >>> num_channels = 3 >>> scale = torch.randn(num_channels, names=('C',)) >>> imgs = torch.rand(32, 128, 128, num_channels, names=('N', 'H', 'W', 'C')) >>> more_imgs = torch.rand(32, num_channels, 128, 128, names=('N', 'C', 'H', 'W')) >>> videos = torch.randn(3, num_channels, 128, 128, 128, names=('N', 'C', 'H', 'W', 'D')) # scale_channels is agnostic to the dimension order of the input >>> scale_channels(imgs, scale) >>> scale_channels(more_imgs, scale) >>> scale_channels(videos, scale)Предупреждение
API именованных тензоров находится в стадии эксперимента и может быть изменено.
-
align_to(*names)[source] -
Переупорядочивает размерности тензора
selfв соответствии с порядком, указанным вnames, добавляя размерности с размером 1 для любых новых имён.Все размерности
selfдолжны быть именованы, чтобы использовать этот метод. Результирующий тензор является представлением исходного тензора.Все имена размерностей
selfдолжны присутствовать вnames.namesможет содержать дополнительные имена, которые отсутствуют вself.names; выходной тензор имеет размерность размером 1 для каждого из этих новых имён.namesможет содержать не более одной многоточие (...). Многоточие расширяется, чтобы равняться всем именам размерностейselfкоторые не упоминаются вnames, в порядке их появления вself.Python 2 не поддерживает многоточие, но можно использовать строковую литерал вместо этого (
'...').- Параметры:
-
names (итерируемый из str) – Желаемый порядок размерностей выходного тензора. Может содержать не более одной многоточие, которая расширяется до всех невспомянутых имён размерностей
self.
Примеры:
>>> tensor = torch.randn(2, 2, 2, 2, 2, 2) >>> named_tensor = tensor.refine_names('A', 'B', 'C', 'D', 'E', 'F') # Move the F and E dims to the front while keeping the rest in order >>> named_tensor.align_to('F', 'E', ...)Предупреждение
API именованных тензоров находится в стадии эксперимента и может быть изменено.
- flatten(dims, out_dim) Tensor
-
Сжимает
dimsв одну размерность с именемout_dim.Все
dimsдолжны быть последовательными в порядке тензораself, но необязательно непрерывными в памяти.Примеры:
>>> imgs = torch.randn(32, 3, 128, 128, names=('N', 'C', 'H', 'W')) >>> flat_imgs = imgs.flatten(['C', 'H', 'W'], 'features') >>> flat_imgs.names, flat_imgs.shape (('N', 'features'), torch.Size([32, 49152]))Предупреждение
API именованных тензоров находится в стадии эксперимента и может быть изменено.
-
© 2024, PyTorch Contributors
PyTorch has a BSD-style license, as found in the LICENSE file.
https://pytorch.org/docs/1.13/named_tensor.html