Scikit-learn 데이터 전처리

scikit-learnBeginner
지금 연습하기

소개

scikit-learn 데이터 전처리 실습에 오신 것을 환영합니다. 머신러닝에서 데이터의 품질은 모델 성능에 직접적인 영향을 미칩니다. 원시 데이터는 종종 지저분하고 일관성이 없으며 알고리즘에 최적화되지 않은 형식입니다. 데이터 전처리는 머신러닝 모델에 적합하도록 데이터를 정리하고 변환하는 중요한 단계입니다.

이 실습에서는 scikit-learn 라이브러리를 사용하여 두 가지 기본적인 전처리 작업을 수행하는 방법을 배우게 됩니다.

  • 특성 스케일링 (Feature Scaling): 데이터의 독립 변수 또는 특성의 범위를 표준화합니다.
  • 레이블 인코딩 (Label Encoding): 범주형 레이블을 숫자 형식으로 변환합니다.

이러한 기법을 연습하기 위해 scikit-learn 에 편리하게 포함된 유명한 Iris 데이터셋을 사용할 것입니다. 이 실습이 끝나면 머신러닝 파이프라인을 위해 데이터를 준비하는 방법에 대한 확실한 이해를 갖게 될 것입니다.

이것은 가이드 실험입니다. 학습과 실습을 돕기 위한 단계별 지침을 제공합니다.각 단계를 완료하고 실무 경험을 쌓기 위해 지침을 주의 깊게 따르세요. 과거 데이터에 따르면, 이것은 초급 레벨의 실험이며 완료율은 88%입니다.학습자들로부터 100%의 긍정적인 리뷰율을 받았습니다.

X = iris.data, y = iris.target 으로 특성과 타겟으로 데이터 분리

이 단계에서는 Iris 데이터셋을 로드하고 특성 (features) 과 타겟 변수 (target variable) 로 분리하는 것부터 시작하겠습니다. 머신러닝에서 X는 특성 (입력 변수) 을 나타내는 관례적인 표기법이며, y는 타겟 (예측하려는 출력 변수) 을 나타내는 표기법입니다.

scikit-learn 라이브러리는 datasets 모듈을 통해 Iris 데이터셋을 제공합니다. 로드된 데이터셋 객체는 딕셔너리처럼 작동합니다.

Iris 데이터셋 구조:

  • iris.data: 특성 행렬 (150 개 샘플 × 4 개 특성)
  • iris.target: 타겟 레이블 (150 개 샘플)
  • iris.feature_names: 4 개 특성의 이름
  • iris.target_names: 3 개 꽃 종의 이름

X 와 y 를 분리하는 이유:

  • X: 입력 특성 (모델이 학습하는 대상)
  • y: 타겟 레이블 (모델이 예측하는 대상)
  • 이는 머신러닝의 표준 관례입니다.

먼저, 왼쪽에 있는 파일 탐색기를 사용하여 ~/project 디렉토리에 있는 preprocess.py 파일을 엽니다. 이 파일에 코드를 추가할 것입니다.

## --- Step 1: Split data --- 주석 아래에 다음 줄을 추가하여 각각 특성과 타겟을 Xy에 할당합니다. 또한 모양 (shape) 을 출력하여 확인할 것입니다.

## --- Step 1: Split data ---
X = iris.data
y = iris.target

print("Shape of features (X):", X.shape)
print("Shape of target (y):", y.shape)

이제 파일을 저장하고 터미널에서 실행하여 출력을 확인합니다.

python3 preprocess.py

다음과 같은 출력을 볼 수 있으며, 이는 150 개의 샘플과 4 개의 특성, 그리고 이에 해당하는 150 개의 타겟 레이블이 있음을 나타냅니다.

Shape of features (X): (150, 4)
Shape of target (y): (150,)

sklearn.preprocessing 의 StandardScaler 를 사용하여 특성 스케일링

이 단계에서는 특성을 스케일링할 준비를 할 것입니다. 특성 스케일링은 입력 특성의 스케일에 민감할 수 있는 많은 머신러닝 알고리즘에 대한 일반적인 요구 사항입니다. StandardScaler는 평균을 제거하고 단위 분산으로 스케일링하여 특성을 표준화하는 인기 있는 기법입니다.

StandardScaler 작동 방식:

  • 공식: z = (x - u) / s (여기서 u는 훈련 샘플의 평균이고, s는 표준 편차입니다.)
  • 효과: 데이터를 평균 0, 표준 편차 1 로 변환합니다.
  • 이점: 더 큰 스케일의 특성이 학습 프로세스를 지배하는 것을 방지합니다.

StandardScaler 의 주요 매개변수:

  • with_mean=True (기본값): 평균을 제거하여 데이터를 중심화합니다.
  • with_std=True (기본값): 표준 편차로 나누어 데이터를 스케일링합니다.

sklearn.preprocessing에서 StandardScaler를 사용할 것입니다. 프로세스의 첫 번째 부분은 스케일러의 인스턴스를 생성하는 것입니다.

