호기심 많은 분석가

[BoostCamp] Week3_Day11. PyTorch를 배워보자! 본문

Coding/BoostCamp

[BoostCamp] Week3_Day11. PyTorch를 배워보자!

DA Hun 2021. 8. 17. 23:20
 

부스트캠프

개발자의 지속 가능한 성장을 위한 학습 커뮤니티

boostcamp.connect.or.kr

굿모닝세션

비몽사몽한 정신으로 굿모닝세션과 함께 이번 주를 시작했다. 이미 학습 일정이 잘 나와있어서 그것을 따라 하기로!

  • 수업은 학습 일정 따라서, Data Viz는 화, 수에 걸쳐서 학습
  • 슬랙에 To-Do list 작성
  • 멘토님께 학습 일정 말씀드리고, 조언받기

개인학습

(01강) Introduction to PyTorch

Computational Graph

  • 연산의 과정을 그래프로 표현
  • $g=(x+y)*z$

  • Define and Run (TF)
    • 그래프를 먼저 정의 → 실행 시점에 데이터 Feed

feed_dict를 통해 cost function에 데이터 Feed

  • Define by Run (Dynamic Computational Graph, DCG, PyTorch)
    • 실행을 하면서 그래프를 생성하는 방식 → 의외로 PyTorch가 빠를 때가 많음
    • 중간중간 값을 확인할 수 있기 때문에 Debug에 유리함

  • Tensorflow는 산업에서 주로 쓰이다 보니 Production, Cloud, Multi-GPU에 유리하다
  • PyTorch는 디버깅이 좋다 보니까 논문을 쓰거나 아이디어를 구현할 때 주로 쓴다

Why PyTorch

  • Define by Run의 장점
  • 즉시 확인 가능 → pythonic code
  • GPU support, Good API and community
  • 사용하기 편한 장점이 가장 큼
  • TF는 production과 scalability의 장점

PyTorch

PyTorch = Numpy + AutoGrad + Function(DL)

  • Numpy 구조를 가지는 Tensor 객체로 array를 표현
  • 자동 미분을 지원하여 DL 연산을 지원
  • 다양한 형태의 DL을 지원하는 함수와 모델을 지원함

우리는 왜 PyTorch를 쓰는가? 디버깅도 편하고 TensorFlow에 비해 굉장히 자유롭다고 함


(02강) PyTorch Basics

Tensor

  • 다차원 Arrays를 표현하는 PyTorch 클래스
  • 사실상 numpy의 ndarray와 동일 (그러므로 TensoFlow의 Tensor와도 동일)
  • Tensor를 생성하는 함수도 거의 동일
# numpt - ndarray
import numpy as np
n_array = np.arange(10).reshape(2, 5)
print(n_array)
print("ndim :", n_array.ndim, "shape ", n_array.shape)
# [[0 1 2 3 4]
# [5 6 7 8 9]]
# ndim : 2 shape : (2, 5)

import torch
t_array = torch.FloatTensor(n_array)
print(t_array)
print("ndim :", t_array.ndim, "shape :", t_array.shape)
# tensor([[0., 1., 2., 3., 4.],
#        [5., 6., 7., 8., 9.]])
# ndim : 2 shape : torch.Size([2, 5])
  • Tensor 생성은 list나 ndarray를 사용 가능
    • 사실 DL을 하면서 이런 식으로 생성하여 쓰지는 않을 것 - 주로 모델 안에 있는 객체들로 사용하기 때문
# data to tensor
data= = [[3, 5], [10, 5]]
x_data = torch.tensor(data)
x_data
# tensor([[ 3,  5],
#        [10,  5]])

# ndarray to tensor
nd_array_ex = np.array(data)
tensor_array = torch.from_numpy(nd_array_ex)
tensor_array
# tensor([[ 3,  5],
#        [10,  5]])

Tensor data types

  • 기본적으로 tensor가 가질 수 있는 data 타입은 numpy와 동일

