본문 바로가기
C.W.K.
Stream
Lesson 04 of 07 · published

건너뛰기 연결과 residual block

~8 min · functional

Level 0Keras 도제
0 XP0/97 lessons0/20 achievements
0/120 XP to next level120 XP to go0% complete

깊은 신경망을 학습하게 만든 연결

건너뛰기 연결은 x = Conv2D(...)(input), x = Conv2D(...)(x)로 변환한 결과에 keras.layers.add([x, input])으로 원래 입력을 더해. 블록이 변환값만 내는 것이 아니라 입력과 변환의 합을 계산하는 셈이야. 이것이 ResNet의 핵심 발상이야.

원래 입력이 왜 도움이 될까

ResNet이 나온 2015년 전에는 레이어를 수십 개 쌓으면 오히려 학습이 어려워지고 정확도가 떨어졌어. 건너뛰기 연결은 두 가지 방식으로 문제를 줄였지. 첫째, 역전파 기울기가 중간의 모든 비선형 연산을 거치지 않고 원래 경로로 흐를 수 있어 기울기 소실이 완화돼. 둘째, 블록은 전체 변환을 새로 배우는 대신 입력 위에 더할 작은 잔차만 학습하면 돼. 이 구조 덕분에 50층, 152층 모델도 학습할 수 있게 됐고 현대 언어 모델의 Transformer 블록을 비롯한 깊은 신경망 전반에 쓰여.

layers.add([x, shortcut])는 원소별 덧셈이므로 두 텐서의 모양이 같아야 해. 블록이 채널 수를 바꾸거나 다운샘플링한다면 shortcut에도 1×1 합성곱이나 Dense를 넣어 같은 모양으로 투영해야 해. 이 불일치가 residual block 생성 실패의 가장 흔한 원인이야.

Code

Residual block 하나를 모델에서 두 번 사용·python
# A simple residual block
def residual_block(x, filters):
    shortcut = x  # Save the input

    x = layers.Dense(filters, activation="relu")(x)
    x = layers.Dense(filters)(x)

    # Add the skip connection
    x = layers.add([x, shortcut])
    x = layers.Activation("relu")(x)
    return x

# Use it in a model
inputs = keras.Input(shape=(128,))
x = layers.Dense(128, activation="relu")(inputs)
x = residual_block(x, 128)
x = residual_block(x, 128)
outputs = layers.Dense(10, activation="softmax")(x)
model = keras.Model(inputs, outputs)

External links

Exercise

입력 → Conv → BN → ReLU → Conv → BN → 입력 더하기 → ReLU 순서의 ResNet 블록을 Functional API로 작성해. 출력과 입력 모양이 다르면 shortcut에 1×1 합성곱을 추가해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.