preprocess.py 파일에서 ## --- Step 2: Initialize the scaler --- 주석 아래에 다음 코드를 추가하여 StandardScaler의 인스턴스를 생성합니다.

## --- Step 2: Initialize the scaler ---
scaler = StandardScaler()

print("Scaler object created:", scaler)

파일을 저장하고 다시 실행합니다.

python3 preprocess.py

이제 출력에 StandardScaler 객체가 성공적으로 생성되었음을 확인하는 줄이 포함됩니다.

Shape of features (X): (150, 4)
Shape of target (y): (150,)
Scaler object created: StandardScaler()

scaler.fit(X) 로 스케일러 학습

이 단계에서는 특성 데이터 XStandardScaler를 학습시킬 것입니다. fit() 메서드는 scikit-learn 의 기본 개념입니다.

fit()의 역할:

  • 훈련 데이터로부터 필요한 통계량 (평균 및 표준 편차) 을 계산합니다.
  • 나중에 사용할 이러한 매개변수를 내부에 저장합니다.
  • 중요: 데이터로부터 학습만 할 뿐, 변환하지는 않습니다.

fit()transform()을 분리하는 이유:

  • 훈련 데이터에만 fit: 훈련 세트에서만 매개변수를 학습하여 데이터 누수 (data leakage) 를 방지합니다.
  • 모든 데이터에 적용: 학습된 동일한 매개변수를 사용하여 훈련 및 테스트 데이터를 모두 변환할 수 있습니다.
  • 일관성: 모든 데이터에 동일한 변환이 적용되도록 보장합니다.

실제 모범 사례:

  • scaler.fit(X_train) - 훈련 데이터에서만 매개변수 학습
  • X_train_scaled = scaler.transform(X_train) - 훈련 데이터 변환
  • X_test_scaled = scaler.transform(X_test) - 동일한 매개변수로 테스트 데이터 변환

preprocess.py 파일에서 ## --- Step 3: Fit the scaler --- 주석 아래에 다음 코드를 추가합니다. 스케일러가 학습한 내용을 확인하기 위해 스케일러의 mean_ 속성도 출력할 것입니다.

## --- Step 3: Fit the scaler ---
scaler.fit(X)

print("Scaler mean:", scaler.mean_)

파일을 저장하고 실행합니다.

python3 preprocess.py

출력에는 이제 스케일러가 데이터로부터 계산한 네 가지 특성 각각의 평균이 표시됩니다.

Shape of features (X): (150, 4)
Shape of target (y): (150,)
Scaler object created: StandardScaler()
Scaler mean: [5.84333333 3.05733333 3.758      1.19933333]

scaler.transform(X) 로 데이터 변환

이 단계에서는 학습된 스케일러를 사용하여 데이터를 변환할 것입니다. transform() 메서드는 fit() 단계에서 계산된 평균과 표준 편차를 사용하여 데이터에 스케일링 변환을 적용합니다. 이를 통해 데이터는 평균 0, 표준 편차 1 로 중심화됩니다.

원본 데이터를 그대로 유지하기 위해 변환된 데이터는 새 변수 X_scaled에 저장할 것입니다.

코드 이해:

  • X_scaled = scaler.transform(X): 학습된 변환을 데이터에 적용합니다.
  • np.set_printoptions(precision=2, suppress=True): 출력을 더 읽기 쉽게 형식화합니다.
    • precision=2: 소수점 이하 2 자리까지 표시합니다.
    • suppress=True: 매우 작거나 큰 숫자에 대해 과학적 표기법을 사용합니다.
  • np.mean(X, axis=0): axis 0(열) 을 따라 평균을 계산합니다.
    • axis=0: 모든 샘플에 걸쳐 각 특성 (열) 에 대한 평균을 계산합니다.
    • 결과: 특성별 평균값 하나

preprocess.py 파일에서 ## --- Step 4: Transform the data --- 주석 아래에 다음 코드를 추가합니다. 변환 효과를 관찰하기 위해 원본 데이터와 스케일링된 데이터의 평균을 출력할 것입니다.

## --- Step 4: Transform the data ---
X_scaled = scaler.transform(X)

## Use numpy to set precision for cleaner output
np.set_printoptions(precision=2, suppress=True)
print("Original data mean:", np.mean(X, axis=0))
print("Scaled data mean:", np.mean(X_scaled, axis=0))
print("Scaled data sample:\n", X_scaled[:5])

파일을 저장하고 실행합니다.

python3 preprocess.py

스케일링된 데이터의 평균이 사실상 0 이 되고 샘플 데이터 값이 변환되었음을 확인할 수 있습니다.