numpy like operations

  • 기본적으로 numpy의 대부분의 사용법이 그대로 적용됨
x_data = torch.tensor(data)
x_data[1:]
x_data[:2, 1:]
x_data.flatten()
# 이거는 생각보다 많이 씀 같은 크기로 맞춰준 뒤 연산을 위해
torch.ones_like(x_data)
x_data.numpy()
x_data.shape
x_data.dtype
  • Pytorch의 tensor는 GPU에 올려서 사용 가능
# device는 메모리(CPU)와 GPU가 있다. 어느 것을 사용할 지 보여줌
x_data.device
# device(type='cpu'), GPU면 cuda라고 나온다

# GPU를 쓸 수 있는가
if torch.cuda.is_available():
    x_data_cuda = x_data.to('cuda')
x_data_cuda.device
# device(type='cuda', index=0)
  • Tip. colab은 docker로 구성된 가상 컴퓨터이다. 그래서 생성이 되고 꺼지고 다시 생성되면 그동안의 resource가 다 reset 된다.

Tensor handling

view, squeeze, unsqueeze 등으로 tensor 조정 가능

  • view : reshape과 동일하게 tensor의 shape을 변환, 조금은 다르나 그냥 reshape 대신에 view를 사용한다 정도만 알면 충분, copy가 아니라 기존의 변수 메모리를 사용(pointer)
  • squeeze : 차원의 개수가 1인 차원을 삭제 (압축)
  • unsqueeze : 차원의 개수가 1인 차원을 추가
  • fill_(num) : matrix를 전부 num으로 채워줌

  • 첫 원소가 2x2x1이면 squeeze를 통해 줄여줌 → 2x2
    • unsqueeze 뒤의 숫자가 axis, tensor에선 dim으로 사용함
      • unsqueeze(0)이면 2x2 → 1x2x2
tensor_ex = torch.rand(size=(2, 1, 2))
tensor_ex.squeeze()
# tensor([[0.3959, 0.6981],
#           [0.1844, 0.4163]])

tensor_ex = torch.rand(size=(2, 2))
print(tensor_ex.squeeze())
tensor_ex.unsqueeze(0).shape
# tensor([[[0.2600, 0.0336],
#       [0.8644, 0.1424]]])
# torch.Size([1, 2, 2])

tensor_ex.unsqueeze(1).shape
# torch.Size([2, 1, 2])

tensor_ex.unsqueeze(2).shape
# torch.Size([2, 2, 1])

Tensor operations

  • 기본적인 tensor의 operations는 numpy와 동일
  • 크기가 맞지 않으면 덧셈(연산) 불가
  • 행렬 곱셈 연산 함수는 dot이 아닌 mm을 사용
    • scalar나 vector일 때는 dot 연산 가능, 반대로 mm은 행렬에서만 가능
n2 = np.arange(10).reshape(5,2)
t2 = torch.FloatTensor(n2)

t1.mm(t2) # matmul도 가능
# tensor([[ 60.,  70.],
#        [160., 195.]])
  • mm은 broadcasting을 지원 안 하지만, matmul은 broacasing 지원 처리
a = torch.rand(5,2, 3)
b = torch.rand(5)
a.mm(b)
# RuntimeError: self must be a matrix

# 2x3 형태를 띈 5개의 batch가 3x1 행렬과 곱해짐 -> 2x1 5개, 5x2x1
a = torch.rand(5, 2, 3)
b = torch.rand(3)
a.matmul(b)
# tensor([[0.9020, 0.1620],
#        [0.5199, 0.2280],
#        [0.3206, 0.7340],
#        [0.4918, 0.9251],
#        [0.7784, 0.5173]])

