- 이미지넷 pretrained model을 사용해서 전이학습과 하이퍼파라미터 튜닝을 진행하는 과제
-> 구체적으로는 ImageNet에서 학습된(pretrained) ResNet 18 딥러닝 모델을 사용해서 MNIST 모델, Fashion-MNIST 모델을 만들었다.
- ImageNet에서 학습된 ResNet 18 딥러닝 모델을 불러온다.
- MNIST 데이터셋(train, test dataset)을 불러온다.
- pretrained 되지 않은 resnet18모델(이하 mnist_resnet18)을 불러온다. 코드는 아래와 같다.(실습에서는 mnist_resnet18이라는 이름으로 불러옴. 여기에 mnist데이터셋을 전이학습시킬 예정이므로!)
mnist_resnet18 = torchvision.models.resnet18(pretrained=False)
4. conv1.weight.shape[1], fc.weight.shape[0]을 통해 모델의 입출력 채널 개수를 각각 확인한다.
print("네트워크 필요 입력 채널 개수", mnist_resnet18.conv1.weight.shape[1])
print("네트워크 출력 채널 개수 (예측 class type 개수)", mnist_resnet18.fc.weight.shape[0])
# 네트워크 필요 입력 채널 개수 3
# 네트워크 출력 채널 개수 (예측 class type 개수) 1000
5. 서로 다른 타입의 데이터를 사용했기 때문에 mnist데이터셋을 mnist_resnet18에 학습 시키기 위해서는, mnist데이터의 차원을 변경할 필요가 있다.
- mnist 원본 데이터(지금 전이학습시키려는 mnist데이터셋)는 흑백(grayscale)인데에 반해, 학습시키려는 모델인 mnist_resnet18은 컬러이다.
- 따라서 mnist는 28*28픽셀 이미지라서 데이터의 차원은 (28, 28)
- mnist_resnet18은 28*28(픽셀)*3(rgb의 3개 채널)의 (3, 28, 28)이다.
mnist_resnet18에 맞추어 mnist 데이터셋의 차원을 (3, 28, 28)으로 만들어주는 과정이 필요하다.
이는 torchvision.transforms.Compose라는 함수를 통해 가능하다.
그 코드는 아래와 같다.
# torchvision.datasets.mnist의 데이터 타입은 PIL Image이고, 학습 때는 torch로 type 변경이 필요함
# + 원본은 grayscale이라서 채널이 한개뿐인 입력이지만 모델은 3채널이기 때문에 grayscale을 RGB로 변경해주어야함
# (참고) grayscale의 입력을 모델에 넣고 싶으면, 모델 입력을 channel 1개만 받도록 변경할 수도 있다!
common_transform = torchvision.transforms.Compose(
[
torchvision.transforms.Grayscale(num_output_channels=3), # grayscale의 1채널 영상을 3채널로 동일한 값으로 확장함
torchvision.transforms.ToTensor() # PIL Image를 Tensor type로 변경함
]
)
# 앞서 선언한 데이터셋에 transform 인자를 넘겨주자
mnist_train_transformed = torchvision.datasets.MNIST(root='./mnist', train=True, download=True, transform=common_transform)
mnist_test_transformed = torchvision.datasets.MNIST(root='./mnist', train=False, download=True, transform=common_transform)
6. resnet18모델에 맞게 변경된 mnist데이터에 대해 데이터로더를 만들어준다.(이때 데이터 shuffle=True 필수!)
7. mnist_resnet18모델의 fully connected layer(mnist_resnet18.fc)의 output features를 mnist데이터의 레이블 개수인 10으로 변경
8. mnist_resnet18.fc의 가중치와 편향을 초기화
6~8번 과정에 대한 코드는 아래와 같다.
import math
# Mnist Dataset을 DataLoader에 붙이기
BATCH_SIZE = 64
mnist_train_dataloader = torch.utils.data.DataLoader(mnist_train_transformed, batch_size=BATCH_SIZE, shuffle=True, num_workers=2)
mnist_test_dataloader = torch.utils.data.DataLoader(mnist_test_transformed, batch_size=BATCH_SIZE, shuffle=False, num_workers=2)
# mnist_resnet18 분류 모델을 학습하기
## 1. 분류 모델의 output 크기가 1000개로 되어 있음으로 mnist data class 개수로 나올 수 있도록 Fully Connected Layer를 변경하고 xavier uniform으로 weight 초기화
MNIST_CLASS_NUM = 10
mnist_resnet18.fc = torch.nn.Linear(in_features=512, out_features=MNIST_CLASS_NUM, bias=True)
torch.nn.init.xavier_uniform_(mnist_resnet18.fc.weight)
# 이해 안가는 부분
# fully connected layer의 bias를 resnet18.fc in_feature의 크기의 1/root(n) 크기의 uniform 분산 값 중 하나로 설정
stdv = 1. / math.sqrt(mnist_resnet18.fc.weight.size(1))
mnist_resnet18.fc.bias.data.uniform_(-stdv, stdv)
print("네트워크 필요 입력 채널 개수", mnist_resnet18.conv1.weight.shape[1])
print("네트워크 출력 채널 개수 (예측 class type 개수)", mnist_resnet18.fc.weight.shape[0])
9. 이후 한 번의 에폭마다 학습과 테스트를 진행하며 전이학습을 마친다. fashion mnist데이터셋에 대해서도 같은 과정을 반복한다.
과제에서는 resnet18모델 각각에 mnist, fashion mnist를 전이학습시켜보았다. 모두 성능이 좋았지만 resnet18에 mnist데이터를 전이학습 시킨 mnist_resnet18모델을 source task로 두고 fashion mnist를 전이학습시켜 보는 것도 성능이 좋을 것 같다.
'AI > AITech 3기' 카테고리의 다른 글
[이미지 분류] 7강 Training & Inference 1 (2) | 2022.02.22 |
---|---|
[이미지 분류] 3강 Dataset (0) | 2022.02.21 |
[DL Basic] 5강 Modern CNN - 1x1 convolution의 중요성 (0) | 2022.02.18 |
[DL Basic] 4강 Convolution은 무엇인가 (0) | 2022.02.17 |
[DL Basic] 3강 Optimization (2) | 2022.02.11 |