Pytorch_텐서 실습 1

텐서 조작 (1)

환경 설정

PyTorch 설치 및 불러오기

  • 패키지 설치 및 임포트
!pip install torch==2.0.1 # PyTorch 를 가장 최근 버전으로 설치
Collecting torch==2.0.1
  Downloading torch-2.0.1-cp310-cp310-manylinux1_x86_64.whl (619.9 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 619.9/619.9 MB 1.8 MB/s eta 0:00:00
[?25hRequirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from torch==2.0.1) (3.13.1)
Requirement already satisfied: typing-extensions in /usr/local/lib/python3.10/dist-packages (from torch==2.0.1) (4.5.0)
Requirement already satisfied: sympy in /usr/local/lib/python3.10/dist-packages (from torch==2.0.1) (1.12)
Requirement already satisfied: networkx in /usr/local/lib/python3.10/dist-packages (from torch==2.0.1) (3.2.1)
Requirement already satisfied: jinja2 in /usr/local/lib/python3.10/dist-packages (from torch==2.0.1) (3.1.2)
Collecting nvidia-cuda-nvrtc-cu11==11.7.99 (from torch==2.0.1)
  Downloading nvidia_cuda_nvrtc_cu11-11.7.99-2-py3-none-manylinux1_x86_64.whl (21.0 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 21.0/21.0 MB 41.7 MB/s eta 0:00:00
[?25hCollecting nvidia-cuda-runtime-cu11==11.7.99 (from torch==2.0.1)
  Downloading nvidia_cuda_runtime_cu11-11.7.99-py3-none-manylinux1_x86_64.whl (849 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 849.3/849.3 kB 45.6 MB/s eta 0:00:00
[?25hCollecting nvidia-cuda-cupti-cu11==11.7.101 (from torch==2.0.1)
  Downloading nvidia_cuda_cupti_cu11-11.7.101-py3-none-manylinux1_x86_64.whl (11.8 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 11.8/11.8 MB 55.2 MB/s eta 0:00:00
[?25hCollecting nvidia-cudnn-cu11==8.5.0.96 (from torch==2.0.1)
  Downloading nvidia_cudnn_cu11-8.5.0.96-2-py3-none-manylinux1_x86_64.whl (557.1 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 557.1/557.1 MB 2.8 MB/s eta 0:00:00
[?25hCollecting nvidia-cublas-cu11==11.10.3.66 (from torch==2.0.1)
  Downloading nvidia_cublas_cu11-11.10.3.66-py3-none-manylinux1_x86_64.whl (317.1 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 317.1/317.1 MB 4.1 MB/s eta 0:00:00
[?25hCollecting nvidia-cufft-cu11==10.9.0.58 (from torch==2.0.1)
  Downloading nvidia_cufft_cu11-10.9.0.58-py3-none-manylinux1_x86_64.whl (168.4 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 168.4/168.4 MB 7.3 MB/s eta 0:00:00
[?25hCollecting nvidia-curand-cu11==10.2.10.91 (from torch==2.0.1)
  Downloading nvidia_curand_cu11-10.2.10.91-py3-none-manylinux1_x86_64.whl (54.6 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 54.6/54.6 MB 13.2 MB/s eta 0:00:00
[?25hCollecting nvidia-cusolver-cu11==11.4.0.1 (from torch==2.0.1)
  Downloading nvidia_cusolver_cu11-11.4.0.1-2-py3-none-manylinux1_x86_64.whl (102.6 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 102.6/102.6 MB 8.8 MB/s eta 0:00:00
[?25hCollecting nvidia-cusparse-cu11==11.7.4.91 (from torch==2.0.1)
  Downloading nvidia_cusparse_cu11-11.7.4.91-py3-none-manylinux1_x86_64.whl (173.2 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 173.2/173.2 MB 5.6 MB/s eta 0:00:00
[?25hCollecting nvidia-nccl-cu11==2.14.3 (from torch==2.0.1)
  Downloading nvidia_nccl_cu11-2.14.3-py3-none-manylinux1_x86_64.whl (177.1 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 177.1/177.1 MB 6.6 MB/s eta 0:00:00
[?25hCollecting nvidia-nvtx-cu11==11.7.91 (from torch==2.0.1)
  Downloading nvidia_nvtx_cu11-11.7.91-py3-none-manylinux1_x86_64.whl (98 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 98.6/98.6 kB 7.6 MB/s eta 0:00:00
[?25hCollecting triton==2.0.0 (from torch==2.0.1)
  Downloading triton-2.0.0-1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (63.3 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 63.3/63.3 MB 10.0 MB/s eta 0:00:00
[?25hRequirement already satisfied: setuptools in /usr/local/lib/python3.10/dist-packages (from nvidia-cublas-cu11==11.10.3.66->torch==2.0.1) (67.7.2)
Requirement already satisfied: wheel in /usr/local/lib/python3.10/dist-packages (from nvidia-cublas-cu11==11.10.3.66->torch==2.0.1) (0.42.0)
Requirement already satisfied: cmake in /usr/local/lib/python3.10/dist-packages (from triton==2.0.0->torch==2.0.1) (3.27.9)
Collecting lit (from triton==2.0.0->torch==2.0.1)
  Downloading lit-17.0.6.tar.gz (153 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 153.0/153.0 kB 16.3 MB/s eta 0:00:00
[?25h  Installing build dependencies ... [?25l[?25hdone
  Getting requirements to build wheel ... [?25l[?25hdone
  Installing backend dependencies ... [?25l[?25hdone
  Preparing metadata (pyproject.toml) ... [?25l[?25hdone
Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from jinja2->torch==2.0.1) (2.1.3)
Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy->torch==2.0.1) (1.3.0)
Building wheels for collected packages: lit
  Building wheel for lit (pyproject.toml) ... [?25l[?25hdone
  Created wheel for lit: filename=lit-17.0.6-py3-none-any.whl size=93255 sha256=a2db675c407969af1bb77b5921c595377dd31dd22a83d4ac2f8ce6da2d296823
  Stored in directory: /root/.cache/pip/wheels/30/dd/04/47d42976a6a86dc2ab66d7518621ae96f43452c8841d74758a
Successfully built lit
Installing collected packages: lit, nvidia-nvtx-cu11, nvidia-nccl-cu11, nvidia-cusparse-cu11, nvidia-curand-cu11, nvidia-cufft-cu11, nvidia-cuda-runtime-cu11, nvidia-cuda-nvrtc-cu11, nvidia-cuda-cupti-cu11, nvidia-cublas-cu11, nvidia-cusolver-cu11, nvidia-cudnn-cu11, triton, torch
  Attempting uninstall: triton
    Found existing installation: triton 2.1.0
    Uninstalling triton-2.1.0:
      Successfully uninstalled triton-2.1.0
  Attempting uninstall: torch
    Found existing installation: torch 2.1.0+cu121
    Uninstalling torch-2.1.0+cu121:
      Successfully uninstalled torch-2.1.0+cu121
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
torchaudio 2.1.0+cu121 requires torch==2.1.0, but you have torch 2.0.1 which is incompatible.
torchdata 0.7.0 requires torch==2.1.0, but you have torch 2.0.1 which is incompatible.
torchtext 0.16.0 requires torch==2.1.0, but you have torch 2.0.1 which is incompatible.
torchvision 0.16.0+cu121 requires torch==2.1.0, but you have torch 2.0.1 which is incompatible.
Successfully installed lit-17.0.6 nvidia-cublas-cu11-11.10.3.66 nvidia-cuda-cupti-cu11-11.7.101 nvidia-cuda-nvrtc-cu11-11.7.99 nvidia-cuda-runtime-cu11-11.7.99 nvidia-cudnn-cu11-8.5.0.96 nvidia-cufft-cu11-10.9.0.58 nvidia-curand-cu11-10.2.10.91 nvidia-cusolver-cu11-11.4.0.1 nvidia-cusparse-cu11-11.7.4.91 nvidia-nccl-cu11-2.14.3 nvidia-nvtx-cu11-11.7.91 torch-2.0.1 triton-2.0.0
import torch # PyTorch 불러오기
import numpy as np # numpy 불러오기
import warnings # 경고 문구 제거
warnings.filterwarnings('ignore')

1. 텐서 이해하기

  • 1-1. 텐서를 생성하고 텐서로 변환하는 방법을 이해 및 실습
  • 1-2. 텐서에서의 indexing 이해 및 실습

1-1 텐서를 생성하고 텐서로 변환하는 방법을 이해 및 실습

Random 한 값을 가지는 텐서를 생성하고, list 나 numpy array 같은 다양한 형태의 배열들을 PyTorch 를 이용하여 텐서로 변환하는 과정을 알아봅니다.

📝 설명 : 텐서의 값을 무작위로 생성하는 방법들

  • rand : 0과 1 사이의 균일한 분포 (Uniform Distribution) 에서 무작위로 생성된 텐서를 반환

📚 참고할만한 자료:

  • [rand] https://pytorch.org/docs/stable/generated/torch.rand.html
# 0부터 1 사이의 값을 랜덤하게 NxM 텐서로 반환
torch.rand(2, 3) # torch.rand(NxM) NxM은 텐서의 크기를 말합니다.
tensor([[0.4832, 0.6079, 0.0965],
        [0.9239, 0.1382, 0.7564]])

📝 설명 : Tensor 의 값을 무작위로 생성하는 방법들

  • randn : 평균이 0이고 표준 편차가 1인 정규 분포(가우시안 분포)에서 무작위로 생성된 텐서를 반환

📚 참고할만한 자료:

  • [randn] https://pytorch.org/docs/stable/generated/torch.randn.html
# 가우시안 분포에서 렌덤하게 값을 추출 후, NxM 텐서로 반환
torch.randn(2, 3) # torch.randn(NxM) NxM은 텐서의 크기를 말합니다.
tensor([[ 0.9027, -0.4474, -0.5633],
        [ 1.6880,  0.0257,  0.3113]])

📝 설명 : 텐서의 값을 무작위로 생성하는 방법들

  • randint : 주어진 범위 내에서 정수값을 무작위로 선택하여 텐서를 생성 (단, 최솟값을 포함하고, 최댓값은 포함하지 않음)

📚 참고할만한 자료:

  • [randint] https://pytorch.org/docs/stable/generated/torch.randint.html
# 범위 내의 정수를 N x M 텐서로 반환
torch.randint(1, 10, (5, 5)) # 생성 가능한 최솟값 : 1, 최댓값 : 9, (5x5) Tensor 크기
tensor([[9, 1, 3, 9, 2],
        [6, 9, 7, 2, 5],
        [4, 9, 4, 7, 1],
        [3, 4, 1, 7, 7],
        [3, 8, 1, 3, 1]])

📝 설명 : 텐서의 값을 지정해서 생성하는 방법들

  • zeros : 모든 요소가 0인 텐서 반환

📚 참고할만한 자료:

  • [zeros] https://pytorch.org/docs/stable/generated/torch.zeros.html
torch.zeros(3, 3) # torch.zeros(*size) 여기서 size 는 ","로 구분하며 차원을 여러개로 늘릴 수 있습니다.
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])

📝 설명 : 텐서의 값을 지정해서 생성하는 방법들

  • ones : 모든 요소가 1인 텐서 반환

📚 참고할만한 자료:

  • [ones] https://pytorch.org/docs/stable/generated/torch.ones.html
torch.ones(2, 2, 2) # torch.ones(*size) 여기서 size 는 ","로 구분하며 채널을 여러개로 늘릴 수 있습니다.
tensor([[[1., 1.],
         [1., 1.]],

        [[1., 1.],
         [1., 1.]]])

📝 설명 : 텐서의 값을 지정해서 생성하는 방법들

  • full: 모든 요소가 지정된 값인 텐서 반환

📚 참고할만한 자료:

  • [full] https://pytorch.org/docs/stable/generated/torch.full.html
torch.full((2, 3), 5) # torch.full((size),value) => 괄호로 텐서의 크기 (2,3) 를 입력하고, 지정한 값 value (5) 로 모든 요소가 설정됩니다.
tensor([[5, 5, 5],
        [5, 5, 5]])

📝 설명 : 텐서의 값을 지정해서 생성하는 방법들

  • eye : 단위 행렬 반환 (※ 단위 행렬이란? 대각선 요소가 1이고, 나머지 요소가 0인 행렬)

📚 참고할만한 자료:

  • [eye] https://pytorch.org/docs/stable/generated/torch.eye.html
torch.eye(3) # torch.eye(n) (nxn) 크기를 가지는 단위 행렬 반환, 단위행렬 특성 상 정사각행렬 (square matrix)만 가능
tensor([[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]])

📝 설명 : 다양한 데이터를 텐서 형식으로 변환하기

  • tensor : 주어진 데이터를 텐서로 변환. 데이터는 list, tuple, numpy array 등의 형태일 수 있음.

📚 참고할만한 자료:

  • [tensor] https://pytorch.org/docs/stable/generated/torch.tensor.html
# list, tuple, numpy array를 텐서로 바꾸기
ls = [[1, 2, 3, 4, 5],[6, 7, 8, 9, 10]] # sample list 생성
tup = tuple([1, 2, 3]) # sample tuple 생성
arr = np.array([[[1, 2, 3],[4, 5, 6]],[[7, 8, 9],[10, 11, 12]]]) # sample numpy array 생성

print(torch.tensor(ls))
print('\n')
print(torch.tensor(tup))
print('\n')
print(torch.tensor(arr))
tensor([[ 1,  2,  3,  4,  5],
        [ 6,  7,  8,  9, 10]])


tensor([1, 2, 3])


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

        [[ 7,  8,  9],
         [10, 11, 12]]])

📝 설명 : 다양한 형태를 텐서 형식으로 변환하기

  • from_numpy : numpy array 를 텐서로 변환

📚 참고할만한 자료:

  • [from_numpy] https://pytorch.org/docs/stable/generated/torch.from_numpy.html
torch.from_numpy(arr) # array 를 tensor로 바꾸기 (2)
tensor([[[ 1,  2,  3],
         [ 4,  5,  6]],

        [[ 7,  8,  9],
         [10, 11, 12]]])

📝 설명: 다양한 형식의 텐서 변환

  • as_tensor: 변환 전 데이터와의 메모리 공유(memory sharing)를 사용하므로, 변환 전 데이터 변경 시 변환되어 있는 텐서에도 반영됨

📚 참고할만한 자료:

  • [as_tensor] https://pytorch.org/docs/stable/generated/torch.as_tensor.html
# torch.tensor 와 torch.as_tensor 의 차이점 알아보기
print("torch.tensor")
data1 = np.array([1, 2, 3, 4, 5]) # 샘플 데이터 리스트 생성
tensor1 = torch.tensor(data1) # memory 공유 X
data1[0] = 10  # 원본 데이터 변경
print(tensor1)  # 원본 데이터의 값 변경에 영향을 받지 않음

print('-------'*10)

print("torch.as_tensor")
data2 = np.array([1, 2, 3, 4, 5])
tensor2 = torch.as_tensor(data2) # memory 공유 O
data2[0] = 10  # 원본 데이터 변경
print(tensor2)  # 원본 데이터의 값 변경에 영향을 받음
torch.tensor
tensor([1, 2, 3, 4, 5])
----------------------------------------------------------------------
torch.as_tensor
tensor([10,  2,  3,  4,  5])

📝 설명 : 다양한 형식의 텐서 변환

  • Tensor : float32 type으로 텐서 변환

📚 참고할만한 자료:

  • [Tensor] https://pytorch.org/docs/stable/tensors.html
data = [1, 2, 3, 4, 5]
tensor1 = torch.tensor(data) # list 에서 Tensor 변환
print("torch.tensor")
print("Output:", tensor1)
print("Type", tensor1.dtype) # dtype : Tensor 안의 원소들의 자료형, torch.tensor 는 원본의 데이터 타입을 그대로 따라감

print('-------'*3)

tensor2 = torch.Tensor(data) # list 에서 Tensor 변환
print("torch.Tensor")
print("Output:", tensor2)
print("Type", tensor2.dtype) # torch.tensor 는 float32 타입으로 Tensor 변환
torch.tensor
Output: tensor([1, 2, 3, 4, 5])
Type torch.int64
---------------------
torch.Tensor
Output: tensor([1., 2., 3., 4., 5.])
Type torch.float32

1-2 텐서에서의 Indexing 을 이해 및 실습

Indexing 개념과 Indexing 을 통해 값을 변경하는 방법에 대해 이해하고 실습합니다.

📝 설명 : Indexing 이란?

Indexing 은 텐서 내의 특정 요소를 index를 통해 접근할 수 있는 방법을 의미합니다.

  • Indexing 기본 : 대괄호(“[ ]”)를 통해 이뤄지며, ”:” 는 특정 범위의 접근을 의미합니다.

📚 참고할만한 자료:

  • [Tensor indexing] : https://pytorch.org/cppdocs/notes/tensor_indexing.html
# 1차원 텐서에서 Indexing 하기
tmp_1dim = torch.tensor([i for i in range(10)]) # 0부터 9 까지의 값을 가지는 1차원 텐서 생성

print(tmp_1dim[0]) # 첫번째 원소 값 추출
print(tmp_1dim[5]) # 6번째 원소 값 추출
print(tmp_1dim[-1]) # -1 번째 원소 값 (뒤에서 첫번째) 추출
tensor(0)
tensor(5)
tensor(9)
# 3차원 텐서에서 Indexing 하기
tmp_3dim = torch.randn(4, 3, 2) # 4채널, 3행, 2열
print("Shape : ", tmp_3dim.shape)
print(tmp_3dim)

print('-------'*8)

print(tmp_3dim[:,:,0].shape)
print(tmp_3dim[:,:,0]) # 전체 채널과 전체 행에서 0번째 열만 추출

print('\n') # 줄 띄움

print(tmp_3dim[0,:,1].shape)
print(tmp_3dim[0,:,1])  # 0번째 채널의 전체 행에서 1번째 열만 추출
Shape :  torch.Size([4, 3, 2])
tensor([[[ 0.9144,  0.3184],
         [ 1.0496,  0.8238],
         [-1.2094,  1.1296]],

        [[ 0.8414, -0.5814],
         [ 1.1207, -0.7272],
         [-2.3303, -0.8834]],

        [[ 0.5461,  1.8506],
         [ 0.2818, -1.4328],
         [-1.5978, -2.4369]],

        [[ 1.6518,  1.2504],
         [-0.0586, -0.0322],
         [-0.1793,  0.2690]]])
--------------------------------------------------------
torch.Size([4, 3])
tensor([[ 0.9144,  1.0496, -1.2094],
        [ 0.8414,  1.1207, -2.3303],
        [ 0.5461,  0.2818, -1.5978],
        [ 1.6518, -0.0586, -0.1793]])


torch.Size([3])
tensor([0.3184, 0.8238, 1.1296])

📝 설명 : Indexing 이란?

  • index_select : 선택한 차원에서 인덱스에 해당하는 요소만 추출하는 함수

📚 참고할만한 자료:

  • [index_select] : https://pytorch.org/docs/stable/generated/torch.index_select.html
# index_select
tmp_2dim = torch.tensor([[i for i in range(10)],[i for i in range(10, 20)]])
print(tmp_2dim)

print('\n')

my_index = torch.tensor([0, 2]) # 선택하고자 하는 index 는 텐서 형태이어야 함.
torch.index_select(tmp_2dim, dim=1, index=my_index) # 열을 기준으로 0열과 2열을 추출
tensor([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])







tensor([[ 0,  2],
        [10, 12]])

📝 설명 : Indexing 이란?

  • Masking 을 이용한 Indexing : 조건에 따른 텐서의 요소를 사용하기 위한 방법으로 조건에 맞는 요소들만 반환하는 방법입니다.
# mask 를 이용한 텐서 Indexing (조건에 맞는 값만 추출)
mask = tmp_2dim >= 5 # 5보다 큰 텐서만 추출
tmp_2dim[mask] # 1차원 Tensor 로 반환
tensor([ 5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])

📝 설명 : Indexing 이란?

  • masked_select : 주어진 mask에 해당하는 요소들을 추출하여 1차원으로 펼친 새로운 텐서를 반환하는 함수

📚 참고할만한 자료:

  • [masked_select] : https://pytorch.org/docs/stable/generated/torch.masked_select.html
torch.masked_select(tmp_2dim, mask = mask) # tmp_2dim[tmp_2dim >= 5] 와 동일
tensor([ 5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])

📝 설명 : Indexing 이란?

  • take : 주어진 인덱스를 사용하여 텐서에서 요소를 선택하는 함수. 인덱스 번호는 텐서를 1차원으로 늘려졌을 때 기준으로 접근해야합니다.

📚 참고할만한 자료:

  • [take] : https://pytorch.org/docs/stable/generated/torch.take.html
tmp_2dim = torch.tensor([[i for i in range(10)], [i for i in range(10, 20)]])
print(tmp_2dim)

print('\n')

my_index = torch.tensor([0, 15])
torch.take(tmp_2dim, index = my_index) # Tensor가 1차원으로 늘려졌을 때 기준으로 index 번호로 접근
tensor([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])







tensor([ 0, 15])

📝 설명 : Indexing 이란?

  • gather : 주어진 차원에서 인덱스에 해당하는 요소들을 선택하여 새로운 텐서를 반환

📚 참고할만한 자료:

  • [gather] : https://pytorch.org/docs/stable/generated/torch.gather.html
tmp_2dim = torch.tensor([[i for i in range(10)],[i for i in range(10,20)]])
print(tmp_2dim)

print('\n')

recon_index =  torch.tensor([[0 ,1],[9, 8]]) # 0번째 값, 1번 째 값을 0번째 행으로 설정하고, 9번째 값, 8번째 값을 1번째 행으로 설정한다.
dim = 1 # 열 기준
print(recon_index)
print('\n')

torch.gather(tmp_2dim, dim = 1, index = recon_index) # dim =1 이므로 열 기준, 0행 0열, 0행 1열 선택, 1행 9열, 1행 8열
tensor([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])


tensor([[0, 1],
        [9, 8]])







tensor([[ 0,  1],
        [19, 18]])

2. 텐서의 모양 바꾸기

2-1 텐서의 shape을 바꾸는 여러가지 함수 이해 및 실습

텐서의 모양을 자유자재로 바꾸는 방법에 대해 알아보고 실습합니다.

📝 설명 : 텐서의 shape 변경

텐서에 대한 모양을 변경하기 위해 명심해야 할 점은 텐서의 크기 (요소의 개수)는 유지되어야 한다는 점입니다.

  • size : 텐서의 모양을 확인합니다.

📚 참고할만한 자료:

  • [size] : https://pytorch.org/docs/stable/generated/torch.Tensor.size.html
a = torch.randn(2, 3, 5) # random 한 값을 가진 (1,3,5) 텐서 생성
a.size() # 차원 크기 확인
torch.Size([2, 3, 5])
a.shape # a.size() 와 동일
torch.Size([2, 3, 5])

📝 설명 : 텐서의 shape 변경

  • reshape : 텐서의 모양을 변경합니다. 메모리를 공유하지 않습니다.

📚 참고할만한 자료:

  • [reshape] : https://pytorch.org/docs/stable/generated/torch.reshape.html
# 모양 변경
a = torch.randn(2, 3, 5) # (2,3,5) 크기를 가지는 텐서 생성
print(a)
print("Shape : ", a.size()) # 텐서 모양 반환
print('\n')

reshape_a = a.reshape(5, 6) # 3차원 텐서를 2차원 텐서로 크기 변경 (2,3,5) -> (5,6)
print(reshape_a)
print("Shape : ", reshape_a.size()) # 변경한 텐서 모양 반환
tensor([[[ 1.4395,  0.5985, -1.1691,  1.5279, -0.0985],
         [-2.0897,  2.5121,  0.0553,  0.2532,  1.1086],
         [-1.2554, -1.1751, -0.0270,  0.0227, -0.6094]],

        [[ 0.8175, -0.7804,  1.2114, -2.4871,  0.7790],
         [-0.4992, -0.0488,  1.5461, -0.1898, -1.0895],
         [ 0.0334,  2.3150, -1.0674, -0.8454, -0.4906]]])
Shape :  torch.Size([2, 3, 5])


tensor([[ 1.4395,  0.5985, -1.1691,  1.5279, -0.0985, -2.0897],
        [ 2.5121,  0.0553,  0.2532,  1.1086, -1.2554, -1.1751],
        [-0.0270,  0.0227, -0.6094,  0.8175, -0.7804,  1.2114],
        [-2.4871,  0.7790, -0.4992, -0.0488,  1.5461, -0.1898],
        [-1.0895,  0.0334,  2.3150, -1.0674, -0.8454, -0.4906]])
Shape :  torch.Size([5, 6])
# -1 로 모양 자동 설정
reshape_auto_a = a.reshape(3, -1) # (2,3,5) 크기를 가지는 Tensor를 (3,n)의 모양으로 변경, "-1" 로 크기 자동 계산
print(reshape_auto_a.size()) # 2x3x5 = 3 x n 의 방정식을 푸는 문제로 n 이 자동설정
torch.Size([3, 10])
a.reshape(7, -1) #  2x3x5 = 3 x n 의 방정식의 해가 정수가 아니면 오류 발생
---------------------------------------------------------------------------

RuntimeError                              Traceback (most recent call last)

<ipython-input-26-7a4b40636089> in <cell line: 1>()
----> 1 a.reshape(7, -1) #  2x3x5 = 3 x n 의 방정식의 해가 정수가 아니면 오류 발생


RuntimeError: shape '[7, -1]' is invalid for input of size 30

📝 설명 : 텐서의 shape 변경

  • view : 텐서의 모양을 변경합니다.

📚 참고할만한 자료:

  • [view] : https://pytorch.org/docs/stable/generated/torch.Tensor.view.html
print(a)
print("Shape : ", a.size()) # 텐서 모양 반환
print('\n')

view_a = a.view(5, 6) # reshape 과 동일하게 (2,3,5) 크기를 (5,6) 크기로 변경
print(view_a)
print("Shape : ", view_a.size())
tensor([[[ 1.4395,  0.5985, -1.1691,  1.5279, -0.0985],
         [-2.0897,  2.5121,  0.0553,  0.2532,  1.1086],
         [-1.2554, -1.1751, -0.0270,  0.0227, -0.6094]],

        [[ 0.8175, -0.7804,  1.2114, -2.4871,  0.7790],
         [-0.4992, -0.0488,  1.5461, -0.1898, -1.0895],
         [ 0.0334,  2.3150, -1.0674, -0.8454, -0.4906]]])
Shape :  torch.Size([2, 3, 5])


tensor([[ 1.4395,  0.5985, -1.1691,  1.5279, -0.0985, -2.0897],
        [ 2.5121,  0.0553,  0.2532,  1.1086, -1.2554, -1.1751],
        [-0.0270,  0.0227, -0.6094,  0.8175, -0.7804,  1.2114],
        [-2.4871,  0.7790, -0.4992, -0.0488,  1.5461, -0.1898],
        [-1.0895,  0.0334,  2.3150, -1.0674, -0.8454, -0.4906]])
Shape :  torch.Size([5, 6])
view_auto_a = a.view(3, -1) # reshape 과 동일하게 (3,n)의 모양으로 변경. "-1" 로 크기 자동 계산
print(view_auto_a.size())
torch.Size([3, 10])

📝 설명 : 텐서의 shape 변경

  • transpose : 텐서의 차원을 전치합니다.

📚 참고할만한 자료:

  • [transpose] : https://pytorch.org/docs/stable/generated/torch.transpose.html
tensor_a = torch.randint(1, 10, (3, 2, 5)) # 1 ~ 9의 값을 가지는 (3,2,5) 사이즈의 Tensor 생성
print(tensor_a)
print("Shape : ", tensor_a.size())
print('\n')

# (3,2,5) 를 (2,3,5) 의 크기로 변경
trans_a = tensor_a.transpose(1, 2) # 행과 열을 서로 전치, 서로 전치할 차원 2개를 지정
print(trans_a)
print("Shape : ", trans_a.size())
tensor([[[2, 9, 8, 1, 5],
         [1, 4, 1, 7, 4]],

        [[3, 5, 2, 9, 9],
         [7, 8, 9, 1, 4]],

        [[4, 4, 6, 3, 4],
         [6, 9, 6, 2, 3]]])
Shape :  torch.Size([3, 2, 5])


tensor([[[2, 1],
         [9, 4],
         [8, 1],
         [1, 7],
         [5, 4]],

        [[3, 7],
         [5, 8],
         [2, 9],
         [9, 1],
         [9, 4]],

        [[4, 6],
         [4, 9],
         [6, 6],
         [3, 2],
         [4, 3]]])
Shape :  torch.Size([3, 5, 2])

📝 설명 : 텐서의 shape 변경

  • permute : 텐서 차원의 순서를 재배열합니다.

📚 참고할만한 자료:

  • [permute] : https://pytorch.org/docs/stable/generated/torch.permute.html
print(tensor_a)
print("Shape : ", tensor_a.size())
print('\n')

permute_a = tensor_a.permute(0, 2, 1) # (3,2,5)의 모양을 (3,5,2)의 모양으로 변경
print(permute_a)
print("Shape : ", permute_a.size())
tensor([[[2, 9, 8, 1, 5],
         [1, 4, 1, 7, 4]],

        [[3, 5, 2, 9, 9],
         [7, 8, 9, 1, 4]],

        [[4, 4, 6, 3, 4],
         [6, 9, 6, 2, 3]]])
Shape :  torch.Size([3, 2, 5])


tensor([[[2, 1],
         [9, 4],
         [8, 1],
         [1, 7],
         [5, 4]],

        [[3, 7],
         [5, 8],
         [2, 9],
         [9, 1],
         [9, 4]],

        [[4, 6],
         [4, 9],
         [6, 6],
         [3, 2],
         [4, 3]]])
Shape :  torch.Size([3, 5, 2])

2-2 텐서의 차원을 추가하거나 변경하는 방법에 대한 이해 및 실습

📝 설명 : 텐서의 차원을 추가하거나 변경하는 방법에 대한 이해 및 실습

  • unsqueeze : 텐서에 특정 차원에 크기가 1인 차원을 추가합니다.

📚 참고할만한 자료:

  • [unsqueeze] : https://pytorch.org/docs/stable/generated/torch.unsqueeze.html
tensor_a = torch.tensor([i for i in range(10)]).reshape(5, 2) # 0부터 9까지의 숫자들을 (5,2) 크기로 변경
print(tensor_a)
print('Shape : ', tensor_a.size())
print('\n')

unsqu_a = tensor_a.unsqueeze(0) # 0번째 차원 하나 추가 (5,2) => (1,5,2)
print(unsqu_a)
print('Shape : ', unsqu_a.size())
tensor([[0, 1],
        [2, 3],
        [4, 5],
        [6, 7],
        [8, 9]])
Shape :  torch.Size([5, 2])


tensor([[[0, 1],
         [2, 3],
         [4, 5],
         [6, 7],
         [8, 9]]])
Shape :  torch.Size([1, 5, 2])
unsqu_a2 = tensor_a.unsqueeze(-1) # 마지막번째에 차원 하나 추가 (5,2) => (5,2,1)
print(unsqu_a2)
print('Shape : ', unsqu_a2.size())
tensor([[[0],
         [1]],

        [[2],
         [3]],

        [[4],
         [5]],

        [[6],
         [7]],

        [[8],
         [9]]])
Shape :  torch.Size([5, 2, 1])

📝 설명 : 텐서의 차원을 추가하거나 변경하는 방법에 대한 이해 및 실습

  • squeeze : 텐서에 차원의 크기가 1인 차원을 제거합니다.

📚 참고할만한 자료:

  • [squeeze] : https://pytorch.org/docs/stable/generated/torch.squeeze.html
print(unsqu_a)
print("Shape : ", unsqu_a.size())
print('\n')

squ = unsqu_a.squeeze() # 차원이 1인 차원을 제거
print(squ)
print("Shape : ", squ.size())
tensor([[[0, 1],
         [2, 3],
         [4, 5],
         [6, 7],
         [8, 9]]])
Shape :  torch.Size([1, 5, 2])


tensor([[0, 1],
        [2, 3],
        [4, 5],
        [6, 7],
        [8, 9]])
Shape :  torch.Size([5, 2])
x = torch.zeros(2, 1, 2, 1, 2) # 모든 원소가 0인 (2,1,2,1,2) 크기를 가지는 텐서
print("Shape (original) : ", x.size()) # 원래 텐서 크기
print('\n')

print("Shape (squeeze()) :", x.squeeze().size()) # 차원이 1인 차원이 여러개일 때, 모든 차원이 1인 차원 제거
print('\n')

print("Shape (squeeze(0)) :", x.squeeze(0).size()) # 0번째 차원은 차원의 크기가 1이 아니므로, 변화 없음
print('\n')

print("Shape (squeeze(1)) :", x.squeeze(1).size()) # 1번째 차원은 차원의 크기가 1이므로 제거
print('\n')

print("Shape (squeeze(0,1,3)) :", x.squeeze((0, 1, 3)).size()) # 여러 차원 제거 가능 (0번째 차원은 차원의 크기가 1이 아니기 때문에 무시)
Shape (original) :  torch.Size([2, 1, 2, 1, 2])


Shape (squeeze()) : torch.Size([2, 2, 2])


Shape (squeeze(0)) : torch.Size([2, 1, 2, 1, 2])


Shape (squeeze(1)) : torch.Size([2, 2, 1, 2])


Shape (squeeze(0,1,3)) : torch.Size([2, 2, 2])

📝 설명 : 텐서의 차원을 추가하거나 변경하는 방법에 대한 이해 및 실습

  • expand : 텐서의 값을 반복하여 크기를 확장합니다.
    • A 텐서가 1차원일 경우 : A 텐서의 크기가 (m,) 이면 m은 고정하고 (x,m)의 크기로만 확장 가능
    • A 텐서가 2차원 이상일 경우 : 크기가 1인 차원에 대해서만 적용 가능. A 텐서의 크기가 (1,m) 이면 (x,m) , (m,1) 이면 (m,y) 로만 확장 가능.

📚 참고할만한 자료:

  • [expand] : https://pytorch.org/docs/stable/generated/torch.Tensor.expand.html
tensor_1dim = torch.tensor([1, 2, 3, 4])
print(tensor_1dim)
print("Shape : ", tensor_1dim.size())
print('\n')

expand_tensor = tensor_1dim.expand(3, 4) # (,4) 를 (3,4) 의 크기로 확장 (값을 반복)
print(expand_tensor)
print("Shape : ", expand_tensor.size())
tensor([1, 2, 3, 4])
Shape :  torch.Size([4])


tensor([[1, 2, 3, 4],
        [1, 2, 3, 4],
        [1, 2, 3, 4]])
Shape :  torch.Size([3, 4])
tensor_2dim = torch.tensor([[1, 2, 3, 4], [1, 2, 3, 4]]) # (2,4) 크기를 가진 Tensor
print(tensor_2dim)
print("Shape : ", tensor_2dim.size())
print('\n')

expand_tensor = tensor_2dim.expand(4,4) # (2,4) 를 (4,8) 의 크기로 확장 (값을 반복)
print(expand_tensor) # 에러 발생
print("Shape : ", expand_tensor.size()) # 에러 발생
tensor([[1, 2, 3, 4],
        [1, 2, 3, 4]])
Shape :  torch.Size([2, 4])





---------------------------------------------------------------------------

RuntimeError                              Traceback (most recent call last)

<ipython-input-36-ca0aa7093d8c> in <cell line: 6>()
      4 print('\n')
      5 
----> 6 expand_tensor = tensor_2dim.expand(4,4) # (2,4) 를 (4,8) 의 크기로 확장 (값을 반복)
      7 print(expand_tensor) # 에러 발생
      8 print("Shape : ", expand_tensor.size()) # 에러 발생


RuntimeError: The expanded size of the tensor (4) must match the existing size (2) at non-singleton dimension 0.  Target sizes: [4, 4].  Tensor sizes: [2, 4]

📝 설명 : 텐서의 차원을 추가하거나 변경하는 방법에 대한 이해 및 실습

  • repeat : 텐서를 반복하여 크기를 확장합니다.
    • ex) A 텐서가 (m,n) 크기를 가진다하고, A 텐서를 repeat(i,j) 를 하면 결과값으로 (m x i, n x j)의 크기의 텐서가 생성됩니다.

📚 참고할만한 자료:

  • [repeat] : https://pytorch.org/docs/stable/generated/torch.Tensor.repeat.html
tensor_1dim = torch.tensor([1, 2, 3, 4])
print(tensor_1dim)
print("Shape : ", tensor_1dim.size())
print('\n')

repeat_tensor = tensor_1dim.repeat(3, 4) # tensor_1dim 자체를 행으로 3번 반복, 열로 4번 반복
print(repeat_tensor)
print("Shape : ", repeat_tensor.size())
tensor([1, 2, 3, 4])
Shape :  torch.Size([4])


tensor([[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4],
        [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4],
        [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]])
Shape :  torch.Size([3, 16])

📝 설명 : 텐서의 차원을 추가하거나 변경하는 방법에 대한 이해 및 실습

  • flatten : 다차원 텐서를 1차원 텐서로 변경합니다.

📚 참고할만한 자료:

  • [flatten] : https://pytorch.org/docs/stable/generated/torch.flatten.html
t = torch.tensor([i for i in range(20)]).reshape(2, 5, 2) # 0부터 19까지의 숫자를 4행 5열 Tensor로 구성
print(t)
print("Shape : ", t.size())
print('\n')

flat_tensor = t.flatten() # (2, 5, 2) 의 Tensor를 (20,)로 모양 변경, 1차원으로 변경
print(flat_tensor)
print("Shape : ", flat_tensor.size())
tensor([[[ 0,  1],
         [ 2,  3],
         [ 4,  5],
         [ 6,  7],
         [ 8,  9]],

        [[10, 11],
         [12, 13],
         [14, 15],
         [16, 17],
         [18, 19]]])
Shape :  torch.Size([2, 5, 2])


tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
        18, 19])
Shape :  torch.Size([20])
flat_tensor2 = t.flatten(start_dim=1) # flatten을 시작할 차원을 지정할 수 있음. 지정한 차원 이후의 모든 차원을 하나의 차원으로 평면화, 기본값 = 0 (1차원)
print(flat_tensor2)
print(flat_tensor2.size())
tensor([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])
torch.Size([2, 10])

📝 설명 : 텐서의 차원을 추가하거나 변경하는 방법에 대한 이해 및 실습

  • ravel : 다차원 텐서를 1차원 텐서로 변경합니다.

📚 참고할만한 자료:

  • [ravel] : https://pytorch.org/docs/stable/generated/torch.ravel.html
t = torch.tensor([i for i in range(20)]).reshape(2, 5, 2) # 0부터 19까지의 숫자를 (2, 5, 2) 크기 Tensor로 구성
print(t)
print("Shape : ", t.size())
print('\n')

ravel_tensor = t.ravel() # flatten 과 동일하게 (2,5,2) 의 텐서를 (20,)로 모양 변경, 1차원으로 변경
print(ravel_tensor)
print("Shape : ", ravel_tensor.size())
tensor([[[ 0,  1],
         [ 2,  3],
         [ 4,  5],
         [ 6,  7],
         [ 8,  9]],

        [[10, 11],
         [12, 13],
         [14, 15],
         [16, 17],
         [18, 19]]])
Shape :  torch.Size([2, 5, 2])


tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
        18, 19])
Shape :  torch.Size([20])
t.ravel(1) # 에러 발생, ravel 은 flatten 과 달리 어떠한 축을 기준으로 평탄화 하는 작업이 없음
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-41-4ad2f534a783> in <cell line: 1>()
----> 1 t.ravel(1) # 에러 발생, ravel 은 flatten 과 달리 어떠한 축을 기준으로 평탄화 하는 작업이 없음


TypeError: _TensorBase.ravel() takes no arguments (1 given)

2-3 역할이 비슷한 함수들의 차이 이해 및 실습

역할이 비슷한 함수들의 공통점과 차이점을 이해하고 활용할 수 있습니다.

📝 설명 : 역할이 비슷한 함수들의 차이 이해 및 실습

  • 모양 변경 : view vs. reshape vs. unsqueeze
    • ※ contiguous 란?
      • 텐서의 메모리 상에 연속적인 데이터 배치를 갖는 것
      • 텐서를 처음 생성 후 정의하면 기본적으로 contiguous 하지만, 이에 대해 차원의 순서를 변경하는 과정을 거치면 contiguous 하지 않습니다.
      • 텐서의 contiguous 함을 확인하기 위해선 is_contiguous() 를 사용합니다.
    • view 는 contiguous 하지 않은 텐서에 대해서 동작하지 않습니다.
    • reshape 는 contiguous 하지 않은 텐서를 contiguous 하게 만들어주고, 크기를 변경합니다.
    • unsqueeze 는 차원의 크기가 1인 차원을 추가하지만, 차원의 크기가 1이 아니면 차원의 모양을 변경할 수 없습니다.

📚 참고할만한 자료:

  • [what is contiguous?] : https://titania7777.tistory.com/3
  • [view vs reshape] : https://inmoonlight.github.io/2021/03/03/PyTorch-view-transpose-reshape/
  • [view, reshape, transpose, permute 비교] : https://sanghyu.tistory.com/3
# view vs reshape
tmp = torch.tensor([[[0, 1], [2, 3], [4, 5]], \
                 [[6, 7], [8, 9], [10, 11]], \
                 [[12, 13], [14, 15], [16, 17]], \
                 [[18, 19], [20, 21], [22, 23]]])
tmp_t = tmp.transpose(0,1) # contiguous 를 False 로 만들기 위한 작업
print(tmp_t.is_contiguous()) # contiguous 한지 검사
print(tmp_t.view(-1)) # view는 contiguous 하지 않은 텐서에 대해선 동작이 되지 않음
False



---------------------------------------------------------------------------

RuntimeError                              Traceback (most recent call last)

<ipython-input-42-58c86dac39d7> in <cell line: 8>()
      6 tmp_t = tmp.transpose(0,1) # contiguous 를 False 로 만들기 위한 작업
      7 print(tmp_t.is_contiguous()) # contiguous 한지 검사
----> 8 print(tmp_t.view(-1)) # view는 contiguous 하지 않은 텐서에 대해선 동작이 되지 않음


RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead.
reshape_tmp = tmp_t.reshape(-1) # reshape은 contiguous 하지 않아도 동작이 됨
print(reshape_tmp)
print(reshape_tmp.is_contiguous()) # contiguous 하지 않았던 Tensor를 contiguous 하게 변경해 줌
tensor([ 0,  1,  6,  7, 12, 13, 18, 19,  2,  3,  8,  9, 14, 15, 20, 21,  4,  5,
        10, 11, 16, 17, 22, 23])
True
# (view , reshape) vs unsqueeze
tensor_a = torch.randn(2, 3)
# (2, 3) 의 텐서를 (2, 3, 1)의 크기로 변경
view_tensor = tensor_a.view(2, 3, 1) # view 를 이용하여 (2,3,1) 의 크기로 변경
reshape_tensor = tensor_a.reshape(2, 3, 1) # reshape 를 이용하여 (2,3,1) 의 크기로 변경
unsqueeze_tensor = tensor_a.unsqueeze(-1) # unsqueeze 를 이용하여 (2,3,1) 의 크기로 변경

print("View output size : ",view_tensor.size())
print("Reshape output size : ",reshape_tensor.size())
print("Unsqueeze output size : ",unsqueeze_tensor.size())
View output size :  torch.Size([2, 3, 1])
Reshape output size :  torch.Size([2, 3, 1])
Unsqueeze output size :  torch.Size([2, 3, 1])

📝 설명 : 역할이 비슷한 함수들의 차이 이해 및 실습

  • 차원 변경 : transpose vs. permute
    • transpose : 두 차원에 대해서만 변경이 가능
      • 인자가 총 2개여야함.
    • permute : 모든 차원에 대해서 변경이 가능
      • 인자가 차원의 개수와 동일해야 함.

📚 참고할만한 자료:

  • [view, reshape, transpose, permute 비교] : https://sanghyu.tistory.com/3
import torch
tensor_a = torch.randn(2, 3, 2)
transpose_tensor = tensor_a.transpose(2, 1) # 행과 열을 전치
permute_tensor = tensor_a.permute(0, 2, 1) # 행과 열을 바꿈.

print("Transpose tensor shape : ", transpose_tensor.size())
print("Permute tensor shape : ", permute_tensor.size())
Transpose tensor shape :  torch.Size([2, 2, 3])
Permute tensor shape :  torch.Size([2, 2, 3])

📝 설명 : 역할이 비슷한 함수들의 차이 이해 및 실습

  • 반복을 통한 텐서 크기 확장 : expand vs. repeat
    • expand
      • 원본 텐서와 메모리를 공유한다.
    • repeat
      • 원본 텐서와 메모리를 공유하지 않는다.

📚 참고할만한 자료:

  • [expand vs repeat] : https://seducinghyeok.tistory.com/9
import torch

# 원본 텐서 생성
tensor_a = torch.rand(1, 1, 3)
print('Original Tensor Size')
print(tensor_a.size())
print(tensor_a)

print('\n')

# expand 사용하여 (1,1,3) => (4, 1, 3)
expand_tensor = tensor_a.expand(4, 1, -1)
print("Shape of expanded tensor:", expand_tensor.size())

print('\n')

# repeat 사용하여 (1,1,3) => (4, 1, 3)
repeat_tensor = tensor_a.repeat(4, 1, 1)
print("Shape of repeated tensor:", repeat_tensor.size())

print('\n')

# 평면화된 뷰 수정 후 원본 텐서 확인
tensor_a[:] = 0

print("Expanded Tensor")
print(expand_tensor) # 값 변경이 됨

print('\n')

print("Repeated Tensor")
print(repeat_tensor) # 깂 변경 안됨
Original Tensor Size
torch.Size([1, 1, 3])
tensor([[[0.8880, 0.6426, 0.6744]]])


Shape of expanded tensor: torch.Size([4, 1, 3])


Shape of repeated tensor: torch.Size([4, 1, 3])


Expanded Tensor
tensor([[[0., 0., 0.]],

        [[0., 0., 0.]],

        [[0., 0., 0.]],

        [[0., 0., 0.]]])


Repeated Tensor
tensor([[[0.8880, 0.6426, 0.6744]],

        [[0.8880, 0.6426, 0.6744]],

        [[0.8880, 0.6426, 0.6744]],

        [[0.8880, 0.6426, 0.6744]]])

3. 텐서 합치기 나누기

  • 3-1. 여러 텐서를 합치는 방법에 대한 이해 및 실습
  • 3-2. 하나의 텐서를 여러 텐서로 나누는 방법에 대한 이해 및 실습

3-1 여러 텐서를 합치는 방법에 대한 이해 및 실습

여러 텐서를 하나의 텐서로 합쳐서 새로운 텐서를 생성하는 과정을 알아봅니다.

📝 설명 : 여러 텐서 합치기

  • cat : 주어진 차원을 따라 텐서들을 연결합니다. (주어진 차원 외의 다른 차원의 크기가 같아야합니다.)

📚 참고할만한 자료:

  • [cat] : https://pytorch.org/docs/stable/generated/torch.cat.html
tensor_a = torch.randint(1, 10, (2, 3)) # 1부터 9까지의 무작위 정수가 있는 (2,3) Tensor
tensor_b = torch.rand(5, 3) # 0부터 1까지의 균등분포를 따르는 (5,3) Tensor

print("Tensor A shape : ", tensor_a.size())
print(tensor_a)

print('\n')

print("Tensor B shape : ", tensor_b.size())
print(tensor_b)

print('\n')

a_cat_b_row = torch.cat((tensor_a, tensor_b), dim=0) # dim = 0 (행), Tensor A 와 Tensor B 를 행 기준으로 합친다.
print("Concat Tensor A and B (by row) Shape : ", a_cat_b_row.shape) # (Tensor A 행 개수 + Tensor B 행 개수, Tensor A/B 열 개수)
print(a_cat_b_row)
Tensor A shape :  torch.Size([2, 3])
tensor([[3, 1, 1],
        [9, 6, 7]])


Tensor B shape :  torch.Size([5, 3])
tensor([[0.7098, 0.1477, 0.1453],
        [0.0746, 0.5604, 0.2862],
        [0.4602, 0.4730, 0.4643],
        [0.4764, 0.1533, 0.3704],
        [0.5958, 0.8291, 0.7434]])


Concat Tensor A and B (by row) Shape :  torch.Size([7, 3])
tensor([[3.0000, 1.0000, 1.0000],
        [9.0000, 6.0000, 7.0000],
        [0.7098, 0.1477, 0.1453],
        [0.0746, 0.5604, 0.2862],
        [0.4602, 0.4730, 0.4643],
        [0.4764, 0.1533, 0.3704],
        [0.5958, 0.8291, 0.7434]])

📝 설명 : 여러 텐서 합치기

  • stack : 주어진 차원을 새로운 차원으로 추가하여 텐서들을 쌓습니다.
    • 합쳐질 텐서들의 크기는 모두 같아야합니다.

📚 참고할만한 자료:

  • [stack] : https://pytorch.org/docs/stable/generated/torch.stack.html
tensor_a = torch.randint(1, 10, (3, 2))  # 1부터 9까지의 무작위 정수가 있는 (3,2) Tensor
tensor_b = torch.rand(3, 2)  # 0부터 1까지의 균등분포를 따르는 (3,2) Tensor

print("Tensor A shape : ", tensor_a.size())
print(tensor_a)

print('\n')

print("Tensor B shape : ", tensor_b.size())
print(tensor_b)

print('\n')

stack_tensor_row = torch.stack([tensor_a, tensor_b], dim=0)  # dim = 0, 행을 기준으로 Tensor A 에 Tensor B 를 쌓기
print("Stack A and B (by row): ", stack_tensor_row.size()) # (쌓은 Tensor 개수, Tensor A/B 행 개수, Tensor A/B 열 개수)
print(stack_tensor_row)
Tensor A shape :  torch.Size([3, 2])
tensor([[9, 9],
        [1, 6],
        [2, 2]])


Tensor B shape :  torch.Size([3, 2])
tensor([[0.5477, 0.6201],
        [0.8358, 0.7233],
        [0.4310, 0.2094]])


Stack A and B (by row):  torch.Size([2, 3, 2])
tensor([[[9.0000, 9.0000],
         [1.0000, 6.0000],
         [2.0000, 2.0000]],

        [[0.5477, 0.6201],
         [0.8358, 0.7233],
         [0.4310, 0.2094]]])

3-2. 하나의 텐서를 여러 텐서로 나누는 방법에 대한 이해 및 실습

하나의 텐서를 다양한 방법을 통해 여러 텐서로 나누는 과정을 알아봅니다.

📝 설명 : 텐서 나누기

  • chunk : 나누고자 하는 텐서의 개수를 지정하여 원래의 텐서를 개수에 맞게 분리합니다.
    • chunks 인자
      • 의 텐서로 나눌 것인지

📚 참고할만한 자료:

  • [chunk] : https://pytorch.org/docs/stable/generated/torch.chunk.html
tensor_a = torch.randint(1, 10, (6, 4))  # (6,4) 텐서
print("Original : ", tensor_a)

print('\n')

chunk_num = 3
chunk_tensor = torch.chunk(tensor_a, chunks = chunk_num, dim=0)  # dim = 0 (행), 6개의 행이 3개로 나누어 떨어지므로 3개의 텐서로 분리
print(f'{len(chunk_tensor)} 개의 Tensor로 분리')

print('\n')

for idx,a in enumerate(chunk_tensor):
    print(f'{idx} 번째 Tensor \n{a}')
    print(f'{idx} 번째 Tensor 크기', a.size())
    print('---'*10)
Original :  tensor([[9, 2, 4, 5],
        [8, 8, 9, 1],
        [5, 6, 6, 3],
        [7, 8, 3, 2],
        [1, 9, 6, 7],
        [9, 7, 4, 2]])


3 개의 Tensor로 분리


0 번째 Tensor 
tensor([[9, 2, 4, 5],
        [8, 8, 9, 1]])
0 번째 Tensor 크기 torch.Size([2, 4])
------------------------------
1 번째 Tensor 
tensor([[5, 6, 6, 3],
        [7, 8, 3, 2]])
1 번째 Tensor 크기 torch.Size([2, 4])
------------------------------
2 번째 Tensor 
tensor([[1, 9, 6, 7],
        [9, 7, 4, 2]])
2 번째 Tensor 크기 torch.Size([2, 4])
------------------------------

📝 설명 : 텐서 나누기

  • split : 입력한 크기로 여러 개의 작은 텐서로 나눕니다.
    • split_size_or_sections 인자
      • split_size (int): 얼마만큼의 크기로 자를 것인지
      • sections (list): 얼마만큼의 크기로 각각 자를 것인지 (리스트 형태로 각 텐서의 크기를 각각 지정해 줄 수 있음)

📚 참고할만한 자료:

  • [split] : https://pytorch.org/docs/stable/generated/torch.split.html
tensor_a = torch.randint(1, 10, (6, 4))  # (6,4) 텐서
print(tensor_a)

print('\n')

split_size = 2
split_tensor = torch.split(tensor_a , split_size_or_sections = split_size, dim=0)  # dim = 0 (행), 텐서 A 를 행의 길이가 2 (split_size)인 텐서로 나눔
print(f'{len(split_tensor)} 개의 Tensor로 분리')

print('\n')

for idx,a in enumerate(split_tensor):
    print(f'{idx} 번째 Tensor \n{a}')
    print(f'{idx} 번째 Tensor 크기', a.size())
    print('---'*10)
tensor([[3, 3, 3, 4],
        [3, 9, 4, 2],
        [7, 4, 8, 2],
        [4, 8, 9, 8],
        [4, 9, 8, 5],
        [1, 7, 7, 8]])


3 개의 Tensor로 분리


0 번째 Tensor 
tensor([[3, 3, 3, 4],
        [3, 9, 4, 2]])
0 번째 Tensor 크기 torch.Size([2, 4])
------------------------------
1 번째 Tensor 
tensor([[7, 4, 8, 2],
        [4, 8, 9, 8]])
1 번째 Tensor 크기 torch.Size([2, 4])
------------------------------
2 번째 Tensor 
tensor([[4, 9, 8, 5],
        [1, 7, 7, 8]])
2 번째 Tensor 크기 torch.Size([2, 4])
------------------------------
tensor_a = torch.randint(1, 10, (6, 4))  # (6,4) 텐서
print("Original : ", tensor_a)

print('\n')

split_num = [2, 4]
split_tensor = torch.split(tensor_a, split_size_or_sections = split_num, dim=0)  # dim = 0 (행), 텐서 A 를 행의 길이가 (2개인 텐서와 4개인 텐서)로 나눔
print(f'{len(split_tensor)} 개의 Tensor로 분리')

print('\n')

for idx,a in enumerate(split_tensor):
    print(f'{idx} 번째 Tensor \n{a}')
    print(f'{idx} 번째 Tensor 크기', a.size())
    print('---'*10)
Original :  tensor([[5, 9, 4, 3],
        [8, 4, 4, 6],
        [3, 6, 3, 3],
        [3, 7, 7, 9],
        [2, 8, 8, 8],
        [5, 6, 1, 5]])


2 개의 Tensor로 분리


0 번째 Tensor 
tensor([[5, 9, 4, 3],
        [8, 4, 4, 6]])
0 번째 Tensor 크기 torch.Size([2, 4])
------------------------------
1 번째 Tensor 
tensor([[3, 6, 3, 3],
        [3, 7, 7, 9],
        [2, 8, 8, 8],
        [5, 6, 1, 5]])
1 번째 Tensor 크기 torch.Size([4, 4])
------------------------------

#Reference

(📒가이드)

Required Package

torch == 2.0.1

콘텐츠 라이선스

저작권 : ©2023 by Upstage X fastcampus Co., Ltd. All rights reserved.</font>

WARNING</font> : 본 교육 콘텐츠의 지식재산권은 업스테이지 및 패스트캠퍼스에 귀속됩니다. 본 콘텐츠를 어떠한 경로로든 외부로 유출 및 수정하는 행위를 엄격히 금합니다. ```python ```