본문 바로가기
Boostcamp AI Tech/[week 1-5] LEVEL 1

[Week 3 - Day 2 ] Pytorch

by newnu 2021. 8. 20.
반응형

1. 강의 내용

torch.nn.Module

  • 딥러닝을 구성하는 layer의 base class
  • input,output,Forward,Backward 정의
  • 학습의 대상이 되는 parameter(tensor) 정의

nn.Parameter

  • Tensor 객체의 상속 객체
  • nn.Module 내에 attribute가 될 때는 required_grad = True로 지정되어 학습 대상이 되는 Tensor

Backward

  • Layer에 있는 Parameter들의 미분 수행
  • Forward의 결과값(model의 output=예측치)과 실제값 간의 차이(loss)에 대해 미분 수행
  • 해당 값으로 parameter 업데이트

Datasets & DataLoaders

Dataset 클래스

  • 데이터 입력 형태를 정의하는 클래스
  • Image, Text,Audio 등에 따른 다른 입력 정의
  • 데이터셋에 대한 표준화된 처리방법 제공
  • 최근 HuggingFace 등 표준화된 라이브러리 사용

DataLoader 클래스

  • Data의 Batch를 생성해주는 클래스
  • 학습직전 데이터의 변환을 책임
  • Tensor로 변환 + Batch 처리

2. 필수과제 1번 Custom Model 제작

torch.Tensor

 - 클래스

 - int 입력시 float로 변환

 - torch 데이터 입력시 입력받은 데이터의 메모리 공간 사용 (원래 데이터 바꾸면 새로운 데이터도 바뀜)

 - list, numpy 데이터 입력 시 복사하여 새롭게 torch.Tensor 만든 후 사용

 

torch.tensor

- 함수

 - int 입력시 그대로 int

 - 입력 받은 데이터를 새로운 메모리 공간으로 복사 후 사용 (원래 데이터 바꿔도 영향 없음)

 

사칙연산

- torch.add

 - torch.sub

 - torch.mul

 - torch.div

 

인덱싱

- torch.index_select(input, dim, index)

import torch

A = torch.Tensor([[1,2],[3,4]])

# 1,3 뽑기

#1
torch.index_select(A,1,torch.tensor([0])).view(-1)

#2
A[:,0]

#torch.Tensor([1, 3])

2D tensor에서 대각선 요소 가져오기

- torch.gather(input,dim,index)

import torch
A = torch.tensor([[1,2],[3,4]])

torch.gather(A,1,torch.tensor([[0],[1]])).view(-1)

3D tensor에서 대각선 요소 가져오기

import torch
A = torch.tensor([[[1,2],[3,4]],[[5,6],[7,8]]])
torch.gather(A,2,torch.tensor([[[0],[1]],[[0],[1]]])).view(2,2)

#torch.Tensor([[1, 4], [5, 8]])

임의의 크기 3D tensor에서 대각선 요소 모으기

import torch

def get_diag_element(A):
    C,H,W = A.size()
    diag_size = min(H,W) # 대각선은 둘 중 짧은 길이 만큼만 가능
    
    # diag_size 만큼 행별로 하나씩 -> C 수만큼 
    gather_index = torch.arange(diag_size).view(diag_size,-1).expand(C,diag_size,1)
    
    output = torch.gather(A,2,gather_index)
    output = output.view(C,diag_size)
    return output

 

Tensors - Creation Ops

- torch.from_numpy : numpy array 를 tensor로

- torch.zeros : 지정한 크기만큼 0으로 채운 tensor

- torch.zeros_like : 같은 크기의 tensor 0으로 채우기

 

Tensors - Indexing, Slicing, Joining, Mutating Ops

 - torch.chunk(input,chunks,dim)

 - torch.swapdims(input,dim0,dim1) (torch.transpose())

 - torch.Tensor.scatter_(dim,index,src,reduce=None)

       src의 숫자들을 index에 scatter

 

Random Sampling

 - torch.randn(size)

 - torch.randperm(n)

     random permutation of integers from 0 to n - 1.

 - torch.poisson(input,generator=None)

    Returns a tensor of the same size as input with each element sampled from a Poisson distribution with rate parameter given by the corresponding element in input

 

Math Operations - Pointwise Ops

- torch.log1p(input)

    natural logarithm of (1 + input)

- torch.rad2deg(input)

    converted from angles in radians to degrees.

- torch.clamp(input,min,max)

    Clamps all elements in input into the range [ min, max ]

Math Operations - Reduction Ops

- torch.prod(input)

    product of all elements

- torch.count_nonzero(input,dim=None)

 

>>> x = torch.zeros(3,3)
>>> x[torch.randn(3,3) > 0.5] = 1
>>> x
tensor([[0., 1., 1.],
        [0., 0., 0.],
        [0., 0., 1.]])
>>> torch.count_nonzero(x)
tensor(3)
>>> torch.count_nonzero(x, dim=0)
tensor([0, 1, 2]) # 순서 상관없이 dim 별로 count nonzero

