Dataset Split (데이터셋 분할)

3단 분석법

순서
분석
단어
내용
1
정의
데이터셋 분할
주어진 데이터를 학습(training), 검증(validation), 테스트(test) 데이터셋으로 나누어 모델의 성능을 평가하고 일반화하기 위한 과정
2
알아야하는 이유
데이터셋 분할
모델을 학습할 때 과적합을 방지하고, 모델의 성능을 객관적으로 평가하며, 실제 데이터를 처리할 때 모델이 잘 일반화되는지 확인하기 위해서
3
동작방식
데이터셋 분할
1. 전체 데이터 수집 2. 학습 데이터 분할 3. 검증 데이터 분할 4. 테스트 데이터 분할 5. 랜덤 분할

정의

데이터셋 분할
주어진 데이터를 학습(training), 검증(validation), 테스트(test) 데이터셋으로 나누어 모델의 성능을 평가하고 일반화하기 위한 과정
데이터셋 분할은 주어진 데이터를 학습, 검증, 테스트 데이터셋으로 나누어 모델의 성능을 평가하고 일반화하기 위한 과정입니다.
이를 통해 모델이 새로운 데이터에서도 잘 작동할 수 있도록 합니다.
데이터셋 분할은 머신러닝 모델을 개발하면서 모델을 검증하는 데 있어 도움이 될 수 있습니다.
하지만, 오히려 검증 데이터가 없을 때 모델이 성능이 더 좋을 수도 있습니다.

데이터의 양

데이터셋이 충분히 큰 경우, 일부 데이터를 검증 데이터로 분할해도 모델의 성능을 평가할 수 있습니다.
하지만 데이터셋이 작은 경우, 검증 데이터를 따로 분리하면 트레이닝 데이터가 너무 적어져 모델 성능이 떨어질 수 있습니다.

모델의 복잡성

간단한 모델의 경우, 데이터 분할 없이도 충분한 성능을 보일 수 있습니다.
반면, 복잡한 모델일수록 과적합(overfitting)을 방지하기 위해 검증 데이터가 필요할 수 있습니다.

검증 데이터의 필요성

특정 프로젝트에서는 검증 데이터 없이도, 예를 들어 교차 검증(cross-validation)과 같은 기법을 통해 모델의 성능을 평가할 수 있습니다.
프로젝트의 특성에 따라, 실제 데이터로 테스트를 하거나 다른 평가 방법을 사용할 수도 있습니다.
무조건 트레이닝 데이터를 분할하여 검증 데이터를 만드는 것보다, 모델의 성능을 검증하면서 검증 데이터의 필요성을 판단하는 것이 중요합니다.
각 모델의 특성과 데이터셋의 크기, 모델의 복잡성 등을 고려하여 최적의 방법을 선택하는 것이 바람직합니다.

알아야하는 이유

데이터셋 분할
모델을 학습할 때 과적합을 방지하고, 모델의 성능을 객관적으로 평가하며, 실제 데이터를 처리할 때 모델이 잘 일반화되는지 확인하기 위해서
이유
설명
과적합 방지
모델이 학습 데이터에만 치우치지 않고, 새로운 데이터에도 잘 일반화되도록 합니다.
성능 평가
모델의 성능을 객관적으로 평가할 수 있도록 합니다.
일반화 확인
모델이 실제 데이터를 처리할 때 잘 일반화되는지 확인할 수 있습니다.
하이퍼파라미터 튜닝
검증 데이터셋을 이용해 모델의 하이퍼파라미터를 최적화할 수 있습니다.
비교 연구
다양한 모델 및 설정을 비교할 때 공정하게 성능을 평가할 수 있습니다.

동작 방식

데이터셋 분할
1. 학습 데이터 분할 2. 검증 데이터 분할 3. 테스트 데이터 분할 4. 랜덤 분할
샘플 데이터셋을 생성하여 분할하는 4가지 방법에 대해 소개하는 방식으로 진행하겠습니다.