# 위의 연산은 아래와 같이 시행할 수 있다.
a[0].mm(torch.unsqueeze(b,1)).squeeze()
a[1].mm(torch.unsqueeze(b,1)).squeeze()
a[2].mm(torch.unsqueeze(b,1)).squeeze()
a[3].mm(torch.unsqueeze(b,1)).squeeze()
a[4].mm(torch.unsqueeze(b,1)).squeeze()

Tensor operations for ML/DL formula

  • nn.functional 모듈을 통해 다양한 수식 변환을 지원함
import torch
import torch.nn.functional as F

tensor = torch.FloatTensor([0.5, 0.7, 0.1])
h_tensor = F.softmax(tensor, dim=0)
h_tensor
# tensor([0.3458, 0.4224, 0.2318])

y = torch.randint(5, (10,5))
display(y)
y_label = y.argmax(dim=1)

y_label
# tensor([[2, 1, 3, 1, 3],
#         [0, 4, 4, 3, 3],
#         [0, 2, 2, 2, 4],
#         [2, 4, 0, 0, 0],
#         [2, 2, 2, 0, 4],
#         [4, 1, 0, 4, 1],
#         [3, 2, 4, 0, 1],
#         [2, 0, 2, 0, 4],
#         [4, 1, 0, 0, 0],
#         [0, 1, 4, 2, 1]])
# tensor([2, 1, 4, 1, 4, 0, 2, 4, 0, 2])

torch.nn.functional.one_hot(y_label)
# tensor([[0, 0, 1, 0, 0],
#        [0, 1, 0, 0, 0],
#        [0, 0, 0, 0, 1],
#        [0, 1, 0, 0, 0],
#        [0, 0, 0, 0, 1],
#        [1, 0, 0, 0, 0],
#        [0, 0, 1, 0, 0],
#        [0, 0, 0, 0, 1],
#        [1, 0, 0, 0, 0],
#        [0, 0, 1, 0, 0]])
import itertools
a = [1, 2, 3]
b = [4, 5]
list(itertools.product(a, b))
# [(1, 4), (1, 5), (2, 4), (2, 5), (3, 4), (3, 5)]

tensor_a = torch.tensor(a)
tensor_b = torch.tensor(b)
torch.cartesian_prod(tensor_a, tensor_b)
# tensor([[1, 4],
#        [1, 5],
#        [2, 4],
#        [2, 5],
#        [3, 4],
#        [3, 5]])

AutoGrad

  • PyTorch의 핵심은 자동 미분의 지원 → backward 함수 사용
    • 보통 미분의 대상이 되는 애들은 requires_grad=True로 설정해주나 이것도 잘하지 않을 것 → 우리는 주로 linear라는 함수나 그 외 함수를 쓰는데, 그것들은 이미 다 설정이 되어있음
w = torch.tensor(2.0, requires_grad = True)
y = w**2
z = 10*y + 25
z.backward()
w.grad
# tensor(40.)

$y=w^2$

$z=10*y+25$

$z=10*w^2+25$

이 z를 w에 대해서 미분하니까 $20w$, 거기에 w가 2니까 z=40, w의 gradient 값이 40

a = torch.tensor([2., 3.], requires_grad=True)
b = torch.tensor([6., 4.], requires_grad=True)
Q = 3*a**3 - b**2
external_grad = torch.tensor([1., 1.])
Q.backward(gradient=external_grad)

a.grad
# tensor([36., 81.])

b.grad
# tensor([-12.,  -8.])

$Q=3a^3-b^2$

$\frac{\partial Q}{\partial a}=9a^2, \frac{\partial Q}{\partial b}=-2b$

Tensor는 Numpy와 굉장히 흡사하다.


(03강) PyTorch 프로젝트 구조 이해하기

ML 코드는 언제나 Jupyter에서?

  • 영원히 세발자전거를 탈 수는 없다.

