12. Neural Network 기초
Perceptron, Backpropagation, Activation Functions
학습 목표
이 튜토리얼을 완료하면 다음을 이해할 수 있습니다:
- 신경망의 기본 구조 (뉴런, 레이어) 이해
- 활성화 함수 (Sigmoid, ReLU, Tanh, Softmax)의 역할과 특징
- 순전파 (Forward Propagation) 과정
- 역전파 (Backpropagation)와 Chain Rule
- 경사하강법을 통한 신경망 학습
- XOR 문제 해결을 통한 비선형 분류 이해
핵심 개념
1. Neural Network란?
뇌의 뉴런 구조를 모방한 머신러닝 모델입니다. 입력층, 은닉층, 출력층으로 구성되며, 각 층의 뉴런들이 연결되어 복잡한 패턴을 학습합니다.
입력층 은닉층 출력층
x1 ────┬───► h1 ────┬───► y
│ │
x2 ────┼───► h2 ────┤
│ │
└───► h3 ────┘2. Perceptron (단일 뉴런)
퍼셉트론은 가장 단순한 형태의 신경망으로, 입력에 가중치를 곱하고 편향을 더한 후 활성화 함수를 적용합니다.
z = w₁x₁ + w₂x₂ + ... + wₙxₙ + b
y = activation(z)class Perceptron:
def __init__(self, n_features, learning_rate=0.1):
self.weights = np.random.randn(n_features) * 0.1
self.bias = 0
self.lr = learning_rate
def step_function(self, z):
return (z >= 0).astype(int)
def predict(self, X):
z = np.dot(X, self.weights) + self.bias
return self.step_function(z)
def fit(self, X, y, epochs=100):
for epoch in range(epochs):
errors = 0
for xi, yi in zip(X, y):
prediction = self.predict(xi.reshape(1, -1))[0]
error = yi - prediction
# 가중치 업데이트
self.weights += self.lr * error * xi
self.bias += self.lr * error
errors += abs(error)
if errors == 0:
print(f'Epoch {epoch+1}: 수렴!')
break
return self단일 퍼셉트론은 선형 분리 가능한 문제만 해결할 수 있습니다. AND, OR 게이트는 학습 가능하지만, XOR 문제는 해결할 수 없습니다.
3. Activation Functions
활성화 함수는 뉴런의 출력을 비선형으로 변환하여 신경망이 복잡한 패턴을 학습할 수 있게 합니다.
| 함수 | 공식 | 범위 | 특징 |
|---|---|---|---|
| Sigmoid | 1/(1+e^(-z)) | (0, 1) | 확률 출력, Vanishing Gradient |
| Tanh | (e^z - e^(-z))/(e^z + e^(-z)) | (-1, 1) | 0 중심, Vanishing Gradient |
| ReLU | max(0, z) | [0, ∞) | 기본 선택, Dead ReLU 문제 |
| Leaky ReLU | max(0.01z, z) | (-∞, ∞) | Dead ReLU 해결 |
| Softmax | e^zᵢ / Σe^zⱼ | (0, 1) | 다중 분류 출력 |
def sigmoid(x):
return 1 / (1 + np.exp(-np.clip(x, -500, 500)))
def sigmoid_derivative(x):
s = sigmoid(x)
return s * (1 - s)
def relu(x):
return np.maximum(0, x)
def relu_derivative(x):
return (x > 0).astype(float)
def leaky_relu(x, alpha=0.01):
return np.where(x > 0, x, alpha * x)
def softmax(z):
exp_z = np.exp(z - np.max(z)) # 수치 안정성
return exp_z / exp_z.sum()활성화 함수 선택 가이드:
- 은닉층: ReLU (기본), Leaky ReLU (Dead neuron 방지)
- 이진 분류 출력층: Sigmoid
- 다중 분류 출력층: Softmax
- 회귀 출력층: Linear (활성화 없음)
4. Forward Propagation (순전파)
입력에서 출력으로 순차적으로 계산하는 과정입니다. 각 층에서 가중합을 계산하고 활성화 함수를 적용합니다.
def forward(X, W1, b1, W2, b2):
# Hidden layer
z1 = X @ W1 + b1
a1 = relu(z1)
# Output layer
z2 = a1 @ W2 + b2
a2 = sigmoid(z2)
return a25. Backpropagation (역전파)
출력에서 입력으로 역방향으로 그래디언트를 계산합니다. Chain Rule을 사용하여 각 가중치에 대한 손실 함수의 기울기를 구합니다.
Chain Rule:
∂L/∂w = ∂L/∂y × ∂y/∂z × ∂z/∂w2층 신경망 예시:
x → [W1] → z1 → [σ] → a1 → [W2] → z2 → [σ] → a2 → L
def backprop(X, y, a1, a2, W2):
m = len(y)
# Output layer gradient
dz2 = a2 - y
dW2 = (1/m) * a1.T @ dz2
db2 = (1/m) * np.sum(dz2, axis=0)
# Hidden layer gradient
dz1 = (dz2 @ W2.T) * relu_derivative(a1)
dW1 = (1/m) * X.T @ dz1
db1 = (1/m) * np.sum(dz1, axis=0)
return dW1, db1, dW2, db26. 다층 신경망 (MLP) 구현
XOR 문제를 해결하려면 은닉층이 필요합니다. 다음은 완전한 다층 신경망 구현입니다:
class NeuralNetwork:
def __init__(self, layer_sizes, learning_rate=0.1, activation='sigmoid'):
"""
layer_sizes: [입력, 은닉1, 은닉2, ..., 출력]
예: [2, 4, 1] = 2 입력, 4 은닉, 1 출력
"""
self.layer_sizes = layer_sizes
self.lr = learning_rate
self.n_layers = len(layer_sizes)
# Xavier initialization
self.weights = []
self.biases = []
for i in range(self.n_layers - 1):
w = np.random.randn(layer_sizes[i], layer_sizes[i+1]) * np.sqrt(2.0 / layer_sizes[i])
b = np.zeros((1, layer_sizes[i+1]))
self.weights.append(w)
self.biases.append(b)
def forward(self, X):
"""순전파"""
self.activations = [X]
self.z_values = []
A = X
for i in range(self.n_layers - 1):
Z = np.dot(A, self.weights[i]) + self.biases[i]
self.z_values.append(Z)
if i == self.n_layers - 2:
A = sigmoid(Z) # 출력층
else:
A = relu(Z) # 은닉층
self.activations.append(A)
return A
def fit(self, X, y, epochs=1000):
"""학습"""
for epoch in range(epochs):
output = self.forward(X)
loss = -np.mean(y * np.log(output + 1e-8) + (1 - y) * np.log(1 - output + 1e-8))
self.backward(X, y)
return selfXavier/He 초기화: 가중치를 적절한 분산으로 초기화하면 학습이 안정적으로 진행됩니다. np.sqrt(2.0 / n_input)을 사용하는 He 초기화는 ReLU와 함께 사용하기 좋습니다.
7. 손실 함수
| 문제 | 손실 함수 |
|---|---|
| 이진 분류 | Binary Cross-Entropy |
| 다중 분류 | Categorical Cross-Entropy |
| 회귀 | MSE |
# Binary Cross-Entropy
def bce_loss(y_true, y_pred):
epsilon = 1e-15
y_pred = np.clip(y_pred, epsilon, 1 - epsilon)
return -np.mean(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))8. Optimizer
| Optimizer | 특징 |
|---|---|
| SGD | 기본, 느림 |
| Momentum | 관성 추가, 수렴 속도 개선 |
| Adam | Adaptive + Momentum (기본 선택) |
| RMSprop | Adaptive learning rate |
학습률 설정 주의:
- 너무 작으면: 학습이 매우 느림
- 너무 크면: 발산하거나 진동
- 권장: 0.001 ~ 0.01로 시작하여 조정
9. Vanishing Gradient 문제
깊은 신경망에서 Sigmoid나 Tanh를 사용하면 역전파 시 기울기가 점점 작아져 학습이 어려워집니다.
기울기 소실 (Vanishing Gradient): Sigmoid의 최대 기울기는 0.25입니다. 5개 층을 통과하면 기울기가 0.25^5 ≈ 0.001로 감소합니다.
해결책:
- ReLU 활성화 함수 사용
- Batch Normalization
- Residual Connection (Skip Connection)
- 적절한 가중치 초기화
Keras/TensorFlow 코드
import tensorflow as tf
from tensorflow.keras import layers, models
# 모델 정의
model = models.Sequential([
layers.Dense(64, activation='relu', input_shape=(n_features,)),
layers.Dense(32, activation='relu'),
layers.Dense(1, activation='sigmoid')
])
# 컴파일
model.compile(
optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy']
)
# 학습
history = model.fit(
X_train, y_train,
epochs=100,
batch_size=32,
validation_split=0.2,
verbose=1
)
# 평가
loss, accuracy = model.evaluate(X_test, y_test)과적합 방지
Dropout
학습 시 무작위로 뉴런을 비활성화하여 과적합을 방지합니다.
model = models.Sequential([
layers.Dense(64, activation='relu'),
layers.Dropout(0.3), # 30% 뉴런 비활성화
layers.Dense(1, activation='sigmoid')
])Early Stopping
검증 손실이 더 이상 개선되지 않으면 학습을 조기 종료합니다.
from tensorflow.keras.callbacks import EarlyStopping
early_stop = EarlyStopping(
monitor='val_loss',
patience=10,
restore_best_weights=True
)
model.fit(X_train, y_train, callbacks=[early_stop])L2 Regularization
가중치의 크기를 제한하여 과적합을 방지합니다.
from tensorflow.keras import regularizers
layers.Dense(64, activation='relu',
kernel_regularizer=regularizers.l2(0.01))하이퍼파라미터 가이드
| 파라미터 | 권장값 | 설명 |
|---|---|---|
| Hidden units | 32, 64, 128, 256 | 문제 복잡도에 따라 조정 |
| Learning rate | 0.001, 0.01 | Adam 기본값 0.001 권장 |
| Batch size | 32, 64, 128 | 메모리와 수렴 속도 고려 |
| Dropout | 0.2 ~ 0.5 | 과적합 정도에 따라 조정 |
| Epochs | 100 ~ 1000 | Early Stopping과 함께 사용 |
면접 질문 맛보기
- Backpropagation의 원리는?
- ReLU의 장점과 단점은?
- Vanishing/Exploding Gradient 문제와 해결책은?
- 단일 퍼셉트론이 XOR 문제를 풀 수 없는 이유는?
- Xavier/He 초기화를 사용하는 이유는?
더 많은 면접 질문은 Premium Interviews (opens in a new tab)에서 확인하세요.
실습 노트북
노트북 추가 내용: 실습 노트북에서는 AND/OR/XOR 게이트 실험, Moon 데이터셋 분류, 학습률과 은닉층 크기에 따른 성능 비교, Scikit-learn MLPClassifier와의 비교, 그리고 결정 경계 시각화 등 더 심화된 내용을 다룹니다.
이전: 11. Time Series | 다음: 13. CNN