[머신러닝] 데이터 인코딩(DataEncoding)/Feature Scaling이란?

2025. 2. 27. 00:56AI & DS/머신러닝

1. Label Encoding (레이블 인코딩)

  • 문자(범주형, Categorical) 데이터를 숫자로 변환하는 방법
  • 예를 들어, "사과", "바나나", "오렌지" 같은 문자열을 0, 1, 2 같은 숫자로 변환함
  • 💡 머신러닝 모델은 숫자만 이해할 수 있기 때문에, 문자 데이터를 숫자로 변환해야 한다!
과일이름 레이블(숫자)
Apple 0
Banana 1
Orange 2

 

from sklearn.preprocessing import LabelEncoder

fruits = ["Apple", "Banana", "Orange", "Apple", "Banana"]
encoder = LabelEncoder()
encoded_labels = encoder.fit_transform(fruits)

print(encoded_labels)  # 출력: [0 1 2 0 1]
💡 fit_transform()
- fit()과 transform()을 한 번에 실행하는 함수, 데이터 변환 과정을 한 줄로 줄여주는 함
- fit(): 데이터를 분석하고 변환 기준을 학습 (ex: 범주 매핑, 평균/표준편차 계산)
- transform(): 학습한 기준을 사용하여 데이터를 변환
  • fit()과 transform()을 따로 실행할 경우, 결과는 같음
encoder.fit(fruits)  # 데이터 학습 (어떤 범주들이 있는지 저장)
print(encoder.classes_)  # ['Apple' 'Banana' 'Orange']

encoded_labels = encoder.transform(fruits)  # 저장된 기준을 사용해 변환
print(encoded_labels)  # [0 1 2 0 1]

 


Label Encoding의 문제점

  • 숫자가 "순서"를 가진다고 오해할 수 있음!
  • "Orange(2)가 Banana(1)보다 크다"는 의미가 없는데, 모델이 오해할 가능성이 있음
  • 특히 선형 회귀나 KNN 같은 모델에서는 문제가 될 수 있음
    • 선형 회귀는 숫자를 선형적인 관계로 해석 : "Orange(2)가 Banana(1)보다 크다"고 생각해버리지만, 과일 사이에 순서는 의미 없음
    • KNN은 거리 기반 알고리즘 : "Orange(2)가 Banana(1)보다 Apple(0)보다 더 가깝다"고 잘못 판단할 수 있음
  • 💡 해결 방법 : One-Hot Encoding
