재형이의 성장통 일지
  • 파이토치 개요, 텐서의 형변환, 연산, 함수
    2024년 02월 10일 15시 31분 38초에 업로드 된 글입니다.
    작성자: 재형이
    반응형
     
     
    • 설 연휴라 집에 내려와서 노트북으로 작성 중이다
    • 노트북이 오래돼서 그런지 너무 느려서 예전에 포맷을 했었는데 그 이후로는 나름 쓸만한 것 같아서 다행이다
    • 이번에는 파이썬에 있는 딥러닝을 위한 프레임워크인 파이토치에 대해서 알아보고 정리해볼 것이다
    • 가보자고~

    출처 : 최고심 작가 트위터 https://twitter.com/gosimperson

     

     

     

     


     

     

     

     

     

    1. 파이토치(PyTorch) 개요

    • PyTorch는 기계 학습 프레임워크(framework) 중 하나다
    • PyTorch를 사용하면, GPU 연동을 통해 효율적으로 딥러닝 모델을 학습할 수 있다
    import torch
    • 파이토치를 사용하여 연산을 할 때 CPU를 사용할 것인지 GPU를 사용할 것인지를 정할 수 있다
    data = [
      [1, 2],
      [3, 4]
    ]
    
    x = torch.tensor(data)
    print(x.is_cuda)
    
    x = x.cuda() # GPU로 옮기기
    print(x.is_cuda)
    
    x = x.cpu() # CPU로 옮기기
    print(x.is_cuda)
    
    # False
    # True
    # False
    • 서로 다른 장치(device)에 있는 텐서끼리 연산을 수행하면 오류가 발생한다. 따라서 가능하면, 연산을 수행하는 텐서들을 모두 GPU에 올린 뒤에 연산을 수행한다. CPU를 사용하는 것보다 GPU를 사용하는 것이 속도적인 측면에서 더 효율적이다
    # GPU 장치의 텐서
    a = torch.tensor([
        [1, 1],
        [2, 2]
    ]).cuda()
    
    # CPU 장치의 텐서
    b = torch.tensor([
        [5, 6],
        [7, 8]
    ])
    
    print(torch.matmul(a, b))

    2. 파이토치에서의 텐서란?

    • 파이토치(PyTorch)에서 텐서(Tensor)는 다차원 배열을 나타내는 자료형이다
    • PyTorch에서의 텐서(tensor)는 기능적으로 넘파이(NumPy)와 매우 유사하다
    • 기본적으로 다차원 배열을 처리하기에 적합한 자료구조로 이해할 수 있다
    • PyTorch의 텐서는 "자동 미분" 기능을 제공한다

    2-1. 텐서(Tensor)의 기본 구성 요소

    1. 모양(shape)
    2. 자료형(data type)
    3. 저장된 장치(device)
    import torch
    
    tensor = torch.rand(3, 4)
    
    print(tensor)
    print(f"Shape: {tensor.shape}")
    print(f"Data type: {tensor.dtype}")
    print(f"Device: {tensor.device}")

    2-2. 텐서(Tensor) 초기화

    • 리스트 데이터에서 직접 텐서를 초기화할 수 있다
    data = [
      [1, 2],
      [3, 4]
    ]
    x = torch.tensor(data)
    
    print(x)

    • NumPy 배열에서 텐서를 초기화할 수 있다
    a = torch.tensor([5])
    b = torch.tensor([7])
    
    # tensor를 numpy로 변환
    c = (a + b).numpy()
    print(c)
    print(type(c))
    
    result = c * 10
    # numpy를 tensor로 변환
    tensor = torch.from_numpy(result)
    print(tensor)
    print(type(tensor))

    • 다른 텐서의 정보를 토대로 텐서를 초기화할 수 있다
    x = torch.tensor([
        [5, 7],
        [1, 2]
    ])
    
    # x와 같은 모양과 자료형을 가지지만, 값이 1인 텐서 생성
    x_ones = torch.ones_like(x)
    print(x_ones)
    # x와 같은 모양을 가지되, 자료형은 float으로 덮어쓰고, 값은 랜덤으로 채우기
    x_rand = torch.rand_like(x, dtype=torch.float32) # uniform distribution [0, 1)
    print(x_rand)

    3. 텐서의 형변환 및 차원 조작

    • 텐서는 넘파이(NumPy) 배열처럼 조작할 수 있다

    3-1. 텐서의 특정 차원 접근하기

    • : 는 텐서의 차원을 전체 선택할 때 사용
    • ... 는 모든 중간 차원을 선택할 때 사용
    tensor = torch.tensor([
        [1, 2, 3, 4],
        [5, 6, 7, 8],
        [9, 10, 11, 12]
    ])
    
    print(tensor[0]) # first row
    print(tensor[:, 0]) # first column
    print(tensor[..., -1]) # last column

    3-2. 텐서 이어붙이기 (Concatenate)

    tensor = torch.tensor([
        [1, 2, 3, 4],
        [5, 6, 7, 8],
        [9, 10, 11, 12]
    ])
    
    # dim: 텐서를 이어 붙이기 위한 축
    # 0번 축(행)을 기준으로 이어 붙이기
    result = torch.cat([tensor, tensor, tensor], dim=0)
    print(result)
    
    # 1번 축(열)을 기준으로 이어 붙이기
    result = torch.cat([tensor, tensor, tensor], dim=1)
    print(result)

    3-3. 텐서 형변환 (Type Casting)

    • 텐서의 자료형(정수, 실수 등)을 변환할 수 있다
    a = torch.tensor([2], dtype=torch.int)
    b = torch.tensor([5.0])
    
    print(a.dtype)
    print(b.dtype)
    
    # 텐서 a는 자동으로 float32형으로 형변환 처리
    print(a + b)
    print((a + b).dtype)
    # 텐서 b를 int32형으로 형변환하여 덧셈 수행
    print(a + b.type(torch.int32))
    print((a + b.type(torch.int32)).dtype)

    3-4. 텐서의 모양 변경

    • view()는 텐서의 모양을 변경할 때 사용한다
    • 이때, 텐서(tensor)의 순서는 변경되지 않는다
    # view()는 텐서의 모양을 변경할 때 사용한다.
    # 이때, 텐서(tensor)의 순서는 변경되지 않는다.
    a = torch.tensor([1, 2, 3, 4, 5, 6, 7, 8])
    b = a.view(4, 2)
    print(b)
    
    # a의 값을 변경하면 b도 변경, 얕은 복사
    a[0] = 7
    print(b)
    
    # a의 값을 복사(copy)한 뒤에 변경, 깊은 복사
    c = a.clone().view(4, 2)
    a[0] = 9
    print(c)

    3-5. 텐서의 차원 교환

    • 하나의 텐서에서 특정한 차원끼리 순서를 교체할 수 있다
    a = torch.rand((64, 32, 3))
    print(a.shape)
    
    b = a.permute(2, 1, 0) # 차원 자체를 교환
    # (2번째 축, 1번째 축, 0번째 축)의 형태가 되도록 한다.
    print(b.shape)

    4. 텐서의 연산과 함수

    4-1. 텐서의 연산

    # 같은 크기를 가진 두 개의 텐서에 대하여 사칙연산 가능
    # 기본적으로 요소별(element-wise) 연산
    a = torch.tensor([
        [1, 2],
        [3, 4]
    ])
    b = torch.tensor([
        [5, 6],
        [7, 8]
    ])
    print(a + b)
    print(a - b)
    print(a * b)
    print(a / b)

    • 행렬 곱을 수행할 수 있다
    a = torch.tensor([
        [1, 2],
        [3, 4]
    ])
    b = torch.tensor([
        [5, 6],
        [7, 8]
    ])
    # 행렬 곱(matrix multiplication) 수행
    print(a.matmul(b))
    print(torch.matmul(a, b))

    4-2. 텐서의 평균 함수

    • 텐서의 평균(mean)을 계산할 수 있다
    a = torch.Tensor([
        [1, 2, 3, 4],
        [5, 6, 7, 8]
    ])
    print(a)
    print(a.mean()) # 전체 원소에 대한 평균
    print(a.mean(dim=0)) # 각 열에 대하여 평균 계산
    print(a.mean(dim=1)) # 각 행에 대하여 평균 계산

    4-3. 텐서의 합계 함수

    • 텐서의 합계(sum)를 계산할 수 있다
    a = torch.Tensor([
        [1, 2, 3, 4],
        [5, 6, 7, 8]
    ])
    print(a)
    print(a.sum()) # 전체 원소에 대한 합계
    print(a.sum(dim=0)) # 각 열에 대하여 합계 계산
    print(a.sum(dim=1)) # 각 행에 대하여 합계 계산

    • dim=0이 "첫 번째 차원"이라는 것은 맞지만, 이것이 "각 행"을 의미하는 것이 아니라 "행"을 대상으로 연산이 수행된다는 것을 의미 → 즉, dim=0일 때 첫번째 행의 첫번째 열, 두번째 행의 첫번째 열 ··· 이런식으로 열은 고정하고 하나의 값 계산, dim=1일 때는 첫번째 열의 첫번째 행, 두번째 열의 첫번째 행 ··· 이런식으로 계산

    4-4. 텐서의 최대 함수

    • max() 함수는 원소의 최댓값을 반환한다
    • argmax() 함수는 가장 큰 원소(최댓값)의 인덱스를 반환한다
    a = torch.Tensor([
        [1, 2, 3, 4],
        [5, 6, 7, 8]
    ])
    print(a)
    print(a.max()) # 전체 원소에 대한 최댓값
    print(a.max(dim=0)) # 각 열에 대하여 최댓값 계산
    print(a.max(dim=1)) # 각 행에 대하여 최댓값 계산

    a = torch.Tensor([
        [1, 2, 3, 4],
        [5, 6, 7, 8]
    ])
    print(a)
    print(a.argmax()) # 전체 원소에 대한 최댓값의 인덱스
    print(a.argmax(dim=0)) # 각 열에 대하여 최댓값의 인덱스 계산
    print(a.argmax(dim=1)) # 각 행에 대하여 최댓값의 인덱스 계산

    4-5. 텐서의 차원 줄이기 혹은 늘리기

    • unsqueeze() 함수는 크기가 1인 차원을 추가한다
      • 배치(batch) 차원을 추가하기 위한 목적으로 흔히 사용된다
    • squeeze() 함수는 크기가 1인 차원을 제거한다
    a = torch.Tensor([
        [1, 2, 3, 4],
        [5, 6, 7, 8]
    ])
    print(a.shape)
    
    # 첫 번째 축에 차원 추가
    a = a.unsqueeze(0)
    print(a)
    print(a.shape)
    
    # 네 번째 축에 차원 추가
    a = a.unsqueeze(3)
    print(a)
    print(a.shape)

    # 크기가 1인 차원 제거
    a = a.squeeze()
    print(a)
    print(a.shape)

     

     

     

     

     

     


     

     

     

     

     

    반응형
    댓글