전체 데이터 수집

먼저, 필요한 라이브러리를 불러오고, 샘플 데이터를 생성합니다. 이 예제에서는 pandas 라이브러리를 사용하여 데이터프레임을 만듭니다.
# 필요한 라이브러리 불러오기 import pandas as pd # 샘플 데이터 생성 data = { 'feature1': range(1, 101), # feature1은 1부터 100까지의 숫자 'feature2': range(101, 201), # feature2는 101부터 200까지의 숫자 'label': [1 if x % 2 == 0 else 0 for x in range(1, 101)] # label은 짝수이면 1, 홀수이면 0 } df = pd.DataFrame(data) # 데이터프레임 생성 # 전체 데이터셋 크기 확인 print("전체 데이터셋 크기:", len(df))
Python
복사
pandas는 데이터 조작 및 분석을 위한 라이브러리입니다.
data 딕셔너리는 feature1, feature2, label 세 개의 키와 각 키에 대응하는 값으로 구성됩니다.
range(1, 101)은 1부터 100까지의 숫자 생성.
label은 짝수인 경우 1, 홀수인 경우 0으로 설정됩니다.
pd.DataFrame(data)data 딕셔너리를 데이터프레임으로 변환합니다.
데이터 프레임이 무엇인가요?
데이터프레임(DataFrame)은 pandas 라이브러리에서 제공하는 2차원 데이터 구조로, 엑셀 시트와 유사합니다. 행(row)과 열(column)로 구성되며, 다양한 형태의 데이터를 다루는 데 매우 유용합니다.
[1 if x % 2 == 0 else 0 for x in range(1, 101)] 어떤 코드인가요?
위와 같이 샘플 데이터셋을 생성하였습니다. 이제부터 분할을 해보도록 하겠습니다.

1. 학습 데이터 분할

전체 데이터셋의 60%를 학습 데이터로 분할합니다.
# 전체 데이터셋에서 학습 데이터 비율 설정 train_size = int(0.6 * len(df)) # 학습 데이터 비율 (60%) # 학습 데이터 분할 train_data = df[:train_size] # 학습 데이터로 분할 # 학습 데이터셋 크기 확인 print("학습 데이터셋 크기:", len(train_data)) # train_data 형태 확인하기 print("train_data:", train_data) # 0 ~ 59
Python
복사
train_size는 전체 데이터셋의 60%를 의미합니다.
df[:train_size]는 데이터프레임의 처음 60%를 학습 데이터로 분할합니다.
슬라이싱(Slicing): : 연산자는 슬라이싱을 나타내며, df[:train_size]는 데이터프레임의 행을 선택합니다.
print("train_data:", train_data) 결과

2. 검증 데이터 분할

나머지 데이터의 20%를 검증 데이터로 분할합니다.
# 전체 데이터셋에서 검증 데이터 비율 설정 validation_size = int(0.2 * len(df)) # 검증 데이터 비율 (20%) # 검증 데이터 분할 validation_data = df[train_size:train_size + validation_size] # 검증 데이터로 분할 (60 ~ 79행 까지) # 검증 데이터셋 크기 확인 print("검증 데이터셋 크기:", len(validation_data)) print("validation_data:", validation_data) # 60 ~ 79
Python
복사
validation_size는 전체 데이터셋의 20%를 의미합니다.
df[train_size:train_size + validation_size]는 학습 데이터 이후의 20%를 검증 데이터로 분할합니다.
"validation_data:", validation_data 결과

3. 테스트 데이터 분할

남은 데이터를 테스트 데이터로 분할합니다.
# 테스트 데이터 분할 test_data = df[train_size + validation_size:] # 테스트 데이터로 분할 # 테스트 데이터셋 크기 확인 print("테스트 데이터셋 크기:", len(test_data)) print("test_data:", test_data) # 80 ~ 99
Python
복사
나머지 20%의 데이터는 테스트 데이터로 사용됩니다.
df[train_size + validation_size:]는 학습 데이터와 검증 데이터 이후의 나머지 데이터를 테스트 데이터로 분할합니다.
"test_data:", test_data 결과