💡 선형 회귀(Linear Regression 
- X(입력 데이터)가 주어졌을 때, Y(출력 값)를 예측하는 모델
- X와 Y 사이의 관계를 직선(선형식)으로 표현하는 알고리즘 = 즉, 데이터를 가장 잘 설명하는 "최적의 직선"을 찾는 과정
- (ex) 키와 몸무게 사이의 관계를 직선으로 찾음 몸무게 = W * 키 + b

- [수식] Y = W X + b
   - W (기울기, 가중치): X가 변할 때 Y가 얼마나 변하는지 결정
   - b (절편): X=0일 때 Y의 값
   - 목표: 데이터를 가장 잘 설명하는 W와 b를 찾는 것

- 선형 회귀는 데이터를 가장 잘 설명하는 직선을 찾고, 새로운 데이터가 주어졌을 때 예측 할 수 있음
💡 KNN(K-Nearest Neighbors, K-최근접 이웃)
- 새로운 데이터가 주어졌을 때, 가장 가까운 K개의 데이터를 찾아 다수결 투표 또는 평균을 계산하는 알고리즘
- 가까운 친구(K개)를 보고 정답을 예측한다

- (ex) 나이별 영화 선호도 예측
   새로운 사람이 "20살"이라면? 주변(가까운 K개)의 데이터를 보고 예측
   K=3 → 가장 가까운 3명의 영화 취향을 조사
   15(액션), 18(액션), 22(로맨스) → 액션이 2표 → "액션" 예측

- KNN은 그래프에서 "비슷한 위치"에 있는 데이터를 보고 결정을 내림
   -  KNN은 거리를 기반으로 하기 때문에 스케일(단위 조정)이 매우 중요
   - 모든 데이터가 숫자 형태여야 비교할 수 있음

 


2. One-Hot Encoding (원-핫 인코딩)

  • 각 카테고리를 0과 1로 이루어진 벡터(Binary Vector)로 변환하는 방법
  • 카테고리 개수만큼 새로운 컬럼을 만들어 해당하는 값만 1, 나머지는 0으로 표시함
과일이름 Apple Banana Orange
Apple 1 0 0
Banana 0 1 0
Orange 0 0 1
Apple 1 0 0
Banana 0 1 0
from sklearn.preprocessing import OneHotEncoder
import numpy as np

fruits = np.array(["Apple", "Banana", "Orange", "Apple", "Banana"]).reshape(-1, 1)

encoder = OneHotEncoder(sparse=False)
onehot_encoded = encoder.fit_transform(fruits)

print(onehot_encoded)

One-Hot Encoding의 장/단점

  • [장점] Label Encoding의 순서 문제 해결, 범주형 데이터를 잘 표현할 수 있음
  • [단점] 카테고리가 많으면 데이터 크기가 커짐(고차원 문제)
    • 예를 들어, 나라 이름(한국, 미국, 일본...)이 100개라면 100개의 컬럼이 생김 = 차원의 저주(Curse of Dimensionality)
    • 해결 방법 : 필요 없는 컬럼을 줄이는 기법을 사용 (PCA, Feature Selection 등)
💡 차원의 저주(Curse of Dimensionality)
- 데이터의 차원이 증가할수록 계산량이 급격히 증가하는 문제
- One-Hot Encoding을 사용하면 카테고리 개수만큼 열(컬럼)이 추가됨
- 예를 들어 100개의 나라가 있다면 100개의 열이 생김

- [문제점]
   메모리 사용량 증가 → 데이터 크기가 커지고 연산 속도 저하
   모델 성능 저하 → 불필요한 변수(컬럼)가 많으면 과적합(overfitting) 발생 가능
- [해결방법] 차원 축소 기법 사용
💡 차원 축소 기법 (PCA, Feature Selection)
1. PCA(Principal Component Analysis, 주성분분석)
- 데이터를 가장 잘 표현하는 "주성분"을 찾아 차원을 줄이는 기법
- 여러 개의 One-Hot Encoding 컬럼을 주요한 몇 개의 컬럼으로 변환
- 데이터를 압축하지만 정보 손실이 발생할 수도 있음

2. Feature Selection (특징 선택)
- 모델 학습에 중요한 컬럼만 선택하고 나머지는 버림
- 카테고리 개수가 많아도 실제로 중요한 컬럼은 일부일 가능성이 큼
- (ex) "Korea", "USA", "Japan"은 중요하지만, "Liechtenstein" 같은 나라는 덜 중요할 수도 있음

 

 


3. Feature Scaling (피처 스케일링, 특성 스케일링)

  • 각각의 숫자 데이터가 너무 크거나 작으면 모델 학습이 어려워짐
  • 모든 데이터 값을 일정한 범위로 맞춰주는 과정
  • 💡필요 이유 : 어떤 데이터는 1 ~ 10 사이의 값을 가지지만, 어떤 데이터는 1000 ~ 10000 사이 값을 가질 수 있음 :  값의 크기 차이가 크면 큰 값이 더 중요한 것처럼 보이는 오류가 발생할 수 있음

숫자가 크면 머신러닝 모델이 어떻게 영향을 받을까?

머신러닝 모델(특히 경사 하강법 기반 모델, 거리 기반 모델)은 특징(Feature) 값이 크면 더 중요한 정보라고 착각할 수 있음
즉, 연봉(만원 단위)의 값이 너무 커서, 나이(단위: 연도)의 영향을 거의 무시하는 문제가 발생함!

 

문제 발생 예시 (선형 회귀) : 머신러닝 모델이 아래 데이터를 학습한다고 가정

나이 연봉(만원)
25 3000
30 5000
35 7000
40 10000

 

  • 선형 회귀의 가중치(Weight)는 위처럼 학습될 가능성이 높음
    • 나이는 25~40 범위이므로 영향이 작음
    • 연봉은 3000~10000 범위이므로 수치가 큼 → 모델이 연봉을 훨씬 더 중요하게 생각함
    • 따라서 모델이 나이보다 연봉에 훨씬 더 집중하게 됨

Feature Scaling을 하지 않으면 영향을 크게 받는 모델들

1. 선형 회귀 (Linear Regression)

  • 선형 회귀는 각 특징(Feature)에 가중치(Weight)를 곱해서 예측
  • 숫자가 큰 Feature는 상대적으로 더 큰 가중치를 가질 가능성이 큼
  • 즉, "연봉"의 영향이 너무 커지고, "나이"의 영향이 거의 사라짐 → 결과적으로 나이는 무시되고 연봉만 보고 예측하는 모델이 될 수도 있음

2. 경사 하강법 (Gradient Descent) 기반 모델들

  • 예: 로지스틱 회귀(Logistic Regression), 신경망(Neural Network) 등
  • 경사 하강법(Gradient Descent)이란?
    • 모델이 학습할 때, 손실 함수(Loss)를 줄이기 위해 가중치(W)를 업데이트함
    • 하지만 Feature 값이 크면 가중치 업데이트 크기가 달라져서 학습이 불균형해짐

3. KNN (K-최근접 이웃) & K-Means (군집 알고리즘)

  • 거리 기반 알고리즘들은 Feature 크기가 다르면 왜곡된 판단을 내릴 수 있음
  • 왜 문제인가 : KNN은 가까운 점을 찾을 때 "유클리드 거리"를 사용

  • 나이(25~40)는 범위가 작음
  • 연봉(3000~10000)은 숫자가 큼 → 거리를 계산할 때 연봉이 압도적인 영향을 미침
  • 즉, 나이가 중요하더라도, 모델은 연봉 차이만 보고 판단할 가능성이 큼
  • 해결 방법: Feature Scaling을 사용해서 모든 Feature 값을 비슷한 범위로 맞춰줌

4. PCA (주성분 분석)

  • PCA는 데이터의 "분산(Variance)"을 기준으로 차원을 줄이는 기법
  • Feature 값의 범위가 다르면, 숫자가 큰 Feature가 더 중요한 것으로 잘못 인식됨
  • 해결 방법: Feature Scaling을 해서 모든 Feature가 동일한 크기를 가지도록 맞춰줌!

1. Standardization (표준화, Z-score 정규화)

  • 데이터의 평균(μ)을 0, 표준편차(σ)를 1로 변환
  • 정규분포(가우시안 분포)를 따르는 데이터에 적합 -> 데이터의 분포를 유지하면서 크기를 조정
  • 음수 값이 나올 수도 있음
    • μ: 평균, σ: 표준편차

  • SVM, KNN, 선형 회귀, PCA 등에서 사용
  • Gradient Descent(경사 하강법) 사용 모델에서 필수
장점 단점
정규분포 데이터에 효과적 이상치(Outlier)에 민감
데이터의 분포가 유지됨 음수 값이 포함될 수 있음
선형 회귀, SVM, PCA 같은 모델에서 성능 향상 데이터가 정규분포가 아닐 경우 효과 ↓

 

from sklearn.preprocessing import StandardScaler
import pandas as pd

# 예제 데이터
data = {"Height": [160, 170, 180, 190], "Weight": [50, 70, 90, 110]}
df = pd.DataFrame(data)

# StandardScaler 적용
scaler = StandardScaler()
df_standardized = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)

print(df_standardized)

 


2. Min-Max Scaling (최소-최대 정규화)

  • 모든 데이터를 0과 1 사이 값으로 변환
  • 모든 데이터가 동일한 범위를 가지므로 해석이 쉬움
  • 이상치(Outlier)에 매우 민감

  • 모든 데이터가 0~1 범위로 변환됨
  • 데이터의 분포가 비정규분포(균등분포 등)일 때 적합
  • 이상치(Outlier)가 있으면 결과가 왜곡될 수 있음

 

  • 딥러닝(Neural Networks) → 입력값 범위를 0~1로 맞추면 학습이 더 잘됨
  • 이미지 처리 (픽셀 값 0~255) → 0~1로 정규화
장점 단점
모든 Feature가 동일한 스케일(0~1)을 가짐 이상치(Outlier)에 민감
직관적이고 해석이 쉬움 정규분포 데이터에는 적합하지 않음
딥러닝(Neural Networks), 이미지 데이터에서 많이 사용됨  
from sklearn.preprocessing import MinMaxScaler

# Min-Max Scaling 적용
scaler = MinMaxScaler()
df_minmax = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)

print(df_minmax)