EfficientNet, ResNet과 함께 실험해 볼 모델인 DenseNet에 대해 정리.
'Densely Connected Convolutional Networks' 논문에서 소개된 모델이다.
모든 레이어 간의 Feature map을 연결한 모델. 첫 번째 Convolution인 빨간 색 layer의 마지막 단인 feature map에서 연결된 빨간 선을 보면 이후 오는 모든 레이어에 연결한다. 즉 이전 레이어의 피처맵을 그 이후의 모든 레이어의 피처맵에 연결해 덧셈이 아닌 연결 연산을 한다. 이 연산을 통해 얻을 수 있는 점은
1. 모델이 이전의 정보를 기억하며 정보의 흐름이 이어진다.
기존의 CNN 모델에서 이전 레이어의 피처 맵이 다음 레이어의 입력 값으로 사용되며 많은 레이어를 통과해 모델의 끝에 다다르면 이전 레이어의 피처 맵 정보가 사라질 수 있다.
하지만 DenseNet의 경우 첫 레이어의 피처맵이 마지막 레이어의 피처맵까지 이어지기에 이 정보가 소실되지 않는다. 따라서 오차 역전파법을 통한 초기의 gradient 값이 소실되는 기울기 소실 문제도 완화된다. 또한 연결의 과정에서 정규화 효과도 얻을 수 있다.
2. 파라미터의 수와 연산량이 적다.
DenseNet은 적은 채널수를 이용한다. 각 레이어의 피처 맵을 다음 레이어들에 계속 전달하기 위해서 피처 맵의 채널 수를 최소화해서 사용하기 때문에 파라미터의 수가 적다.
ResNet과의 비교
Resnet connect
Resnet의 skip-connection은 l번째 레이어 출력값에 대해 잔차 계산식을 활용하기 위해 CNN 연산을 통틀은 H() 함수 내에서 l번째 시점의 H() 함수를 거친 연산과 x의 l-1 번째 시점의 값을 더한다.
이 식에선 한 시점 전의 값을 계속 더해서 연산하기 때문에 정보의 흐름이 지연될 수 있다.
Densenet connect
Densenet은 이전 레이어을 모든 다음 레이어에 직접적으로 연결한다.
즉 H() 함수 내에 l - 1시점부터 0까지 시점의 모든 값이 들어간다. 따라서 정보의 흐름이 향상된다.
Dense Block
연결 연산을 위해 피처맵의 크기를 맞춰야 하지만 pooling 연산을 위해 Dense Block 개념을 사용해야 한다.
각각의 Dense Block에서 모든 layer의 feature map을 input으로 받는다. Pooling 기준으로 Dense block이 존재하며, 앞서 말한 Densenet connect의 Concat 연산이 모든 layer가 아닌 Dense Block에서 일어난다.
이 표의 Dense Block에서 초록색 표시된 수가 Dense block에 존재하는 layer의 갯수이다. 따라서 이 Dense block의 layer와 나머지 layer를 모두 합쳤을 때의 총 layer갯수가 모델의 이름인 DenseNet-000 의 갯수이다.
PyTorch에서 사용하기
torchvision.models 모듈에서 pretrained 모델을 불러올 수 있다.
논문에서 언급된 121, 169, 201 외에 161을 사용할 수 있다. (264는 torchvision.models에는 없다)
class Densenet201(nn.Module):
def __init__(self, num_classes = 18):
super(Densenet201, self).__init__()
self.model = models.densenet201(pretrained = True).features
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.fc = nn.Linear(1920, out_features=num_classes)
def forward(self, x):
x = self.model(x)
x = self.avgpool(x).view(x.size()[0], -1)
x = self.fc(x)
return x
DenseNet - 201을 불러와 transfer learning으로 사용하는 함수. pretrained model을 불러와 .features로 마지막 FC layer전까지의 학습된 가중치를 불러온다.
이후 논문에서 Classification Layer를 위해 사용한 output 1x1 global average pool을 위해 AdaptiveAvgPool2d((1,1)) 을 사용한다. 이 코드는 global average pool의 기능을 한다. 이후 1920개의 벡터로 이루어진 input을 nn.Linear(1920, 예측하고자 하는 클래스 수 = 18) 을 통해 최종 클래스 예측을 하게 한다.
forward에서는 앞서 설정한 model, avgpool, fc를 사용하는데 avgpool 단계에서 x의 사이즈를 view 함수를 통해 조정해 1,1 벡터의 형태로 들어갈 수 있게 만든다.
Reference
https://deep-learning-study.tistory.com/528
https://gaussian37.github.io/dl-concept-densenet/
'네이버 부스트캠프 학습 정리 > 7주차' 카테고리의 다른 글
7주차 회고 (0) | 2023.04.24 |
---|---|
[P-stage 1] methodology (0) | 2023.04.22 |
[P-stage 1] Swin Transformer (2) | 2023.04.21 |