4. 랜덤 분할

데이터를 무작위로 섞어 학습, 검증, 테스트 데이터셋을 분할합니다.
# 필요한 라이브러리 불러오기 from sklearn.model_selection import train_test_split # 데이터셋을 학습, 검증, 테스트 세트로 랜덤 분할 (60:20:20 비율) train_data, temp_data = train_test_split(df, test_size=0.4, random_state=42) # 먼저 학습 데이터 분할 validation_data, test_data = train_test_split(temp_data, test_size=0.5, random_state=42) # 남은 데이터에서 검증 및 테스트 데이터 분할 # 각 데이터셋 크기 확인 print("학습 데이터셋 크기:", len(train_data)) print("검증 데이터셋 크기:", len(validation_data)) print("테스트 데이터셋 크기:", len(test_data))
Python
복사
train_test_split 함수는 데이터를 무작위로 섞어 주어진 비율로 분할합니다.
train_test_split(df, test_size=0.4, random_state=42)는 전체 데이터의 60%를 학습 데이터로, 40%를 임시 데이터(temp_data)로 분할합니다.
train_test_split(temp_data, test_size=0.5, random_state=42)는 임시 데이터를 다시 검증 데이터와 테스트 데이터로 50:50 비율로 분할합니다.
random_state=42는 무작위 분할을 재현 가능하게 하기 위한 시드 값입니다.
"train_data:", train_data 결과
"validation_data:", validation_data 결과
"test_data:", test_data 결과
코랩에서 동작하기 : link iconGoogle Colab

알면 좋은 정보

Cross Validation (교차 검증)

교차 검증은 Training Data에서 일정 부분을 Validation Data로 분할해 여러 번 검증하는 것을 의미합니다.
위의 이미지는 일반적으로 많이 사용하는 K-Fold 교차 검증을 그림으로 표현한 것입니다.
K-Fold 교차 검증은 데이터셋을 K개의 폴드로 나누어 각 폴드를 한번씩 검증 데이터로 사용하고 나머지 폴드를 학습 데이터로 사용하는 방식입니다.

K Fold 교차 검증 과정

1.
데이터셋 분할
전체 데이터셋을 K개의 폴드로 나눕니다.
2.
모델 학습 및 검증
첫 번째 폴드를 검증 데이터로 사용하고, 나머지 폴드를 학습 데이터로 사용하여 모델을 학습시킵니다.
학습된 모델을 첫 번째 폴드로 검증합니다.
이 과정을 K번 반복하여 모든 폴드가 한 번씩 검증 데이터로 사용되도록 합니다.
3.
결과 통합
각 폴드에서의 검증 결과를 평균내어 최종 모델의 성능을 평가합니다.

장단점

장점
단점
모든 데이터를 검증에 사용하기 때문에 데이터셋의 특정 분할에 따른 편향을 줄일 수 있습니다.
K번의 학습과 검증을 반복해야 하므로 계산 비용이 많이 듭니다.
학습과 검증에 모든 데이터를 사용하여 모델의 일반화 성능을 높일 수 있습니다.
만약 데이터셋 자체가 한쪽으로 치우쳐 있다면, 교차 검증 결과가 왜곡될 수 있습니다.

데이터 분할 비율

데이터셋을 분할할 때 일반적으로 70:15:15, 60:20:20 등의 비율을 사용합니다.
상황에 따라 다르게 조정할 수 있습니다.

K-Fold 교차 검증 예제

1. 라이브러리 설치 및 불러오기

먼저 필요한 라이브러리를 설치하고 불러옵니다.
# Scikit-Learn 라이브러리는 일반적으로 코랩에 기본 설치되어 있습니다. # 만약 설치되어 있지 않다면 아래 주석을 제거하고 실행하세요. # !pip install scikit-learn import numpy as np import pandas as pd from sklearn.model_selection import KFold from sklearn.metrics import accuracy_score
Python
복사

