일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- BoostCamp
- Conversation System
- scaled dot-product attention
- FSML
- huggingface
- Dialogue System
- fine-tuning
- beam search
- Chatbot
- Transformer
- KLUE
- pytorch
- 취업
- Relation Extraction
- NLP
- Prompt Tuning with Rules for Text Classification
- 백준
- Transformers
- ai-tech
- boj
- KLUE-RE
- bert
- multi-head attention
- MT-DNN
- GPT-1
- BELU
- Eliza
- BLEU Score
- text classification
- layer normalization
- Today
- Total
dukim's blog
[WK03-Day013][21.08.19.Thu] PyTorch Project Template 뜯어보기, Transfer Learning & Hyper Parameter Search 본문
[WK03-Day013][21.08.19.Thu] PyTorch Project Template 뜯어보기, Transfer Learning & Hyper Parameter Search
eliza.dukim 2021. 8. 20. 02:00Intro
- 오늘 피어세션 발표차례라 발표 내용 준비하면서 강의 때 소개되었던 프로젝트 템플릿을 CIFAR10 Tutorial code에 맞게 수정해보았다.
- CV 분야의 transfer learning 방법 및 Hyperparameter Search 도구인 Ray Tune을 선택과제로 학습하였다.
강의 내용 복습
PyTorch 프로젝트 구조 이해
- victoresque/pytorch-template를 뜯어 구조를 살펴보면서 새롭게 알게된 내용 정리
Tip: import 순서
- python 내장 모듈 or 라이브러리 -> 오픈소스 -> 사용자정의 모듈 순으로
조각코드: random seed 고정
SEED = 123
torch.manual_seed(SEED)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
np.random.seed(SEED)
getattr
의 사용
getattr
을 지금까지 클래스 객체에 대해서 attribute 접근하는 함수로만 알고 있었다.template 코드에서는
.py
로 정의된 모듈 파일이 포함하고 있는 클래스나 함수를 선택할 때 사용 가능하다. 특히 factory pattern을 만들때 유용하게 사용된다. 예를 들어 아래와 같은 directory로 구성되어 있고pytorch-template/ │ ├── train.py - main script to start training │ ├── model/ - models, losses, and metrics │ ├── model.py │ ├── metric.py │ └── loss.py │...
model.loss.py
가 다음과 같이 작성되어 있을 때import torch.nn.functional as F def nll_loss(output, target): return F.nll_loss(output, target)
trian.py
내부에서 model.loss의 nll_loss 함수 객체에 접근해 변수에 할당하거나... import model.loss as module_loss ... criterion = getattr(module_loss, 'nll_loss')
다음처럼 특정 라이브러리의 모듈내에서 원하는 클래스에 접근해 원하는 인스턴스를 만드는데 사용된다.
import torch def get_optimizer_by_lr(model, optm_name:str, lr:float): return getattr(torch.optim, optm_name)(model.parameters(), lr=lr)
pathlib
: 경로관리를 편리하게하는 built-in module
템플릿 코드를 보다보면 string type끼리
/
로 나누는 이상한 코드가 보이는데, 이건pathlib.Path
객체와 string type 객체 간의 연산으로, 경로 구분자(/
)로 합쳐진pathlib.Path
객체를 리턴하는 것.# template code # set save_dir where trained model and log will be saved. save_dir = Path(self.config['trainer']['save_dir']) exper_name = self.config['name'] if run_id is None: # use timestamp as default run-id run_id = datetime.now().strftime(r'%m%d_%H%M%S') self._save_dir = save_dir / 'models' / exper_name / run_id self._log_dir = save_dir / 'log' / exper_name / run_id
# Example usage of pathlib.Path from pathlib import Path base_dir = Path('data/') print(base_dir / 'exp01' / 'log')
collections.namedtuple
- tuple 형태로 Data 구조체 저장
- 저장되는 Data의 variable을 사전에 지정해 저장
# template code ... from collections import namedtuple ... # 구조체의 이름: 'CustomArgs' CustomArgs = collections.namedtuple('CustomArgs', 'flags type target') custom_arg1 = CustomArgs(['--lr', '--learning_rate'], type=float, target='optimizer;args;lr') custom_arg2 = CustomArgs(['--bs', '--batch_size'], type=int, target='data_loader;args;batch_size') options = [custom_arg1, custom_arg2]
과제 수행 / 결과물
Transfer Learning & Hyperparameter Search(Ray Tune)
ImageNet Pretrained Modeld을 torchvision에서 불러오기(PyTorch Hub)
import torchvision
import torch
import np
imagenet_resnet18 = torchvision.models.resnet18(pretrained=True)
불러온 모델을 현재 데이터에 맞게 수정하기
- input 수정(1 channel gray scale -> 3 channels RGB)에는 2가지 선택지가 있다
- 모델의 input_layer를 수정하거나
- 입력 데이터를 transform하거나
# 0. check model input, output shape
print("# of input channels", mnist_resnet18.conv1.weight.shape[1])
print("# of labels", mnist_resnet18.fc.weight.shape[0])
# 1. 모델의 input_layer를 수정
mnist_input_num = 1
mnist_label_num = 10
mnist_resnet18.conv1 = torch.nn.Conv2d(mnist_input_num, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
mnist_resnet18.fc = torch.nn.Linear(in_features=512, out_features=mnist_label_num, bias=True)
# weight initialization
torch.nn.init.xavier_uniform_(target_model.conv1.weight)
torch.nn.init.xavier_uniform_(target_model.fc.weight)
stdv = 1/np.sqrt(FASHION_CLASS_NUM)
target_model.fc.bias.data.uniform_(-stdv, stdv)
# 2. 입력 데이터를 Transform(1 channel grayscale -> 3 channel grayscale)
common_transform = torchvision.transforms.Compose(
[
torchvision.transforms.Grayscale(num_output_channels=3), # grayscale의 1채널 영상을 3채널로 동일한 값으로 확장함
torchvision.transforms.ToTensor() # PIL Image를 Tensor type로 변경함
]
)
tqdm에서 progress bar에 정보 표시하기(ipython notebook)
from tqdm.notebook import tqdm
for epoch in range(n_epoch):
with tqdm(dataloaders) as pbar:
for ind, (data, labels) in enmerate(pbar):
data = data.to(device)
labels = labels.to(device)
...
cur_loss = loss.item() / data.size(0)
cur_acc = torch.sum(preds == labels.data) / data.size(0)
pbar.set_description(f'Epoch : {epoch} / Step : {i} / Loss : {cur_loss:.4f} / Acc : {cur_acc:.4f}')
Ray Tune을 이용한 Hyper Parameter Tuning
코드 작성 전에 결정할 내용
- 최대/최소화 해야할 대상이 되는 값(e.g. Accuracy)이 무엇인지
- 어떤 hyper parameter(e.g. epoch, batch size)를 최적화할 것인지를 정하고 Search Space를 설정
Ray Tune 설치
$pip uninstall -y -q pyarrow
$pip install -q -U ray[tune]
$pip install -q ray[debug]
training setup:
매 실험을 돌릴 때마다 초기화해줘야하므로 함수에서 출력하는 형태로 작성
... import numpy as np import torch from torch.utils.data import Subset, DataLoader import torchvision as tv from sklearn.model_selection import train_test_split # helper function : Stratified Random Split def _balanced_val_split(dataset, val_split=0.2): targets = np.array(dataset.targets) train_idxs, val_idxs = train_test_split( np.arange(targets.shape[0]), test_size=val_split, stratify=targets ) train_dataset = Subset(dataset, indices=train_idxs) val_dataset = Subset(dataset, indices=val_idxs) return train_dataset, val_dataset # set up function & datasets def get_pretrained_model(model_name:str): model = getattr(tv.models, model_name)(pretrained=True) FASHION_INPUT_NUM = 1 FASHION_CLASS_NUM = 10 model.conv1 = torch.nn.Conv2d(FASHION_INPUT_NUM, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False) model.fc = torch.nn.Linear(in_features=512, out_features=FASHION_CLASS_NUM, bias=True) torch.nn.init.xavier_uniform_(model.conv1.weight) torch.nn.init.xavier_uniform_(model.fc.weight) stdv = 1/np.sqrt(FASHION_CLASS_NUM) model.fc.bias.data.uniform_(-stdv, stdv) return model def get_optimizer_by_lr(model, optm_name:str, lr:float): return getattr(torch.optim, optm_name)(model.parameters(), lr=lr) def get_epch_by_epch(epch:int): return epch basic_transform = tv.transform.Compose([tv.transforms.ToTensor()]) train_transformed = tv.datasets.MNIST(root='./fashion', train=True, download=True, transform=basic_transform) train_transformed, val_transformed = _balanced_val_split(train_transformed) def get_dataloaders_by_bs(bs:int): batch_size= bs train_dataloader = DataLoader(train_transformed, batch_size=batch_size, shuffle=True, num_workers=2) val_dataloader = DataLoader(val_transformed, batch_size=batch_size, shuffle=False, num_workers=2) dataloaders = { "train" : train_dataloader, "val" : val_dataloader } return dataloaders
Search space 설정
from ray import tune
config_space = {
"n_epoch" : tune.choice([7,8,9]),
"learning_rate" : tune.uniform(1e-5, 1e-4),
"batch_size" : tune.choice([32,64,128]),
}
training
function 설정
def training(config):
# controlled variables: model architecture, non-freeze, loss function
model = get_pretrained_model('resnet18') # fix architecture set up
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)
criterion = torch.nn.CrossEntropyLoss()
# manipulated variables: n_epoch, learning_rate, batch_size
n_epoch = config["n_epoch"]
optimizer = get_optimizer_by_lr(model, config["learning_rate"])
dataloaders = get_dataloaders_by_bs(config["batch_size"])
# training
best_test_accuracy = 0.
best_test_loss = 0.
for epoch in range(n_epoch):
for phase in ["train", "test"]:
running_loss = 0.
running_acc = 0.
if phase == "train":model.train()
elif phase == "test":model.eval()
for ind, (images, labels) in enumerate(tqdm(dataloaders[phase])):
images = images.to(device)
labels = labels.to(device)
optimizer.zero_grad()
with torch.set_grad_enabled(phase == "train"):
logits = model(images)
_, preds = torch.max(logits, 1)
loss = criterion(logits, labels)
if phase == "train":
loss.backward()
optimizer.step()
running_loss += loss.item() * images.size(0)
running_acc += torch.sum(preds == labels.data)
epoch_loss = running_loss / len(dataloaders[phase].dataset)
epoch_acc = running_acc / len(dataloaders[phase].dataset)
if phase == "test":
if best_test_accuracy < epoch_acc:
best_test_accuracy = epoch_acc
if best_test_loss < epoch_loss:
best_test_loss = epoch_loss
tune.report(accuracy=best_test_accuracy.item(), loss=best_test_loss)
Search Algorithm 선택: HyperOptSearch
모듈
ray.tune.suggest.hyperopt.HyperOptSearch
: Bayesian Optimization 기반 hyper-parameter search 제공from ray.tune.suggest.hyperopt import HyperOptSearch optim = HyperOptSearch( metric='accuracy', mode="max", )
참고
Hyper parameter search 실행
*Reporter: 진행 상황을 관리하는 클래스로,
CLIReporter,
JupyterNotebookReporter` 두 가지가 있다.tune.run
: hyper parameter search 실행하는 함수로, 분석 결과를 담은 객체를 리턴함num_samples
파라미터의 의미: 각각의 hyper-parameter 조합을 몇 번 반복할 것인지(e.g. Gride Search를 할 경우 각 Grid 지점에서num_samples
에 지정된 값 만큼의 실험을 반복함. search space가 총 10가지 조합이고num_samples=10
이면10 * 10 = 100
번의 학습을 실행함.from ray.tune import CLIReporter import ray n_trial = 2 reporter = CLIReporter( parameter_columns=["n_epoch", "learning_rate", "batch_size"], metric_columns=["accuracy", "loss"]) ray.shutdown() # ray 초기화 analysis = tune.run( training, config=config_space, search_alg=optim, #verbose=1, progress_reporter=reporter, num_samples=n_trial, resources_per_trial={'gpu': 1} )
피어세션
역할
- 모더레이터: 준수
- 발표자: 준수, 대웅
- 회의록: 창한
발표
준수
- Back of Tricks for image classification with convolutional neural networks(https://arxiv.org/abs/1812.01187)에서 소개되었던 기법들을 간략하게 소개
- Cosine Learning Rate Decay
- Label Smoothing
- Knowledge Distillation
- Mixup Training
대웅
- 프로젝트를 위한 베이스라인 코드 및 실행 방법 제시
- 강의에서 소개되었던 PyTorch project template에 PyTorch Image Classification Tutorial을 적용하며 일부 수정
- 여기에 각자가 시도해볼 모델 및 실험 조건을 각자 시도해 볼 수 있을 것
- TODO: transforms 관리 기능 추가, Weights & Biases 기능 추가, 실험 관리 및 Hyper parameter search에 대한 고민
내일 회의
- 모더레이터: 대웅
- 발표자: 창한, 한진
- 회의록: 한진
마스터 클래스 내용 요약
- ML/DL 엔지니어의 필요성이 증대되고 있다. 따라서 단순 ML/DL 코드 작성을 넘어야 한다
- 자동화하고, 데이터와 연계, 실험 결과를 기반으로 설득, 시스템화
- 좋은 엔지니어이자 좋은 기획자적인 요소들이 필요하다(아직 AI화 되지 않은 영역의 AI화, 데이터를 어떻게 먹일? 것인가))
- ML/DL 과정의 주변에 있는 에코시스템에 대한 지식과 경험이 필요
- Linux shell script
- DB
- Cloud
- Deply 관련 툴(e.g. Docker)
- 대용량 데이터 처리: Multi-node(Spark 코드를 읽고 이해할 수 있는 능력), Multi-Processing
멘토링 요약
- 이번 P-stage에서는 기본에 충실하자.
- 나만의 Template, BoilerPlate 를 만들자
- 각 과정의 요소들(실험 결과 정리 및 기록, 문서화, 토의, 깃 & 깃헙사용, 커밋 메시지 습관 들이기 등)에 익숙해지고 습관을 들이자.
학습 회고
- 학습 내용 정리 시간을 더 줄일 수 있는 방법 없을까
- 오늘 최성철 교수님의 마스터 클래스는 CS지식 학습에 대한 가이드라인을 얻을 수 있었다.
- 멘토님께서 강조하신 템플릿 코드의 중요성에 동의한다. 각 태스크별 상황별 바로 적용해 볼 수 있는 템플릿 코드를 만들어 둬야겠다.
- Ray Tune에 대한 사용법을 그동안 어렴풋이 알고만 있었는데, 선택과제를 하면서 내용과 사용법이 정리 되었다.
밀린 학습 내용
- 오늘은 없음
'Boostcamp AI Tech 2th' 카테고리의 다른 글
[WK04] P-Stage level 1 - 이미지 분류 1주차 (0) | 2021.08.28 |
---|---|
[WK03-Day014][21.08.20.Fri] Multi-GPU, Hyperparameter Tuning, PyTorch Troubleshooting (0) | 2021.08.20 |
[WK03-Day012][21.08.18.Wed] PyTorch Datasets & DataLoader (0) | 2021.08.19 |
[WK03-Day011][21.08.17.Tue] PyTorch Basics (0) | 2021.08.18 |
[WK02-Day010][21.08.13.Fri] Generative Models, 주간 회고 (0) | 2021.08.13 |