호기심 많은 분석가
[BoostCamp] Week3_Day11. PyTorch를 배워보자! 본문
굿모닝세션
비몽사몽한 정신으로 굿모닝세션과 함께 이번 주를 시작했다. 이미 학습 일정이 잘 나와있어서 그것을 따라 하기로!
- 수업은 학습 일정 따라서, 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
- unsqueeze 뒤의 숫자가 axis, tensor에선 dim으로 사용함
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 + 모듈 → 프로젝트
- 다양한 프로젝트 템플릿이 존재
- 사용자 필요에 따라 수정하여 사용
- 실행, 데이터, 모델, 설정, 로깅, 지표, 유틸리티 등 다양한 모듈들을 분리하여 프로젝트 템플릿화
- PyTorch Template 추천 repository
작업 순서
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편 추천해주셨습니다.
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,...
- 좋은 - 공유, 협업
공유하는 매우 현실적인 이유
- 주변이 똑똑해져야 내가 편함
- 사고를 수습하는 일이 줄어듦
- 중요한 일을 할 여유를 가질 수 있음
- 좋은 평판을 얻을 수 있음
- 주변의 덕을 볼 확률이 올라감
협업의 전제조건 : 상대를 이해하자
자아존중감
- 자신이 존중받을 가치가 있다고 믿음
- 있는 그대로의 자신을 인정함
- 타인의 부정적 견해에 크게 영향받지 않음
협업, 공유, 깔끔한 코드, 적절한 논리력, 기본기를 다지자.
'Coding > BoostCamp' 카테고리의 다른 글
[BoostCamp] Week3_Day13. 따뜻한 피드백 (0) | 2021.08.21 |
---|---|
[BoostCamp] Week3_Day12. 역대 최고의 교육자료, Custom Model (0) | 2021.08.21 |
[BoostCamp] Data_Viz_1. Line Plot & Scatter Plot (0) | 2021.08.17 |
[BoostCamp] Data_Viz_1. 시각화의 기본, Bar Plot (0) | 2021.08.15 |
[BoostCamp] Data_Viz_1. Data Visualization Introduction (0) | 2021.08.15 |