😶 초록 (Abstract)

- ResNet은 는 설득력 있는 정확도와 멋진 수렴동작을 보여주는 매우 심층적인 아키텍처군으로 부상했다.

본 논문에서는 "Identity Mapping"을 "Skip Connection" 및 "After-addition Activation"로 사용할 때
순전파/후전파 signal이 한 블록에서 다른 블록으로 직접 전파될 수 있음을 제안하는 residual building block 이후의 propagation공식을 분석한다.

일련의 제거(ablation)실험은 이런 identity mapping의 중요성을 뒷받침한다.
이는 새로운 residual unit을 제안하도록 동기부여하여 훈련을 더 쉽게 하고 일반화를 개선한다.

CIFAR-10(4.62% 오류) 및 CIFAR-100의 1001층 ResNet과 ImageNet의 200-layer ResNet을 사용하여 개선된 결과를 적으며 이에 대한 코드는 https://github.com/KaimingHe/resnet-1k-layers 에서 확인할 수 있다.
 

GitHub - KaimingHe/resnet-1k-layers: Deep Residual Networks with 1K Layers

Deep Residual Networks with 1K Layers. Contribute to KaimingHe/resnet-1k-layers development by creating an account on GitHub.

github.com

 

 

 

1. 서론 (Introduction)

 

 

 

2. Analysis of Deep Residual Networks


Discussions

 

 

 

3. On the Importance of Identity Skip Connections


 

 

3.1  Experiments on Skip Connections  


 • Constant scaling




 • Exclusive gating

이는 Highway  Network논문의 지침에 따라(people.idsia.ch/~rupesh/very_deep_learning/)




 • Shortcut-only gating

 



 1x1 convolutional shortcut





 • Dropout Shortcut

 

 

3.2   Discussions

 

 

 

 

 

 

4. On the Usage of Activation Functions

 

 

4.1  Experiments on Activation

이 Section에서는 ResNet-110과 164층의 Bottleneck Architecture(ResNet-164라고도 함)으로 실험한다.

Bottleneck Residual Unit은 다음과 같이 구성된다.
차원축소를 위한 1×1 및 3×3 layer
차원복원을 위한 1×1 layer 
이는 [ResNet논문]에서의 설계방식처럼 계산복잡도는 2개의 3×3 Residual Unit과 유사하다. (자세한 내용은 부록에 기재)
또한, 기존의 ResNet-164는 CIFAR-10에서 5.93%의 결과를 보였다.(표2)


 •BN after addition




 • ReLU before addition



 • Post-activation or Pre-activation ?
 



 

 

4.2  Analysis


 •Ease of optimization

- 이 효과는 ResNet-1001을 훈련할 때 매우 두드러진다. (그림 1의 곡선.)
[ResNet논문]
의 기존 설계방식으로 훈련을 시작하면 training Loss가 매우 느리게 감소한다.
f = ReLU가 음의 값을 경우, 신호에 영향을 미치는데 이는 Residual Unit이 많으면 이 효과가 두드러진다.
즉, 
Eqn.(3)(따라서 Eqn.(5))은 좋은 근사치가 아니게 된다.
반면, f가 identity mapping인 경우, 신호는 임의의 두 Unit 사이에 직접 전파될 수 있다.
1001층이나 되는 신경망의 training Loss값을 매우 빠르게 감소시킨다(그림 1).
또한 우리가 조사한 모든 모델 중 가장 낮은 Loss를 달성하여 최적화의 성공을 보여준다.


- 또한 ResNet이 더 적은 층을 가질 때 f = ReLU의 영향이 심각하지 않다는 것을 발견했다(: 그림 6(오른쪽)).
훈련 초반, training곡선이 조금 힘들어 보이지만 곧 좋은 상태로 된다.

그러나 단절(truncation)은 1000개의 레이어가 있을 때 더 빈번히 일어난다.





 • Reducing Overfitting

 
제안된 "pre-activation" unit을 사용하는 것이 Regualarizatoin에 미치는 또 다른 영향은 그림 6(오른쪽)과 같다.

"pre-activation" 버전은 수렴 시 training Loss값이 약간 더 높지만 "test Error"는 더 낮다.

 현상은 CIFAR-10 100 모두에서 ResNet-110, ResNet-110(1-layer)  ResNet-164에서 관찰된다.
이때, 우리는 이것이 BN의 "regularization" 효과에 의해 발생한 것으로 추정된다.

