🖇 1. 딥러닝 모델의 구조
🖇 2. 레이어란?
🖇 3. 주요 레이어의 종류와 예시
🖇 4. 활성화 함수 종류와 특징
🖇 5. 레이어 예제: Dense Layer와 랜덤 입력
딥러닝 모델을 만들기 위해서는 모델의 구성 요소들이 어떤 역할을 하고, 어떻게 연결되는지를 정확히 이해해야 한다.
이 글에서는 Keras에서 딥러닝 모델을 구성할 때 활용하는 주요 API 구조와 레이어(Layer)의 개념, 종류, 특징, 실제 코드 사용법의 순서로 정리해 보았다.
입력 → 레이어 → 출력 → 손실 함수로 이어지는 기본 흐름을 바탕으로 딥러닝 모델이 내부적으로 어떻게 작동하는지 감을 잡는 데 도움이 될 것이라 생각한다.
딥러닝 모델은 여러 구성 요소로 나뉘고, Keras에서는 크게 세 가지 API 계층으로 볼 수 있다.

Core Modules API: 딥러닝의 기본을 이루는 요소들이 포함된다. 모델을 학습하고 평가할 때 꼭 필요한 기능들이다.
Model API: 모델 구조를 정의하는 방식이다. Sequential API는 레이어를 순서대로 쌓는 방식이고, Functional API는 더 복잡한 모델을 만들 수 있는 함수형 연결 방식이다. 이와 관련해서는 다음 글에서 다뤄 볼 예정이다.
Layer API: 실제로 모델을 구성하는 레이어들을 정의한다.문제 유형과 데이터 형태에 따라 적절하게 선택해서 조합한다.
이처럼 Keras는 세 가지 API를 통해 딥러닝 모델을 구성하는 전체 구조를 레고 블록처럼 조립할 수 있게 해준다. 각각의 구성요소는 독립적이지만 조합해서 더 강력한 모델을 만드는 게 가능하다.
딥러닝 모델은 여러 개의 레이어(Layer) 로 구성된다.
레이어는 딥러닝 모델에서 정보를 처리하는 기본 단위라고 생각할 수 있다. 구조는 일반적으로 다음과 같다.
[Input Layer] → [Hidden Layer 1] → [Hidden Layer 2] → ... → [Output Layer]
각 레이어는 입력 데이터를 받아서 가중치와 바이어스를 적용하고, 활성화 함수를 통해 출력을 변환한다. 이렇게 변환된 출력은 다음 레이어로 전달되고, 이런 과정이 반복되면서 점점 더 복잡한 함수를 학습하게 된다. 결국 이 구조가 딥러닝 모델의 핵심인 것이다.
💡 쉽게 말하면, 레이어는 정보를 점점 더 복잡하게 바꿔주는 필터 역할을 한다고 보면 된다. 하나의 레이어는 간단한 연산만 하더라도 여러 개가 쌓이면 복잡한 패턴도 잘 잡아낸다.
모델의 입력 형상을 정의할 때 사용한다. shape, dtype, batch_size, name 등을 설정할 수 있다.
keras.Input(shape=(28, 28), dtype=tf.float32)
keras.Input(shape=(28, 28), dtype=tf.float32, batch_size=16, name='input')
Input은 말 그대로 모델에 데이터를 넣는 입구 역할이다. 모델 설계 시 가장 먼저 정의해 줘야 한다.
모든 입력 노드와 출력 노드를 연결하는 기본 레이어다. (Fully Connected) 유닛 수를 지정하면 해당 개수만큼의 뉴런이 만들어진다. name, activation 등도 설정 가능하다.
layers.Dense(10)
layers.Dense(10, name='layer1')
layers.Dense(10, activation='relu', name='dense_layer')
입력 뉴런: x₁ x₂ x₃
\ | /
\ | /
\ | /
\ | /
Dense Layer
/ | \
/ | \
y₁ y₂ ← 출력 뉴런
이렇게 입력의 모든 노드가 출력의 모든 노드에 연결돼 있어서 모든 조합에 대해 계산이 이루어지는 구조다.
대부분의 MLP에서 가장 많이 쓰이는 레이어로, 뉴런마다 입력을 모두 받아서 가중치 곱을 수행한 뒤 바이어스를 더한다.
다차원 입력을 1차원으로 변환해주는 레이어다. 주로 CNN 모델에서 Fully Connected Layer로 연결할 때 사용한다.
inputs = keras.Input(shape=(28, 28, 1))
layer = layers.Flatten()(inputs)
print(layer.shape) # 출력: (None, 784)
Flatten은 CNN에서 마지막에 Dense와 연결하기 전에 꼭 필요하다. (e.g., MNIST 숫자 분류에서 28x28 이미지를 784 벡터로 펴기)
활성화 함수만 따로 쓰고 싶을 때 사용하는 레이어다. Dense 안에 넣을 수도 있지만, 더 명시적으로 표현할 수 있다. 비선형성을 추가해서 복잡한 함수 근사가 가능해진다.
layer = layers.Activation('relu')
명시적으로 레이어를 나눔으로써 네트워크 구조가 더 읽기 쉬워지고, 중간에 수정하거나 실험할 때 유리하다.
1) Sigmoid 함수
2) tanh (하이퍼볼릭 탄젠트)
3) ReLU (Rectified Linear Unit)
4) Leaky ReLU
5) ELU (Exponential Linear Unit)
| 함수명 | 출력 범위 | 특징 |
|---|---|---|
| Sigmoid | 0 ~ 1 | 확률 해석 쉬움, gradient vanishing 문제 |
| Tanh | -1 ~ 1 | 중심 0, sigmoid보다 학습 빠름 |
| ReLU | 0 ~ ∞ | 가장 많이 사용, 계산 빠름, dying 문제 |
| Leaky ReLU | (-∞, ∞) | ReLU 보완, 음수 영역도 gradient 유지 |
| ELU | (-α, ∞) | 중심 0, 빠른 수렴, 계산 비용 높음 |
ReLU와 그 변형 함수들은 대부분의 모델에서 성능이 잘 나오기 때문에 기본값처럼 사용된다. 상황에 따라 적절한 선택이 필요하다.
inputs = tf.random.uniform(shape=(5, 2))
layer = layers.Dense(10, activation='relu')
outputs = layer(inputs)
print(layer.weights)
print(layer.bias)
print(outputs)
이 코드는 5×2 크기의 입력 데이터를 무작위로 만든 다음, Dense 레이어를 거쳐서 출력 결과와 가중치, 바이어스를 출력해 보는 예시다. 레이어 내부에서 어떤 연산이 이루어지는지 직접 확인해볼 수 있다.
출력 결과를 보면 레이어가 입력 데이터를 어떻게 처리하고 변환하는지 눈으로 확인할 수 있어서 직관적인 학습에 도움이 된다.
딥러닝 모델은 다양한 구성 요소와 레이어로 이루어져 있고, 각각의 레이어는 입력 데이터를 가공해서 다음 단계로 전달하는 역할을 한다.
모델 구조는 Sequential 방식으로 간단하게 쌓을 수도 있고, Functional 방식으로 유연하게 만들 수도 있다는 것을 알 수 있었다.
Input 객체로 입력을 정의하고, Dense나 Flatten, Activation 같은 레이어들을 조합해서 모델을 구성하게 된다. 또, 어떤 활성화 함수를 쓰느냐에 따라서 학습 속도와 성능이 달라질 수 있으니까 그 특성을 잘 이해하고 모델에 맞는 걸 선택하는 것이 중요하겠다.
이런 기본 개념들을 잘 익히고 직접 실습해본다면 딥러닝을 좀 더 이해할 수 있을 거라 생각한다.