본문 바로가기
파이썬(Python), 머신러닝, 딥러닝

(딥러닝 with 파이썬) k겹 교차검증(k-fold cross validation / k-fold cv)

by 굳세라(goodsarah) 2022. 8. 10.
728x90
반응형

 데이터를 분석하다보면, 확보할 수 있는 데이터의 양이 무한정 충분할 수 없으니, 가지고 있는 데이터를 학습용과 테스트용으로 구분하여 사용해야 한다.

 이때, 테스트용 데이터는 모델 학습에 사용할 수 없다는 단점이 생긴다.특히,  데이터가 부족할 시 더 큰 문제가 되는데, 이러한 문제점을 해결하고자 k겹 교차검증(k-fold cross validation)을 실시하여 그 문제점을 보완할 수 있다.

 

K겹 교차검증은, 가지고 있는 전체 데이터를 K겹(K-fold)로 나누어서,  
 
k겹 중 1겹은 테스트용으로, 나머지는 학습용으로 선정하여 학습시키는 것을 말하며, 이것을 모든 겹이 한번
씩 테스트용이 될때까지 반복하는 것을 말하기에 '교차검증'이라고 하는 것이다.
 
 
 
광물 데이터를 바탕으로 K겹 교차검증을 활용한 딥러닝 모델을 만들어보자.

 

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#초음파 광물 예측
 
#분석에 필요한 모듈들을 호출
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
import seaborn as sns
import matplotlib.pyplot as plt
 
#깃허브 taehojo 님의 자료를 참조
!git clone https://github.com/taehojo/data.git
 
#분석을 위해 데이터를 df 라는 변수로 저장
df = pd.read_csv('./data/sonar3.csv', header=None)
cs

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#분석을 위해 X와 y로 데이터를 분리
 
= df.iloc[:,0:60]
= df.iloc[:,60]
 
#전체 데이터를 k 겹으로 나누기
 
k=5
 
kfold = KFold(n_splits=k, shuffle=True)
 
 
#Accuracy(정확도)를 정리할 빈 리스트 만들기
acc_score = []
cs

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#k겹 검증으로 인해, train/test의 구성이 시행마다 바뀌므로,
#편하게 사용하기 위해 함수를 하나 만듦
 
def model_fn():
  model=Sequential()
  model.add(Dense(24, input_dim=60, activation='relu', name='Dense_1')) 
  #Input layer의 노드는 60개(파라미터 개수와 동일)
  #Input layer 다음 첫번째 Hidden layer의 노드 : 24
  #활성화 함수(Input -> hidden layer1) : Rectified Linear Unit
  #해당 Dense의 이름을 Dense_1 으로 명명
 
  model.add(Dense(10, activation ='relu', name='Dense_2'))
  #두번째 Hiddenlayer의 노드 갯수 : 10
  #활성화 함수(hidden layer1 -> hidden layer2) : Rectified Linear Unit
  #해당 Dense의 이름을 Dense_2 으로 명명
 
  model.add(Dense(1, activation='sigmoid', name='Dense_3'))
  #출력층(Output layer)의 노드 갯수 : 1 
  #활성화 함수(hidden layer2 -> Output layer2) : 단일 분류 이므로 sigmoid 를 활성화 함수로 사용
  #해당 Dense의 이름을 Dense_3 으로 명명
  return model
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
#5개의 겹으로 나누었으니, 5겹 중 1겹은 테스트/ 나머지는 트레인
#각 겹이 모두 테스트로 들어가려면 5번 반복 필요 -> for 구문 활용
 
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]
 
  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=0)
 
  accuracy = model.evaluate(X_test, y_test)[1]
  acc_score.append(accuracy)
cs

 

1
2
3
4
5
#k번 실시된 정확도의 평균
avg_acc_score = sum(acc_score) / k
 
print('정확도:',acc_score)
print('정확도 평균',avg_acc_score)
cs

 각 시행마다 다른 테스트용과 학습용 데이터가 들어가기에 정확도에 편차가 생기나, 평균값을 내본다면 꽤나 신뢰할만한 결과로 해석할 수 있다.

 

 k가 더 커질수록 더 세분화되어 교차검증이 진행되기에 결과는 더 신뢰할만한 수준으로 수렴하게 될 것이다.

728x90
반응형

댓글