머신러닝 모델을 학습하다 보면, 우리가 만든 모델이 진짜 잘 작동하는지, 아니면 우연히 훈련 데이터에 잘 맞는 것인지 궁금할 때가 많다.
이때 사용하는 가장 대표적인 기법이 바로 교차 검증 (Cross Validation)이다.

 

교차 검증이란?

교차 검증이란 전체 데이터를 여러 조각으로 나눈 뒤,
여러 번 모델을 훈련하고 평가하여 평균 성능을 측정하는 방식이다.
가장 널리 쓰이는 방식은 K-겹 교차 검증 (K-Fold Cross Validation)이다.

  1. K-겹 교차 검증은 데이터를 K개의 균등한 덩어리로 나눈다.
  2. K번 반복i 번째 fold를 검증용 데이터 (Validation Set)으로 사용하고,
    나머지 k-1개 fold를 학습용 데이터 (Training Set)으로 사용한다.
  3. 각 반복의 성능을 기록하고, 평균 성능을 계산하여 모델을 평가한다.

예를 들어, 5-fold라고 하면 전체 데이터를 5등분으로 나누고, 5번 반복하여 모델을 평가하는 것이다.

5-Fold Cross Validation

 

교차 검증이 중요한 이유는?

단일 분할 방식의 문제

보통은 데이터를 훈련/검증으로 나누고 성능을 평가하지만 여러 가지 문제가 있다.
운에 따라 성능이 달라질 수 있으며, 데이터가 적을수록 분할에 민감해지며, 과대적합 (Overfitting)을 알아차리기 어렵다.

교차 검증의 장점

  • 모든 데이터를 한 번씩 검증에 사용해볼 수 있으므로 성능 신뢰도가 상승된다.
  • 일반화 성능에 대한 더 정확한 추정이 가능해진다.
  • 과적합 방지에 도움이 된다.

 

 

"선형 회귀로 분류 문제를 풀고 싶다면, 로지스틱 회귀를 보아라"

로지스틱 회귀 (logistic regression)은 분류 문제, 특히 이진 분류 (binary classification) 문제를 해결하기 위한 대표적인 지도학습 알고리즘이다. 이름에 회귀라는 단어가 붙었지만, 실제로는 분류에 사용된다. 이 알고리즘은 선형 회귀와 동일하게 선형 방정식을 학습하여 연속적인 값을 예측한다.

하지만 이진 분류 문제에서는 결과가 0 또는 1 같은 범주형 값이어야 하기에, 선형 회귀를 사용하면 예측 값이 0보다 작거나 1보다 커질 수 있으며, 확률 해석이 불가능할 수 있다. 이를 위해서는 출력값이 0과 1 사이인 함수가 필요하며, 로지스틱 회귀에는 시그모이드 함수 (Sigmoid Function)를 활용한다.

 

시그모이드 함수 (Sigmoid Function)

시그모이드 함수는 실수 값을 입력받아, 0과 1사이의 확률 값으로 변환한다.

import numpy as np
import matplotlib.pyplot as plt

z = np.arange(-5, 5, 0.1)
phi = 1 / (1 + np.exp(-z))
plt.plot(z, phi)
plt.xlabel('z')
plt.ylabel('phi')
plt.title('Sigmoid Function', fontweight = 'bold')
plt.show()

 

k-최근접 이웃 회귀 (K-Nearest Neighbors Regression, K-NN 회귀)에서 k 값에 따라 과대적합 (overfitting)과 과소적합 (underfitting)이 발생하기도 한다. 과대적합은 학습 데이터에 너무 민감하게 반응하여, 새로운 데이터에 일반화하지 못하는 현상을 의미하며, 예측할 때 가장 가까운 단 1개의 이웃만을 참고하기 때문에 훈련 데이터에는 정확하지만 테스트 데이터나 새로운 데이터에서는 성능이 낮아진다. 한편, 과소적합은 모델이 너무 단순해서 학습 데이터의 패턴조차 잘 설명하지 못하는 현상을 말하는 것으로, k 값이 너무 커서 많은 이웃의 평균을 사용하기 때문에 국지적인 패턴을 놓치게 된다. 2주차에서는 k-최근접 이웃 회귀 모델에서 과대적합과 과소적합 현상을 직접 코드를 통하여 구현해보고 현상을 관찰해보았다.

 

예시 코드 (실행 코드 일부)

 

적절한 모델인 경우 (k = 5)

k 값이 적절하게 설정된 경우, 아래와 같이 훈련 데이터의 분포를 적절하게 표현하고 있음을 확인할 수 있다.

 

 

과대적합인 경우 (k = 1)

k 값이 1이거나 작은 경우에는 아래처럼 훈련 데이터를 매우 충실히 잘 따라감을 확인할 수 있다.
하지만 이상치에 대해서도 과하게 반응하는 것을 확인할 수 있어, 이런 경우에는 k 값을 적절히 높여줄 필요가 있다.

 

 

과대적합인 경우 (k = 10)

k 값이 지나치게 높아지면 그래프가 평탄화하거나 급격하게 단순화되며, 국지적 패턴을 무시하는 경향을 확인할 수 있었다.
이런 경우, 예측이 평균값에 가까워지고 정확도가 저하되기에 이런 경우에는 k 값을 낮출 필요가 있다.

 

 

구글 계정이 있다면 누구나 무료로 사용할 수 있는 코랩 (Colab)

우선 구글 계정을 로그인 한 후, 코랩 홈페이지 (https://colab.research.google.com) 에 접속하면 이용할 수 있었다.
로그인하지 않아도 코랩은 들어갈 수 있으나, 로그인하지 않으면 실습이 불가능하기에 구글 계정을 통한 로그인은 필수적이다.

구글 코랩을 몇 차례 이용한 적이 있는데다가 주피터 노트북 (Jupyter Notebook)은 평소에 사용하고 있기에 인터페이스는 익숙했다.
이번 주는 혼공학습단 14기의 1주차 학습 과정을 진행했으며, 1~2단원까지 공부한 내용을 정리해보았다.

 

생산 분류 문제

도미 데이터 준비하기

 

빙어 데이터 준비하기

 

K-최근접 이웃 알고리즘 (K-Nearest Neighbors Algorithm)

어떤 데이터가 주어질 때, 그 주변에 있는 k개의 가장 가까운 이웃들을 살펴보고, 다수에 의해 데이터의 레이블 (label) 또는 값을 결정한다.

In this class, I learned about one-dimensional array for containing the values.

Unlike general variables, one-dimensional arrangement can be accessed through an index to each space.
For example, if you declare five variables, each variable must be defined with a specific value.
However, if you declare a 1D array with five spaces only once, each value can be accessed through an index.

/* General Variables */
int A1 = 10;
int A2 = 20;
int A3 = 30;
int A4 = 40;
int A5 = 50;

/* One-dimensional Array */
int A[5] = {10, 20, 30, 40, 50};

 

In case of charater array, string values can be seperated by each letter with indexing.

/* General Variables */
char Char1 = 'H';
char Char2 = 'E';
char Char3 = 'L';
char Char4 = 'L';
char Char5 = 'O';

printf("%c \n", Char1);
printf("%c \n", Char2);
printf("%c \n", Char3);
printf("%c \n", Char4);
printf("%c \n", Char5);


/* One-dimensional Array */
char Str[6] = "HELLO";

printf("%s \n", Str);
printf("%c \n", Str[0]);
printf("%c \n", Str[1]);
printf("%c \n", Str[2]);
printf("%c \n", Str[3]);
printf("%c \n", Str[4]);

 

+ Recent posts