.expand(shape)
과 같다.>>> x = torch.tensor([1, 2, 3]) # shape (3,)
>>> torch.broadcast_to(x, (3, 3)) #shape (3, 3)
tensor([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
>>> x = torch.tensor([[1], [2], [3]]) # (3, 1)
>>> x.size()
torch.Size([3, 1])
>>> x.expand(3, 4) # -> (3, 4)
tensor([[ 1, 1, 1, 1],
[ 2, 2, 2, 2],
[ 3, 3, 3, 3]])
>>> x.expand(-1, 4) # -1 means not changing the size of that dimension
# (3, 4)
tensor([[ 1, 1, 1, 1],
[ 2, 2, 2, 2],
[ 3, 3, 3, 3]])
self.expand(other.size())
와 같음.>>> x = torch.tensor([1, 2, 3]) # (3,)
>>> x.repeat(4, 2)
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]])
>>> x.repeat(4, 2, 1).size()
torch.Size([4, 2, 3]) # (4, 2, 3)
repeats
: The number of repetitions for each element. repeats is broadcasted to fit the shape of the given axis.dim
output_size
Repeated tensor which has the same shape as input, except along the given axis.
>>> x = torch.tensor([1, 2, 3])
>>> x.repeat_interleave(repeats=2)
tensor([1, 1, 2, 2, 3, 3])
>>> y = torch.tensor([[1, 2], [3, 4]])
>>> torch.repeat_interleave(y, repeats=2)
tensor([1, 1, 2, 2, 3, 3, 4, 4])
>>> torch.repeat_interleave(y, repeats=3, dim=1)
tensor([[1, 1, 1, 2, 2, 2],
[3, 3, 3, 4, 4, 4]])
>>> torch.repeat_interleave(y, repeats=torch.tensor([1, 2]), dim=0)
tensor([[1, 2],
[3, 4],
[3, 4]])
>>> torch.repeat_interleave(y, repeats=torch.tensor([1, 2]), dim=0, output_size=3)
tensor([[1, 2],
[3, 4],
[3, 4]])
원본 텐서의 데이터를 실제로는 변경하지 않으면서, 다른 차원으로 '보이게' 하는 방법입니다.
메모리 상에서 데이터의 위치는 그대로 두고, 단지 데이터를 읽는 방법만 바꾸는 것입니다.
torch.transpose
와 torch.view
는 다름! (결과 shape이 같더라도)stride
라는 것은 각 차원에 대해 텐서 안에서 다음 원소까지 건너뛰어야 하는 메모리 상의 거리
입니다.그렇지 않으면 새로운 텐서를 만들기 위해 데이터를 실제로 복사해야 합니다(예를 들어 reshape 사용).
이러한 복사 과정은 추가적인 메모리를 사용하고, 계산 비용이 듭니다.>>> x = torch.randn(4, 4)
>>> x.size()
torch.Size([4, 4])
>>> y = x.view(16)
>>> y.size()
torch.Size([16])
>>> z = x.view(-1, 8) # the size -1 is inferred from other dimensions
>>> z.size()
torch.Size([2, 8])
>>> a = torch.randn(1, 2, 3, 4)
>>> a.size()
torch.Size([1, 2, 3, 4])
-----------------------------
>>> b = a.transpose(1, 2) # Swaps 2nd and 3rd dimension
>>> b.size()
torch.Size([1, 3, 2, 4])
-----------------------------
>>> c = a.view(1, 3, 2, 4) # Does not change tensor layout in memory
>>> c.size()
torch.Size([1, 3, 2, 4])
>>> torch.equal(b, c)
False
Contiguous inputs and inputs with compatible strides
can be reshaped without copying, but you should not depend on the copying vs. viewing behavior.Contiguous
라는 단어는 텐서가 메모리 상에서 연속적으로 배열되어 있다는 것을 의미view
를 반환하고, 그렇지 않으면 복사본을 만듭니다(contiguous()
를 호출하는 것과 같습니다).명시적으로 텐서가 연속적이게 만들기 위해 contiguous()를 호출하는 습관
필요>>> a = torch.arange(4.)
>>> torch.reshape(a, (2, 2))
tensor([[ 0., 1.],
[ 2., 3.]])
>>> b = torch.tensor([[0, 1], [2, 3]])
>>> torch.reshape(b, (-1,))
tensor([ 0, 1, 2, 3])
Contiguous
라는 단어는 텐서가 메모리 상에서 연속적으로 배열되어 있다는 것을 의미
텐서의 일부를 슬라이싱하거나 전치(transpose) 연산을 수행하면,
결과 텐서는 원본 텐서와 메모리를 공유하지만, 원소들이 메모리 상에서 더 이상 연속적이지 않을 수 있습니다. Contiguous
라는 단어는 텐서가 메모리 상에서 연속적으로 배열되어 있다는 것을 의미
if input has shape (8, 6, 4, 2) and dims is (2, 2), then dims is treated as (1, 1, 2, 2).
For example, if input has shape (4, 2) and dims is (3, 3, 2, 2), then input is treated as if it had the shape (1, 1, 4, 2).
>>> x = torch.tensor([1, 2, 3])
>>> x.tile((2,))
tensor([1, 2, 3, 1, 2, 3])
>>> y = torch.tensor([[1, 2], [3, 4]])
>>> torch.tile(y, (2, 2))
tensor([[1, 2, 1, 2],
[3, 4, 3, 4],
[1, 2, 1, 2],
[3, 4, 3, 4]])
>>> t = torch.tensor([[[1, 2],
... [3, 4]],
... [[5, 6],
... [7, 8]]]) # (2, 2, 2)
>>> torch.flatten(t) # (8)
tensor([1, 2, 3, 4, 5, 6, 7, 8])
>>> torch.flatten(t, start_dim=1)
tensor([[1, 2, 3, 4], # (2, 4)
[5, 6, 7, 8]])
>>> x = torch.tensor([1, 2, 3, 4]) # (4,)
>>> torch.unsqueeze(x, 0) # (1, 4)
tensor([[ 1, 2, 3, 4]])
>>> torch.unsqueeze(x, 1) # (4, 1)
tensor([[ 1],
[ 2],
[ 3],
[ 4]])
>>> x = torch.zeros(2, 1, 2, 1, 2)
>>> x.size()
torch.Size([2, 1, 2, 1, 2])
>>> y = torch.squeeze(x)
>>> y.size()
torch.Size([2, 2, 2])
>>> y = torch.squeeze(x, 0)
>>> y.size()
torch.Size([2, 1, 2, 1, 2])
>>> y = torch.squeeze(x, 1)
>>> y.size()
torch.Size([2, 2, 1, 2])
>>> y = torch.squeeze(x, (1, 2, 3))
torch.Size([2, 2, 2])
지정하는 차원에 새로운 차원이 생긴다=차원의 갯수가 증가한다
torch.split()
and torch.chunk()
.차원의 갯수는 유지되고 해당 차원이 늘어난다.
>>> x = torch.randn(2, 3) # (2, 3)
>>> x
tensor([[ 0.6580, -1.0969, -0.4614],
[-0.1034, -0.5790, 0.1497]])
>>> torch.cat((x, x, x), dim=0) # (6, 3)
>>> torch.cat((x, x, x), dim=1) # (2, 9)
int
or list[int]
>>> a = torch.arange(10).reshape(5, 2)
>>> a
tensor([[0, 1],
[2, 3],
[4, 5],
[6, 7],
[8, 9]])
>>> torch.split(a, 2)
(tensor([[0, 1],
[2, 3]]),
tensor([[4, 5],
[6, 7]]),
tensor([[8, 9]]))
>>> torch.split(a, [1, 4])
(tensor([[0, 1]]),
tensor([[2, 3],
[4, 5],
[6, 7],
[8, 9]]))
>>> torch.arange(11).chunk(6)
(tensor([0, 1]),
tensor([2, 3]),
tensor([4, 5]),
tensor([6, 7]),
tensor([8, 9]),
tensor([10]))
>>> torch.arange(12).chunk(6)
(tensor([0, 1]),
tensor([2, 3]),
tensor([4, 5]),
tensor([6, 7]),
tensor([8, 9]),
tensor([10, 11]))
>>> torch.arange(13).chunk(6)
(tensor([0, 1, 2]),
tensor([3, 4, 5]),
tensor([6, 7, 8]),
tensor([ 9, 10, 11]),
tensor([12]))