CS/딥러닝

[딥러닝] 4. Deep Neural Network

CSE 2026. 3. 30. 10:39

 

 

일반적으로 layer수가 3이상이면 deep neural network라고 한다.

이전 글에서 봤던 Shallow neural network와 거의 비슷하지만 deep neural network에서 사용되는 notation을 한 번 더 확인하고 넘어가자.

두 번째 layer와 관련된 항들의 차원을 표시해보면 아래와 같다.

$z^{[2]} = W^{[2]} a^{[1]} + b^{[2]}$

$(5,1) = (5,3) (3,1) + (5,1)$

 

일반화하면 아래와 같이 쓸 수 있다.

$W^{[l]} : (n^{[l]}, n^{[n-1]})$

$b^{[l]} : (n^{[l]},1)$

 

 

아래 그림은 순전파와 역전파의 과정을 한 눈에 보여주는 다이어그램이다.

마지막으로 파이토치를 사용해 deep neural network를 구현한 코드를 한번 보자.

-5 < x < 5 의 범위를 그 외의 범위와 구분하는 예시이다.

직선 하나로 구분할 수 없는 문제이므로 hidden layer가 필요하다.

 

은닉층의 유닛 수는 10개로 구성했다.

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np


m = 10000
x1_train = np.random.uniform(-10, 10, m)
x2_train = np.random.uniform(-10, 10, m)


y_train = ((x1_train < -5) | (x1_train > 5)).astype(int)


X = torch.tensor(np.column_stack((x1_train, x2_train)), dtype=torch.float32)
Y = torch.tensor(y_train, dtype=torch.float32).unsqueeze(1) # (m, 1)


class onehiddenlayer(nn.Module):
    def __init__(self):
        super().__init__()

        self.linear1 = nn.Linear(2, 10)
        self.linear2 = nn.Linear(10, 1)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        out = self.linear1(x)
        out = self.sigmoid(out)
        out = self.linear2(out)
        out = self.sigmoid(out)
        return out

model = onehiddenlayer()

criterion = nn.BCELoss()

learning_rate = 0.01

optimizer = optim.SGD(model.parameters(), lr=learning_rate)

K = 5000

for epoch in range(K):
    
    outputs = model(X)           #순전파
    cost = criterion(outputs, Y) #현재 값이랑 정답(Y)랑 손실 계산
    
    optimizer.zero_grad() 
    cost.backward()        #오차 역전파
    
    optimizer.step()      #가중치 업데이트
    
    if (epoch + 1) % 500 == 0:
        print(f"\n[Iteration {epoch + 1}/{K}]")
        for name, param in model.named_parameters():
            if param.requires_grad:
                print(f"  {name}: {param.data.numpy().flatten()}")
        
        with torch.no_grad(): #테스트때는 기울기 계산하지마
            preds = (model(X) > 0.5).float() 
            correct_count = (preds == Y).sum().item() #다 더해서 텐서말고 일반 변수로 가져오기
            accuracy = (correct_count / m) * 100
            print(f"  -> Cost: {cost.item():.4f} | Accuracy: {accuracy:.2f}%")

print("\n--- 학습 완료 ---")

 

시각화를 한다면 아래처럼 나오게 된다.

점의 색은 정답을 의미하고,

모델이 분류하는 기준 (decision boundary)는 배경의 색으로 표현되었다.

 

 

 

Overfitting 막기

regularization은 overfitting을 막는 방법이다.

 

1. 손실함수 수정

추가된 항은 가중치 값이 너무 커지지 않도록 규제한다.

원래 역전파를 통해 가중치를 조절하는 식을 보면 $W = W - dW$꼴이다.

그런데 $dW$가 추가된 항으로 인해 바뀌게 되고,

따라서 아래 그림에서처럼 $W = kW - (backprop)$ 꼴이 된다.

여기서 $k$는 1보다 작으므로 가중치가 점점 줄어드는 효과가 생긴다.

 

여기서 사람이 직접 컨트롤하는 값 $\lambda$가 있는데, 이 값을 너무 크게 설정하면 모델은 너무 크게 가중치의 크기를 줄이려고 할 것이다.

이렇게 되면 가중치는 0에 가까워지고 결국 모델은 선형에 가까워진다.

이는 여러 층을 쌓는 의미를 흐리게 한다.

 

 

2. Dropout

다른 regularization의 방법인 Dropout이다.

훈련 중 유닛들을 확률적으로 비활성화 시키는 방법이다.

 

실제 추론시에는 모든 유닛을 활성화한다.

 

 

3. Data Augmentation

데이터 증강이라고 하는 것으로 훈련데이터를 늘리는 효과이다.

회전, 자르기, 반전 등의 조작을 가해서 여러 데이터를 만들어낸다.

4. Early Stopping

학습 중 성능을 평가해서 성능이 더 이상 좋아지지 않을 때 학습을 중단하는 방법이다.

 

5. Normalization

정규화라고 부르는 방법으로 평균과 분산을 이용해 데이터를 변형한다.

 

뭉쳐있는 데이터를 고르게 펼 수 있으므로 학습에 도움이 된다.