2. 데이터 생성

간단한 샘플 데이터를 생성합니다.
# 샘플 데이터 생성 data = { 'feature1': range(1, 101), # 1부터 100까지의 숫자 'feature2': range(101, 201), # 101부터 200까지의 숫자 'label': [1 if x % 2 == 0 else 0 for x in range(1, 101)] # 짝수이면 1, 홀수이면 0 } df = pd.DataFrame(data) # 데이터프레임 생성 # 특성(features)와 라벨(label) 분리 X = df[['feature1', 'feature2']] y = df['label']
Python
복사

3. K-Fold 교차 검증 설정 및 수행

K-Fold 교차 검증을 설정하고 수행합니다.
# KFold 설정 kf = KFold(n_splits=5, shuffle=True, random_state=42) # 결과를 저장할 리스트 accuracy_scores = [] # 각 폴드에 대해 학습 및 평가 for train_index, test_index in kf.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] # 간단한 모델: 예제에서는 feature1의 값이 짝수면 1, 홀수면 0으로 예측 y_pred = [1 if x % 2 == 0 else 0 for x in X_test['feature1']] # 정확도 계산 accuracy = accuracy_score(y_test, y_pred) accuracy_scores.append(accuracy) # 각 폴드의 정확도 출력 for i, score in enumerate(accuracy_scores): print(f"폴드 {i+1}의 정확도: {score:.2f}") # 평균 정확도 출력 print(f"평균 정확도: {np.mean(accuracy_scores):.2f}")
Python
복사
결과
폴드 1의 정확도: 1.00 폴드 2의 정확도: 1.00 폴드 3의 정확도: 1.00 폴드 4의 정확도: 1.00 폴드 5의 정확도: 1.00 평균 정확도: 1.00
Python
복사
random_state=42가 가 무엇인가요?
난수 생성기의 초기값입니다. 특정 시드를 설정하면 난수 생성기는 항상 동일한 순서의 난수를 생성합니다.

사용이유

재현 가능성(Reproducibility): 실험이나 테스트를 반복할 때, 동일한 입력 데이터와 동일한 시드 값이 사용되면 항상 동일한 결과를 얻을 수 있습니다. 이는 결과를 검증하거나 문제를 디버그할 때 매우 유용합니다.
공정한 비교: 모델의 성능을 비교할 때, 동일한 데이터 분할과 동일한 조건을 보장하여 공정하게 비교할 수 있습니다.

예제

아래는 랜덤 시드를 설정하지 않았을 때와 설정했을 때의 차이를 보여주는 예제입니다.

랜덤 시드를 설정하지 않은 경우

import numpy as np # 난수 생성 (랜덤 시드 없음) random_numbers1 = np.random.rand(5) random_numbers2 = np.random.rand(5) print("Random numbers without seed (first call):", random_numbers1) print("Random numbers without seed (second call):", random_numbers2)
Python
복사
Random numbers without seed (first call): [0.51718097 0.31576424 0.03235194 0.44730853 0.58715261] Random numbers without seed (second call): [0.23335989 0.09808566 0.41867871 0.69419256 0.89127382]
Python
복사
이 경우, random_numbers1random_numbers2는 각각 다른 값을 가집니다.

랜덤 시드를 설정한 경우

