지금까지의 포스팅에서는 검증 셋을 따로 생성하지 않았으나, 이번엔 검증 셋을 데이터에서 추출해보도록 하겠다. 검증 셋 추출 시, 주의할 점은 검증 셋에서 편향이 발생해서는 안된다는 것이다.
검증 셋(Validation set)
1. 검증 셋이란?
검증 셋은 앞선 "Tensorflow-1.0. 기초(1)-데이터 셋 만들기"에서 한 번 언급하긴 하였으나, 이번엔 좀 더 자세히 설명해보도록 하겠다.
- 검증 셋은 학습 도중에 학습된 내용을 평가하는 "가짜 최종 시험"이다.
- 예를 들어, 수능을 준비하는 고3 학생에게 모의고사 문제가 5개가 있다면, 4개는 공부를 할 때 사용하고, 나머지 1개는 수능 전에 자신이 얼마나 잘 공부를 했는지 평가하는 용도로 사용하는 것이라 생각하면 된다.
- 최종 목표인 수능(Test set)을 보기 전에 자신의 실력을 평가하는 용도(학습된 파라미터 평가)로 사용되기 때문에 검증 셋을 얼마나 잘 추출하느냐는 꽤 중요한 문제다.
- 검증 셋은 파라미터 갱신에 영향을 주는 것이 아니라, 학습 과정에서 생성된 여러 모델 중 어느 모델이 가장 좋은지를 평가하는 용도로 사용된다.
- 검증 셋(Validation set)과 학습 셋(Train set)이 중복되면, 편향이 발생하여, 제대로 된 평가가 이루어지지 않을 수 있다. 이렇게 검증 셋과 학습 셋이 중복된 현상을 Leakage라고 한다.
2. 검증 셋의 효과
- 검증 셋을 사용한 학습 데이터의 평가는, 학습 과정에서 생긴 여러 모델들이 만들어낸 수많은 파라미터 중 최적의 파라미터를 선택하므로, 파라미터를 튜닝하는 효과가 있다고 할 수 있다.
- 만약 학습 셋(Train set)으로만 학습하고, 시험 셋(Test set)으로만 모델을 검증한다면, 모델은 시험 셋(Test set)에 과적합(Overfitting)된 모델이 될 수 있다.
- 시험 셋(Test set)은 모델의 성능을 평가하기 위해 사용되는 것이긴 하지만, 모델 성능 향상의 기준이 시험 셋이 돼버린다면, 시험 셋의 "모델 성능 평가"라는 목적이 "모델 성능을 맞추는 기준"으로 변질되게 된다. 이 경우, 검증 셋을 사용한다면, 이 문제를 해결할 수 있다.
3. 검증 셋 추출 방법
- 검증 셋 추출 방법에서 핵심은 "어떻게 검증 셋의 편향을 피하는가"이다.
- 예를 들어, 총 10개의 시험 단원이 있고, 여기서 랜덤 하게 문제를 뽑아, 수능 시험을 보러 가기 전 최종 평가를 하려고 한다. 그런데, 우연히 1~6단원 문제가 90% 가까이 나왔고, 7~10단원 문제가 10%밖에 나오지 않았다고 가정해보자. 이 시험 문제를 최종 기준으로 사용하는 것은 꼭 피해야 할 문제다.
- 즉, 최대한 검증 셋의 편향을 없애는 것이 다양한 검증 셋 추출 방법들이 생기게 된 이유라고 할 수 있다.
3.1. Hold-out
- 단순하게 일정 비율의 데이터 셋을 분리해내는 방법이다.
- 데이터의 양이 적을수록, 전체 데이터를 대표하지 못할 가능성이 높으며, 편향된 결과를 얻을 가능성이 있다.
3.2. Random subsampling
- Hold-out을 완전 무작위 표본 추출로 반복 시행하고, 정확도의 평균으로 성능을 평가한다.
3.3. K-fold cross validation
- 데이터 셋을 중복되지 않는 K개의 집단으로 나눈다.
- K개의 집단에서 1개의 집단을 검증 셋으로 사용하며, K번 검증 셋을 집단이 중복되지 않게 바꿔가며 정확도를 계산하고, 그 평균으로 성능을 평가한다.
- 데이터 셋이 많으면 많을수록 지나치게 시간을 많이 소모하므로, 빅데이터를 사용하는 현 트렌드에는 맞지 않다.
- 물론, 데이터의 양이 매우 적다면, 가지고 있는 모든 데이터를 학습과 평가에 사용할 수 있다는 장점이 있다.
3.4. Leave p-out cross validation
- 중복되지 않은 전체 데이터 n개에서 p개의 샘플을 검증 셋으로 사용하여 정확도를 계산하고, 그 결과의 평균으로 성능을 평가한다.
- 전체 경우의 수가 ${n}C{p}$개이기 때문에 k-fold cross validation보다 소모되는 시간이 K-fold cross validation보다 많다.
- 데이터 셋의 양이 매우 적은 경우에나 사용할만하다.
- 여기서 p=1로 하면 Leave one-out cross validation(LOOCV)라 하며, 소모 시간과 성능 모두 Leave p-out cross validation보다 우수하다고 한다.
3.5. Stratified Sampling
- 전체 데이터 셋을 구성하는 클래스별로 데이터를 일부 추출한다.
- 전체 데이터셋에서 클래스의 비율이 불균형할수록 편향을 줄여준다는 장점이 있다.
- 완전 무작위 표본 추출 시, 우연히 특정 클래스에 표본이 편중되는 현상을 피할 수 있다.
- Stratified Sampling 역시 k-fold 방식처럼 k개의 집단을 생성하여 그 평균을 낼 수도 있다(Stratified k-fold cross validation).
3.6. Bootstrap
- 전체 데이터 셋에서 중복을 허용한 샘플링을 반복 실시해, 모집단으로부터 새로운 데이터 셋을 만들어 냄
- 크기가 n인 데이터셋에 대하여 부트스트랩을 b번 한다고 가정할 때, 공식은 다음과 같다.
$$ACC_{boot} = \frac{1}{b}\sum_{j=1}^{b}\frac{1}{n}\sum_{i=1}^{n}(1-L(\hat{y_i},y_i))$$
- 전체 데이터 셋에서 하나의 샘플을 뽑고, $j$번째 부트스트랩에 할당
- 1번 과정을 부트스트랩 샘플 크기가 원본 데이터 셋 크기인 n이 될 때까지 반복한다.
(중복을 허용하여 완전 무작위 추출하므로 부트스트랩 샘플에 한번 이상 포함되었거나, 아예 없을 수도 있다.) - b개의 부트스트랩 샘플 하나하나를 모델에 학습시키고 훈련에 사용된 데이터를 이용하여 성능을 평가한다(재치환 정확도).
- b개의 부트스트랩 샘플의 정확도의 평균으로 모델 정확도를 구한다.
- 부트스트랩은 데이터의 분포를 알 수 없고, 추가적인 데이터를 구할 수 없는 경우 추정량의 통계적 속성을 결정하기 위해 사용한다.
- 보다 자세한 설명을 보고 싶은 사람은 다음 출처를 확인하기 바란다.
출처: 텐서 플로우 블로그 (Tensor ≈ Blog)
머신 러닝의 모델 평가와 모델 선택, 알고리즘 선택 – 2장. 부트스트래핑과 불확실성
이 글은 파이썬 머신 러닝의 저자 세바스찬 라쉬카(Setabstian Raschka)가 쓴 ‘Model evaluation, model selection, and algorithm selection in machine learning Part II – Bootstrapping and uncertainties‘를 원저자의 동의하에 번
tensorflow.blog
4. 검증 셋 추출
- 검증 셋 추출 방법은 데이터 셋의 크기가 크면 클수록 교차 검증 방식을 사용하지 않는 것이 좋다.
- k-fold 교차 검증이나 LOOCV은 데이터의 양이 늘어나면 늘어날수록 연산량이 지나치게 늘어나게 되는데, 현대 같이 빅데이터를 사용하여 딥러닝을 실시하는 경우에는 개인적으로 추천하지 않는다.
- 검증 셋을 추출하기 전에 Label의 빈도를 보도록 하자.
>>> pd.Series(train_labels).value_counts()
1 6742
7 6265
3 6131
2 5958
9 5949
0 5923
6 5918
8 5851
4 5842
5 5421
dtype: int64
# 히스토그램을 보자
plt.hist(train_labels)
plt.show()
- 데이터셋의 분포는 특정 클래스에 치우치지 않은 평탄한 상태인 것을 알 수 있다.
- 그러므로, Hold-Out을 사용하되 완전 무작위 표본 추출로 검증 셋을 생성하도록 하겠다.
# 무작위로 샘플 추출
np.random.seed(1234)
index_list = np.arange(0, len(train_labels))
valid_index = np.random.choice(index_list, size = 5000, replace = False)
# 검증셋 추출
valid_images = train_images[valid_index]
valid_labels = train_labels[valid_index]
# 학습셋에서 검증셋 제외
train_index = set(index_list) - set(valid_index)
train_images = train_images[list(train_index)]
train_labels = train_labels[list(train_index)]
- 완전 무작위 표본 추출을 위해 index를 무작위로 추출하였다.
- 차집합을 이용해서 간단하게 index의 차를 구하였다.
>>> pd.Series(valid_labels).value_counts()
1 616
9 518
3 514
7 497
4 491
8 488
6 482
2 481
0 480
5 433
dtype: int64
- valid set의 빈도 표를 통해 데이터가 어느 정도 이쁘게 뽑힌 것을 볼 수 있다.
- 혹시 모르니 표준편차도 뽑아보도록 하자.
>>> np.std(train_labels)
2.887480385250541
>>> np.std(valid_labels)
2.9085488065356584
- 검증 셋과 학습 셋의 표준편차가 거의 유사하게 나온 것으로 볼 때, 검증 셋이 대표성을 갖고 있다고 할 수 있다.
5. 스케일 조정
- 앞서 이야기 하긴 했으나, 다시 한번 이야기하자면, 데이터의 범위 차이를 줄여 최적해에 보다 쉽게 수렴하게 하는 방법이다.
- 스케일 조정에서 사용되는 값의 기준은 Train set이 되어야 한다.
- 보다 자세한 내용은 "Tensorflow-1.3. 기초(4)-특성 스케일 조정"을 참고하기 바란다.
- min-max scaling을 이용해 표준화시키도록 하겠다.
# min-max scaling
min_key = np.min(train_images)
max_key = np.max(train_images)
train_images = (train_images - min_key)/(max_key - min_key)
valid_images = (valid_images - min_key)/(max_key - min_key)
test_images = (test_images - min_key)/(max_key - min_key)
지금까지 MNIST 데이터셋에서 검증 셋을 추출해보았다. 다음 포스트에서는 모델을 만들어보도록 하겠다.
'Machine Learning > TensorFlow' 카테고리의 다른 글
Tensorflow-3.4. 이미지 분류 모델(4)-모델 컴파일 (0) | 2021.02.16 |
---|---|
Tensorflow-3.3. 이미지 분류 모델(3)-모델 생성 (0) | 2021.02.16 |
Tensorflow-3.1. 이미지 분류 모델(1)-MNIST 데이터셋 (0) | 2021.02.16 |
Tensorflow-3.0. Keras 소개 (0) | 2021.02.15 |
Tensorflow-2.5. 타이타닉 다중 분류 모델(4) (0) | 2021.02.15 |