- torch.argmax(input)

   max값의 index

>>> a = torch.randn(4, 4)
>>> a
tensor([[ 1.3398,  0.2663, -0.2686,  0.2450],
        [-0.7401, -0.8805, -0.3402, -1.1936],
        [ 0.4907, -1.3948, -1.0691, -0.3132],
        [-1.6092,  0.5419, -0.2993,  0.3195]])
>>> torch.argmax(a)
tensor(0)
>>> a = torch.randn(4, 4)
>>> a
tensor([[-0.8995,  1.0854, -1.3916, -0.2326],
        [ 1.5765, -1.6868, -0.6414,  0.6763],
        [ 1.6658,  0.4947,  0.9403,  1.5973],
        [ 0.5412,  0.4130,  0.1965, -0.8740]])
>>> torch.argmax(a)
tensor(8) # 순서대로 index 부여해서 가장 큰 숫자의 index 리턴
>>> a = torch.randn(4, 4)
>>> a
tensor([[ 1.3398,  0.2663, -0.2686,  0.2450],
        [-0.7401, -0.8805, -0.3402, -1.1936],
        [ 0.4907, -1.3948, -1.0691, -0.3132],
        [-1.6092,  0.5419, -0.2993,  0.3195]])
>>> torch.argmax(a, dim=1)
tensor([ 0,  2,  0,  1])

Math Operations - Comparison Ops

 - torch.allclose(input,other,atol,rtol,equal_nan)

  • input (Tensor) – first tensor to compare
  • other (Tensor) – second tensor to compare
  • atol (float, optional) – absolute tolerance. Default: 1e-08
  • rtol (float, optional) – relative tolerance. Default: 1e-05
  • equal_nan (bool, optional) – if True, then two NaN s will be considered equal. Default: False
>>> torch.allclose(torch.tensor([10000., 1e-07]), torch.tensor([10000.1, 1e-08]))
False
>>> torch.allclose(torch.tensor([10000., 1e-08]), torch.tensor([10000.1, 1e-09]))
True
>>> torch.allclose(torch.tensor([1.0, float('nan')]), torch.tensor([1.0, float('nan')]))
False
>>> torch.allclose(torch.tensor([1.0, float('nan')]), torch.tensor([1.0, float('nan')]), equal_nan=True)
True

 - torch.argsort(input,dim=-1,descending=False)

>>> a = torch.randn(4, 4)
>>> a
tensor([[ 0.0785,  1.5267, -0.8521,  0.4065],
        [ 0.1598,  0.0788, -0.0745, -1.2700],
        [ 1.2208,  1.0722, -0.7064,  1.2564],
        [ 0.0669, -0.2318, -0.8229, -0.9280]])


>>> torch.argsort(a, dim=1)
tensor([[2, 0, 3, 1],
        [3, 2, 1, 0],
        [2, 1, 0, 3],
        [3, 2, 1, 0]])

 - torch.topk(input,k,dim=None,largest=True,sorted=True)

  • input (Tensor) – the input tensor.
  • k (int) – the k in “top-k”
  • dim (int, optional) – the dimension to sort along
  • largest (bool, optional) – controls whether to return largest or smallest elements
  • sorted (bool, optional) – controls whether to return the elements in sorted order
>>> x = torch.arange(1., 6.)
>>> x
tensor([ 1.,  2.,  3.,  4.,  5.])
>>> torch.topk(x, 3)
torch.return_types.topk(values=tensor([5., 4., 3.]), indices=tensor([4, 3, 2]))

 

Math Operations - other operations

 - torch.triu(input, diagonal)

    upper triangular part of a matrix

>>> b = torch.randn(4, 6)
>>> b
tensor([[ 0.5876, -0.0794, -1.8373,  0.6654,  0.2604,  1.5235],
        [-0.2447,  0.9556, -1.2919,  1.3378, -0.1768, -1.0857],
        [ 0.4333,  0.3146,  0.6576, -1.0432,  0.9348, -0.4410],
        [-0.9888,  1.0679, -1.3337, -1.6556,  0.4798,  0.2830]])
>>> torch.triu(b, diagonal=1)
tensor([[ 0.0000, -0.0794, -1.8373,  0.6654,  0.2604,  1.5235],
        [ 0.0000,  0.0000, -1.2919,  1.3378, -0.1768, -1.0857],
        [ 0.0000,  0.0000,  0.0000, -1.0432,  0.9348, -0.4410],
        [ 0.0000,  0.0000,  0.0000,  0.0000,  0.4798,  0.2830]])
>>> torch.triu(b, diagonal=-1)
tensor([[ 0.5876, -0.0794, -1.8373,  0.6654,  0.2604,  1.5235],
        [-0.2447,  0.9556, -1.2919,  1.3378, -0.1768, -1.0857],
        [ 0.0000,  0.3146,  0.6576, -1.0432,  0.9348, -0.4410],
        [ 0.0000,  0.0000, -1.3337, -1.6556,  0.4798,  0.2830]])

 - torch.einsum(equation,operands)

