본문 바로가기

Data Science/Deep Learning

딥러닝 모델 개선 | 2. DNN 모델의 크기를 변경하는 방법

딥러닝 모델 개선 방법

  1. Epoch 수와 과적합
  2. DNN 모델 크기 변경
  3. Dropout Layer 추가를 통한 Overfitting 규제
  4. Batch Normalization (배치정규화)
  5. Optimizer의 Learning rate(학습율) 조정을 통한 성능 향상
  6. Hyper parameter tuning

 


2. DNN 모델의 크기를 변경하는 방법

DNN 모델 크기

  • 모델의 layerunit 수가 많을 수록 복잡한 모델이 된다.
    • Overfitting일 경우 모델을 간단하게 만들고 Underfitting일 경우 모델을 크게 만든다
      ⇒ 큰 모델에서 시작하여(overfitting 발생, 최적화 가능) ⇒ layer나 unit수를 줄여가며 validation loss의 감소 추세를 관찰해 최적화
      - linear에서는 특정 수를 784→200→100→50 이렇게 unit수를 절반씩 줄여나가는 경우 많다.
데이터에 비해 작은 모델의 특징 데이터에 비해 큰 모델의 특징
- Train/Validation 성능 개선의 속도가 느리다.

→ 반복횟수가 충분하지 않으면 학습이 덜된 상태에서 중단될 수 있다.

- Underfitting이 발생할 가능성이 크다.
- Validation 이 성능이 학습 초반부터 나빠진다.

- Train에 대한 성능은 빠르게 개선된다.

- Overfitting 발생할 가능성이 크다.

 

 

 

모델의 크기에 따른 성능 변화

< 모델이 작은 경우>  

모델이 작은 경우 성능 개선이 충분히 이루어지지 않은 상태에서(성능 개선이 진행되는 와중에) epoch이 끝나는 경향을 보인다 → 따라서 모델 학습을 더 진행시킨다.

작은 모델을 정의한 후 → 모델 객체를 만들고 → 모델에 학습을 진행해보자
이는 1. 모델 정의(Smallsizemodel(nn.Module)) 2. 모델 생성(모델 변수 = 모델객체생성) → 3. 손실함수 정의(CrosseEntropyLoss) + 최적화 함수 정의(torch.optim.Adam) 4. 학습(module.fit) 단계를 따른다.

 

1. 모델 정의

class SmallsizeModel(nn.Module):
    
    def __init__(self):
        super().__init__()
        self.output = nn.Linear(784, 10) #layer가 1개인 모델
        #in: feature 수 - (1*28*28), out: class개수(10)
        
    def forward(self, X) :
        out = nn.Flatten()(X)
        out = self.output(out)
        return out

2. 모델 생성

small_model = SmallsizeModel()
torchinfo.summary(small_model, (BATCH_SIZE,1,28,28))

3. 손실함수 정의(CrosseEntropyLoss) + 최적화 함수 정의(torch.optim.Adam

# loss
loss_fn = nn.CrossEntropyLoss() 

# optimizer
optimizer = torch.optim.Adam(small_model.parameters(), lr =LR)

4. 학습 (module.fit())

train.py 모듈(학습 모듈)에 저장했던 학습함수+검증함수인 fit함수 dataloader와(train_loader, test_loader)모델( small_model), 손실함수와 최적화함수, 에폭수를 넣고, 추가적으로 모델 저장여부 +경로, device, mode를 정의하여 학습한다.

# train -> module.fit()
train_loss_list, train_acc_list, valid_loss_list, valid_acc_list = \
 train.fit(train_loader, test_loader, small_model, loss_fn, optimizer,
           N_EPOCH, 
           save_best_model=True,
           save_model_path=os.path.join(MODEL_SAVE_ROOT_PATH, "small_model.pth"),
           device=device, 
           mode="multi")

 

아래 그래프는 모델 학습이 끝난 이후의 Epoch횟수가 늘어남에 따라 trian set과 validation set의 loss와 accuracy를 그래프로 나타낸 것이다.
- loss 그래프를 보면, validation set에서 더 성능 개선이 일어나고 있는 와중에 Epoch가 중단되었으므로, 더 많은 학습을 시켜 과소적합문제를 해결하고, 모델 성능을 개선한다.



< 모델이 큰 경우>  

모델이 작은 겨우와 동일하게 모델정의후, 모델을 생성해 손실함수와 최적화함수를 정하고 학습하는 단계를 따른다. 다만 큰 모델로 바뀐다. 
1. 
모델 정의(Smallsizemodel(nn.Module)) 2. 모델 생성(모델 변수 = 모델객체생성) → 3. 손실함수 정의(CrosseEntropyLoss) + 최적화 함수 정의(torch.optim.Adam) 4. 학습(module.fit) 단계



1.  모델 정의 + 2. 모델 생생

#이번엔 큰사이즈의 모델을 만들어보자 -> 과대적합문제와 관련
class BigSizeModel(nn.Module):
    
    def __init__(self):
        super().__init__()
        self.b1 = nn.Sequential(nn.Linear(784, 2048), nn.ReLU()) #layer가 6개, 2048개의 feature로 시작
        self.b2 = nn.Sequential(nn.Linear(2048, 1024), nn.ReLU())
        self.b3 = nn.Sequential(nn.Linear(1024, 512), nn.ReLU())
        self.b4 = nn.Sequential(nn.Linear(512, 256), nn.ReLU())
        self.b5 = nn.Sequential(nn.Linear(256, 128), nn.ReLU())
        self.b6 = nn.Sequential(nn.Linear(128, 64), nn.ReLU())
        
        self.output = nn.Linear(64, 10)
        
    def forward(self, X):
        X = nn.Flatten()(X)
        out = self.b1(X)
        out = self.b2(out)
        out = self.b3(out)
        out = self.b4(out)
        out = self.b5(out)
        out = self.b6(out)
        return self.output(out)
        
#모델 생성
big_model = BigSizeModel()
torchinfo.summary(big_model, (BATCH_SIZE, 1, 28, 28))

 loss 그래프를 보면,  traindata set은 loss가 점점 줄어들어 성능이 개선되는 반면 validation set은 성능이 초반부터 나쁠뿐더러 train set과의 차이를 보이고 있다. 이는 과대적합 문제가 발생했다는 것이므로,

layer나 unit수를 줄이거나, epoch수를 줄여 학습을 덜하거나, data의 양을 늘려 과대적합문제를 해결해야한다.