1. Version
우선 코드들을 실행하기 위한 PyTorch를 불러오고, 사용하고 있는 Python과 PyTorch 버전은 아래와 같다.
import torch
import sys
print("Python version : ", sys.version)
print("PyTorch version : ", torch.__version__)
2. 텐서 모양 바꾸기
2.1. view 와 reshape
텐서 모양을 바꾸는 대표적인 메서드는 view()와 reshape()이 있다. 두 메서드 모두 Tensor.view(Size) / Tensor.reshape(Size) 형태로 메서드를 사용하며, 조작하고 싶은 텐서의 사이즈를 입력받아 텐서의 모양을 바꿔준다. 다만, view는 메모리가 인접하게 연속적(contiguous)이어야만 사용이 가능하다.
Tip)
- 맨 끝 차원의 값에 -1을 넣을 경우 PyTorch에서 알아서 배열 사이즈를 지정해준다.
# view
tensor = torch.arange(12)
print(tensor)
print(tensor.is_contiguous())
tensor.view(4, -1)
reshape() 메서드는 연속적이지 않은 경우에도 사용이 가능하. 제한이 적어 유연하게 사용할 수 있지만, 텐서 사이즈가 커질수록 성능이 떨이질 수 있으니 주의가 필요하다.
# reshape : non-contiguos에 대해서도 적용하지만, 성능은 떨어짐
tensor_sliced = tensor.view(4, -1)[:,:2]
print(tensor_sliced)
print(tensor_sliced.is_contiguous())
print(tensor_sliced.reshape(2,-1))
print(tensor_sliced.view(2,-1))
2.2. 평탄화
딥러닝을 수행하기 위해 입력 데이터의 차원을 맞춰줘야 하는 경우가 발생한다. 이럴 때 torch.flatten(Tensor, start, end) 메서드를 활용해 평탄화를 수행하면 view나 reshape 외에 모양변경을 수월하게 수행할 수 있다.
# flatten
tensor_3d = tensor.reshape(2,2,3)
print(tensor_3d)
# 1차원으로 평탄화
print("1차원으로 평탄화 : \n", torch.flatten(tensor_3d))
# n 차원부터 마지막 차원까지 평탄화
n = 1
print("n차원부터 마지막 차원까지 평탄화 : \n", torch.flatten(tensor_3d, n))
# m 차원부터 n차원까지 평탄화
m = 0
n = 1
print("m차원부터 n차원까지 평탄화 평탄화 : \n",torch.flatten(tensor_3d, m, n))
2.3. squeeze와 unsqueeze
텐서의 여러 차원 중 사인즈가 1인 차원들에 대해 squeeze() 메서드를 통해 차원을 축소 가능하다. 사용방법은 Tensor.squeeze(d), torch.squeeze(Tensor, d) 모두 가능하다. 기본 값은 사이즈가 1인 모든 차원에 대해 적용하며, 특정 차원(값 또는 튜플)을 지정하면 해당 차원을 축소한다. 만약, 사이즈가 1이 아니면 차원이 축소되지 않는다.
# squeeze : size 1을 제거 (만약 없다면, 그대로 유지)
tensor_sq = torch.randn(1,1,4)
print("Squeeze 전 : \n", tensor_sq)
print("Squeeze 후 : \n", torch.squeeze(tensor_sq))
# 특정 차원 d에 대해서 squeeze : d는 int 또는 tuple
d = 0
print("d차원에 대해서 squeeze : \n", torch.squeeze(tensor_sq, d))
squeeze의 반대로 차원을 확장하고자 한다면, unsqueeze 메서드를 사용하면 된다. 사용 방법은 squeeze와 동일하며, 한 차원이 확장되는 효과를 볼 수 있다.
# unsqueeze
tensor = torch.arange(12)
tensor_sliced = tensor.view(4,-1)[:,:2]
print("Unsqueeze 전 : \n", tensor_sliced)
print("0차원 Unsqueeze : \n", torch.unsqueeze(tensor_sliced, 0))
print("1차원 Unsqueeze : \n", torch.unsqueeze(tensor_sliced, 1))
2.4. 전치 (transpose)
행과 열을 바꿔서 새로운 행렬을 만드는 전치 행렬(Transposed Matrix)이라는 개념이 있다.[1] 텐서에서도 특정 축끼리 바꿔서 만드는 텐서의 모양을 바꾸는 방법이 있다. Tensor.transpose(m, n)의 형태를 통해 사용이 가능하다.
# transpose
# m 차원과 n 차원 바꾸기
print("Transpose 전 : \n", tensor_3d)
m = 0
n = 1
print("Transpose 후 : \n",tensor_3d.transpose(m,n))
2.5. 텐서 연결 (stack, cat)
우선, 기존에 있던 차원은 그대로 유지하면서 텐서를 연결(붙이는) 방법은 torch.cat(Tensors, dim) 메서드를 활용하는 것이다. Tensors는 일련의 텐서들을 묶음(튜플, 리스트) 형태로 입력하고, dim에는 연결할 차원을 입력한다. cat을 사용하기 위해서는 크기가 같아야 한다.
# cat : 기존 차원에 따라 연결
print(torch.cat((x, y)))
print("Size : ", torch.cat((x, y)).size())
print(torch.cat((x, y), 1))
# 만약 크기가 다르다면, 맞춰주는 과정 필요
print(torch.cat((x, y[:1, :].reshape(2, 1)), 1))
서로 다른 텐서를 연결하는 방법 중 새로운 차원을 생성하면서 연결하려면 stack을 활용하여 torch.stack(Tensors, dim=)를 통해 사용한다. Tensors는 일련의 텐서들을 묶음(튜플, 리스트) 형태로 입력하고, dim은 새롭게 추가될 차원의 위치를 입력한다. stack 역시 사용하기 위해서는 모든 텐서들이 같은 사이즈여야 한다. [2]
# stack
x = torch.arange(1,5).view(2,2)
y = torch.arange(5,9).view(2,2)
z = torch.arange(9,13).view(2,2)
print("dim 0 : \n", torch.stack([x,y,z], dim=0))
print(torch.stack([x,y,z], dim=0).shape)
print("dim 1 : \n", torch.stack([x,y,z], dim=1))
print(torch.stack([x,y,z], dim=1).shape)
print("dim 2 : \n", torch.stack([x,y,z], dim=2))
print(torch.stack([x,y,z], dim=2).shape)
2.6. 텐서 확장 (expand, repeat)
크기가 1인 차원이 있는 텐서를 여러개를 붙여 확장하는 방법은 Tensor.expand(size) 형태로 사용한다. 사용하는 방법은 아래와 같이 정리할 수 있다.
1) 사이즈가 1이 아닌 차원은 그대로 유지 (-1을 대입하면 유지할 수 있음)
2) 사이즈가 1인 차원은 확장할만큼 사이즈를 대입
3) 새로운 차원으로 확대할 경우 sizes의 가장 앞에 값을 대입
# expand : tensor 차원 중 일부 크기가 1인 경우 해당 차원의 크기를 확장
x = torch.tensor([[1], [2], [3]])
print(x.shape)
print(x.expand(3, 4))
print(x.expand(3, 4).shape)
print(x.expand(2, -1, 4))
print(x.expand(2, -1, 4).shape)
차원이 1이라는 제한 조건이 있는 expand 대신에 repeat 메서드를 사용 가능하다. 해당 메서드는 Tensor.repeat(size)로 사용 가능하며, size에 입력된 차원 방향으로 입력된 숫자만큼 복제한다. repeat 메서드의 동작 방식은 데이터를 복사해서 확장하기 때문에 추가 메모리 할당으로 인해 메모리 효율성이 떨어지게 된다.[4]
# repeat
x = torch.tensor([1, 2])
print(x.repeat(3,2))
print(x.repeat(3,2).shape)
print(x.repeat(3,2,1))
print(x.repeat(3,2,1).shape)
3. 참고자료
[1] https://ko.wikipedia.org/wiki/%EC%A0%84%EC%B9%98_%ED%96%89%EB%A0%AC
[2] https://pytorch.org/docs/stable/generated/torch.stack.html
[3] https://pytorch.org/docs/stable/generated/torch.Tensor.expand.html
[4] https://pytorch.org/docs/stable/generated/torch.Tensor.repeat.html
4. 수정사항
'Python > Data Analysis' 카테고리의 다른 글
머신러닝 과정에서 손실함수와 최적화가 필요한 이유 (1) | 2024.08.17 |
---|---|
[PyTorch] 파이토치 메서드로 텐서의 연산 수행하기 (0) | 2024.08.16 |
[PyTorch] PyTorch를 활용한 텐서 생성하기 (0) | 2024.08.09 |
[NLP] 임베딩과 Word2Vec 실습해보기 (0) | 2022.09.07 |
[NLP] Char-RNN 을 활용하여 언어 모델링 실습 | 텍스트 생성 (0) | 2022.06.06 |