Transfer Learning & Hyperparameter Tuning

김동환·2023년 3월 17일
0

AI_tech_5기

목록 보기
4/18

Pretraine 된 ImageNet으로 한 번 FashionMnist를 학습시켜보기

imagenet_resnet18 = torchvision.models.resnet18(pretrained=True)

ImageNet은 1000개의 클래스로 이루어져있다. 또한 input image도 3 채널. 따라서 첫 conv 레이어와 마지막 fc 레이어의 수정이 필요하다.

 FASHION_INPUT_NUM = 1
  FASHION_CLASS_NUM = 10
  target_model.conv1 = torch.nn.Conv2d(FASHION_INPUT_NUM, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
  target_model.fc = torch.nn.Linear(in_features= imagenet_resnet18.fc.in_features, out_features=FASHION_CLASS_NUM, bias=True)

그리고 이제 weight와 bias를 초기화해야하는데 bias는 해당 1/math.sqrt(layer.w.size(1))을 분산으로 하는 정규분포로 초기화한다.

torch.nn.init.xavier_uniform_(target_model.fc.weight)
  torch.nn.init.xavier_uniform_(target_model.conv1.weight)
  stdv =  1/ math.sqrt(imagenet_resnet18.fc.in_features)
  target_model.fc.bias.data.uniform_(-stdv, stdv)

HyperParameter Tuning

Ray

우리가 지정한 파라미터를 바꾸면서 실험을 한다고 생각을 하면 된다.

# 조작 변인
## 1. Learning Rate
def get_adam_by_learningrate(model, learning_rate:float):
  return torch.optim.Adam(model.parameters(), lr=learning_rate)
## 2. Epoch 개수
def get_epoch_by_epoch(epoch:int):
  return epoch
## 3. BatchSize 크기에 따른 데이터 로더 생성

def get_dataloaders_by_batchsize(batch_size:int):
  # Mnist Dataset을 DataLoader에 붙이기
  BATCH_SIZE = batch_size
  fashion_train_dataloader = torch.utils.data.DataLoader(fashion_train_transformed, batch_size=BATCH_SIZE, shuffle=True, num_workers=2)
  fashion_test_dataloader = torch.utils.data.DataLoader(fashion_test_transformed, batch_size=BATCH_SIZE, shuffle=False, num_workers=2)

  dataloaders = {
      "train" : fashion_train_dataloader,
      "test" : fashion_test_dataloader
  }

  return dataloaders

이렇게 input에 따라 각기 다른 hyperparameter를 가진 optim이나 dataloader가 생성이 되고 config를 통해 옵션을 설정하면 된다.

config_space = {
    "NUM_EPOCH" : tune.choice([4,5,6,7,8,9]),
    "LearningRate" : tune.uniform(0.0001, 0.001),
    "BatchSize" : tune.choice([32,64,128]),
}

train 정의

def training(config):
	...모델 생성 및 cuda에 먹이기..
      #config에 따른 생성
      NUM_EPOCH = get_epoch_by_epoch(config["NUM_EPOCH"])
      dataloaders = get_dataloaders_by_batchsize(config["BatchSize"])
      optimizer = get_adam_by_learningrate(target_model, config["LearningRate"])
  .... 
  학습이 끝나면 report
  tune.report(accuracy=best_test_accuracy.item(), loss=best_test_loss)

HyperOptSearch

metric을 기준으로 max가 되는 값들을 찾는 방법

from ray.tune.suggest.hyperopt import HyperOptSearch

optim = HyperOptSearch( # HyperOptSearch 통해 Search를 진행합니다. 더 다양한 Optimizer들은 https://docs.ray.io/en/master/tune/api_docs/suggestion.html#bayesopt 문서를 참고해주세요
    metric='accuracy', # hyper parameter tuning 시 최적화할 metric을 결정합니다. 본 실험은 test accuracy를 target으로 합니다
    mode="max", # target objective를 maximize 하는 것을 목표로 설정합니다
)

실행

NUM_TRIAL = 10 # Hyper Parameter를 탐색할 때에, 실험을 최대 수행할 횟수를 지정합니다.

reporter = CLIReporter( # jupyter notebook을 사용하기 때문에 중간 수행 결과를 command line에 출력하도록 함
    parameter_columns=["NUM_EPOCH", "LearningRate", "BatchSize"],
    metric_columns=["accuracy", "loss"])

ray.shutdown() # ray 초기화 후 실행

analysis = tune.run(
    training,
    config=config_space,
    search_alg=optim,
    #verbose=1,
    progress_reporter=reporter,
    num_samples=NUM_TRIAL,
    resources_per_trial={'gpu': 1} # Colab 런타임이 GPU를 사용하지 않는다면 comment 처리로 지워주세요
)

결과

나는 첫 conv와 마지막 fc 를 제외하고는 freezing을 했는데 오히려 정확도가 떨어졌다. 아무래도 pretrained가 1000개 label로 학습이 되었고 fashion은 훨씬 그 수가 적으므로 freezing을 하게 되면 새로운 task에 잘 적응을 못했던 듯

profile
AI Engineer

0개의 댓글