인공지능 개론 (9) : 모델 성능 향상시키기

STUDY_J·2024년 8월 23일
0

인공지능개론

목록 보기
10/13
  • 문제 :
    레드와인 샘플 1599개를 등급과 맛, 산도를 측정해 분석하고 화이트 와인 샘플 4898개를 마찬가지로 분석해 데이터를 만들었다.
    => 두 데이터를 합쳐 레드 와인과 화이트 와인을 구분하는 모델을 만들기

1. 모델 구현하기 (와인 구분)

  • 와인데이터 확인해보기
import pandas as pd

!git clone https://github.com/taehojo/data.git

df = pd.read_csv('./data/wine.csv', header = None)

df

  • 모델 생성 (검증셋 사용)
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from sklearn.model_selection import train_test_split

import pandas as pd

!git clone https://github.com/taehojo/data.git

df = pd.read_csv('./data/wine.csv', header = None)

X = df.iloc[:, 0:12]
y = df.iloc[:, 12]

X_train, X_test, y_train, y_test = train_test_split(X,y, test_size = 0.2, shuffle = True)

model = Sequential()
model.add(Dense(30, input_dim = 12, activation = 'relu'))
model.add(Dense(12, activation = 'relu'))
model.add(Dense(8, activation = 'relu'))
model.add(Dense(1, activation = 'sigmoid'))
model.summary()

model.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy'])
history = model.fit(X_train, y_train, epochs = 50, batch_size = 500, validation_split = 0.25)

score = model.evaluate(X_test, y_test)
print('Test accuracy:', score[1])

학습이 끝난 모델을 테스트해 보는 것이 테스트 셋의 목적이었다면, 최적의 학습 파라미터를 찾기 위해서 학습과정에서 사용하는 것이 검증 셋이다.

  • 검증셋을 설정하면 검증셋에 테스트한 결과를 추적하면서 최적의 모델을 만들 수 있다.
  • 검증셋을 사용하면 과적합을 방지하고, 모델의 성능을 조정할 수 있다


  • 3개의 은닉층, 각각 30, 12, 8개의 노드
  • 50번 반복시 정확도가 93.5%로 높은 결과를 나타낸다

2. 모델 업데이트하기 (성능향상)

학습을 많이 반복한다고 해서 모델 성능이 지속적으로 좋아지지는 않는다

  • 각 에포크마다 정확도를 함께 기록하면서 저장하고 몇 번의 반복 학습에서 가장 높은 정확도를 나타내는지 확인할 필요가 있음
  • 우선 에포크 수를 2000번으로 학습해보았다
history = model.fit(X_train, y_train, epochs = 2000, batch_size = 500, validation_split = 0.25)

history

  • model.fit()은 매 에포크마다 결과를 출력한다.
  • 일반적으로 loss 값이 출력되지만 model.compile()에서 metrics를 accuracy로 지정하면 accuracy도 함께 출력된다
model.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy'])
  • 검증셋을 지정한다면 검증셋의 val_lossval_accuracy도 같이 출력된다
  • historymodel.fit()의 결과를 가진 객체로, 모든 에포크 정보가 들어있다
  • history 데이터 프레임 확인해보기
hist_df = pd.DataFrame(history.history)
hist_df

2-1. 결과 확인하기

import numpy as np
import matplotlib.pyplot as plt

history = model.fit(X_train, y_train, epochs = 2000, batch_size = 500, validation_split = 0.25)

hist_df = pd.DataFrame(history.history)
hist_df

# y_vloss 에 검증셋의 오차를 저장
y_vloss = hist_df['val_loss']
# y_loss 에 학습셋의 오차를 저장
y_loss = hist_df['loss']

x_len = np.arange(len(y_loss))
plt.plot(x_len, y_vloss, "o", c = "red", markersize = 2, label = "Testset_loss")
plt.plot(x_len, y_loss, 'o', c = 'blue', markersize = 2, label = 'Trainset_loss')

plt.legend()
plt.xlabel('epochs')
plt.ylabel('loss')
plt.show()

학습이 진행될수록 학습셋의 오차는 줄어들지만, 검증셋(빨간색)의 오차는 다시 커진다
(과도한 학습으로 인해 과적합이 발생)

  • 이는 검증셋 오차가 커지기 직전까지 학습한 모델이 최적의 횟수로 학습한 모델이라는 것을 의미함
    • 검증셋의 오차가 커지기 전에 학습을 자동으로 중단시키고, 그때의 모델을 저장하는 방법이 필요함

3. 학습 자동중단 (검증셋의 오차를 확인하여 최적의 반복횟수 찾기)

  • 다시 학습을 시킬 때, 위에서 실행했던 학습에 누적되어 학습이 진행될 수 있다.
  • 따라서 다음 셀을 다시 실행해준다
X = df.iloc[:, 0:12]
y = df.iloc[:, 12]

