PyTorch의 다양한 함수들을 직접 과제에서 nn.Module
클래스를 활용한 Custom Model 정의하고, torch.utils.data
라이브러리 및 DataLoader
함수를 활용한 Custom Dataset을 정의하며, 적용해보며 성장한 한 주였다.
이전에는 TensorFlow가 좀 더 익숙하기도 했었고, 늘 클래스 단위로 구현하는 PyTorch를 사용해 직접 모델을 수정하며 구현할 줄 알고 싶었기에 과제가 어렵고 시간이 부족하기도 했었지만 너무 좋았다.
평소에 부족했던 Official Documentation을 보는 습관을 만들 수 있었고, 딥러닝 적용의 Flow를 익힐 수 있었다.
이번 주에는 팀원들과 피어세션 시간(4시~5시)가 아닌 시간에 줌을 켜놓고 질문/의논 시간 또는 모각공(모여서 각자 공부) 시간을 가졌는데 성공적이었다.
마스터클래스를 통해서는 빅데이터 과제에서 앞으로 가져야하는 자세/생각/접근 방향성 등을 배울 수 있었다. 개인적으로는 최근에 Web을 공부하고 있었는데 결국에는 사용자에게 접접에서 서비스를 제공할 수 있어야 된다는 생각이 들었고 이전 AI퀴즈 서비스 프로젝트를 진행하면서 많이 느끼기도 했기 때문에 시작했다. (+ BERT/ELECTRA를 써보며 모델은 잘 학습된 Pre-trained 모델이나 API화 되어있는 모델을 선택하면 현재 Domain Task에 더 대용량 데이터&파라미터 튜닝이 된 모델을 활용할 수 있을 것이란 생각도 있었다.) 그렇지만 문득 방향성에 대한 고민?이 들기도 했었는데 이러한 방향이 맞다는 생각을 가질 수 있었고 더욱 부스팅하자고 다짐할 수 있었다.
❓ torch.Tensor.scatter_() 함수와 torch.Tensor.scatter() 함수의 차이점 ?
❓ torch.gather() 함수의 존재 및 사용법 ?
❓ 3차원 텐서에서 dims 인자값으로 들어가는 0, 1, 2 축의 의미 & torch.swapdims() 함수의 사용법 ?
Pytorch의 Math operations (특히, Reduction Ops
연산자들 읽어보기)
"reduction"의 의미
: 함수들이 조건에 따라 tensor에서 특정 값만을 가져오거나, 연산을 통해서 크기를 줄이는 등 주어진 tensor의 크기를 줄여서
출력하기 때문
❓ 딥러닝 모델에서 Hook
(훅) 이란..? 훅의 의미는? ✨
torch.nn
관련 함수 공부하기
nn.Linear
함수
- 적용 예
import torch from torch import nn X = torch.Tensor([[1, 2], [3, 4]]) m = nn.Linear(2, 5) ## nn.Linear() : Applies a linear transformation to the incoming data: y = xA^T + by output = m(X) print(output) print(output.size())
- 출력 결과
tensor([[-0.7835, 1.1883, -0.5315, 0.1118, -0.2081], [-1.0765, 2.0393, -1.5225, 0.6674, -0.7737]], grad_fn=<AddmmBackward0>) torch.Size([2, 5])
❓ nn.Identity
를 사용하는 이유?
nn.Module
클래스 ✨
중첩 및 재사용 가능
nn.Module
이라는 상자에 기능들을 가득 모아놓은 경우 basic building blocknn.Module
이라는 상자에 basic building block인 nn.Module들을 가득 모아놓은 경우 딥러닝 모델nn.Module
이라는 상자에 딥러닝 모델인 nn.Module들을 가득 모아놓은 경우 더욱 큰 딥러닝 모델
function
/ layer
/ model
- 최소의 기능 단위인 function
- function들로 이루어진 layer
- layer로 이루어진 model
Pytorch에서 동적 계산 그래프
의 장점 ? ✨
동적 그래프의 주요 장점은 시퀀스 길이가 가변적인 순환 신경망에 있습니다. 정적 그래프는 이를 깔끔하게 처리할 수 없습니다. 가장 큰 시퀀스를 먼저 배치해야 하기 때문에 텍스트에 대해서는 작동하지 않는다는 점을 제외하고는 문장을 전환할 수 없으므로 가능한 가장 긴 문장을 위한 공간을 예약해야 합니다.
또 다른 장점은 autograd입니다. 사용자 지정 레이어를 생성할 때 동적 프레임워크는 모두 자동 미분 기능을 가지고 있으므로 역방향 패스를 작성할 필요가 없습니다. LSTM 또는 GRU의 역방향 패스를 작성하는 것은 매우 까다롭고 잘못되기 쉽습니다.
이제 모든 프레임워크에는 autograd가 있으므로 관련이 없습니다.
마지막이자 가장 큰 것은 동적 프레임워크를 사용하여 Python을 작성하고 Python과 같은 기능/제어 흐름을 작성한다는 것입니다. 일반적인 예는 다음과 같습니다.
for 루프를 사용할 수 있으므로 "스캔"을 강제로 사용할 필요가 없습니다(Python for 루프는 컴파일 타임에 알려져 있지 않기 때문입니다).
if/then/else와 같은 일반적인 제어 흐름을 사용하고 여전히 역전파할 수 있습니다.
torch.nn.parameter.Parameter(data=None, requires_grad=True)
Parameter
로서 보관 가능..!A kind of Tensor that is to be considered a module parameter. Parameters are Tensor subclasses, that have a very special property when used with Module s - when they’re assigned as Module attributes they are automatic.
주요 개념
gather
함수의 2D/3D 적용 ✨
- gather란, 주어진 텐서에서,
대각선 값
만 가져올 때 사용하는 함수..!대각 행렬
을 만들 수 있다.- List에서 인덱싱 하던 것처럼 한번에 여러 요소를 선택할 수 없다..!
- 따라서 원하는 요소의 갯수만큼 인덱싱을 만들어줘야 한다
- gather(input, k차원 방향으로 인덱싱하겠다, )
- k차원의 값이 2개면, input의 k차원에서, 2개의 값을 가져올 수 있음 (?)
- 직관적으로 생각하는 것이 도움됨
nn.Module
분석하기
깃허브 등 오픈소스로 모델을 가져와 사용할 때, pre-trained된 모델을 transfer-learning할 때 weight
값 등 변경하고 싶을 때 / 다른 사람이 작성한 모델의 코드를 이해할 때 등을 위한 문제들
(named_children
vs named_modules
/ get_submodule
/ Parameter
/ buffer
/ docstring
)
hook
모델에서 특정 조건을 만족하는 일부만 출력(디버깅) / 모델의 일부만 수정할 때 사용
apply
함수 ✨
이건 제가 설명드릴 수 있을 것 같아요! 공부를 열심히 했죠! 우리는 PyTorch의 nn.Module은 상자라는 것을 같이 배웠어요! 그래서 module은 module를 포함할 수 있고 다른 module 속에 들어갈 수도 있죠! 하나의 module에 다른 모든 module들이 담기면 우리는 이 거대한 module들의 집합을 모델이라고 부르죠! 모델은 수많은 module과 module들이 서로 복잡하게 얽혀있는 트리(Tree) 혹은 그래프(Graph)라고 볼 수 있어요! 모델에 무언가를 적용하면 단지 맨 꼭대기의 module 하나가 아니라 모델을 구성하는 전체 module에 모두 적용이 되어야 하고 nn.Module의 method들은 대부분 내부적으로 이를 지원해요! 예로 ".cpu()"를 맨 위 module에 적용하면 우리는 신경쓰지 않아도 module이 그 아래에 존재하는 모든 module에 ".cpu()"를 적용해요! 그러면 nn.Module에 이미 구현되어있는 method가 아닌 저희만의 custom 함수를 모델에 적용하고 싶다면 어떻게 하면 좋을까요? 모델에 속하는 모든 module에 일일이 함수를 적용해야할까요? 이때 사용하는게 바로 "apply"에요! 함수를 적용한다는 문구가 잘 와닿지 않으시죠? 함께 사용해봐요!
TORCH.UTILS.DATA
라이브러리Map-Style datasets
와, (2) Iterable-style datasets
이 있다.
Map-style datasets
A map-style dataset is one that implements the getitem() and len() protocols, and represents a map from (possibly non-integral) indices/keys to data samples.
For example, such a dataset, when accessed with dataset[idx], could read the idx-th image and its corresponding label from a folder on the disk.
See Dataset for more details.
Iterable-style datasets
An iterable-style dataset is an instance of a subclass of IterableDataset that implements the iter() protocol, and represents an iterable over data samples. This type of datasets is particularly suitable for cases where random reads are expensive or even improbable, and where the batch size depends on the fetched data.
For example, such a dataset, when called iter(dataset), could return a stream of data reading from a database, a remote server, or even logs generated in real time.
불균형 데이터셋
의 경우, 클래스의 비율에 맞게끔 데이터를 제공해야할 필요가 있음. 이럴 때 사용하는 옵션이 sampler..! ✨checkpoint
저장하기torch.save({ 'epoch': e, 'model_state_dict': model.state_dict(), 'optimizer_state_dict': optimizer.state_dict(), 'loss': epoch_loss, }, f"saved/checkpoint_model_{e}_{epoch_loss/len(dataloader)}_{epoch_acc/len(dataloader)}.pt") 모델의 정보를 epoch과 함께 저장 checkpoint = torch.load(PATH) model.load_state_dict(checkpoint['model_state_dict']) optimizer.load_state_dict(checkpoint['optimizer_state_dict']) epoch = checkpoint['epoch'] loss = checkpoint['loss']
Source Tasks과 Target Tasks에 정답(Label)의 유무에 따라 다양한 Transfer Learning 방법론 존재
(실습 과제는 Source Tasks와 Target Tasks에 모두 정답이 있는 상황에서의 Fine-Tuning
)
❓ 어떤 종류의 방법론들이 있을까?
PyTorch에서 모델 Weight
/Bias
초기화하는 방법
초기화 방법 2가지
- [1]
nn.sequential
함수 사용하기
- [2]
torch.nn.Module.apply
함수 사용하기
- Custom Model에서 초기화 함수를 선언하여,
torch.nn.Module.apply
를 사용해 전달해주어 사용- 이는
nn.Module
에 재귀적으로 전체 가중치를 초기화한다..! ✨
- 데이터 전처리
- 데이터 불러오는 함수 생성
- 신경망 구성
- 오차 함수 및 최적화 기법 선택하기
- 학습 및 추론 설정
- 학습 및 추론 실행
torch.utils.data.DataLoader
내 다양한 함수들
sampler()
함수 설정 ✨
불균형한 데이터셋
에서도 많이 쓰임...! (예: 암 환자 데이터)shuffle()
은 단순히 섞는 설정 함수이지만, sampler()
는 섞으면서 더 세밀한 설정이 함께 가능한 함수..! ✨collate_fn
함수 ✨
가변적인 데이터
의 경우 사용 - zero-padding
관련됨. (같은 size
로 맞춰줘야 모델이 학습할 수 있기 때문에)collate_fn
을 사용해서, 길이
를 맞춰줄 필요가 있기 때문)drop_last
옵션
drop_last
설정 넣어주어서 미연에 방지 가능
batch 단위로 데이터를 불러온다면, batch_size에 따라 마지막 batch의 길이가 달라질 수 있습니다. 예를 들어 data의 개수는 27개인데, batch_size가 5라면 마지막 batch의 크기는 2가 되겠죠.
batch의 길이가 다른 경우에 따라 loss를 구하기 귀찮은 경우가 생기고, batch의 크기에 따른 의존도 높은 함수를 사용할 때 걱정이 되는 경우 마지막 batch를 사용하지 않을 수 있습니다.
(https://subinium.github.io/pytorch-dataloader/)
- drop_last 인자의 경우, 배치 크기를 채우지 못한 마지막 불완전 배치를 사용할 것인지, 사용하지 않을 것인지를 결정하는 Boolean 인자