머신러닝 & 딥러닝

[딥러닝] 9. 언더피팅 & 오버피팅

김초송 2023. 5. 10. 15:00

언더피팅 문제 해결

1. 배치 정규화

  • 층이 깊어질수록 정규분포 모양이 틀어지는 것을 막는 방법
  • 신경망에 들어오는 데이터에 대한 학습 가중치(W) 에 대해서 강제로 정규성을 유지함
  • 활성화함수 전에 실행

출처 : https://gomguard.tistory.com/186, https://excelsior-cjh.tistory.com/178

import tensorflow as tf   # 텐써 플로우 2.0
from tensorflow.keras.datasets.mnist import load_data  # 텐써플로우에 내장되어있는 mnist 데이터를 가져온다.
from tensorflow.keras.models import Sequential  # 모델을 구성하기 위한 모듈
from tensorflow.keras.layers import Dense, Flatten, BatchNormalization  # 완전 연결계층을 구성하기 위한 모듈
from tensorflow.keras.utils import to_categorical # one encoding 하는 모듈
import numpy as np

tf.random.set_seed(777)

(x_train, y_train), (x_test, y_test) = load_data(path='mnist.npz')  # mnist 데이터 로드
   
# 2. 정규화 진행  
x_train = (x_train.reshape((60000, 28 * 28))) / 255
x_test = (x_test.reshape((10000, 28 * 28))) / 255

# 3. 정답 데이터를 준비한다.
# 하나의 숫자를 one hot encoding 한다. (예:  4 ---> 0 0 0 0 1 0 0 0 0 0 )
y_train = to_categorical(y_train)  # 훈련 데이터의 라벨(정답)을 원핫 인코딩
y_test = to_categorical(y_test)    # 테스트 데이터의 라벨(정답)을 원핫 인코딩


# 4. 모델을 구성합니다. 2층 신경망으로 구성
# (100, 784) ◎ ( 784, 100) = (100, 100) ◎ (100, 50 ) = (100, 50) ◎ (50, 10 ) = (100,10)
model = Sequential()            
model.add(Flatten(input_shape=(784,  ))) # 입력층(0층)
model.add(BatchNormalization())
model.add(Dense(100, activation='sigmoid' ))  # 은닉층(1층)
model.add(BatchNormalization())
model.add(Dense(50, activation ='sigmoid'))  # 은닉층 (2층)
model.add(Dense(10, activation='softmax'))  # 출력층 (3층)


# 5. 모델을 설정합니다. ( 경사하강법, 오차함수를 정의해줍니다. )
model.compile(optimizer='SGD',
              loss = 'categorical_crossentropy',
              metrics=['acc'])  # 학습과정에서 정확도를 보려고

#6. 모델을 훈련시킵니다.

history = model.fit(x_train, y_train,
                    epochs=30,  # 30에폭
                    batch_size=100,
                    validation_data=(x_test, y_test))

# 7.모델을 평가합니다. (오차, 정확도가 출력됩니다.)

model.evaluate(x_test, y_test)

# 위의 코드들 밑에 바로 구현

train_acc_list = history.history['acc']
test_acc_list = history.history['val_acc']

print(train_acc_list)
print(test_acc_list)

# 시각화
import matplotlib.pyplot as plt

x = np.arange(len(train_acc_list))
plt.plot(x, train_acc_list, label='train acc')
plt.plot(x, test_acc_list, label='test acc',  linestyle='--')
plt.legend(loc='lower right')
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.show()

 

2. 경사하강법 + 활성화 함수

- SGD

  • 확률적 경사하강법
  • 가중치 = 가중치 - 학습률 * 기울기
  • 배치단위로 복원 추출한 데이터를 학습

 - Adam

  • 관성을 이용해 local minimum 을 빠져나오는 Momentum
    + 학습률을 자동조절하는 Adagrade 를 결합
  • 모멘텀
    • 속도 = 마찰계수 * 속도 - 학습률 * 기울기
    • 가중치 = 가중치 + 속도

- RMSprop

  • Adagrade + 학습률 조절할 때 이전 경험을 바탕으로 조절
  • Adagrade
    •  h = h + 기울기 ◎ 기울기
    • 가중치 = 가중치 - 러닝레이트 * 기울기 * ( 1 / √h )

 

오버피팅 문제 해결