# batch matrix multiplication
>>> As = torch.randn(3,2,5)
>>> Bs = torch.randn(3,5,4)
>>> torch.einsum('bij,bjk->bik', As, Bs)
tensor([[[-1.0564, -1.5904,  3.2023,  3.1271],
        [-1.6706, -0.8097, -0.8025, -2.1183]],

        [[ 4.2239,  0.3107, -0.5756, -0.2354],
        [-1.4558, -0.3460,  1.5087, -0.8530]],

        [[ 2.8153,  1.8787, -4.3839, -1.2112],
        [ 0.3728, -2.1131,  0.0921,  0.8305]]])

 - torch.bucketsize(input,boundaries,right = False)

input의 원소들이 boundaries의 어떤 원소 사이에 있는지

boundaries는 단조 증가하는 시퀀스 

right 가 False 이면 right에 == 

right이 True 이면 left에 ==

>>> boundaries = torch.tensor([1, 3, 5, 7, 9])
>>> boundaries
tensor([1, 3, 5, 7, 9])
>>> v = torch.tensor([[3, 6, 9], [3, 6, 9]])
>>> v
tensor([[3, 6, 9],
        [3, 6, 9]])
>>> torch.bucketize(v, boundaries)
tensor([[1, 3, 4],
        [1, 3, 4]])
>>> torch.bucketize(v, boundaries, right=True)
tensor([[2, 3, 5],
        [2, 3, 5]])

 

Math Operations - BLAS and LAPACK Operations

BLAS : Basic Linear Algebra Subprograms

LAPACK : Linear Algebra PACKage

 

- torch.addmm(input,mat1,mat2)

 input + mat1 * mat2

 

- torch.matrix_rank(input,tol,symmetric)

numerical rank of a 2-D tensor

>>> a = torch.eye(10)
>>> torch.matrix_rank(a)
tensor(10)
>>> b = torch.eye(10)
>>> b[0, 0] = 0
>>> torch.matrix_rank(b)
tensor(9)

 - torch.qr(

Computes the QR decomposition of a matrix

QR 분해는 실수 행렬을 직교 행렬과 상삼각 행렬의 곱으로 나타내는 행렬 분해

>>> a = torch.tensor([[12., -51, 4], [6, 167, -68], [-4, 24, -41]])
>>> q, r = torch.qr(a)
>>> q
tensor([[-0.8571,  0.3943,  0.3314],
        [-0.4286, -0.9029, -0.0343],
        [ 0.2857, -0.1714,  0.9429]])
>>> r
tensor([[ -14.0000,  -21.0000,   14.0000],
        [   0.0000, -175.0000,   70.0000],
        [   0.0000,    0.0000,  -35.0000]])
>>> torch.mm(q, r).round()
tensor([[  12.,  -51.,    4.],
        [   6.,  167.,  -68.],
        [  -4.,   24.,  -41.]])
>>> torch.mm(q.t(), q).round()
tensor([[ 1.,  0.,  0.],
        [ 0.,  1., -0.],
        [ 0., -0.,  1.]])
>>> a = torch.randn(3, 4, 5)
>>> q, r = torch.qr(a, some=False)
>>> torch.allclose(torch.matmul(q, r), a)
True

 

torch.nn (Linear Layers)

>>> m = nn.Linear(20, 30)
>>> input = torch.randn(128, 20)
>>> output = m(input)
>>> print(output.size())
torch.Size([128, 30])

torch.nn.Identity

>>> m = nn.Identity(54, unused_argument1=0.1, unused_argument2=False)
>>> input = torch.randn(128, 20)
>>> output = m(input)
>>> print(output.size())
torch.Size([128, 20])

torch.nn.LazyLinear

- 출력값만 지정

- 입력값의 크기는 첫 forward 진행할 때 자동으로 지정

입력값의 크기 변화에 맞추어 유연하게 대응

 

hook

 - 프로그램의 실행 로직을 분석 및 추가 기능

- package를 사용할 때 custom 코드를 package 중간중간에 실행

- tensor에는 backward hook만 

- nn.Module에 등록하는 모든 hook은 __dict__ 이용하여 한번에 확인 가능

- Module:

    register_full_backward_hook

    register_forward_pre_hook

    register_forward_hook

- Tensor (backward만 가능)

    register_hook

 

apply

- 구현되어 있는 모델에 custom 함수 적용할 때 사용

- 가중치 초기화,..등

import torch
from torch import nn

def init_weights(m):
    if type(m) == nn.Linear:
        m.weight.fill_(1.0)
        print(m.weight)

net = nn.Sequential(nn.Linear(2, 2), nn.Linear(2, 2))
net.apply(init_weights)

맨 위 module에 적용하면 하위 module에 모두 적용

반응형