Shape of features (X): (150, 4)
Shape of target (y): (150,)
Scaler object created: StandardScaler()
Scaler mean: [5.84333333 3.05733333 3.758      1.19933333]
Original data mean: [5.84 3.06 3.76 1.2 ]
Scaled data mean: [-0. -0. -0. -0.]
Scaled data sample:
 [[-0.9   1.02 -1.34 -1.32]
 [-1.14 -0.13 -1.34 -1.32]
 [-1.39  0.33 -1.4  -1.32]
 [-1.51  0.1  -1.28 -1.32]
 [-1.02  1.25 -1.34 -1.32]]

sklearn.preprocessing 의 LabelEncoder 를 사용하여 범주형 타겟 인코딩

이 단계에서는 타겟 변수 y를 전처리할 것입니다. Iris 데이터셋의 타겟은 범주형이며, 세 가지 다른 Iris 꽃 종에 해당하는 숫자 0, 1, 2 로 표현됩니다. 이미 숫자 형식이지만, 범주형 레이블을 인코딩하는 방법을 이해하는 것은 좋은 습관입니다. 특히 문자열 형식 (예: 'setosa', 'versicolor') 인 경우 더욱 그렇습니다.

LabelEncoder 설명:

  • 목적: 범주형 레이블 (문자열 또는 혼합 유형) 을 정수로 변환합니다.
  • 작동 방식: 고유한 각 범주에 고유한 정수를 할당합니다.
  • 예시: ['cat', 'dog', 'cat'] → [0, 1, 0]

LabelEncoder 를 사용하는 이유:

  • 많은 ML 알고리즘은 숫자 입력을 요구합니다.
  • 효율적인 저장 및 계산이 가능합니다.
  • 데이터의 범주형 특성을 유지합니다.

주요 메서드:

  • fit(y): 범주에서 정수로의 매핑을 학습합니다.
  • transform(y): 학습된 매핑을 적용합니다.
  • fit_transform(y): 두 단계를 하나의 호출로 결합합니다.
  • inverse_transform(y_encoded): 정수를 원래 범주로 다시 변환합니다.

중요 참고 사항:

  • 순서는 임의적입니다 (첫 번째 등장 또는 정렬 기준).
  • 순서가 중요한 순서형 데이터에는 적합하지 않습니다 (대신 OrdinalEncoder 를 사용하세요).
  • 특성 (타겟이 아닌) 의 경우, 명목형 데이터에는 OneHotEncoder 를 고려하세요.

preprocess.py 파일에서 ## --- Step 5: Encode the target --- 주석 아래에 다음 코드를 추가합니다. LabelEncoder 인스턴스를 생성하고 fit_transform() 메서드를 사용할 것입니다. 이 메서드는 학습과 변환을 단일 단계로 결합합니다.

## --- Step 5: Encode the target ---
encoder = LabelEncoder()
y_encoded = encoder.fit_transform(y)

print("\nOriginal target sample:", y[:5])  ## Show first 5 original labels
print("Encoded target sample:", y_encoded[:5])  ## Show first 5 encoded labels
print("Unique encoded values:", np.unique(y_encoded))  ## Show all unique encoded values

파일을 저장하고 마지막으로 실행합니다.

python3 preprocess.py

출력에서 타겟 변수가 인코딩되었음을 확인할 수 있습니다. 이미 올바른 정수 형식이었기 때문에 결과는 동일하지만, 문자열 기반 레이블에 사용할 프로세스를 보여줍니다.

Shape of features (X): (150, 4)
Shape of target (y): (150,)
Scaler object created: StandardScaler()
Scaler mean: [5.84333333 3.05733333 3.758      1.19933333]
Original data mean: [5.84 3.06 3.76 1.2 ]
Scaled data mean: [-0. -0. -0. -0.]
Scaled data sample:
 [[-0.9   1.02 -1.34 -1.32]
 [-1.14 -0.13 -1.34 -1.32]
 [-1.39  0.33 -1.4  -1.32]
 [-1.51  0.1  -1.28 -1.32]
 [-1.02  1.25 -1.34 -1.32]]

Original target sample: [0 0 0 0 0]
Encoded target sample: [0 0 0 0 0]
Unique encoded values: [0 1 2]

요약

실습을 완료하신 것을 축하드립니다! scikit-learn 을 사용하여 필수적인 데이터 전처리 작업을 성공적으로 수행했습니다.

이번 실습에서는 다음을 배웠습니다.

  • scikit-learn 에서 표준 데이터셋을 로드하는 방법.
  • 데이터를 특성 (X) 과 타겟 (y) 으로 분리하는 방법.
  • StandardScaler를 사용하여 수치형 특성을 스케일링하는 방법. 먼저 데이터를 fit하여 파라미터를 학습한 다음 데이터를 transform합니다.
  • 범주형 타겟 레이블을 LabelEncoder를 사용하여 기계가 읽을 수 있는 정수 형식으로 인코딩하는 방법.

이러한 전처리 단계는 강력하고 성능이 뛰어난 머신러닝 모델을 구축하는 데 필수적입니다. 이제 향후 머신러닝 프로젝트를 위해 자체 데이터셋을 준비할 수 있는 역량을 갖추게 되었습니다.