1. Drop out

  • 뉴런을 임의로 삭제하면서 학습 시키는 방법
  • 너무 많이 삭제하게 되면 훈련 데이터, 테스트 데이터 둘 다 정확도 떨어짐
  • 배치 정규화 다음에 실행
import tensorflow as tf   # 텐써 플로우 2.0
from tensorflow.keras.datasets.mnist import load_data  # 텐써플로우에 내장되어있는 mnist 데이터를 가져온다.
from tensorflow.keras.models import Sequential  # 모델을 구성하기 위한 모듈
from tensorflow.keras.layers import Dense, Flatten, BatchNormalization, Dropout  # 완전 연결계층을 구성하기 위한 모듈
from tensorflow.keras.utils import to_categorical # one encoding 하는 모듈
import numpy as np
tf.random.set_seed(777)

(x_train, y_train), (x_test, y_test) = load_data(path='mnist.npz')  # mnist 데이터 로드
   
# 2. 정규화 진행  
x_train = (x_train.reshape((60000, 28 * 28))) / 255
x_test = (x_test.reshape((10000, 28 * 28))) / 255

# 3. 정답 데이터를 준비한다.
# 하나의 숫자를 one hot encoding 한다. (예:  4 ---> 0 0 0 0 1 0 0 0 0 0 )
y_train = to_categorical(y_train)  # 훈련 데이터의 라벨(정답)을 원핫 인코딩
y_test = to_categorical(y_test)    # 테스트 데이터의 라벨(정답)을 원핫 인코딩

# 4. 모델을 구성합니다. 2층 신경망으로 구성
# (100, 784) ◎ ( 784, 100) = (100, 100) ◎ (100, 50 ) = (100, 50) ◎ (50, 10 ) = (100,10)
model = Sequential()            
model.add(Flatten(input_shape=(784,  ))) # 입력층(0층)
model.add(BatchNormalization())
model.add(Dropout(0.2))
model.add(Dense(100, activation='sigmoid' ))  # 은닉층(1층)
model.add(BatchNormalization())
model.add(Dropout(0.2))
model.add(Dense(50, activation ='sigmoid'))  # 은닉층 (2층)
model.add(Dense(10, activation='softmax'))  # 출력층 (3층)

# 5. 모델을 설정합니다. ( 경사하강법, 오차함수를 정의해줍니다. )
model.compile(optimizer='RMSprop',
              loss = 'categorical_crossentropy',
              metrics=['acc'])  # 학습과정에서 정확도를 보려고

#6. 모델을 훈련시킵니다.

history = model.fit(x_train, y_train,
                    epochs=30,  # 30에폭
                    batch_size=100,
                    validation_data=(x_test, y_test))

# 7.모델을 평가합니다. (오차, 정확도가 출력됩니다.)
model.evaluate(x_test, y_test)

# 위의 코드들 밑에 바로 구현
train_acc_list = history.history['acc']
test_acc_list = history.history['val_acc']
print(train_acc_list)
print(test_acc_list)

# 시각화
import matplotlib.pyplot as plt

x = np.arange(len(train_acc_list))
plt.plot(x, train_acc_list, label='train acc')
plt.plot(x, test_acc_list, label='test acc',  linestyle='--')
plt.legend(loc='lower right')
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.show()

2. Early Stopping

# 오버피팅 전에 epoch 중지
from tensorflow.keras.callbacks import EarlyStopping
callbacks = [EarlyStopping(monitor='val_acc', patience=4, verbose=1)]
model.fit(x_train, y_train, batch_size=100, validation_data=(x_test, y_test), 
          epochs=200, callbacks=callbacks)
  • monitor:  관찰하고자 하는 항목, val_loss / val_acc
    • val_acc: 테스트데이터 정확도
  • patience: 학습을 하는 도중 개선의 여지가 없어도 pass 하는 횟수
  • verbose: 훈련 되는 과정에서 조기종료한 이유 출력, 0 / 1 / 2, 숫자 클수록 자세히

3. 가중치 감소

  • 큰 가중치에 대해서 그에 상응하는 패널티 부여
  • dropout 다음에 실행
# L2 정규화 코드
model.add(Dense( 50, kernel_regular='l2',  activation='relu'))

 

본 내용은 아이티윌 '빅데이터&머신러닝 전문가 양성 과정' 을 수강하며 작성한 내용입니다.