원래 Residual Unit(그림 4(a)에서 BN이 신호를 정규화(normalize)하지만, 이는 곧 shortcut에 추가되므로 병합된 신호는 정규화(normalize)되지 않습니다.

 정규화되지 않은 신호는 그다음 weight-layer의 입력값으로 사용된다.

대조적으로, 우리의 "pre-activation"버전에서, 모든 weight-layer의 입력값 정규화되었다.

 

 

 

 

 

 

5. Results

 • Comparisons on CIFAR-10/100
  - 표 4는 CIFAR-10/100에 대한 최첨단 방법을 비교하여 경쟁력 있는 결과를 얻는다.
   우린 신경망 폭이나 filter크기를 특별히 조정하거나 작은 dataset에 매우 효과적인 정규화 기술(예: Dropout)을 사용하지 않는다는 점에 주목한다.
  우리는 단순하지만 필수적인 개념을 통해 더 깊이 들어가 이러한 결과를 얻어서 깊이의 한계를 밀어내는 잠재력을 보여준다.



 •Comparisons on ImageNet
  - 다음으로 1000-class ImageNet dataset에 대한 실험 결과이다.
ResNet-101을 사용해 ImageNet의 그림 2와 3에서 연구한 skip connection을 사용하여 예비 실험을 수행했을 때, 유사한 최적화 어려움을 관찰했다.
이러한 non-idntity shortcut network의 training오류는 첫 learning rate(그림 3과 유사)에서 기존 ResNet보다 분명히 높으며, 자원이 제한되어 훈련을 중단하기로 결정했다.
그러나 우리는 ImageNet에서 ResNet-101의 "BN after addition" 버전(그림 4(b)을 마쳤고 더 높은 training Loss와 validation error오류를 관찰했다.
이 모델의 단일 크롭(224×224)의 validation error는 24.6%/7.5%이며 기존ResNet-101의 23.6%/7.1%이다.
이는 그림 6(왼쪽)의 CIFAR 결과와 일치합니다.


- 표 5는 모두 처음부터 훈련된 ResNet-152와 ResNet-200의 결과를 보여준다.
우리는 기존 ResNet 논문이 더 짧은 측면 s
[256, 480]을 갖는 scale-jittering을 사용하여 모델을 훈련시켰기 때문에 s = 256 ([ResNet논문]에서와 같이)에서 224×224crop의 test는 negative쪽으로 편향되어 있었다.

대신, 모든 기존 및 ResNets에 대해 s = 320에서 단일 320x320 crop을 test한다.
ResNets는 더 작은 결과물에 대해 훈련받았지만, ResNets는 설계상 Fully-Convolution이기 때문에 더 큰 결과물에서 쉽게 테스트할 수 있다.
이 크기는 Inception v3에서 사용한 299×299에 가깝기 때문에 보다 공정한 비교가 가능하다.



- 기존 ResNet-152는 320x320 crop에서 top-1 error가 21.3%이며, "pre-activation"은 21.1%이다.
ResNet-152에서는 이 모델이 심각한 일반화(generalization) 어려움을 보이지 않았기 때문에 이득이 크지 않다.
그러나 기존 ResNet-200의 오류율은 21.8%로 기존 ResNet-152보다 높다.
그러나 기존 ResNet-200은 ResNet-152보다 training error가 낮은데, 이는 overfitting으로 어려움을 겪고 있음을 시사한다.


"pre-activation" ResNet-200의 오류율은 20.7%로 기존 ResNet-200보다 1.1% 낮고 ResNet-152의 두 버전보다 낮다. GoogLeNet과 InceptionV3의 scale 및 종횡(aspect)의 비율의 확대를 사용할 때, ResNet-200은 Inception v3보다 더 나은 결과를 보인다(표 5).
우리의 연구가 진행될 때와 동시에, Inception-ResNet-v2 모델은 19.9%/4.9%의 single crop 결과를 달성하였다.




 • Computational Cost
  - 우리 모델의 계산 복잡도는 깊이에 따라 선형적이다(따라서 1001-layer net은 100-layer net보다 10배 복잡하다).
CIFAR에서 ResNet-1001은 2개의 GPU에서 훈련하는 데 약 27시간이 걸리고,
ImageNet에서 ResNet-200은 8개의 GPU에서 훈련하는 데 약 3주가 걸린다(VGGNet논문과 동등).

 

 

6. Conclusions

이 논문은 ResNet의 connection메커니즘 뒤에서 작동하는 전파 공식을 조사한다.
우리의 결과물은 identity shortcut connectionidentity after-addition activation이 정보의 전파를 원활하게 하기 위해 필수적이라는 것을 시시한다.
이런 변인통제실험(Ablation Experimanet)은 우리의 결과물과 일치하는 현상을 보여준다.
우리는 또한 쉽게 훈련되고 정확도를 향상시킬 수 있는 1000층 심층신경망을 제시한다

 

 

 

 •Appendix: Implementation Details

 

 

 

 

 

 

🧐 논문 감상_중요개념 핵심 요약

"Identity Mappings in Deep Residual Networks"
Kaiming He, Xiangyu Zhang, Shaoqing Ren 및 Jian Sun이 2016년에 발표한 연구 논문으로 이 논문은 심층 신경망의 성능 저하 문제를 해결하는 새로운 잔차 네트워크 아키텍처를 제안한다.

 

 

[핵심 개념]

1. 기존 ResNet과의 차이점
1. Shortcut Connections
이 논문은 기존의 ResNet에서 layer간의 shortcut connection에서 "Identity Mapping"을 사용한다는 것이다.
  - 기존 ResNet: 다음층의 출력차원과 일치하도록 입력을 변환하는 Residual Mapping을 사용
  - ResNet V2: transformation을 우회하고 입력을 다음층으로 직접전파하는 "Identity Mapping"을 사용


2. Pre-activation

이 논문은 ResNet을 응용한 ResNetV2로 사전 활성화(pre-activation)에 대한 개념을 도입했다.
  - BatchNormalization 및 ReLU를 각 conv.layer이후가 아닌, 이전에 적용한다.
  - 이를 통해training performance를 개선하고 매우 깊은 신경망에서의 overfitting을 줄여주었다.

[장점 ①_ Easy to Optimization]
  - 이 효과는 깊은 신경망(1001-layer ResNet)을 학습시킬 때 분명하게 나타난다.
기존 ResNet은 Skip connetion을 거쳐서 입력값과 출력값이 더해지고, ReLU 함수를 거친다.
더해진 값이 음수이면 ReLU 함수를 거쳐서 0이 되는데, 이는 만약, 층이 깊다면 이 증상의 영향이 더 커지게 되어 더 많은 값이 0이 되어 초기 학습시에 불안정성으로 인한 수렴이 되지 않는 문제가 발생할 수 있다.
실제로 아래 학습 곡선을 보면 초기에 Loss가 수렴되지 않는 모습을 볼 수 있다.
Bold: test, 점선: train

 하지만 pre-activation 구조는 더해진 값이 ReLU 함수를 거치지 않아, 음수 값도 그대로 이용할 수 있게 된다.
실제로 학습 곡선을 살펴보면 제안된 구조가 초기 학습시에 loss를 더 빠르게 감소시킴을 볼 수 있다.

[장점 ②_ Reduce Overfitting]
  - 위 그림을 보면 수렴지점에서 pre-activation 구조의 training loss가 original보다 높다.
  - 반면, test error가 낮다는 것은 overfitting을 방지하는 효과가 있다는 것을 의미합니다.
  - 이 논문에서 이 효과에 대해 Batch Normalization 효과 때문에 발생한다고 추측하는데, Original Residual unit은 BN을 거치고 값이 shortcut에 더해지며, 더해진 값은 정규화되지 않는다.
이 정규화되지 않은 값이 다음 conv. layer의 입력값으로 전달된다.

  Pre-activation Residual unit은 더해진 값이 BN을 거쳐서 정규화 된 뒤에 convolution layer에 입력되서 overfitting을 방지한다고 저자는 추측한다.

3. Recommendation
이 논문에서는 ResNet V2 설계 및 훈련을 위해 소개된 실용적인 권장사항을 제안하는데,  아래와 같다.
 ① Initialization
   - 표준편차 = sqrt(2/n) 인 Gaussian분포를 사용해 Conv.layer weight초기화를 권장
      (이때, n은 input channel수) 

 ② Batch Normalization 
   - pre-activation을 이용한 Batch Normalization을 권장한다.
   - mini-batch의 statistics 영향을 줄이기 위해 training/test중에는 statistics이동평균을 사용한다.

 ③ Learning Rate Schedule
   - 초기 수렴의 가속화를 위해 warming up구간에서 상대적으로 큰 학습률 사용
   - 미세조정을 위해 decay구간에서 더 작은 학습률 사용

 ④ Weight Decay
   - overfitting 방지를 위해 weight_decay = 1e-4 (0.0001)를 사용

 ⑤ Data Augmentation
   - random cropping
   - horizontal flipping

 

 

 

 

 

 

🧐  논문을 읽고 Architecture 생성 (with tensorflow)

import tensorflow as tf
from tensorflow.keras.layers import Input, Conv2D, BatchNormalization, ReLU, Add, GlobalAveragePooling2D, Dense
from tensorflow.keras.models import Model

def conv2d_bn(x, filters, kernel_size, strides=1, padding='same'):
    x = Conv2D(filters=filters,
               kernel_size=kernel_size,
               strides=strides,
               padding=padding)(x)
    x = BatchNormalization()(x)
    return x

def residual_block(x, filters, kernel_size, strides=1):
    shortcut = x
    x = conv2d_bn(x, filters, kernel_size, strides)
    x = ReLU()(x)
    x = conv2d_bn(x, filters, kernel_size, 1)
    
    if x.shape != shortcut.shape:
        shortcut = Conv2D(filters=filters,
                          kernel_size=1,
                          strides=strides,
                          padding='same')(shortcut)
    x = Add()([x, shortcut])
    x = ReLU()(x)
    return x

def resnetv2(input_shape, num_classes, num_layers, use_bottleneck=False):
    num_blocks = (num_layers - 2) // 9
    filters = 16

    inputs = Input(shape=input_shape)

    x = conv2d_bn(inputs, filters, 3)

    for i in range(num_blocks):
        for j in range(3):
            strides = 1
            if j == 0:
                strides = 2
            x = residual_block(x, filters, 3, strides)
        filters *= 2

    x = GlobalAveragePooling2D()(x)
    x = Dense(num_classes, activation='softmax')(x)

    model = Model(inputs=inputs, outputs=x)

    return model
    
    
model = resnetv2(input_shape=(224,224,3),  num_classes=200, num_layers=152, use_bottleneck=True)
model.summary()

 

😶 초록 (Abstract)

- 심층신경망은 학습시키기 더욱 어렵다.
- "residual learning framework"로 이전과 달리 상당히 깊은 신경망의 training을 쉽게하는 방법을 소개하고자 한다.
unreferenced함수 대신 layer input을 참조해 "learning residual function"으로 layer를 명시적으로 재구성하였다.
이런 잔차신경망(residual network)이 최적화하기 더욱 쉽고 상당히 증가된 깊이에서 정확도를 얻을 수 있다는 것을 보여주는 포괄적인(comprehensive) 경험적 증거를 제공한다.
- ImageNet dataset에서 VGGNet보다 8배 더 깊지만 복잡성은 낮은 152층의 잔차신경망에 대해 평가한다.
이런 잔차신경망의 앙상블은 ImageNet testset에서 3.57%의 오류를 달성했는데, 이는 ILSVRC-2015에서 1위를 차지했다.
또한 100층과 1000층을 갖는 CIFAR-10에 대한 분석도 제시한다.

- 깊이에 대한 표현은 많은 시각적인지작업에서 매우 중요하다.
우리의 매우깊은묘사는 COCO Object Detection dataset에서 상대적으로 28% 향상된 결과를 얻었다.
심층잔차신경망(Deep residual net)은 ILSVRC. &. COCO 2015 대회1에 제출한 자료의 기반으로 ImageNet감지, ImageNet Localization, COCO 감지, COCO segmentation 작업에서도 1위를 차지했다.

 

 

1. 서론 (Introduction)

Deep CNN은 image classification의 돌파구로 이어졌다.
심층신경망은 당연하게도 저·중·고수준의 특징을 통합하고, 분류기는 다층을 처음부터 끝까지 분류하며 feature의 "level"은 깊이가 깊어지면서 층이 쌓일수록 풍부해진다. (현재 신경망의 깊이는 아주 중요하다는 것이 정론이다.)

- Depth의 중요성에 대해 다음과 같은 질문이 발생한다: 더 많은 층을 쌓은 것 만큼 신경망을 학습시키기 더 쉬울까?
[
Is learning better networks as easy as stacking more layers?]
- 이 질문의 답을 위한 큰 장애물은 악명높은 gradient vanishing/exploding문제로 시작부터 수렴을 방해하는 것이다.
다만, 이 문제는 초기화를 정규화하거나 중간에 정규화층을 넣어 수십개(tens)의 층의 신경망이 역전파를 통해 SGD를 위한 수렴을 시작하는 방법과 같이 대부분 다뤄졌다.

Figure 1. Degradation Problem
[Degradation Problem]
- 더 깊은 신경망이 수렴을 시작할 때, 성능저하(degradation)문제가 노출되었다 : 신경망깊이가 증가하면 정확도가 포화상태가 되고, 그 다음에 빠르게 저하된다. 
- 이 문제의 예상치 못한 문제점은 바로 overfitting이 이 문제를 야기하지 않는다는 점인데, 적절한 심층모델에 더 많은 층을 추가하면 (우리의 연구결과처럼) 더 높은 training error가 발생한다.
위의 그림은 대표적인 예시이다.

- training 정확도의 성능저하는 모든 시스템이 optimize를 비슷한 수준으로 쉽게 할 수 없다는 것을 시사한다.
이를 위해 더 얕은 구조와 더 많은 층을 추가하는 더 깊은 구조를 고려해보자.

[Shallow Architecture. vs. Deeper Architecture]
더 깊은 모델에 대한 구성에 의한 해결책이 존재한다
 - 추가된 layer는 identity mapping이다.
 - 다른층은 학습된 얕은모델에서 복사된다.
이런 구조의 해결책심층모델이 얕은모델보다 더 높은 training error를 생성하지 않아야 함을 나타낸다.
하지만, 실험은 현재의 해결책은 이런구조의 해결책보다 비교적 좋거나 더 나은 해결책을 찾을 수 없었다.

cf. [Identity. &. Identity Mapping]
ResNet구조에서 Residual Block은 identity(= identity mapping) 을 말한다.
- 입력에서 출력으로의 전체 매핑을 학습하는 대신 입력을 약간 조정하는 방법을 학습을 진행한다.
- Identity Block은 Skip Connection이 Identity mapping을 수행하는 residual block의 일종이다.
- 즉, 변환없이 입력이 block의 출력에 직접 추가되는 것으로 Identity Block은 input의 차원을 유지시킨다.
- Identity Block은 Residual Networks에서 입력의 차원을 유지하면서 비선형성을 도입하는 데 사용된다.
이는 신경망이 더 복잡한 특징을 학습하도록 돕고 매우 깊은 신경망에서 발생할 수 있는 기울기 소실 문제를 방지한다.

이 논문에서, Degradation Problem을 "deep residual learning framework"를 이용해 다룰 것이다.
- 각 몇 개의 적층(stacked layer)이 원하는 기본적 맵핑에 직접 맞추기(fit)를 바라는 대신, 이러한 layer가 잔차맵핑에 적합하도록 명시적으로 허용한다.


- 우린 성능저하문제(Degradation Problem)를 보여주고 우리의 해결법을 평가하기 위해 ImageNet으로 포괄적인 실험을 진행하여 다음 2가지를 확인하였다.
 ① 극도로 깊은 잔차신경망은 최적화 하기 쉽다.
   - 단순히 층만 쌓는 상대적으로 "평범한(plain)" 신경망깊이가 증가하면 더 높은 training error를 보여준다.
 ② 우리의 심층잔차신경망은 깊이가 크게 증가하여 정확도를 쉽게 높였다.
이는 optimization의 어려움과 우리의 방법의 효과가 특정 dataset와 유사하지 않음을 시사한다.


- ImageNet Classification dataset에서 우리는 극도로 심층적인 잔차신경망에의해 우수한 결과를 얻었다.
우리의 "152-layer residual net"은 ImageNet에 제출된 가장 깊은 신경망이지만 VGG보다도 복잡성이 낮다.
앙상블은 ImageNet testset에서 3.57%의 top-5 error를 기록했으며 ILSVRC 2015 classification대회에서 1위를 차지했다.
극도로 깊은신경망은 서로다른 인식작업에서도 우수한 일반화(generalization)성능을 발휘해 다음같은 ILSVRC 및 COCO 2015에서 1위를 추가로 달성했다 : ImageNet detection, ImageNet localization, COCO detection, and COCO segmentation in ILSVRC & COCO 2015 competitions

 

 

 

 

2. Related Work

Residual Representations.
- image recognition에서, VLAD(Vector of Locally Aggregated Descriptors)는 dictionary에 관하여 잔차벡터에 의해 encoding되는 표현이며, Fisher Vector는 VLAD의 확률론적인 버전의 공식으로 만들어진다.
두가지 모두 image 회복 및 분류를 위한 강력한 shallow representation이다.
Vector 양자화(quantization)의 경우, 잔차벡터의 인코딩이 기존벡터 인코딩보다 더 효과적으로 나타났다.

cf) VLAD는 feature encoding을 위한 이미지처리기술로 Local Image feature를 고정길이벡터표현(fixed-length vector representation)으로 인코딩하는 것이다.
ResNet을 사용하는 일부과제에서 VLAD는 분류를 위해 최종 softmax층을 사용하는 대신, ResNet의 중간층에서 추출한 특징을 인코딩하는데 사용하여 더욱 세분화된 특징표현이 가능하다.

- 저수준의 비전에서 편미분방정식(PDE.,Partial Differential Equations)을 해결하기 위해 널리 사용되는 Mulit-Grid방법은 시스템을 여러척도(multiple scale)에서 하위문제(subproblem)로 재구성(reformulate)한다. 이때, 각 하위문제는 더 거친 척도와 미세한 척도사이에서 잔차해결(residual solution)을 담당한다.
Multi-Grid의 대안은 계층적 기본 딕셔너리의 조건화(hierarchical basis pre-conditioning)이다.
이는 두 척도 사이의 잔차벡터를 나타내는 변수에 의존하며 이런 해결법은 해결책의 잔차특성(residual nature)을 모르는 기존의 해결책보다 훨씬 빠르게 수렴하는 것으로 나타났으며 이런 방법은 좋은 재구성(reformulation)이나 전제조건(preconditioning)이 최적화를 단순화 한다는 것을 시사한다.



Shorcut Connections
- Shorcut Connection을 유도하는 이론 및 실습은 오래 연구해왔다.
MLP training의 초기실습은 신경망 입력에서 출력으로 연결된 선형층(linear layer)를 추가하는 것이다.
몇몇의 중간층이 gradient vanishing/exploding을 다루기 위해 보조분류기(auxiliary classifier)에 "직접연결"된다.
GoogLeNet(https://chan4im.tistory.com/149)에서, "Inception"층은 shortcut 분기와 몇개의 더 깊은 분기로 구성된다.

- 우리의 연구가 진행될 때 동시에, "highway networks"는 gating function이 있는 shortcut연결을 제시하였다.
이 gate는 parameter가 없는 identity shortcut과 달리 data에 의존하고 parameter를 갖고 있다.
gate shortcut이 "closed"(= 0에 접근할 수록) "hightway networks"의 layer는 non-residual function을 나타낸다.
 대조적으로, 우리의 공식은 항상 잔차함수를 학습한다.
우리의 identity shortcut은 결코 "closed"되지 않고 학습해야할 추가 잔차함수와 모든 정보가 항상 통과한다.
게다가 highway network는 깊이가 극도로 증가(100개 이상의 층)하여도 정확도의 향상을 보여주지 않았다.

 

 

 

3. Deep Residual Learning

3.1. Residual Learning

 

 

3.2. Identity Mapping by Shortcuts

 

 

3.3. Network Architectures

Plain Network
  - plain 신경망의 토대는 주로 VGGNet의 철학에서 영감을 받았다. (Fig.3, 왼쪽)
  - conv.layer는 대부분 3x3 filter를 사용하며, 2가지의 간단한 설계방식을 따른다.
    ① 동일한 크기의 특징맵출력에 대하 layer는 동일한 수의 filter를 갖는다.
    ② 특징맵 크기가 1/2(절반으로 줄)이면, layer당 시간복잡성을 유지해야 하기에 filter수가 2배가 된다.
  - 우린 stride=2인 conv.layer에 의해 직접 downsampling을 수행한다. 
  - 신경망은 Global AveragePooling과 Softmax가 있는 1000-way Fully-Connected로 종료된다.
  - weight-layer의 총 개수는 그림3의 중간과 같은 34개이다.

 Residual Network
  - 위의 plain신경망을 기반으로, 우리는 신경망을 counterpart residual 버전으로 바꾸는 Shortcut Connection(그림 3, 오른쪽)을 삽입한다.
  - Identity shortcuts(Eqn. (1))은 입력과 출력이 동일한 치수일 때 직접 사용할 수 있다(그림 3의 실선 shortcuts).

  - 차수가 증가하면(그림 3의 점선 shortcuts), 우리는 두 가지 옵션을 고려한다:
    ① shortcut은 차원을 늘리기 위해 추가적으로 0개의 항목이 패딩된 상태에서 Identity mapping을 계속 수행합니다.
        이때, 추가적인 매개 변수를 도입하지 않습니다;

    ② Eqn. (2)의 Projection shortcut은 차원을 일치시키는 데 사용된다(1×1 convolutions로 수행).

  - 두 옵션 모두에서 shortcut은 두 가지 크기의 특징맵 통과 시, stride=2로 수행된다.


 

 

3.4. Implementation

- [AlexNet, VGGNet]의 실험을 따라서 구현을 진행하였다. [https://chan4im.tistory.com/145, https://chan4im.tistory.com/146]
- scale augmentation[VGGNet]을 위해 [256, 480]로 random하게 샘플링, resize를 진행하였다.
- 224x224 crop은 랜덤하게 image에서 샘플링되거나 [AlexNet]처럼 픽셀 당 평균값의 차를 이용한 horizontal flip을 진행하였으며 정석적인 color augmentation은 [Alexnet]방식을 이용했다.

- Batch Normalization을 채택하여 BN논문[https://chan4im.tistory.com/147]에서 나온 것 처럼 Conv.layer 직후, activation이전에 사용을 해주었다.
- ReLU논문[https://chan4im.tistory.com/150]에서 처럼 weight를 초기화하고 모든 기본/잔차신경망을 처음부터 training한다.

- mini-batch size가 256인 SGD(weight decay=0.0001. &. momentum=0.9)를 사용하며, learning rate는 초기값이 0.1로 시작해 학습정체현상 즉, error plateaus(
SGD는 Plateau에 취약함)가 발생하면 10씩 학습률을 나누어 준다.
모델은 최대 60 x 10^4 iteration으로 training된다.
- [Batch Normalization]논문에 근거하여 Dropout은 배제하고 실험을 진행한다.


- 실험시, 비교분석을 위해 standard 10-crop testing을 채택하며[AlexNet], 최상의 결과를 위해 [VGG, Delving Deep into Rectifiers]논문처럼 Fully-Convolutional형태를 채택한다.
또한, 여러 척도에서의 score를 평균(average)하는데, 이때 image의 크기는 짧은쪽이 {224, 256, 384, 480, 640}에 오도록 조정된다.

 

 

 

4. Experiments

4.1. ImageNet Classification


 Plain Networks.
  - 먼저 18층, 34층 plain신경망을 평가한다. [34-layer plain net (Fig.3.중간), 자세한 구조는 아래 표1을 참조.]




 - 표 2의 결과는 더 깊은 34-layer plain net이 더 얕은 18-layer plain net보다 더 높은 val_Error값을 갖음을 보인다.

이유를 밝히기 위해 그림 4(왼쪽)에서 training과정 중 발생한 training/validation error를 비교한다
위 그림에서 우리는 성능저하문제(Degradation Problem)을 발견했다.
18-layer plain net의 solution space가 34-layer plain net을 대체함에도 불구하고 34-layer plain net은 전체적인 training절차에 걸쳐 높은 training error를 갖는다.


- 우린 이런 최적화 어려움이 gradient vanishing으로 인한 가능성은 낮다고 주장한다.
이런 plain신경망은 순전파신호가 0이 아닌 분산값을 갖도록 보장하는 Batch Normalization으로 훈련된다.
우린 또한 역전파된 기울기가 BN과 함께 healthy norm을 나타내는 것을 확인했다.
그래서 순전파와 역전파의 신호들이 사라지지 않는다.
(실제로 34-layer plain net은 표 3에서 보이듯 여전히 경쟁력있는 정확도를 달성하기에 solver가 어느정도 작동하는 것을 보여준다.)
우린 deep plain신경망이 기하급수적으로 낮은 수렴률을 가질  수 있어서 training error감소에 영향을 미친다고 추측한다.





 Residual Networks.
다음으로 18 및 34-layer residual nets (ResNets)을 평가한다.
근간이 되는 구조는 위의 plain신경망과 동일하며 그림 3(우측)처럼 3x3 filter의 각 쌍에 shortcut connection을 추가한다.
첫 비교(표2와 그림4,오른쪽)에선 모든 Shortcut에 identity mapping을 사용하고 차수를 늘리기 위해 zero-padding을 하기에 [option A], plain에 비해 추가적인 parameter가 없다.

[표 2와 그림 4에서 얻은 3가지 주요 관찰결과]
① 먼저, 잔차학습으로 상황이 역전된다.
  - 34-layer ResNet은 18-layer ResNet보다 2.8%낫다.
  - 더 중요한 점은, 34-layer ResNet이 상당히 낮은 training error를 나타내기에 validation dataset으로 generalization, 즉 일반화가 가능하다는 점인데, 이는 성능저하문제가 이 설정에서 잘 해결되었기에 깊이증가를 이용해 정확성의 이득을 얻을 수 있다는 점을 시사한다.

② 둘째로, plain신경망과 비교해 34-layer ResNet은 표 2처럼 top-1 error rate를 3.5% 감소시키며 성공적으로 감소된 training error를 보여준다. (그림 4에서 오른쪽  vs. 왼쪽)
이 비교는 극도로 심층적인 신경망에 대한 잔차학습의 효과를 검증해준다.

③ 마지막으로, 18-layer plain/ResNet이 비교적 정확하지만 (표 2), 18-layer ResNet은 더 빨리 수렴한다는 것에 주목하자.(그림 4에서 오른쪽  vs. 왼쪽)
  - 여기서 18-layer처럼 신경망이 "지나치게 깊지 않은" 경우, 현재의 SGD solver는 여전히 plain신경망에 대해 좋은 해결책을 찾는다.
  - 이 경우, ResNet은 초기단계에서 더 빠른 수렴을 제공해 최적화를 완화해준다.




Identity. vs. Projection Shortcuts.
  - parameter가 없는 identity shorcut은 training에 도움이 된다는 것을 보여주었으므로 다음으로는 projection shortcut(Eqn. (2))에 대해 조사한다.
표 3에서는 3가지 옵션을 비교한다.
(A) zero-padding shortcut은 차수를 늘리기 위해 사용된다.
  - 이때, 모든 shortcut은 parameter가 없다(표 2 및 그림 4의 오른쪽)

(B) projection shortcut은 차수를 늘리기 위해 사용된다.
  - 이때, 다른 shortcut은 identity이다.

(C) 모든 shortcut은 projection이다.

- 표 3은 3가지 옵션 모두 plain보다 낫다는 것을 보여준다. 이때, B가 A보다 약간 더 낫고 C가 B보다 약간 낫다. (C > B > A)
우린 이에 대해 A의 zero-padding차원이 실제로 잔차학습을 갖지 않기 때문이며 (B > A인 이유)
13개의 많은 projection shortcut에 의해 도입된 추가적 매개변수 때문이라 본다. (C > B인 이유)
그러나 A/B/C사이 작은 차이는 성능저하문제해결을 위해 Projection Shortcut이 필수적이지는 않다는 것을 시사한다.
메모리/시간복잡성과 모델크기를 줄이기 위해 이 논문의 나머지 파트에서는 C를 사용하지 않는다.
identity shortcut은 아래에 소개된 Residual Architecture의 복잡성을 증가시키지 않기에 더욱 중요하다.




 Deeper Bottleneck Architectures.

 [50-layer ResNet]
  - 우리는 34-layer net
의 각 2층 block3-layer bottleneck block으로 대체하여 50-layer ResNet(표 1)을 생성한다.
  - 우리는 차수를 늘리기 위해 option B를 사용한다.
  - 이 모델에는 38억 개의 FLOPS가 있습니다.


 [101-layer ResNet. &. 152-layer ResNet]
  - 우리는 더 많은 3-layer blocks(표 1)을 사용하여 101층 및 152층 ResNets를 구성한다.
  - 놀랍게도 깊이가 크게 증가했지만 152층 ResNet(113억 FLOP)은 여전히 VGG-16/19(153억/196억 FLOP)보다 복잡성이 낮다.
  - 50/101/152-layer ResNets는 34-layer보다 상당히 정확하다(표 3 및 4). 
  - 우리는 성능저하를 관찰하지 않기에 상당히 증가된 깊이에서 상당한 정확도 향상을 이뤘다.
  - 깊이의 이점은 모든 평가 지표(evaluation metric)에서 확인할 수 있다(표 3 및 4).


cf. FLOPs
컴퓨터의 성능을 수치로 나타낼 때 주로 사용되는 단위이다. 초당 부동소수점 연산이라는 의미로 컴퓨터가 1초동안 수행할 수 있는 부동소수점 연산의 횟수를 기준으로 삼는다.







Comparision with  State-of-the-art  Method.
  - 표 4에서 이전의 최고의 단일 모델 결과와 비교하였는데, 우리의 근-본 34층 ResNets는 매우 경쟁력 있는 정확도를 달성했다.
  - 152층 ResNet은 단일 모델에서 top-5 error rate에서 4.49%를 갖는다.
  - 이 단일 모델 결과는 이전까지의 모든 앙상블 결과를 능가한다 (표 5).


  - 깊이가 다른 6개의 모델을 결합하여 앙상블을 형성하였는데, testset에서 top-5 error가 3.57% 였다(표 5).
  (제출 당시, 앙상블 기법은 152층 모델 두 개만 포함하였으며
ILSVRC 2015에서 1위를 차지했다.)

 

 

4.2. CIFAR-10  and  Analysis

- 우리는 10개의 클래스에서 5만개의 traininset과 1만개의 test image로 구성된 CIFAR-10 dataset에 대해 더 많은 연구를 수행했다.
우리는 training set에 대해 훈련되고 testset에 대해 평가된 실험을 결과로 제시한다.
우리는 극도로 심층적인 신경망의 동작에 초점을 맞춘다.
최첨단 결과를 추진하는 것에는 초점을 맞추지 않기에 다음과 같이 단순한 구조를 의도적으로 사용한다.


- plain/residual architecture는 그림 3(가운데/오른쪽)의 형태를 따른다.
신경망의 입력은 픽셀당 평균의 차(per-pixel mean subtracted)의 32x32 이미지이다.
첫 번째 층은 3×3 convolution이며
그 후 크기가 각각 {32, 16, 8}인 특징맵에서 3×3 convolution을 가진 6n layers의 적층 후 각 특징맵 크기에 대해 2n layer를 사용한다. 이때, filter수는 각각 {16, 32, 64}개이다.
sub-sampling은 stride=2인 convolution에 의해 수행된다.

신경망은 Global AveragePooling, 10-way FC.layer 및 softmax로 종료되며 총 6n+2개의 적층된 weight 층이 있다.
다음 표는 Architecture를 요약한 것이다:
Shortcut Connection 사용시, 한 쌍의 3x3 layer(총 3n개의 shortcut)에 연결된다.
이 dataset에서 (option A을 포함한)모든 경우에 identity shortcut을 사용한다.
따라서 Residual Model은  Plain Model과 depth, width. &. parameter수가 정확하게 동일하다.



- weight decay=0.0001과 momentum=0.9을 사용하고 가중치 초기화 및 Batch Normalization을 사용하지만 Dropout은 사용하지 않는다. (이때, 가중치 초기화는 https://chan4im.tistory.com/150를 따른다.)
이 모델들은 2개의 GPU에서 128의 mini-batch로 훈련된다.
learning rate=0.1의 학습 속도로 시작해 32000과 48000 iteration에서 10으로 나눈다.
64000번의 iteration에서 45k/5k로 나뉜 train/validation의 값이 결정되기에 training을 종료한다.

training을 위해 [Supervised Net.,https://arxiv.org/abs/1409.5185]에 소개된 간단한 Data Augmentation을 따른다.
각 면에 4개의 pixel이 padding되며
32x32 crop은 padding된 이미지 혹은 horizontal flip 중 무작위로 샘플링된다.
test를 위해 원본 32x32 이미지의 single view만 평가합니다.




- 20, 32, 44 및 56 층 신경망으로 이어지는 n = {3, 5, 7, 9}을 비교한다.
그림 6(왼쪽)은 Plain 신경망의 작동을 보여준다.
깊은 Plain 신경망은 깊이가 증가하면서 어려움을 겪고, 더 깊이 들어갈 때 더 높은 train error를 보인다.
이런 현상은 ImageNet(그림 4, 왼쪽) 및 MNIST([42] 참조)에서의 현상과 유사하여 이러한 최적화의 어려움이 근본적인 문제임을 시사한다.


그림 6(가운데)은 ResNets의 동작을 보여준다.
또한 ImageNet 사례(그림 4, 오른쪽)와 유사하게 ResNets는 최적화 어려움을 극복하고 깊이가 증가할 때 정확도가 향상됨을 보여준다.



- 110층 ResNet으로 이어지는 n = 18을 추가로 탐구한다.
이 경우, 우리는 초기의 learning rate=0.1이 "수렴을 시작하기"에 약간 너무 크다는 것을 발견했다.
따라서 training error가 80%미만이 될 때까지 낮은 학습률인 0.01로 사전 training을 진행한 후(약 400 iteration) 0.1로 다시training을 계속한다.
나머지 training schedule은 이전과 동일하며, 이 110층 신경망은 잘 수렴된다(그림 6, 중간).
FitNet[https://arxiv.org/abs/1412.6550] 및 Highway[https://arxiv.org/abs/1505.00387](표 6)와 같은 깊고 및 얇은 신경망보다 parameter수가 적지만, 최첨단 결과(6.43%, 표 6) 중 하나를 얻었다.


 Analysis of Layer Response.
  - 그림 7은 layer response의 표준 편차(std)를 보여준다.
이때, response는 BN 이후 및 기타 비선형성(ReLU/추가) 이전의 각 3x3 layer의 출력이다.
ResNets의 경우, 이 분석은 잔차 함수의 response강도를 나타낸다.

- 그림 7은 ResNet이 일반적인 응답보다 일반적으로 더 작은 응답을 가지고 있음을 보여준다.
이런 결과는 잔차 함수가 비잔차 함수보다 일반적으로 0에 가까울 수 있다는 기본 가정(3.1절)을 뒷받침한다.

- 또한 그림 7의 ResNet-20, 56 및 110의 비교에서 입증된 바와 같이 더 깊은 ResNet이 응답의 크기가 더 작다는 것을 주목하자.
즉, 더 많은 층이 있을 때, ResNets의 각각의 층은 신호를 덜 수정하는 경향이 있다.



 Exploring Over 1000 layers.
  - 공격적으로 1000개 이상의 층을 쌓는 깊은 모델을 탐구한다.
위에서처럼 훈련된 1202층 신경망으로 이어지는 n = 200을 설정한다.
우리의 방법은 최적화 어려움을 보이지 않고, 이 103층 신경망은 training error < 0.1%를 달성할 수 있다(그림 6, 오른쪽).
test error는 여전히 상당히 양호합니다(7.93%, 표 6).


- 그러나 그러한 공격적 심층모델은 여전히 미해결 문제가 있다.
이 1202층 신경망 test 결과는 우리의 110층 신경망 결과보다 나쁘지만, 둘 다 비슷한 training error를 갖는다.
우린 이런 현상이 "Overfitting"때문이라 주장한다.

- 1202층 신경망은  작은 dataset에 대해서는 불필요하게 클 수 있다(19.4M).
이 dataset에서 최상의 결과를 얻기 위해 maxout / dropout 같은 강력한 정규화가 적용된다.

본 논문에서는, 최적화의 어려움에 초점을 맞추지 않기에 maxout/dropout을 사용하지 않는다. 
설계에 따라 깊고 얇은 구조를 통해 정규화를 적용하지만 더 강력한 정규화와 결합하면 결과가 개선될 수 있다.

 

 

4.3. Object Detection on  PASCAL  and  MS COCO

- 우리의 방법은 다른 인식과제에서도 일반화 성능이 좋다.
- 표 7과 8은 PASCAL VOC 2007과 2012 [5] 및 COCO에 대한 Object Detection의 기준결과를 보여준다.
- 우리는 Detection방법은 Faster R-CNN을 사용한다.
이때, VGG-16을 ResNet-101로 대체하는 개선 사항에 관심을 두고 주목한다.
두 모델을 사용하는 Detection의 구현(부록 참조)은 동일., 결과물은 더 나은 신경망에 귀속된다.

- 가장 주목할 만한 것은 까다로운 COCO dataset에서 COCO의 표준 metric인 (mAP@[.5, .95])이 6.0% 증가하여 28%의 상대적 개선을 얻었는데, 이는 오직 learned representation 때문이다.

- 심층 ResNet을 기반으로 ILSVRC 및 COCO 2015 대회에서 여러 트랙에서 1위를 차지했습니다:
ImageNet Detection, ImageNet Localization, COCO Detection 및 COCO Segmentation.

- 자세한 내용은 부록에 기재.

 

 

 

 

 

😶 부록 (Appendix)

A. Object Detection. Baselines

• PASCAL VOC
  -
• MS COCO
  -

 

B. Object Detection Improvements

• MS COCO
  -

• PASCAL VOC
  -

• ImageNet Detection
  - 

 

C. ImageNet Localization

  -

  -

 

 

 

 

 

🧐 논문 감상_중요개념 핵심 요약

"Deep Residual Learning for Image Recognition"
심층 신경망에서 gradient vanishing problem을 해결하는 심층 ConvNet을 위한 새로운 구조를 소개하는 연구 논문으로 이 논문은 ResNet이라는 심층 합성곱 신경망을 위한 새로운 아키텍처를 제안한다.

 

 

[핵심 개념]

1. Problem
- 이 논문은 네트워크 깊이가 증가함에 따라 신경망의 정확도가 포화되거나 저하될 수 있는 기울기 소실 문제로 인해 매우 깊은 신경망을 훈련하는 것이 어렵다는 점을 강조했다.
  [Degradation Problem]
 - 더 깊은 신경망이 수렴을 시작할 때, 신경망깊이가 증가하면 정확도가 포화상태가 되고, 그 다음에 빠르게 저하된다. 
 - 이 문제의 예상치 못한 문제점은 바로 overfitting이 이 문제를 야기하지 않는다는 점인데, 적절한 심층모델에 더 많은 층을 추가하면 더 높은 training error가 발생한다.

2. Solution
이 논문은 기본 맵핑을 직접 학습하는 대신 잔차 함수(residual functions)를 학습하는 잔차 학습(residual learning)이라는 새로운 접근 방식을 제안했다.
이 접근 방식은 신경망이 identity mapping을 학습할 수 있도록 skip connection을 사용하는 residual block을 통해 구현된다.

cf. [Identity. &. Identity Mapping]
ResNet구조에서 Residual Block은 identity(= identity mapping) 을 말한다.
- 입력에서 출력으로의 전체 매핑을 학습하는 대신 입력을 약간 조정하는 방법을 학습을 진행한다.
- Identity Block은 Skip Connection이 Identity mapping을 수행하는 residual block의 일종이다.
- 즉, 변환없이 입력이 block의 출력에 직접 추가되는 것으로 Identity Block은 input의 차원을 유지시킨다.
Identity Block은 Residual Networks에서 입력의 차원을 유지하면서 비선형성을 도입하는 데 사용된다.
이는 신경망이 더 복잡한 특징을 학습하도록 돕고 매우 깊은 신경망에서 발생할 수 있는 기울기 소실 문제를 방지한다.

[Shortcut Connection]
- skip connection이라고도 불린다.
- 층의 입력과 이후 층의 출력 사이에 추가함으로써 ResNet은 층을 우회하고 입력을 이후 계층으로 "직접 전달"할 수 있습니다.
- 이를 통해 네트워크는 잔차 함수를 학습할 수 있으므로 매우 깊은 신경망의 훈련이 가능하다.
- 또한 여러 conv.layer와 기존의 입력을 블록의 출력에 추가하여 신경망이 identity mapping을 학습할 수 있게 해준다.
이를 통해 training의 정확성 및 속도를 향상시킬 수 있다.

[Residual learning]
이 논문은 원하는 기본 매핑을 직접 학습하는 대신 레이어 입력을 참조하여 잔차 함수를 학습하는 잔차 학습의 개념을 도입했다.
이 접근 방식은 gradient vanishing을 피할 수 있어서 심층신경망훈련을 허용한다.

[Residual blocks]
ResNet은 여러 conv.layer와 기존의 입력을 블록의 출력에 추가하는 skip connection으로 구성된 잔차 블록(residual block)을 사용하여 구축된다.
이를 통해 신경망은 잔차 함수를 학습할 수 있으므로 매우 깊은 신경망의 훈련이 가능합니다.



3. Bottleneck Architecture
- ResNet 구조는 매우 깊은 잔여 블록 스택(예: 152개 층)으로 구성되며 정확도를 유지하면서 계산을 줄이는 bottleneck설계를 사용한다.
- 논문에서는 세 개의 층으로 구성된 병목 구조를 소개했으며 이 세 층을 Add를 이용해 더한다.
① channel수를 줄이기 위한 1x1 conv.layer
② feature 학습을 위한 3x3 conv.layer
③ channel수를 다시 늘리기 위한 또 다른 1x1 conv.layer


cf. Pre-activation
이 논문을 응용한 ResNetV2는 사전 활성화(pre-activation)에 대한 개념을  도입했다.
 - BatchNormalization 및 ReLU를 각 conv.layer 이후가 아닌 이전에 적용한다.
 - 이를 통해 training performance를 개선하고 매우 깊은 신경망에서의 overfitting을 줄여주었다.



5. Results
- ResNet은 훨씬 더 깊은 신경망으로 이전 방법을 능가해 ImageNet dataset의 classification작업에서 최첨단 성능을 달성했다.
- 또한 ResNet은 Objcet Detection 및 Semantic Segmentation과 같은 다양한 dataset 및 작업에서 더 나은 일반화 성능(generalization performance)을 달성했다.

- 이때, 초기의 learning rate=0.1이 "수렴을 시작하기"에 약간 너무 크다는 것을 발견하였기에
 training error가 80%미만이 될 때까지 낮은 학습률인 0.01로 사전 training을 진행한 후(약 400 iteration) 0.1로 다시training을 진행하였다.

전반적으로 ResNet 논문은 딥러닝과 특히 컴퓨터 비전 영역에서 많은 최신 모델의 핵심 구성 요소가 된 매우 깊은 ConvNet의 훈련을 가능하게 하는 새로운 구조를 제안하는 혁신적인 성과를 이룩하였다.

 

 

 

 

 

🧐  논문을 읽고 Architecture 생성 (with tensorflow)

import tensorflow as tf
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, GlobalAveragePooling2D, Dense, ReLU, BatchNormalization, ZeroPadding2D, Activation, Add

def conv_bn_relu(x, filters, kernel_size, strides=1, padding='same'):
    x = Conv2D(filters, kernel_size, strides=strides, padding=padding)(x)
    x = BatchNormalization()(x)
    x = ReLU()(x)
    return x

def identity_block(x, filters):
    shortcut = x
    x = conv_bn_relu(x, filters, 1)
    x = conv_bn_relu(x, filters, 3)
    x = conv_bn_relu(x, filters * 4, 1)
    x = Add()([x, shortcut])
    x = ReLU()(x)
    return x

def projection_block(x, filters, strides):
    shortcut = conv_bn_relu(x, filters * 4, 1, strides)
    x = conv_bn_relu(x, filters, 1, strides)
    x = conv_bn_relu(x, filters, 3)
    x = conv_bn_relu(x, filters * 4, 1)
    x = Add()([x, shortcut])
    x = ReLU()(x)
    return x

def resnet(input_shape, num_classes, num_layers):
    if num_layers == 50:
        num_blocks = [3, 4, 6, 3]   
    elif num_layers == 101:
        num_blocks = [3, 4, 23, 3]   
    elif num_layers == 152:
        num_blocks = [3, 8, 36, 3]

    conv2_x, conv3_x, conv4_x, conv5_x = num_blocks

    inputs = Input(shape=input_shape)
    x = ZeroPadding2D(padding=(3, 3))(inputs)
    x = conv_bn_relu(x, 64, 7, strides=2)
    x = MaxPooling2D(pool_size=(3, 3), strides=2, padding='same')(x)

    x = projection_block(x, 64, strides=1)
    for _ in range(conv2_x - 1):
        x = identity_block(x, 64)

    x = projection_block(x, 128, strides=2)
    for _ in range(conv3_x - 1):
        x = identity_block(x, 128)

    x = projection_block(x, 256, strides=2)
    for _ in range(conv4_x - 1):
        x = identity_block(x, 256)

    x = projection_block(x, 512, strides=2)
    for _ in range(conv5_x - 1):
        x = identity_block(x, 512)

    x = GlobalAveragePooling2D()(x)
    outputs = Dense(num_classes, activation='softmax')(x)

    model = tf.keras.Model(inputs, outputs)
    return model




model = resnet(input_shape=(224,224,3),  num_classes=200, num_layers=152)
model.summary()

 

Model: "ResNet152"
__________________________________________________________________________________________________
 Layer (type)                   Output Shape         Param #     Connected to                     
==================================================================================================
 input_24 (InputLayer)          [(None, 224, 224, 3  0           []                               
                                )]                                                                
                                                                                                  
 zero_padding2d_10 (ZeroPadding  (None, 230, 230, 3)  0          ['input_24[0][0]']               
 2D)                                                                                              
                                                                                                  
 conv2d_4159 (Conv2D)           (None, 115, 115, 64  9472        ['zero_padding2d_10[0][0]']      
                                )                                                                 
                                                                                                  
 batch_normalization_4158 (Batc  (None, 115, 115, 64  256        ['conv2d_4159[0][0]']            
 hNormalization)                )                                                                 
                                                                                                  
 re_lu_540 (ReLU)               (None, 115, 115, 64  0           ['batch_normalization_4158[0][0]'
                                )                                ]                                
                                                                                                  
 max_pooling2d_23 (MaxPooling2D  (None, 58, 58, 64)  0           ['re_lu_540[0][0]']              
 )                                                                                                
                                                                                                  
 conv2d_4161 (Conv2D)           (None, 58, 58, 64)   4160        ['max_pooling2d_23[0][0]']       
                                                                                                  
 batch_normalization_4160 (Batc  (None, 58, 58, 64)  256         ['conv2d_4161[0][0]']            
 hNormalization)                                                                                  
                                                                                                  
 re_lu_542 (ReLU)               (None, 58, 58, 64)   0           ['batch_normalization_4160[0][0]'
                                                                 ]                                
                                                                                                  
 conv2d_4162 (Conv2D)           (None, 58, 58, 64)   36928       ['re_lu_542[0][0]']              
                                                                                                  
 batch_normalization_4161 (Batc  (None, 58, 58, 64)  256         ['conv2d_4162[0][0]']            
 hNormalization)                                                                                  
                                                                                                  
 re_lu_543 (ReLU)               (None, 58, 58, 64)   0           ['batch_normalization_4161[0][0]'
                                                                 ]                                
                                                                                                  
 conv2d_4163 (Conv2D)           (None, 58, 58, 256)  16640       ['re_lu_543[0][0]']              
                                                                                                  
 conv2d_4160 (Conv2D)           (None, 58, 58, 256)  16640       ['max_pooling2d_23[0][0]']       
                                                                                                  
 batch_normalization_4162 (Batc  (None, 58, 58, 256)  1024       ['conv2d_4163[0][0]']            
 hNormalization)                                                                                  
                                                                                                  
 batch_normalization_4159 (Batc  (None, 58, 58, 256)  1024       ['conv2d_4160[0][0]']            
 hNormalization)                                                                                  
                                                                                                  
 re_lu_544 (ReLU)               (None, 58, 58, 256)  0           ['batch_normalization_4162[0][0]'
                                                                 ]                                
                                                                                                  
 re_lu_541 (ReLU)               (None, 58, 58, 256)  0           ['batch_normalization_4159[0][0]'
                                                                 ]                                
                                                                                                  
 add_1150 (Add)                 (None, 58, 58, 256)  0           ['re_lu_544[0][0]',              
                                                                  're_lu_541[0][0]']              
                                                                                                  
 re_lu_545 (ReLU)               (None, 58, 58, 256)  0           ['add_1150[0][0]']               
                                                                                                  
 conv2d_4164 (Conv2D)           (None, 58, 58, 64)   16448       ['re_lu_545[0][0]']  



...


conv2d_4312 (Conv2D)           (None, 8, 8, 512)    2359808     ['re_lu_741[0][0]']              
                                                                                                  
 batch_normalization_4311 (Batc  (None, 8, 8, 512)   2048        ['conv2d_4312[0][0]']            
 hNormalization)                                                                                  
                                                                                                  
 re_lu_742 (ReLU)               (None, 8, 8, 512)    0           ['batch_normalization_4311[0][0]'
                                                                 ]                                
                                                                                                  
 conv2d_4313 (Conv2D)           (None, 8, 8, 2048)   1050624     ['re_lu_742[0][0]']              
                                                                                                  
 batch_normalization_4312 (Batc  (None, 8, 8, 2048)  8192        ['conv2d_4313[0][0]']            
 hNormalization)                                                                                  
                                                                                                  
 re_lu_743 (ReLU)               (None, 8, 8, 2048)   0           ['batch_normalization_4312[0][0]'
                                                                 ]                                
                                                                                                  
 add_1199 (Add)                 (None, 8, 8, 2048)   0           ['re_lu_743[0][0]',              
                                                                  're_lu_740[0][0]']              
                                                                                                  
 re_lu_744 (ReLU)               (None, 8, 8, 2048)   0           ['add_1199[0][0]']               
                                                                                                  
 global_average_pooling2d_6 (Gl  (None, 2048)        0           ['re_lu_744[0][0]']              
 obalAveragePooling2D)                                                                            
                                                                                                  
 dense_6 (Dense)                (None, 200)          409800      ['global_average_pooling2d_6[0][0
                                                                 ]']                              
                                                                                                  
==================================================================================================
Total params: 58,780,744
Trainable params: 58,629,320
Non-trainable params: 151,424
__________________________________________________________________________________________________

+ Recent posts