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)
우리가 지정한 파라미터를 바꾸면서 실험을 한다고 생각을 하면 된다.
# 조작 변인
## 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]),
}
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)
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에 잘 적응을 못했던 듯