import numpy as np # 난수 생성 (랜덤 시드 설정) np.random.seed(42) random_numbers1 = np.random.rand(5) np.random.seed(42) random_numbers2 = np.random.rand(5) print("Random numbers with seed (first call):", random_numbers1) print("Random numbers with seed (second call):", random_numbers2)
Python
복사
Random numbers with seed (first call): [0.37454012 0.95071431 0.73199394 0.59865848 0.15601864] Random numbers with seed (second call): [0.37454012 0.95071431 0.73199394 0.59865848 0.15601864]
Python
복사
이 경우, random_numbers1random_numbers2는 동일한 값을 가집니다. 이는 두 번째 호출에서도 동일한 시드를 사용하여 동일한 난수를 생성했기 때문입니다.
iloc()는 무엇인가요?
iloc는 pandas 라이브러리에서 제공하는 인덱싱 방법 중 하나로, 위치 기반 인덱싱을 의미합니다. 이는 데이터프레임의 행과 열을 정수 인덱스를 사용하여 선택할 수 있게 해줍니다.
import pandas as pd # 샘플 데이터프레임 생성 data = { 'feature1': [10, 20, 30, 40, 50], 'feature2': [60, 70, 80, 90, 100], 'label': [0, 1, 0, 1, 0] } df = pd.DataFrame(data) # 위치 기반 인덱싱 사용 예제 print(df) print("-----") print(df.iloc[0]) # 첫 번째 행 선택 print("-----") print(df.iloc[:, 1]) # 모든 행에서 두 번째 열 선택 print('-----') print(df.iloc[1:3]) # 두 번째와 세 번째 행 선택
Python
복사
결과
feature1 feature2 label 0 10 60 0 1 20 70 1 2 30 80 0 3 40 90 1 4 50 100 0 ----- feature1 10 feature2 60 label 0 Name: 0, dtype: int64 ----- 0 60 1 70 2 80 3 90 4 100 Name: feature2, dtype: int64 ----- feature1 feature2 label 1 20 70 1 2 30 80 0
Python
복사
코랩에서 동작하기 : link iconGoogle Colab

미니퀘스트

1번 미니퀘스트 - 데이터셋 분할 실습

데이터셋을 랜덤으로 분할하고 각 데이터셋의 크기를 출력하여 분할이 제대로 이루어졌는지 확인해 보세요.

문제 설명

1.
데이터 로드
샘플 데이터셋을 로드합니다.
예제데이터
# 샘플 데이터 생성 data = { 'feature1': range(1, 101), 'feature2': range(101, 201), 'label': [1 if x % 2 == 0 else 0 for x in range(1, 101)] } df = pd.DataFrame(data)
Python
복사
2.
데이터셋 분할
데이터를 학습, 검증, 테스트 데이터셋으로 나눕니다.
3.
결과 확인
각 데이터셋의 크기를 출력하여 분할 결과를 확인합니다.

코드

# 필요한 라이브러리 불러오기 import pandas as pd from sklearn.model_selection import train_test_split # 샘플 데이터 생성 data = { 'feature1': range(1, 101), 'feature2': range(101, 201), 'label': [1 if x % 2 == 0 else 0 for x in range(1, 101)] } df = pd.DataFrame(data) # 전체 데이터셋 크기 확인 print("전체 데이터셋 크기:", len(df)) # 데이터셋을 학습, 검증, 테스트 세트로 분할 (60:20:20 비율) train_data, temp_data = train_test_split(df, test_size=0.4, random_state=42) validation_data, test_data = train_test_split(temp_data, test_size=0.5, random_state=42) # 각 데이터셋 크기 출력 print("학습 데이터셋 크기:", len(train_data)) print("검증 데이터셋 크기:", len(validation_data)) print("테스트 데이터셋 크기:", len(test_data))
Python
복사

결과 예시

전체 데이터셋 크기: 100
학습 데이터셋 크기: 60
검증 데이터셋 크기: 20
테스트 데이터셋 크기: 20

결과 설명

전체 데이터셋 크기
주어진 데이터셋의 총 샘플 수는 100개입니다.
학습 데이터셋 크기
전체 데이터셋의 60%인 60개 샘플이 학습 데이터로 할당되었습니다. 이 데이터는 모델을 학습시키는 데 사용됩니다.
검증 데이터셋 크기
나머지 데이터의 20%, 즉 20개 샘플이 검증 데이터로 할당되었습니다. 이 데이터는 학습 과정 중 모델의 성능을 평가하고 튜닝하는 데 사용됩니다.
테스트 데이터셋 크기
최종적으로 남은 20개 샘플이 테스트 데이터로 할당되었습니다. 이 데이터는 모델의 최종 성능을 객관적으로 평가하는 데 사용됩니다.

