👩‍💻LEARN : ML&Data/Book Study

[모두의 딥러닝] #4-13. 모델 성능 검증하기

쟈니유 2023. 2. 19. 22:54
728x90

모델을 만들었으면 성능을 검증해보자

 

 

앞서 모델 만들기 까지는

1. 우선 모델을 만들고 (모델 레이어 설정, 오차함수 및 경사하강법 설정)

2. epoch 만큼 모델을 실행해서 history에 저장했다. 

 

이젠 학습셋과 검증셋을 분리하여 

이게 진짜 ...괜찮나...? 확인해봐야 한다. 

 

 


#4-13. 모델 성능 검증하기 

 

우선 이번에도, 실습을 하면서 새로운 개념을 익히는 것이기 때문에

먼저 따라해보고 새로 배운 내용 + 기억해야할 내용 위주로만 정리해보려고 한다.

 

#라이브러리 가저오기

import pandas as pd

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense


#data가져오기


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

# X, Y setting

X = df.iloc[:,:60]
y = df.iloc[:,60]

#과적합 방지를 위해 테스트셋 구분

from sklearn.model_selection import train_test_split

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


#모델 설정

model = Sequential()

model.add(Dense(24,input_dim=60, activation='relu'))
model.add(Dense(10,activation = 'relu'))
model.add(Dense(1,activation = 'sigmoid'))

#compile

model.compile(loss='binary_crossentropy', optimizer = 'adam', metrics=['accuracy'])

history = model.fit(X_train,y_train, epochs=200, batch_size=10)

#Get accuracy with model-test set

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

 

학습셋과 테스트셋 분리 

목적 : 과적합 방지. 학습이 계속되면 학습셋에서의 에러는 줄어들지만 테스트셋에서는 에러가 올라감 (과적합)

방법 : 사이킷런(sklearn)에서 train_test_split() 함수 이용하여 구분 가능 

train_test_split() 사용법 
- sklearn.model_selection에 있는 함수 
- 모델 설정 이전에 사용 
- 파라미터(입력값)
  : train_test_split(arrays,test_size,train_size,random_state,shuffle,stratify)
    arrays - 나눌 데이터셋 (x,y를 둘다 넣는 경우 그냥 차례대로 넣으면 됨)
    test_size - 검증셋을 몇프로로 할 것인 지 
- Return 값 
  : X_train, X_test, y_train, y_test 로 각각 저장됨 

 

학습셋에서 만든 모델 테스트셋에 적용하기 

model.evaluate (x,y)
- loss, accuracy를 차례대로 계산해서 출력함 

 

모델 저장하고 불러오기 

model.save('위치') 
: 모델 저장하기 
del model
: 저장된 모델 삭제하기 
from tensorflow.keras.models import Sequential, load_model 
model = load_model('위치')
: 모델 지정된 위치에서 불러오기 

 


K겹 교차 검증 

 

  • 목적 : 데이터 수가 한정되어 있지만 모델 성능을 높이고 싶을 때 
  • 방법 : 데이터 셋을 k개로 나눈 다음, 각각의 데이터셋 마다 테스트셋-학습셋을 다른 데이터셋과 겹치지 않게 나누어 k번 evaluate하는 것 
  • 사용 함수 
from sklearn.model_selection import KFold 

k=n                                                                      # 몇개의 데이터셋으로 나눌 지 설정 
kfold = KFold(n_splits=k, shuffle=True)         # KFold 함수 설정 
acc_score = []                                                   # 정확도 accuracy를 넣어줄 빈 리스트 만들기 

for train_index, test_index in kfold.split(X):   # .split에 인해 kfold에서 선언한 k개 만큼 쪼개지게됨 (train,test 각각 쪼개질 인덱스 넘버를 반환하는듯? ) 
   X_train, X_test = X.iloc[train_index, :], X.iloc[test_index, :]
   y_train, y_test = y.iloc[train_index], y.iloc[text_index] 

  accuracy = model.evaluate(X_test, y_test)[1]
  acc_score.applend(accuracy) 

 

하지만 이렇게만 한다고 뭐든게 해결되는 것이 아니다...왜냐하면 모델도 반복해야하기때문...

모델 반복까지 for문에 넣은 토탈 버전은 아래와 같다 

 

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

from sklearn.model_selection import KFold
from sklearn.metrics import accuracy_score

import pandas as pd


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

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

k = 5
kfold = KFold(n_splits=k, shuffle = True)
acc_score = []


def model_fn():
model = Sequential()
model.add(Dense(24,input_dim=60, activation='relu'))
model.add(Dense(10,activation='relu'))
model.add(Dense(1,activation='sigmoid'))
return model


for train_index, test_index in kfold.split(X):
  X_train, X_test = X.iloc[train_index,:], X.iloc[test_index,:]
  y_train, y_test = y.iloc[train_index], y.iloc[test_index]


#궁금해서 train_index를 프린트해보니 208개 중 167개의 index를 리스트 형식으로 반환하고 있었다. 또한 5번 각각 인덱스가 모두 달랐다. 
for문을 단순히 5번 돌리는데 167개를 어떻게..X_train에 매번 넣는 지...의문이긴 하다... iloc 에 인덱스 형태로 반환하면 해당 인덱스들만으로 재구성이 되는걸까..? → 헐 맞았다. loc이나 iloc에서 원하는 행/열의 인덱스를 리스트 형태로 넣어도 된다고 함! 
 

  model = model_fn()
  model.compile(loss='binary_crossentropy', optimizer = 'adam', metrics = ['accuracy'])
  history = model.fit(X_train, y_train, epochs = 200, batch_size=10, verbose=10)

  accuracy = model.evaluate(X_test, y_test)[1]
  acc_score.append(accuracy)
avg_acc_score = sum(acc_score) / k

print('accuracy', acc_score)
print('accuracy_mean', avg_acc_score)

accuracy [0.8333333134651184, 0.8809523582458496, 0.7857142686843872, 0.8780487775802612, 0.7317073345184326] accuracy_mean 0.8219512104988098