[DL] 성능 관리

송아지·2024년 11월 2일

Deep Learning

목록 보기
3/7

1. 모델의 복잡도

  • 너무 단순한 모델 -> train, val 성능이 떨어짐
  • 적절히 복잡한 모델 -> 적절한 예측력
  • 너무 복잡한 모델 -> train 성능이 높고, val 성능이 떨어짐 -> 과적합
  • 복잡하다고 무조건 과적합을 일으키진 않음. 하지만 과할 경우 과적합

1-1. 딥러닝에서 모델의 복잡도를 조절하는 방법

  1. Epoch와 learning_rate
  2. hidden layer 수, node 수
  3. Early Stopping
  4. Dropout
  5. 가중치 규제

2. Early Stopping

  • epoch가 많으면 과적합 될 수 있음
    • 반복횟수가 증가할 수록 val error이 줄어들다가 어느 순간 다시 증가 가능
  • val error가 더 이상 줄어들지 않을 경우 멈추는 방법으로 과적합 방지
    • Early stopping

2-1. 코드

  • monitor
    • 주목할 값
    • default = val_loss
  • min_delta
    • 오차의 최소값에서 얼마나 감소해야 감소로 인정하는 지
    • default = 0
  • patience
    • 오차가 더 이상 줄어들지 않은 상황에서 얼마나 더 학습할 것인지
    • default = 0
from keras.callbacks import EarlyStopping

es = EarlyStopping(monitor = 'val_loss', min_delta = 0.01, patience = 5)
# val_loss가 0.01 이상 감소하지 않은 상태가 5번 발생할 경우 학습 종료

model.fit(x_train, y_trin, epochs = 100, 
		  validation_split = 0.2, callbacks = [es])

2-2. 문제점

  • 오차율이 가장 낮을 때의 가중치가 아닌, 추가 학습을 진행하였을 때(ex) 오차가 5번 학습할 동안 더 이상 감소하지 않을 경우)의 가중치를 사용

2-3. 해결

  • 중간 체크 포인트 저장
  • ModelCheckPoint
from keras.callbacks import ModelCheckpoint

cp_path = '/content/best_model.keras' # 코랩에선 모든 작업들이 /content/에 저장됨
mcp = ModelCheckpoint(cp_path, monitor = 'val_loss', verbose = 1, save_best_only = True)
# 최고 성능 모델 저장

model.fit(x_train, y_trin, epochs = 100, 
		  validation_split = 0.2, callbacks = [mcp])
        
from keras,models import load_model
model = load_model('best_model.keras') # 최고 성능 모델을 불러옴

3. Dropout

  • 과적합을 줄이기 위한 방법
  • 훈련 과정에서 신경망의 일부 뉴런을 임의로 비활성화
  • 훈련 배치에서 랜덤하게 선택된 일부 뉴런 제거
  • 매 epochs 마다 다른 뉴런을 비활성화 -> 앙상블 효과

3-1. 코드

model = Sequential( [Input(shape = (x_train.shape[1],)),
                      Dense(128, activation= 'relu'),
                      Dropout(0.4),    # 40% 제거
                      Dense(64, activation= 'relu'),
                      Dropout(0.4),
                      Dense(32, activation= 'relu'),
                      Dropout(0.4),
                      Dense(1, activation= 'sigmoid')] )
  • 보통 0.2 ~ 0.5의 범위 지정
  • feature가 적을 경우 rate를 낮추고, 많을 경우 rate를 높임

4. 딥러닝 모델 함수

from tensorflow.keras import Sequential, Input, Model
from tensorflow.keras.layers import Dense, Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from tensorflow.keras.models import load_model
from tensorflow.keras.backend import clear_session
from sklearn.metrics import *
import numpy as np
import matplotlib.pyplot as plt

# x_train, y_train, x_val, y_val 모두 스케일링이 된 상태여야 함
# 다중 분류 일 경우 정수 인코딩 상태여야함
def deep_learning_model(type, Dense_node = [], act = 'relu', drop_rate = 0,learn = 0.01, min_del = 0, pati_num = 0, epochs_size = 50, ver = 0) :
    # type는 binary, multi, regg 중 하나 입력
    # Dense_node : 은닉 layer의 노드 수를 리스트로 입력
    # act : 은닉 layer의 활성함수
    # learn : learning_rate
    # epochs_size : 에폭 사이즈
    # ver : verbose 지정
    
    clear_session()
    
    
    # 첫번째 레이어는 input_shape가 필요.
    layer_list = [Input(shape = (x_train.shape[1],))]


    if len(Dense_node) != 0 :
        # 주어진 레이어 수에 맞게 레이어 추가
      for i in range(len(Dense_node)) :
        layer_list.append(Dense(Dense_node[i] , activation = act))
        layer_list.append(Dropout(drop_rate))

    # 회귀 모델
    if type == 'regg' :
      layer_list.append(Dense(1))
      
      loss_method = 'mse'
      

    # 이진 분류
    elif type == 'binary' :
      layer_list.append(Dense(1, activation = 'sigmoid'))

      loss_method = 'binary_crossentropy'
    
    # 다중 분류
    elif type == 'multi' :
      layer_list.append(Dense(len(np.unique(y_train)), activation = 'softmax'))
      
      loss_method = 'sparse_categorical_crossentropy'
    else:
      raise ValueError("type은 'regg', 'binary', 'multi' 중 하나여야 합니다.")

    model = Sequential(layer_list)
    print(model.summary())

    model.compile(optimizer=Adam(learning_rate = learn), loss = loss_method)

    es = EarlyStopping(monitor = 'val_loss', min_delta = min_del, patience = pati_num)
    cp_path = '/content/best_model.keras' # 코랩에선 모든 작업들이 /content/에 저장됨
    mcp = ModelCheckpoint(cp_path, monitor = 'val_loss', verbose = ver, save_best_only = True)  

    history = model.fit(x_train, y_train, epochs = epochs_size, validation_split= 0.2, verbose = ver, callbacks = [es, mcp]).history
    plt.plot('loss', data=history, label = 'train', marker = '.')
    plt.plot('val_loss', data=history, label = 'val', marker = '.')
    plt.grid()
    plt.legend()
    plt.show()

    model = load_model(cp_path)

    pred = model.predict(x_val)

    if type == 'regg' :
      print(f'RMSE : {root_mean_squared_error(y_val, pred)}')
      print(f'MAE  : {mean_absolute_error(y_val, pred)}')
      print(f'MAPE : {mean_absolute_percentage_error(y_val, pred)}')
    elif type == 'binary' :
      pred = np.where(pred >= .5, 1, 0)
      print(confusion_matrix(y_val, pred))
      print(classification_report(y_val, pred))
    else :
      pred = pred.argmax(axis=1)
      print(confusion_matrix(y_val, pred))
      print(classification_report(y_val, pred))
profile
데이터 분석가&엔지니어를 희망하는 취준생

0개의 댓글