티스토리 뷰
ResNet을 활용한 자세 판별 모델 구현하기(with pytorch) (1) - ResNet과 전이학습(transfer learning)
Nyugati 2021. 8. 15. 19:37이번 프로젝트에는 주어진 이미지를 보고 거북목인지 아닌지를 판단하는 모델이 필요하다.
지난 주, 각 팀원들마다 1,000장의 이미지를 모아 총 4,000장의 이미지 데이터셋을 만들었다. 이제 여러 딥러닝 모델을 학습시켜보면서 우리의 데이터셋을 가장 잘 판별해주는 모델을 찾아야 한다. 내가 맡게 된 CNN 모델은 마이크로소프트가 2015년 ILSVRC 대회에서 제안하여 1위를 차지한 ResNet이다. 아마 전이학습으로 파이토치에서 제공해주는 모델을 그대로 가져와 마지막 레이어만 추가해서 사용할 것 같긴한데, 그래도 ResNet이 어떤 구조로 이루어져 있는지 어떤 특징이 있는지에 대해서는 짚고 넘어가야 할 것 같아 이 포스팅을 쓰게 되었다.
총 2개의 포스트로 나뉠 것 같다. 이번 포스트에서는 ResNet과 전이학습에 대해서 설명하고, 다음 포스트에서는 커스텀 데이터셋을 가지고 직접 ResNet18을 전이학습시켜보면서 성능을 살펴보겠다.
ResNet
이미지 분류의 기본 모델로 널리 쓰이고 있는 ResNet의 가장 큰 특징은 Residual Block 의 존재다. 이 block은 이전 layer의 feature map을 다음 layer의 feature map에 더해주는 개념이다. 이를 skip connection이라고도 하는데, 네트워크가 깊어짐에 따라 앞 단의 layer에 대한 정보가 뒷 단의 layer에서 희석되는 것을 보완하고자 이전의 정보를 뒤에서도 함께 활용하는 개념이라고 볼 수 있다. skip connection을 통해 레이어가 깊어질수록 gradient 값이 잘 전달되지 않는 vanishing gradient 문제를 해결할 수 있다.
파이토치를 통한 ResNet 모델의 구현은 다음과 같다.
① BasicBlock
우선 skip connection 과정이 구현된 Basic Block이다. resnet은 내부에 Basic Block을 반복적으로 이용한다. basic block에서 skip connection 은 shortcut으로 정의한다. stride 값이 1이 아니거나 입력 데이터의 채널 수 (in_planes)와 출력 데이터의 채널 수(planes)가 같지 않는 경우(= 두 번째 레이어부터 모든 레이어를 의미), shorcut을 통해서 기존의 값과 convolution 및 batch normalization한 결과를 더한다(= skip connection).
위 코드의 Basic Block에서 일어나는 과정을 정리하면 다음과 같다.
- ResNet 모델은 내부에 반복적으로 이용하는 Block으로 구성되어 있다.
- BasicBlock 클래스의 생성자의 인자 중 in_planes는 BasicBlock이 input으로 사용하는 데이터의 채널 수를 의미한다.
- 첫 번째 convolution
- Filter의 채널 수는 입력 이미지의 채널 수와 동일하게 설정한다.
- Filter의 개수는 planes로 설정. 이 개수만큼 Output(Feature Map)의 depth가 결정된다.
- Filter의 크기는 3 * 3, 움직이는 단위는 1.
- 이미지 픽셀의 구석 부분과 중앙 부분이 convolution 연산되는 횟수를 동일하게 맞춰주기 위해 zero padding = 1로 설정
- 컨볼루션 연산 후 bias값은 더하지 않음
- 첫 번째 컨볼루션 연산이 끝나면 안정적인 학습을 위해 배치 정규화를 적용한다.
- 두 번째 convolution
- Filter의 채널 수는 self.conv1와 self.bn1을 통과한 결괏값의 채널 수(planes)와 동일하게 설정한다.
- 두 번째 컨볼루션 연산이 끝난 후 생성된 feature map의 채널 수는 변화가 없을 것으로 예상된다. 따라서 Filter의 개수는 planes로 설정한다.
- Filter의 크기는 3 * 3, 움직이는 단위는 1.
- 이미지 픽셀의 구석 부분과 중앙 부분이 convolution 연산되는 횟수를 동일하게 맞춰주기 위해 zero padding = 1로 설정
- 컨볼루션 연산 후 bias값은 더하지 않음
- 두 번째 컨볼루션 연산이 끝나면 안정적인 학습을 위해 배치 정규화를 적용한다.
- shortcut(skip connection)
- 기존의 값과 컨볼루션 및 배치 정규화 한 값을 더하는 과정을 정의한다
② ResNet
본격적인 ResNet 모델의 내부에는 위에서 구현한 BasicBlock을 여러겹 쌓아 올리는 과정이 나열되어 있다. make_layer 메서드를 호출하여 인자 값으로 주어지는 stride를 이용해 stride 범위를 BasicBlock마다 설정하고 만들어진 block들을 리스트에 저장한다.
위 코드의 Resnet에서 일어나는 과정을 정리하면 다음과 같다.
- convolution 계산할 때는 16의 채널 수를 바탕으로 진행한다.
- Input으로 이용하는 컬러 이미지에 적용하기 위한 convolution을 새로 정의한다.
- 컨볼루션 연산 이후 크기가 16인 2차원 데이터에 배치 정규화를 수행한다.
- self.layer1 : input 16채널 output 16채널로 계산하는 BasicBlock 2개 생성
- self.layer2 : input 16채널 output 32채널로 계산하는 BasicBlock 1개, input 32채널 output 32채널로 계산하는 BasicBlock 1개 생성
- self.layer3 : input 32채널 output 64채널로 계산하는 BasicBlock 1개, input 64채널 output 64채널로 계산하는 BasicBlock 1개 생성
basic block을 만들어나가는 과정을 표시해보면 다음과 같다.
여기 resnet에 대해서 굉장히 잘 설명한 유튜브 영상이 있다. 이해에 도움이 될 것이다!
Transfer Learning
딥러닝을 구축할 때 충분한 양의 이미지 데이터가 없다면 학습시키기가 쉽지 않다. 이때 사용하는 학습 기술이 바로 전이학습(transfer learning)이다. 전이학습이란 미리 학습해 놓은 딥러닝 모델(pretrained model)을 가져와 재학습(fine-tuning_시키는 방법을 말한다. pretrained 모델을 로드한 후 fully conected layer 앞단 네트워크의 weight을 가져와 fully connected layer을 디자인한다.
이때 주로 Fully Connected Layer는 그대로 사용하고 Output Layer를 디자인한다. 해결할 문제마다 output layer의 dimension이 다르기 때문에 이는 직접 수정해줘야 한다. 그리고 우리가 보유한 데이터를 input으로 학습을 진행해야 한다는 것을 잊으면 안된다! 여기서 일반적으로 pretrained model의 fully connected layer 이전의 weight는 학습시키지 않는다(weight freezing). 즉, 보유하고 있는 데이터를 갖고서 fully connected layer 부분의 weight만 학습을 진행하는 것이다.
transfer learning은 보유하고 있는 데이터가 많지 않을 때 Pre-trained model을 fine-tuning하는 기법이라 말할 수 있다. 이전에 모델을 수많은 데이터에 대해 학습시켜놨기 때문에 우리는 그저 pretrained model을 불러와 그들의 feature를 이용하는 것이다.
다음 포스트에서 직접 transfer learning 으로 모델을 학습시키는 과정을 소개하겠다!
'프로젝트 기록 > CUAI 4기 하계컨퍼런스' 카테고리의 다른 글
Python & OpenCV 마우스이벤트를 활용하여 이미지 상의 좌표 찾기 (0) | 2021.08.16 |
---|