코드 설명

2번 미니퀘스트 - 데이터 분할과 성능 평가

간단한 모델을 학습하고, 검증 및 테스트 데이터셋을 사용하여 모델의 성능을 평가해보세요.

문제 설명

1.
데이터 로드 및 분할
데이터를 학습, 검증, 테스트 데이터셋으로 분할합니다.
예제데이터
# 샘플 데이터 생성 data = { 'feature1': range(1, 101), 'feature2': range(101, 201), 'label': [1 if x % 2 == 0 else 0 for x in range(1, 101)] } df = pd.DataFrame(data)
Python
복사
2.
모델 학습
학습 데이터셋을 사용하여 간단한 모델을 학습합니다.
3.
모델 평가
검증 데이터셋을 사용하여 모델의 성능을 평가합니다.
4.
최종 평가
테스트 데이터셋을 사용하여 모델의 최종 성능을 평가합니다.

코드

# 필요한 라이브러리 불러오기 import pandas as pd from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score # 샘플 데이터 생성 data = { 'feature1': range(1, 101), 'feature2': range(101, 201), 'label': [1 if x % 2 == 0 else 0 for x in range(1, 101)] } df = pd.DataFrame(data) # 데이터셋을 학습, 검증, 테스트 세트로 분할 (60:20:20 비율) train_data, temp_data = train_test_split(df, test_size=0.4, random_state=42) validation_data, test_data = train_test_split(temp_data, test_size=0.5, random_state=42) # 학습 데이터와 레이블 분리 X_train = train_data[['feature1', 'feature2']] y_train = train_data['label'] X_validation = validation_data[['feature1', 'feature2']] y_validation = validation_data['label'] X_test = test_data[['feature1', 'feature2']] y_test = test_data['label'] # 모델 학습 model = LogisticRegression() model.fit(X_train, y_train) # 검증 데이터로 성능 평가 y_val_pred = model.predict(X_validation) val_accuracy = accuracy_score(y_validation, y_val_pred) print("검증 데이터 정확도:", val_accuracy) # 테스트 데이터로 최종 성능 평가 y_test_pred = model.predict(X_test) test_accuracy = accuracy_score(y_test, y_test_pred) print("테스트 데이터 정확도:", test_accuracy)
Python
복사

결과 예시

검증 데이터 정확도: 0.55
테스트 데이터 정확도: 0.5

결과 설명

검증 데이터 정확도
검증 데이터셋을 사용하여 모델의 성능을 평가한 결과, 정확도는 0.55(55%)입니다. 이는 모델이 검증 데이터셋에서 55%의 정확도로 예측했음을 의미합니다.
테스트 데이터 정확도
테스트 데이터셋을 사용하여 모델의 최종 성능을 평가한 결과, 정확도는 0.5(50%)입니다. 이는 모델이 테스트 데이터셋에서 50%의 정확도로 예측했음을 의미합니다.

결과 분석

1.
검증 데이터 정확도가 55%로, 데이터셋이 무작위로 분할된 경우 모델이 검증 데이터에 대해 과적합 되지 않았음을 나타냅니다. 그러나, 정확도가 높지 않으므로 모델의 성능이 그다지 좋지 않음을 시사합니다.
2.
테스트 데이터 정확도가 50%로, 모델이 새로운 데이터에 대해 예측할 때 동전 던지기와 같은 수준의 성능을 보이고 있습니다. 이는 모델이 학습 데이터에서 충분히 학습하지 못했거나, 단순한 모델로 인해 복잡한 패턴을 제대로 학습하지 못했기 때문일 수 있습니다.

코드 설명

미니퀘스트 답안지

ⓒ 2024 startupcode. 모든 권리 보유. 무단 복제 금지.