expandir y repetir en Pytorch

       En torch , si desea cambiar la dimensión de un cierto tensor, puede usar métodos como ver, expandir, repetir, transponer y permutar. Aquí hay un resumen de algunos lugares confusos en estos métodos.

Las funciones de expansión y repetición se usan comúnmente en pytorch para la replicación de datos de tensor y la expansión de dimensión, pero sus mecanismos de trabajo son bastante diferentes.Este artículo compara estas dos funciones.

1 torch.expand()

  • Rol:  expand()las funciones pueden transmitir tensores a nuevas formas.
  • Nota: Solo se pueden expandir las dimensiones con un valor de dimensión de 1. Para las dimensiones que no necesitan expandirse, el valor de la dimensión permanece sin cambios y la posición correspondiente se puede escribir con el tamaño de dimensión original o escribirse directamente como -1; y el tensor expandido no asignará nueva memoria, solo crea una nueva vista basada en el original y regresa, la memoria del tensor devuelta no es continua. Similar a la función broadcast_to en numpy. Si desea que la memoria tensorial sea contigua, puede llamar a la función contigua.

La función de expansión se usa para expandir los datos unidimensionales en el tensor al tamaño especificado.

Primero, vamos a explicar lo que se llama dimensiones singleton, si el tamaño de un tensor en una determinada dimensión es 1, se llama dimensión singleton. Por ejemplo, zeros(2,3,4) no tiene una dimensión singular y zeros(2,1,4) es una dimensión singular en la segunda dimensión (es decir, la dimensión 1). La función de expansión solo puede actuar en estas dimensiones singulares.
El parámetro *sizes se utiliza para especificar el tamaño expandido de cada dimensión una por una (también puede entenderse como el número de expansiones).Para las dimensiones que no necesitan o no pueden expandirse (es decir, dimensiones no singulares), la posición correspondiente puede escribirse en el tamaño de dimensión original o escribirse directamente -1 .
La función de expansión puede conducir a un aumento en la dimensión del tensor original, que actúa sobre la dimensión frontal del tensor (agregando más dimensiones a la dimensión inferior del tensor), por lo que los datos del tensor se pueden copiar en múltiples copias a través de la expandir la función (comprensible como a lo largo de la dimensión del primer lote).
 

import torch

a = torch.tensor([1, 0, 2])     # a -> torch.Size([3])
b1 = a.expand(2, -1)            # 第一个维度为升维,第二个维度保持原样
'''
b1为 -> torch.Size([3, 2])
tensor([[1, 0, 2],
        [1, 0, 2]])
'''

a = torch.tensor([[1], [0], [2]])   # a -> torch.Size([3, 1])
b2 = a.expand(-1, 2)                 # 保持第一个维度,第二个维度只有一个元素,可扩展
'''
b2 -> torch.Size([3, 2])
b2为  tensor([[1, 1],
             [0, 0],
             [2, 2]])
'''

a = torch.Tensor([[1, 2, 3]])   # a -> torch.Size([1, 3])
b3 = a.expand(4, 3)              # 也可写为a.expand(4, -1)  对于某一个维度上的值为1的维度,
                                # 可以在该维度上进行tensor的复制,若大于1则不行
'''
b3 -> torch.Size([4, 3])
tensor(
	[[1.,2.,3.],
	[1.,2.,3.],
	[1.,2.,3.],
	[1.,2.,3.]]
)
'''

a = torch.Tensor([[1, 2, 3], [4, 5, 6]])  # a -> torch.Size([2, 3])
b4 = a.expand(4, 6)  # 最高几个维度的参数必须和原始shape保持一致,否则报错
'''
RuntimeError: The expanded size of the tensor (6) must match 
the existing size (3) at non-singleton dimension 1.
'''

b5 = a.expand(1, 2, 3)  # 可以在tensor的低维增加更多维度
'''
b5 -> torch.Size([1,2, 3])
tensor(
	[[[1.,2.,3.],
	 [4.,5.,6.]]]
)
'''
b6 = a.expand(2, 2, 3)  # 可以在tensor的低维增加更多维度,同时在新增加的低维度上进行tensor的复制
'''
b5 -> torch.Size([2,2, 3])
tensor(
	[[[1.,2.,3.],
	 [4.,5.,6.]],
	 [[1.,2.,3.],
	 [4.,5.,6.]]]
)
'''

b7 = a.expand(2, 3, 2)  # 不可在更高维增加维度,否则报错
'''
RuntimeError: The expanded size of the tensor (2) must match the 
existing size (3) at non-singleton dimension 2.
'''

b8 = a.expand(2, -1, -1)  # 最高几个维度的参数可以用-1,表示和原始维度一致
'''
b8 -> torch.Size([2,2, 3])
tensor(
	[[[1.,2.,3.],
	 [4.,5.,6.]],
	 [[1.,2.,3.],
	 [4.,5.,6.]]]
)
'''

# expand返回的张量与原版张量具有相同内存地址
print(b8.storage())  # 存储区的数据,说明expand后的a,aa,aaa,aaaa是共享storage的,
# 只是tensor的头信息区设置了不同的数据展示格式,从而使得a,aa,aaa,aaaa呈现不同的tensor形式
'''
1.0
2.0
3.0
4.0
5.0
6.0
'''

1.1 expand_as

 Puede verse expandcomo otra representación de , que está definida sizepor el tensor de destino pasado a la función .size

import torch
a = torch.tensor([1, 0, 2])
b = torch.zeros(2, 3)
c = a.expand_as(b)  # a照着b的维度大小进行拓展
# c为 tensor([[1, 0, 2],
#        [1, 0, 2]])

