AI/Pytorch

[Pytorch] Tensor 기초 다지기 + AutoGrad

jihuSunbae 2024. 7. 26. 15:05

 

 
 

목차

     

    학습 목표

    - 파이토치의 기본 연산 단위인 Tensor를 생성하고 연산하는 방법을 안다. 

    - 파이토치의 AutoGrad(자동 미분) 작동원리에 대해서 안다. 

     

    실습 자료 추가(To Do)

     

     

     

    Remind

    • Pytorch = numpy + AutoGrad

    Tensor란?

    Pytorch에서 다차원 array를 표현하는 클래스 cf) TF는 ndarry

    • 대부분 numpy arr와 비슷

     

    Tensor 생성하기 

    1) 직접 data 삽입

    # 1. 직접 생성 
    x = torch.tensor([1, 2, 3])  # 1D 텐서 생성​

     

    2) numpy arr 기반으로 생성 

    data = [[1, 2, 3]]
    np_array = np.array(data)
    y = torch.tensor(np_array)

     

    3) 차원 사이즈를 주고 텐서 생성

    • torch.ones(N,M,...)        # 주어진 사이즈를 가진, 1로 채워진 tensor로 생성
    • torch.zeros(N,M,...)      # 주어진 사이즈를 가진, 0로 채워진 tensor로 생성
    • torch.rand(N,M,...)        # 주어진 사이즈를 가진, 랜덤 tensor로 생성
    x = torch.rand(3, 3)   # 크기가 3x3인 랜덤 텐서 생성
    z = torch.ones(2, 3)   # 모든 값이 1인 2x3 텐서 생성
    y = torch.zeros(4, 5)  # 모든 값이 0인 4x5 텐서 생성

     

    4) 특정 텐서와 같은 shape의 텐서 생성

    • torch.ones_like(tensor)    # 주어진 텐서와 같은 형태이고, 1로 채워진 tensor로 생성
    • torch.zeros_like(tensor)   # 주어진 텐서와 같은 형태이고, 0로 채워진 tensor로 생성
    • random_like(tensor)         # 주어진 텐서와 같은 형태인 랜덤 텐서 생성
    x = torch.rand(3, 3)   # 크기가 3x3인 랜덤 텐서 생성
    
    y_ones = torch.ones_like(x)     # 모든 값이 1인 3x3 텐서 생성
    y_zeros = torch.zeros_like(x)   # 모든 값이 0인 3x3 텐서 생성
    y_random = torch.rand_like(x)   # 크기가 3x3인 랜덤 텐서 생성​

     


    Tensor와 numpy arr 간 변환

    - tensor > np array: numpy()

    - np array> tensor : from_numpy()  

     

    * 주의점! CPU 상  tensor와 numpy 배열을 메모리 공간을 공유하기 때문에, 하나를 변경하면 다른 하나도 변경된다.

    # tensor를 array로 변환하기, tensor를 변환하면 arr 도 같이 변형된다.
    t = torch.tensor([1,2,3])
    arr = t.numpy()
    print(f'tensor:{t}\n numpy arr:{arr}\n') # [1,2,3], [1,2,3]
    
    t.add_(1)
    print(f'tensor에 1을 더한 이후 결과 -\n tensor:{t}\n numpy arr:{arr}\n')  #[2 3 4], [2 3 4]

    Tensor Attributes

    shape # 텐서 형태

    size() # 텐서 형태 

    dim # 차원

    dtype # 데이터 타입

    device # 어떤 장치에 저장되는지 (cpu, gpu면 'cuda')

    # 텐서의 속성
    print(x.shape)  # 텐서의 형태
    print(x.size()) # 텐서의 크기
    print(x.dtype)  # 텐서의 데이터 타입
    print(x.device) # 텐서가 어느 장치에 저장되는지

     


    Tensor 슬라이싱

    : numpy arr 의 슬라이싱과 매우 유사하다

    • tensor[row,col] 의 형태 
    • row, col 인덱스 지정 : tensor[N, M] 사용
    • 범위를 지정하고 싶으면 tensor[N:M, N:M]을 사용
      • - e.g. 처음 2개의 row를 찾고 싶음 tensor[:2, :]

    Tensor Method

    산술 연산 

    더하기 빼기 가능 

    # 수학 기본연산
    a = torch.tensor([1, 2, 3])
    b = torch.tensor([4, 5, 6])
    c = a + b  # 텐서 덧셈
    d = a * b  # 텐서 곱셈
    
    print("덧셈 결과:", c)
    print("곱셈 결과:", d)

     

    행렬곱 연산

    여러 개가 있는데, mm()을 사용하는 것을 추천

    A.dot(B)

    A.mm(B)

    A.matmul(B)

    A @ B

     

    *dot vs mm 

    • dot()은 1차원 tensor 끼리만 가능
    • mm()은 N차원 tensor 끼리만 연산 가능(1차원 tensor는 안된다.)

        예를 들어, dot은 [1,2,3]과 [4,5,6] 과 같이 1차원 tensor 끼리의 내적만 가능 

        즉, [[1,2],[3,4]] 와 [[5,6],[7,8]] 의 내적은 dot으로 불가 

        

        반면, mm()은 [[1,2],[3,4]] 와 [[5,6],[7,8]] 는 내적 가능하지만 1차원 텐서끼리 내적은 불가!

     

    *dot, mm vs matmul

    • matmul는 dot & mm 와 달리, 차원이 다른 tensor 끼리 연산 가능함 (자동으로 broadcasting).
    • 예상하지 못한 결과값을 나타낼 수 있기 때문에 사용에 유의 해야함. 
      연산 가능 차원 Auto Broadcasting(다른 차원끼리 계산 가능한가?)
    dot() 1차원 텐서 끼리만 연산 가능  X
    mm() 다차원 텐서 끼리만 연산 가능 X
    matmul() 1~N O

     

    tensor handling 

    view() # reshape와 결과는 똑같음 

    reshape()

    squeeze(dim) :  차원 삭제 (dim이 None이면 차원의 개수가 1인 차원을 삭제)

    unsqueeze(dim) : 차원 추가(dim이 None이면 차원의 개수가 1인 차원을 추가)

    flatten() # 1차원으로 변환

     

     

    * view, reshape 과의 차이 

    • 실행 결과는 같음 BUT view를 쓰는 것을 추천
    • tensor 형태가 달라지는 경우 값을 보장해주는지 안보장해주는지 차이 
      • view: 형태가 달라지는 경우에도 같은 메모리를 공유 -> 값의 변화가 반영된다
      • reshape: 형태가 달라지면, 원래 값을 copy해서 다른 메모리에 저장 -> 값의 변화가 반영 X
    # view()
    a1 = torch.zeros(3,2)
    b1 = a1.view(2,3) # 텐서 형태를 바꿔줌
    a1.fill_(1) 
    
    # 결과: b가 바뀌면, a의 값도 바뀜
    print("a", a1) # a [[1., 1.],[1., 1.], [1., 1.]]
    print("b", b1) # b [[1., 1., 1.], [1., 1., 1.]]
    # reshape
    a1 = torch.zeros(3,2)
    b1 = a1.t().reshape(6) # 텐서 형태를 변형
    a1.fill_(1) 
    
    # 결과 b가 바뀌어도 a는 바뀌지 않음. 
    print("a", a1) # a [[1., 1.],[1., 1.], [1., 1.]]
    print("b", b1) # b [0., 0., 0., 0., 0., 0.]

     

    *squeeze와 unsqueeze 원리

    • squeeze(dim) :  차원 삭제 (dim이 None이면 차원의 개수가 1인 차원을 삭제)
    • unsqueeze(dim) : 차원 추가(dim이 None이면 차원의 개수가 1인 차원을 추가)

    - 일단 눈으로 한 번 풀어봐라!

     

     

    - 코드 예상 결과를 상상해보세요. 

    tensor_ex =  torch.zeros((2,2))
    print(tensor_ex) # [[0,0],[0,0]]
    
    #unsqueeze- dim0 
    print(f'unsqueeze- dim0 result:\n', tensor_ex.unsqueeze(0), '\n') # [[[0,0],[0,0]]]
    print('-shape:',tensor_ex.unsqueeze(0).shape, '\n') # (1,2,2)
    
    #unsqueeze- dim1 
    print(f'unsqueeze- dim1 result:\n', tensor_ex.unsqueeze(1), '\n') # [[[0,0]],[[0,0]]]
    print('-shape:',tensor_ex.unsqueeze(1).shape, '\n')  # (1,2,2)
    
    #unsqueeze- dim2
    print(f'unsqueeze- dim2 result:\n', tensor_ex.unsqueeze(2), '\n') # [[[[0],[0]],[[0],[0]]]]
    print('-shape:, ',tensor_ex.unsqueeze(2).shape, '\n')

     

    Tensor GPU에 올리기!

    # GPU가 존재하면 텐서를 이동합니다
    if torch.cuda.is_available():
        print("available")
        tensor = tensor.to("cuda")

     


    Tensor Operations for ML/DL formula

    torch.nn.functional 

    - softmax(), argmax(), one_hot() 등 다양한 인공지능 함수들을 사용할 수 있음. 

     


    AutoGrad(자동 미분)

    pytorch의 핵심은 자동 미분 지원이다 -> backward() 함수 사용 

    - 미분 주체 :  tensor에 requires_grad= True 설정 

    -  backward() 함수를 통해 실제 미분 수행 

     

     

     

     


    Reference

     

     

    인공지능 기초 다지기

    부스트코스 무료 강의

    www.boostcourse.org

     

     

    (2강-실습) Pytorch basics for DL newbies.ipynb

    Colaboratory notebook

    colab.research.google.com

     

     

     

    텐서(Tensor)

    파이토치(PyTorch) 기본 익히기|| 빠른 시작|| 텐서(Tensor)|| Dataset과 Dataloader|| 변형(Transform)|| 신경망 모델 구성하기|| Autograd|| 최적화(Optimization)|| 모델 저장하고 불러오기 텐서(tensor)는 배열(array)이

    tutorials.pytorch.kr