Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Auto-Encoding Variational Bayes
- 포지셔널 인코딩
- VAE
- 어텐션
- Transformer model
- 셀프 어텐션
- 네이버 부스트캠프 AI Tech
- 네이버 부스트캠프 코딩테스트 후기
- 네이버 부스트캠프 AI Tech 6기
- self-attention
- Positional Encoding
- boostcamp
- VAE 논문 리뷰 #
- 네이버 부스트캠프
- AI Math
- VAE 설명
- 네이버 ai 부스트캠프
- 트랜스포머 모델
- Transformer Decoder
- Transformer 디코더
- 트랜스포머 행렬
- 어텐션 행렬
- 주간학습정리
- 트랜스포머
- Transformer 모델
- seq2seq
- pytorch
- transformer
- 부스트캠프
- 네이버 부스트캠프 KDT 전형
Archives
- Today
- Total
DH. AI
[Boost Camp AI Tech] Week2 본문
Notion에 정리한 내용중 새로 알게된 내용과 중요하다고 생각되는 내용을 다시 정리하며 복습하기 위해서 쓰는 글.
Pytorch에 대해서 전반적으로 다룸.
1. Pytorch 기본
- Pytorch는 역전파할때, Graph그릴때 실행시점에서 동시에 그림!! Dynamic Computation Graph 연산과정을 그래프로 그린것 → Computation Graph
- Tensor - 다차원 Arrays 를 표현하는 Pytorch의 클래스. 사실상 numpy의 ndarray와 동일하다. Tensor를 생성하는 함수도 거의 동일. → GPU를 사용할 수 있냐 없냐가 차이가 있음 ex : torch.cuda.FloatTensor
- Pytorch의 tensor는 GPU에 올려서 사용가능!!
if torch.cuda.is_available():
# GPU사용가능하면 해당 데이터를 cuda로 할당해라
x_data_cuda = x_data.to('cuda')
x_data_cuda.device
- view(텐서 차원 변경은 numpy의 reshape 대신 view를쓰자) reshape은 구조가 변경되면 메모리를 새로잡음.
a = torch.zeros(3, 2)
b = a.view(2, 3)
a.fill_(1)
# view는 같은 메모리 주소를 가지게 하고 표현하는 형태만 바꿔줌
# 따라서 b의 값도 1로 바꿔져 있음.
- squeeze : 차원의 개수가 1인 차원을 삭제, unsqueeze : 차원의 개수가 1인 차원을 추가.
- Tensor에서 행렬 곱셈은 numpy의 dot이 아닌 mm(matmul)을 쓴다. 벡터곱은 mm안되고 dot으로
- mm은 boradcasting 지원 x, matmul은 boradcasting 지원 O
a = torch.rand(5,2, 3)
b = torch.rand(3)
a.matmul(b)
# 5는 보통 배치를 의미함 5,2,3 matmul 3 하면 5, 2이 나온다!
nn.functional
- nn.functional 모듈을 통해서 다양한 수식 변환을 지원한다. -> 그때그때 찾아보자! ex : nn.functional.softmax(tensor, dim = 0)
AutoGrad
- Pytorch의 핵심은 자동 미분 지원 → backward 함수 사용
w = torch.tensor(2.0, requires_grad=True) # 미분이 되는 대상 : requires_grad=True 지정
# 보통 Linear와 같은 함수를 쓰는데, requires_grad 가 전부 True로 되어있음!!
y = w**2
z = 10*y + 50
z.backward()
w.grad
- 위의 requires_grad 인자 값은 fine tuning 시에 backbone의 네트워크를 freeze 시켜줄때 False로 두고 사용할 수도 있다.
- 그게 귀찮다면 optimizer의 파라미터의 뒤에 붙는 fc의 파라미터만 넣어서 학습 시킬 수도 있다!
Pytorch 프로젝트 구조 이해하기
- 개발 초기 단계에서는 대화식(주피터, 코랩) 개발과정이 유리 → 학습과정과 디버깅 등 지속적인 확인
- 배포 및 공유 단계에서는 notebook 공유의 어려움. → 쉬운 재현의 어려움, 실행순서 꼬임.
- DL 코드도 하나의 프로그램 → 개발 용이성 확보와 유지보수 향상 필요
- 실행, 데이터, 모델, 설정, 로깅, 지표, 유틸리티 등 다양한 모듈들을 분리하여 프로젝트 템플릿화.
Pytorch-template : config 파일만 변경해주면서 프로젝트를 진행가능. 학부연구생 할때 mmdetection을 조금이나마 만져봤어서 꽤 익숙했음. 코드 하나하나 주석을 달며 공부 했지만 다시 이해가 필요할듯. 시간날때마다 강의 다시 들으면서 공부하기!
2. Pytorch 구조 학습하기
torch.nn.Module
- Transformer나 ResNet같은 모델을 보면 레이어(블록) 반복의 연속이다. 이런 모델을 구현하기 위해 torch.nnModule을 사용한다.
- torch.nn.Module : 딥러닝을 구성하는 Layer의 base class로써 일반적으로 나의 모델을 class로 정의하고 nn.Module을 상속받아서 사용한다.
- 기본적으로 네가지 정의 Input, Output, Forward, Backward(weight값) 정의
- 학습의 대상이 되는 weights를 parameter(tensor) 클래스로 정의.
- super().__init__() 으로 nn.Module의 생성자를 호출하는것.
super()로 기반 클래스(부모 클래스)를 초기화해줌으로써, 기반 클래스의 속성을 subclass가 받아오도록 한다.
parameter, modules 등의 네트워크 학습에 있어서 중요한 특성을 포함하는 속성(attribute)들을 가져옴. forward도! - forward() 함수는 model 객체를 데이터와 함께 호출하면 자동으로 실행이됩니다.
nn.Parameter (클래스)
- Tensor 객체의 상속 객체
- nn.Module 내에 attribute(속성)가 될 때는 required_grad = True로 자동으로 지정되어 AutoGrad 학습 대상이 되는 Tensor들!
- 우리가 직접 지정할 일은 잘 없다 -> torch.nn.Linear와 같은 함수 내부에 weight는 모두 nn.Parameter로 지정 되어 있어서 실제로는 다룰 일이 많이 없지만 알고 있자!
Backward
- Layer에 있는 Parameter들의 미분을 수행 (자동 미분으로 연산)
- epoch 돌아가면서 Forward의 결과값 (model의 ouput=예측치)과 실제값 간의 차이(loss)에 대해 미분을 수행.
- 해당 값을 이용하여 Parameter 업데이트. optimizer.zero_grad(), loss.backward(), optimizer.step()을 사용
- 실제 backward는 Module 단계에서 직접 지정도 가능하긴 해;;
- Module에서 backward와 optimizer오버라이딩
- 사용자가 직접 미분 수식을 써야하는 부담.. 쓸일은 없으나 순서는 이해할 필요 있음
Dataset
- 데이터의 입력 형태를 정의하는 클래스. 데이터를 입력하는 방식의 표준화! 데이터 형태에 따라 (Image, Text, Audio) 등에 따른 다른 입력정의.
- 모든것을 데이터 생성 시점(init)에서 처리할 필요는 없다.
- 예를 들어 Image를 Tensor객체로 변환하는 과정은 Dataset으로 데이터를 변환하면서 바로 수행할 수도(성민석 조교님은 그냥 이렇게 하시라고 하심!! 별 상관 없는 듯) 있지만, 모델에 먹이기 직전에 바꾸는 경우도 많다. -> Dataloader에서 데이터를 던져줄때!
- 모델에 먹이기 직전에 바꾸는것 -> image의 Tensor 변화는 학습에 필요한 시점에 변환 getitem시에 변환된 Tensor를 반환해주는 것이 아니라, CPU에서는 tensor로 바꾸고 GPU로 넘겨주면 GPU는 학습을 한다. -> Dataloader에서 함
- __init__() : Dataset 객체를 생성할때 데이터를 어떻게 불러올껀지 img같은 경우 data directory를 정의하던가 함..
- __ len__() : 데이터의 전체 길이
- __getitem__() : map-style !! 하나의 데이터를 가져올때 어떻게 반환을 해줄건지 보통 index같은 것을 사용함.
Transform
- transforms : 데이터 전처리 하거나 데이터 agumentation할때 데이터를 조금씩 변형 해주거나.. 가능 (텐서로 바꿔주기도 가능 → ToTensor() : 0~1사이로 normalization해줌)
- 데이터 셋을 전처리 하는 부분과, 데이터셋을 텐서(숫자)로 바꾸는 부분은 구분이 된다. → Transform에서 한다. Dataset은 하나의 이미지를 넘겨주는 역할
Dataloader
- Dataset은 하나하나를 어떻게 처리할지를 정의했으면, Dataloader는 데이터를 묶어서 모델에 feeding(먹여주는) 해주는 역할 (batch, shuffle,,,) 가능
- Data의 Batch를 생성해주는 클래스 학습직전(GPU feed전) 데이터의 변환을 책임.
- Tensor로 변환 + Batch 처리가 메인 업무 병렬적인 데이터 전처리 코드의 고민 필요.
- epoch가 한번 돌아가는 것은 dataloader가 한번 돌아가는 것.
- batch_size에 따라서 마지막에 남는 데이터들을 버리던지 쓰던지 정해줄수 있음. shuffle도 정해줄 수 있다.
- 파라미터 collate_fn : 텍스트 데이터 다루다보면 0으로 패딩을 해줘야하는 경우가 있는데 배치 크기에 맞게 해줌
- sampler는 데이터를 어떻게 뽑을지 index를 정해주는 기법입니다.
- 프로젝트 폴더의 data_loader.py를 보면 dataloader안에 transform을 해줌
모델 불러오기
model.save()
- 학습의 결과를 저장하기 위한 함수.
- 모델 형태, 파라미터만도 저장 가능.
- 모델 학습 중간 과정의 저장을 통해 최선의 결과모델을 선택.
- 만들어진 모델을 외부 연구자와 공유하여 학습 재연성 향상.
- 모델을 저장할때 pt나 pth를 사용한다. 보통 pt를 씀.
- torch.save(model.state_dict()) : 모델의 파라미터를 저장(Ordereddict type으로 저장)
- model.load_state_dict() 같은 모델(architecture)의 형태에서는 파라미터만 load하는방식!!
- torch.save(model), model torch.load() : 모델의 architecture(코드로)와 함께 저장 python pickle형식
checkpoints
- 학습의 중간 결과를 저장하여 최선의 결과를 선택!!
- earlystopping 기법 사용시 이전 학습의 결과물을 저장
- loss와 metric 값을 지속적으로 확인 저장
- 일반적으로 epoch, loss, metric을 함께 저장하여 확인
- colab에서 지속적인 학습을 위해 필요
Pretrained model Transfer learning
- 다른 데이터셋으로 만든 모델을 현재 데이터에 적용
- 일반적으로 대용량 데이터셋으로 만들어진 모델의 성능 상승!!!
- 현재의 DL에서는 가장 일반적인 학습 기법!
- backbone architecture가 학습된 모델에서 일부분(fc)만 변경하여 학습을 수행함.
- 불러올때는 TorchVision(다양한 기본 모델 제공)을 이용해서 불러올 수 있다.
- NLP에서는 HuggingFace가 사실상 표준이다!
- pretrained model을 활용 시 모델의 일부분을 frozen 시키고 나머지만 커스텀 데이터로 학습시킴!! -> fine tuing 방법은 가지고 있는 데이터 셋 크기, pretrained model 학습 데이터와 내가 가지고 있는 데이터 셋의 유사성, 에 따라 여러가지로 나뉜다.
- pretrained model을 가져오는 것은 간단히 Trochvision의 models에서 가져와서 쓰면 된다. ImageNet은 1000개의 이미지를 맞춤!! 보통은 pretrained model을 가져와서 내 모델을 만들고 내 모델의 끝에 추가 Linear layer를 만들어준다. → Linear(1000,1)
- for param in my_model.parameters() : param.requires_grad = False,
for param in my_model.linear_layers.parameters() : param.requires_grad = True → 마지막 레이어를 제외하고 Frozen!
Monitoring tools for PyTorch -> 대회 진행하면서부터 자세히 공부하고 다뤄볼 생각!
Tensorboard
- TensorFlow의 프로젝트로 만들어진 시각화 도구!
- 학습 그래프, metric, 학습 결과의 시각화 지원
- PyTorch도 연결 가능 → DL 시각화 핵심(기본) 도구. 거의 모든 딥러닝 FrameWork들은 Tensorboard와 연결할 수 있는 방법을 찾고있다.
- 세부적인 코드에 대한 설명은 Colab에 있음.
Weight & biases (wandb)
- 딥러닝 뿐만아니라 머신러닝 실험을 원할히 지원하기 위한 상용도구 → mlops 도구중에 하나로 생각된다.
- 협업, code versioning, 실험 결과 기록 등 제공 (W and B) → code, model, data 등 부분을 나눠서 git처럼 사용 가능, metric 보드 사용해서 그때그때 모델에 점수를 올릴 수있음
- MLOps의 대표적인 툴로 저변 확대 중
- → 텐서보드도 좋지만 WandB는 프로젝트 별로 접근을 하기 때문에 공유를 하거나 다른 사람에게 프로젝트 형태로 실험을 공유할때 편하다.
- 세부적인 코드에 대한 설명은 Colab에 있음.
3. PyTorch 활용하기
Multi - GPU 학습
- 데이터가 굉장히 많고 모델도 커져서 이제는 하나의 GPU 만으로는 학습이 매우 오래걸림.. -> Multi GPU를 사용하자!
- Single Node에 Multi GPU가 설치되어있다.
- Multi GPU에 학습을 분산하는 두가지 방법
- 모델을 나누기 Model parallel
- 데이터를 나누기 Data parallel
- 모델을 나누는 것은 생각보다 예전부터 써왔음(AlexNet)
- 모델의 병목, 파이프라인의 어려움 등으로 인해 모델 병렬화는 고난이도 과제. - 배치처리를 잘해줘야 해 모델 병렬화로 성능을 올리는 연구 분야로 자리잡음! → 흔하게 많이 쓰진 않음
Data parallel
- 데이터를 50만, 50만으로 나눠서 각각 돌림.
- 각각의 GPU에서 나오는 Loss 값을 미분 해줘서 그 각각의 미분값의 평균을 가지고 전체 미분값을 구해줌!
- 데이터를 나눠 GPU에 할당후 결과의 평균을 취함. minibatch 수식과 유사한데, 한번에 여러 GPU에서 수행.
- Forward
- GPU가 여러 GPU들에게 데이터를 쪼개준다.
- 모델들을 각각의 GPU들에게 replicate 시켜준다.
- forward 연산을 실행.
- 결과값을 한번에 모음. - Global interpreter lock이라는 Python의 Multi processing 제약 때문에!
- Backward
- 각각 4개의 loss gradient를 구해준다.
- gradient를 각각의 GPU에 뿌려준다.
- 각각의 GPU가 Backward 과정을 거친다. 모든 weight에 대해서 gradient 구함
- 최종적으로 gradient를 하나의 GPU에 뿌려주게된다. → 하나의 GPU가 모인 weight gradient로 평균을 내서 gradient를 업데이트 함
- PyTorch에서는 두가지 방식을 제공함
- DataParallel : 단순히 데이터를 분배한 후 평균을 취함 → GPU 사용 불균형 문제 발생, Batch 사이즈 감소(한 GPU가 많은 일을 하기 때문에 이 GPU에 맞춰서), GLI ( Global interpreter lock )
parallel_model = torch.nn.DataParallel(model) → 모델 학습 직전에 이 코드만 써주면 된다. - DistributedDataParallel : 각 CPU 마다 process 생서하여 개별 GPU 에 할당 → 하나로 모으는 작업이 없음!! 각각이 forward, backward 하고 gradient 구해서 gradient가지고 개별적으로 연산해서 평균 냄.
가능한 이유 : 각각이 GPU도 있지만 CPU도 할당을 해주기 때문!!! - DistributedDataParallel은 사용이 좀 더 복잡하다.
sampler를 사용 → sampler는 데이터를 어떻게 뽑을지 index를 정해주는 기법입니다. sampler를 정의해서 데이터로더에 넣어줘야함.
pin_memory = True로 해야함 -> DRAM(메모리)에 데이터를 바로바로 올릴 수 있도록 절차를 간소하게 데이터를 저장하는 방식.
num_workers (데이터를 불러올때 사용하는 서브 프로세스(subprocess) 개수 = CPU의 코어 개수)는 보통 GPU X 4개 - aws나 gcp, 네이버 클라우드 등을 이용해서 언젠간 multi gpu를 사용해보자..!
Hyperparameter Tuning
- Hyperparameter : 학습할때 사람이 지정해주는 여러가지 파라미터!
성능이 낮을때 크게 세가지 방법
- 모델 변경 → 이미 모델들이 잘 나와있어서 성능의 key 요인은 아니다
- 새로운 데이터 추가 or 기존 데이터 변경 : 성능에 가장 중요하다!! 데이터를 많이 모을수록 성능 높아짐!!
- 하이퍼파라미터 튜닝 → 생각보다 크지 않다… 마른 수건도 한번짜보자 하는 마인드로 하는것
- 가장 기본적인 방법은 grid search VS random search
- 최근에는 베이지안 기반 기법들이 주도!!!!
Ray : 가장 대표적인 하이퍼 파라미터 튜닝 도구
- 세부적인 코드에 대한 설명은 Colab에 있음.
- 대회할때 마지막으로 성능을 쥐어짜보고 싶을때 한번 써보자!
Pytorch Troubleshooting 은 그때 그때 찾아보자..!
과제1 내용 간단 정리
torch.gather()
- 대각선 요소만 가져올때 편한 함수! gather( input, dim, index )
import torch
A = torch.Tensor([[[1, 2],
[3, 4]],
[[5, 6],
[7, 8]]])
index=torch.arange(2).expand(2,2).reshape(2,1,2) # expand 할때에는는 마지막 axis의 차원이 같이야함
# print(f'index', index)
output = torch.gather(A, 1, torch.tensor( [[[0, 1]], [[0, 1]]]))
# out[i][j][k] = input[i][index[i][j][k]][k]
# print(A[0][0][0], A[0][1][1], A[1][0][0], A[1][1][1])
# out[0][0][0] = A[0][index[0][0][0]][0]
# out[0][0][1] = A[0][index[0][0][1]][1]
# out[1][0][0] = A[1][index[1][0][0]][0]
# out[1][0][1] = A[1][index[1][0][1]][1]
output = output.view(2,2)
print(output)
>>> tensor([[1., 4.],
[5., 8.]])
buffer
- Parameter : 역전파시 grad계산, 모델 저장시 저장.
- Tensor : 역전파시 grad를 게산하지 않아서 업데이트 되지않고, 모델 저장 시에도 무시된다.
- buffer : 역전파시 grad계산 X, 모델 저장시 저장. -> BatchNorm에서 사용된다고 한다..
apply
- apply : 모델에 속하는 모든 module에 일일이 함수를 적용 해준다.
- model.apply(weight_initialization) 과 같이 초기화도 가능하고, 모듈의 출력할때의 형식도 수정 가능하다.
hook
- 프로그램의 실행 로직을 분석하거나, 프로그램에 추가적인 기능을 제공하고 싶을 때 사용 가능!
- pytorch의 hook은 두가지로 나뉜다. tensor에 적용, module에 적용.
- forward전, forward후 -> tensor에만 적용
- full_backward -> tensor, module 모두 적용 가능
Pytorch를 사용하고는 있었지만 완벽하게 알지는 못했다. 이번 주차에 좋고 많은 강의들과 과제를 통해서 Pytorch와 친해질 수 있어서 좋았다! 특히 gather, buffer, apply, hook,등의 새로운 개념들을 알게 되어서 좋았다.
'[Boost Camp AI Tech]' 카테고리의 다른 글
[Boost Camp AI Tech] Week4 (0) | 2023.04.30 |
---|---|
[Boost Camp AI Tech] Week3 (0) | 2023.04.29 |
[Boost Camp AI Tech] Week1 (4) | 2023.03.20 |
[Review] 네이버 부스트 캠프 AI Tech 5기 합격 후기 (0) | 2023.02.14 |