PyTorch Project Template Overview

  • 초기 단계에서는 대화식 개발 과정이 유리
    • 학습과정과 디버깅 등 지속적인 확인
  • 배포 및 공유 단계에서는 notebook 공유의 어려움
    • 쉬운 재현의 어려움, 실행 순서 꼬임
  • DL 코드도 하나의 프로그램
    • 개발 용이성 확보와 유지보수 향상 필요

코드도 레고 블록처럼, OOP + 모듈 → 프로젝트

작업 순서

https://github.com/victoresque/pytorch-template에서 git clone 받아서, anaconda prompt 이용해서 conda activate torch, cd ../pytorch-template, cd Myproject, code .을 이용해서 VS Code 띄워줌

  • Colab을 ssh로 Local에서 사용할 수도 있음
  • train.py 파일로 시작하니까 들어가 본다. 그중 main을 들어가 보면 config.json을 통해 설정해주는 걸 확인할 수 있음 → config.json 파일 탐색
  • 그다음 불러와서 namedtuple로 변환 후 ConfigParser 시켜준다. 그럼 parse_config의 ConfigParser 파일 탐색 → 팩토리 패턴 (재료를 넣어주면 Object(객체)를 생성해주는 패턴) → 팩토리 패턴을 사용해서 arg를 불러온 것을 해석을 한다.
  • 여기서 핵심은 config = read_json(cfg_fname)의 config이다. 그렇다면 read_json을 알아보자. → utils의 read_json을 본다. json을 읽어와서 Dict 타입으로 변환시켜 줌
    • 대부분 설정 정보는 이 config에 저장이 됨, 그걸 cls로 return 시켜주면 class로 return 객체가 생성이 되는 것
  • 그것을 이제 main(config)를 해줌으로써 main이 시작이 된다.

  • getitem 함수는 Test(items)를 해주면 item의 타입과 그 값을 출력해준다.
  • 실제 main에서도 class를 입력받았지만 getitem을 통해 config를 사용하게 되는 것
  • 모델을 바꿔주더라도 하드코딩을 하는 것이 아닌 config 파일만 고쳐줌으로써 편한 작업을 위해서 시행해줌

프로젝트 템플릿 보는 법, 만드는 법에 대해 간단히 배웠다. 아직까지 해보지 못한 작업이지만 이렇게 또 한발 나아가는구나


피어세션

  • 조현동 캠퍼님이 저번 수업 리뷰 해주심

Generative Model

Q1. 왜 $p(x_1, \cdots, x_n) = p(x_1)p(x_2|x_1)p(x_3|x_2)\cdots p(x_n|x_{n-1})$ 일 때, 2n-1 개의 파라미터가 되었는가?

A. p(x_1) =1 개고 그 이후의 값들은 표현하는데 2개의 변수가 필요하기 때문에 2n-1 개가 필요하다.

Q2. 왜 auto-regressive model에서 $x \in {0,1}^{784}$ 라고 표현했는가?

A. 각 픽셀의 값이 0과 1로 이루어져 있는 게 784개라고 생각

  • x는 (x1, x2,..., xn)으로 이루어진 벡터다

Q3. NADE에서 $where \ \ h_i = \sigma(W_{<i}x_{1:i-1} +c)$ 에서 c의 의미는?

A. bias 추가해준 것이라고 생각하면 되겠습니다.

한 주가 지나고 다시 들은 GAN 수업 리뷰는 정말 혼돈이었다. 많은 것이 기억나지 않는데 빠른 시간 내에 다시 들어야겠다.

  • 황원상 캠퍼님이 이번 수업 리뷰 해주심

PyTorch 1 ~3 회 수업

Q1. AutoGrad()가 동작하는 방식에 대해서 설명할 수 있는가?

A. 아래 블로그에 자세한 설명이 기술되어 있다.

  • 밑바닥부터 시작하는 딥러닝 1편 추천해주셨습니다.
 

오차 역전파 (backpropagation) · ratsgo's blog