2 tensor.repetir()

  • Función: expand()Similar a la función, es transmitir el tensor a una nueva forma.
  • Nota: La dimensión -1 no está permitida, 1 significa sin cambios.

Como se mencionó anteriormente, expandir solo puede actuar en dimensiones singulares, por lo que para la expansión de dimensiones no singulares, debe usar la función de repetición.

tensor.repeat(*tamaños)

El parámetro *sizes especifica cuántas veces se copia el tensor original en cada dimensión. Todo el tensor original se copia como un todo, lo cual es muy diferente de la función de repetición en Numpy, y está más cerca del efecto de la función de mosaico.

A diferencia de expandir, la función de repetición en realidad copiará los datos y los almacenará en la memoria. La repetición abre un nuevo espacio de memoria y el tensor devuelto por torch.repeat es continuo en la memoria

import torch
a = torch.tensor([1, 0, 2])
b = a.repeat(3,2)  # 在轴0上复制3份,在轴1上复制2份
# b为 tensor([[1, 0, 2, 1, 0, 2],
#        [1, 0, 2, 1, 0, 2],
#        [1, 0, 2, 1, 0, 2]])


import torch
a = torch.Tensor([[1,2,3]])
'''
tensor(
	[[1.,2.,3.]]
)
'''

aa = a.repeat(4, 3) # 维度不变,在各个维度上进行数据复制
'''
tensor(
	[[1.,2.,3.,1.,2.,3.,1.,2.,3.],
	 [1.,2.,3.,1.,2.,3.,1.,2.,3.],
	 [1.,2.,3.,1.,2.,3.,1.,2.,3.],
	 [1.,2.,3.,1.,2.,3.,1.,2.,3.]]
)
'''

a = torch.Tensor([[1,2,3], [4, 5, 6]])
'''
tensor(
	[[1.,2.,3.],
	 [4.,5.,6.]]
)
'''
aa = a.repeat(4,6) # 维度不变,在各个维度上进行数据复制
'''
tensor(
	[[1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.],
	 [4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.],
	 [1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.],
	 [4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.],
	 [1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.],
	 [4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.],
	 [1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.],
	 [4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.]]
)
'''

aaa = a.repeat(1,2,3) # 可以在tensor的低维增加更多维度,并在各维度上复制数据
'''
tensor(
	[[[1.,2.,3.,1.,2.,3.,1.,2.,3.],
	  [4.,5.,6.,4.,5.,6.,4.,5.,6.],
	  [1.,2.,3.,1.,2.,3.,1.,2.,3.],
	  [4.,5.,6.,4.,5.,6.,4.,5.,6.]]]
)
'''
aaaa = a.repeat(2,3,1) # 可以在tensor的高维增加更多维度,并在各维度上复制数据
'''
tensor(
	[[[1.,2.,3.],
	  [4.,5.,6.],
	  [1.,2.,3.],
	  [4.,5.,6.],
	  [1.,2.,3.],
	  [4.,5.,6.]],
	 [[1.,2.,3.],
	  [4.,5.,6.],
	  [1.,2.,3.],
	  [4.,5.,6.],
	  [1.,2.,3.],
	  [4.,5.,6.]]]
)
'''

aaaaa = a.repeat(2, 3, -1) 
'''
RuntimeError: Trying to create tensor with negative dimension -3: [2,6,-3]
'''

print(aaaa.storage()) # 存储区的数据,说明repeat后的a,aa,aaa,aaaa是有各自独立的storage的
'''
1.0
2.0
3.0
4.0
5.0
6.0
1.0
2.0
3.0
4.0
5.0
6.0
1.0
2.0
3.0
4.0
5.0
6.0
1.0
2.0
3.0
4.0
5.0
6.0
1.0
2.0
3.0
4.0
5.0
6.0
1.0
2.0
3.0
4.0
5.0
6.0
'''

2.1 repetir_intertilo

En Pytorch, la función similar a la función Numpyes :repeattorch.repeat_interleave

torch.repeat_interleave(input, repeats, dim=None)

La entrada del parámetro es el tensor original, las repeticiones son el número de copias en el eje especificado y dim es el eje de operación de la copia. Si el valor es Ninguno, todos los elementos se copiarán de forma predeterminada y un tensor unidimensional después de aplanar Será devuelto. A diferencia de repetir, que toma todo el tensor original como un todo, la operación repetir_intercalar es por elementos.

a = torch.tensor([[1], [0], [2]])
b = torch.repeat_interleave(a, repeats=3)   # 结果flatten
# b为tensor([1, 1, 1, 0, 0, 0, 2, 2, 2])

c = torch.repeat_interleave(a, repeats=3, dim=1)  # 沿着axis=1逐元素复制
# c为tensor([[1, 1, 1],
#        [0, 0, 0],
#        [2, 2, 2]])

El resumen
es el mismo:
(1) Ambas dimensiones se pueden expandir, o el tensor se puede copiar en una determinada dimensión

Diferencias:
(1) Los significados de los parámetros son diferentes, el parámetro de repetición indica el múltiplo de replicación de datos a lo largo de una determinada dimensión, que puede ser cualquier valor entero mayor que 0, el parámetro de expansión indica el valor en la dimensión correspondiente a el tensor, y solo cuando se agrega una nueva dimensión baja Indica el múltiplo de la replicación de datos a lo largo de la dimensión baja, otros parámetros deben ser consistentes con el tensor original (2)
El área de almacenamiento del resultado devuelto es diferente, el tensor devuelto by repeat volverá a tener un área de almacenamiento independiente, y el tensor devuelto por expand será el mismo que la memoria compartida del tensor original

Supongo que te gusta

Origin blog.csdn.net/ytusdc/article/details/128094432
Recomendado
Clasificación