X_train, X_test, y_train, y_test = train_test_split(X,y, test_size = 0.2, shuffle = True)

model = Sequential()
model.add(Dense(30, input_dim = 12, activation = 'relu'))
model.add(Dense(12, activation = 'relu'))
model.add(Dense(8, activation = 'relu'))
model.add(Dense(1, activation = 'sigmoid'))
model.summary()

model.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy'])
history = model.fit(X_train, y_train, epochs = 50, batch_size = 500, validation_split = 0.25)

score = model.evaluate(X_test, y_test)
print('Test accuracy:', score[1])

  • 그러면, 검증셋의 오차가 낮아지지 않을 경우 학습을 종료하는 코드를 작성해보기
from tensorflow.keras.callbacks import EarlyStopping

early_stopping_callback = EarlyStopping(monitor = 'val_loss', patience = 20)
# monitor 옵션은 model.fit()의 실행 결과 중 어떤 것을 이용할지 정하는 것 : 여기서는 검증셋의 오차를 지정
# patience 값은 지정된 값이 몇 번 이상 향상되지 않으면 학습을 종료시킬지 정하는 것 
# 즉, 검증셋의 오차가 20번 이상 낮아지지 않을 경우 학습을 종료하라는 뜻

#최적화 모델이 저장될 폴더와 모델 이름을 저장
modelpath = './data/model/Ch-14-4-bestmodel.keras'

# 최적화 모델을 업데이트하고 저장
checkpointer = ModelCheckpoint(filepath = modelpath, monitor = 'val_loss', verbose = 0, save_best_only = True)

# 모델 실행
history = model.fit(X_train, y_train, validation_split = 0.25, epochs = 2000, batch_size = 500, verbose = 1, callbacks = [early_stopping_callback, checkpointer])

위에서 실행했던 기본 소스가 93.8% 의 정확도를 나타낸 것에 비해, 검증셋의 정확도가 높은 것을 확인할 수 있음

  • 그러면 테스트셋을 사용하여 정말 잘 학습이 되었는지 확인해보기
score = model.evaluate(X_test, y_test)
print('Test accuracy:', score[1])

  • 테스트 셋의 정확도는 98.3% 로 기본 소스로 학습을 했을 때보다 약 4% 더 높은 정확도를 나타낸다
    즉, 검증셋을 추가하고 검증셋의 오차가 줄어들지 않는 지점을 찾아서 학습모델의 적합한 반복횟수를 찾아낼 수 있다

4. 최종 summary

  1. 학습셋과 테스트셋 분리의 중요성
  • 딥러닝 모델을 학습할 때, 데이터를 학습셋테스트셋으로 분리하는 것은 매우 중요함
  • 과적합은 모델이 학습 데이터에 너무 맞춰져서 새로운 데이터에 대한 성능이 떨어지는 현상을 말함
  • 테스트셋은 모델이 학습하지 않은 데이터로, 이를 통해 모델이 실제로 새로운 데이터를 얼마나 잘 처리하는지, 즉 과적합 여부를 판단할 수 있음
  1. 검증셋 추가로 모델 성능 향상
  • 테스트셋을 사용하는 것만으로는 학습 중 과적합을 사전에 방지할 수 없음
  • 따라서 검증셋을 추가해 학습 중 모델의 성능을 모니터링하면, 과적합을 방지하고 모델의 성능을 최적화할 수 있음
  • 검증셋은 학습하는 동안 모델이 지나치게 학습되지 않도록 도와주며, 학습이 진행되는 과정에서 하이퍼파라미터나 반복 횟수를 조정할 수 있는 기준이 됨
  1. 반복 학습이 많을수록 좋은 것은 아니다
  • 모델을 반복해서 학습시키는 것이 무조건 성능을 높이는 것은 아님
  • 반복 횟수가 많아질수록 검증셋의 성능이 더 이상 좋아지지 않고 오히려 악화될 수 있음
  • 이때 검증셋을 사용하면 학습셋과 검증셋의 오차를 비교하여, 어느 지점에서부터 과적합이 시작되는지 알 수 있음
  • 검증셋의 오차가 더 이상 줄어들지 않는 시점을 확인해 적절한 학습 반복 횟수를 찾는 것이 중요함
  1. 최적의 반복 횟수를 찾아 최적화된 모델을 얻기
  • 검증셋의 오차가 줄어들지 않는 지점을 파악하면, 그 시점이 최적의 학습 반복 횟수임을 알 수 있음
  • 그 후, 해당 반복 횟수만큼 학습을 시키고 최종적으로 테스트셋을 사용해 모델의 성능을 평가
  • 이를 통해 학습되지 않은 테스트셋에서의 최적화된 성능을 확인할 수 있으며, 과적합을 방지하면서도 높은 정확도를 달성할 수 있음

0개의 댓글