이번 글에서는 오차 역전파법(backpropagation)에 대해 살펴보도록 하겠습니다. 이번 글은 미국 스탠포드대학의 CS231n 강의를 기본으로 하되, 고려대학교 데이터사이언스 연구실의 김해동 석사과정

ratsgo.github.io

Q2. 이미지 분류 대회 시 프로젝트 템플릿 사용?

A. 사용하자, 대신 최대한 작업을 나누어서 진행해야 코드 상의 충돌이 없다


프로그래머특강1

라이엇 게임즈_유석문 CTO

  • 오프라인이면 롤 스킨이라도 줄텐데 아쉽다 → 제가 더 아쉽습니다.
  • 왜 개발자가 되려고 하냐? 10에 9는 재밌어서 한다고 한다.
    • 화장실에서도 할 만큼 재밌는 일일 때 하자

개발자???

면접을 보는데 자바 3~5년 경력인데도 불구하고, Class Stack() {} 이렇게 기본도 못쓰곤 한다.

  • 왜 그럴까? 좋지 못한 기업을 가면 시간은 적게 주고 일을 시킴
    • 그렇게 되면 검색 → 복사 & 붙여 넣기 → 되는 것처럼 보일 때까지 작업

필수 능력

깔끔한 코드

이 능력 갖고 있으면 진짜 유리함

  • 사람이 이해하기 쉬운 코드
  • 변경이 용이한 코드
  • 유지보수 비용이 낮은 코드
  • "저는 코드를 지우는 사람입니다.", 인상 깊었던 한 분의 소개

적절한 논리력

  • 원리 탐색 능력
  • 제약조건을 고려한 해법
  • 단순한 디자인

깔끔한 코드 작성법

  • ATDD - Acceptance Test Driven Development (고객 입장에서 테스트한다)
  • TDD - Test Driven Development (내 코드가 기대대로 돌아가는지 자동화 테스트)

  • 사용하는 코드만 만들기 (Caller Create)
    • 만들었지만 나중에 필요 없어진 코드는 다 지워줘야 한다.
  • 리팩터링 (Refactoring)
    • 외부는 그대로 두고 내부 코드를 계속 살펴보는 것 (잘 읽히는지, 틀린 코드는 없는지)
  • 코드 읽기 (Code Review)
    • 소설 쓰기 위해서 여러 책 읽는 것처럼 다른 사람들의 코드를 읽어보자

적절한 논리력

  • 알고리즘과 데이터 구조 (Don`t Reinvent The Wheel)
  • 단순한 디자인 (Simple Desigh)
  • 진화적 디자인 (Evolutionary Design)
  • 협업 (Cooperative Design, Design Review)
  • 기술 벤치마킹 (Benchmarking)

실천법

  • 꾸준한 연습 (Daily Practice)
  • 매일 몸값 올리는 시간을 가져라
  • 멀리 가고 싶다면 함께 가라
  • 현재 필요한 만큼만 하라
  • 간단하게 하라

좋은 ㅇㅇ 개발자

  • 서버, 웹, 클라이언트, 임베디드, 모바일, 게임, AI,...
  • 좋은 - 공유, 협업

공유하는 매우 현실적인 이유

  • 주변이 똑똑해져야 내가 편함
    • 사고를 수습하는 일이 줄어듦
    • 중요한 일을 할 여유를 가질 수 있음
  • 좋은 평판을 얻을 수 있음
  • 주변의 덕을 볼 확률이 올라감

협업의 전제조건 : 상대를 이해하자

자아존중감

  • 자신이 존중받을 가치가 있다고 믿음
  • 있는 그대로의 자신을 인정함
  • 타인의 부정적 견해에 크게 영향받지 않음

 

협업, 공유, 깔끔한 코드, 적절한 논리력, 기본기를 다지자.

 

 

[AI Tech]Daily Report

Naver AI Tech BoostCamp 2기 캠퍼 허정훈 2021.08.03 - 2021.12.27 https://bit.ly/3oC70G9

www.notion.so