머신러닝에서 모델의 성능을 높이고 과적합(overfitting)을 방지하기 위해 특성 선택(Feature Selection)은 중요한 과정이다. 데이터셋의 모든 변수가 유용한 것은 아니며, 불필요한 변수를 제거하면 모델의 해석력과 학습 속도를 향상시킬 수 있다. 이번 글에서는 특성 선택의 개념, 주요 기법을 소개한다.
1. 특성 선택(Feature Selection)란?
특성 선택은 모델 학습에 유용한 변수를 선택하고 불필요하거나 관련성이 낮은 변수를 제거하는 과정이다. 주된 목적은 다음과 같다.
- 모델 성능 향상: 중요한 변수만을 사용하여 과적합을 방지하고 일반화 성능을 높인다.
- 계산 비용 감소: 변수 수를 줄여 학습 속도를 개선한다.
- 모델 해석력 증가: 핵심 변수만 남겨 가독성을 높인다.
2. 특성 선택 방법
2.1 필터 방법(Filter Method)
필터 방법은 각 특성에 대해 독립적으로 평가 기준을 적용하여 불필요한 변수를 선택하는 방법이다. 이 방법은 모델에 의존하지 않고, 단지 데이터를 기반으로 통계적 기법을 사용하여 변수를 평가한다.
특징
- 모델 독립적: 데이터의 특성을 이용한 평가가 이루어지므로 특정 모델에 의존하지 않는다.
- 빠르고 간단: 평가가 빠르며 계산 비용이 낮다.
- 모델 성능에 영향을 주지 않음: 필터 방법은 모델 학습 전에 특성을 선택하므로, 최종 모델 성능에 영향을 미치지 않는다.
주요 기법
1. 분산 임계값(Variance Threshold)
- 분산이 낮은 변수는 정보량이 적기 때문에 제거할 수 있다. 예를 들어, 모든 샘플에서 값이 거의 일정한 변수를 제거할 수 있다.
- 예제 코드는 아래와 같다.
import pandas as pd
from sklearn.datasets import make_regression
from sklearn.feature_selection import VarianceThreshold
# 예제 데이터 생성
X, y = make_regression(n_samples=100, n_features=10, noise=0.1, random_state=42)
# DataFrame 생성
df = pd.DataFrame(X, columns=[f'Feature{i+1}' for i in range(X.shape[1])])
# 분산 임계값을 설정하여 특성 선택
selector = VarianceThreshold(threshold=0.1)
selected_features = selector.fit_transform(X)
# 선택된 특성의 인덱스를 추출
selected_feature_indices = selector.get_support(indices=True)
# 선택된 특성의 이름을 출력
selected_feature_names = df.columns[selected_feature_indices]
print("Selected Features:", selected_feature_names.tolist())
2. 상관계수(Correlation Coefficient)
- 목표 변수와의 상관계수가 낮은 특성을 제거한다. 상관계수가 0에 가까운 변수는 예측에 큰 영향을 미치지 않기 때문에 제거하는 것이 좋다.
3. 카이제곱(Chi-Square) 검정
- 카이제곱 검정은 범주형 변수에 대해 변수와 클래스 간의 독립성을 확인하고, 유의미한 변수를 선택하는 데 사용된다.
2.2 래퍼 방법(Wrapper Method)
래퍼 방법은 특성 선택을 위해 학습된 모델을 기반으로 변수를 선택하는 방식이다. 이 방법은 변수의 조합을 평가하여 가장 좋은 특성 집합을 선택한다. 모델을 반복적으로 학습시키고 평가하는 과정이 포함된다.
특징
- 모델 의존적: 특정 모델에 의존하므로, 선택된 특성은 해당 모델에 최적화되어 있다.
- 과적합 위험: 반복적인 학습과정에서 과적합(overfitting)이 발생할 수 있다.
- 성능 개선 가능성: 변수를 모델과 함께 최적화하므로 성능 향상 가능성이 크다.
주요 기법
1. 순방향 선택(Forward Selection)
- 순방향 선택은 특성을 하나씩 추가하면서 모델의 성능을 평가하고, 성능이 일정 임계값 이상 향상될 경우 해당 특성을 유지하는 방식으로 진행된다. 이 과정을 통해 불필요한 특성을 배제하고 중요한 특성만을 포함하는 최적의 모델을 구축한다.
- 주요 로직은 아래와 같다.
- 초기 상태 설정: 먼저 아무 특성도 포함하지 않은 모델을 학습한다.
- 특성 추가: 모든 후보 특성 중에서 모델 성능을 가장 많이 개선하는 변수를 하나 추가한다.
- 모델 평가: 추가된 변수로 학습한 모델의 성능을 평가한다. 일반적으로 p-value, AIC(Akaike Information Criterion), BIC(Bayesian Information Criterion) 등의 기준을 사용한다.
- 과정 반복: 특정 종료 조건(예: 추가된 특성이 일정 기준 이상 성능 향상을 가져오지 않음)이 충족될 때까지 반복한다.
- 최적 특성 집합 도출: 더 이상 추가할 특성이 없거나 모델 성능이 더 이상 개선되지 않으면 최종 특성 집합을 결정한다.
- 예제 코드는 아래와 같다.
import pandas as pd
from sklearn.datasets import make_regression
from sklearn.linear_model import LinearRegression
from sklearn.feature_selection import SequentialFeatureSelector
# 예제 데이터 생성
X, y = make_regression(n_samples=100, n_features=10, noise=0.1, random_state=42)
df = pd.DataFrame(X, columns=[f'Feature{i+1}' for i in range(X.shape[1])])
df['Target'] = y # Target 열 추가
# 후방향 제거 적용
model = LinearRegression()
sfs = SequentialFeatureSelector(model, n_features_to_select=5, direction="forward")
sfs.fit(X, y)
# 선택된 특성 확인
selected_feature_indices = sfs.get_support(indices=True)
selected_feature_names = df.columns[:-1][selected_feature_indices] # Target 열 제외
print("선택된 특성:", selected_feature_names.tolist())
2. 후방향 제거(Backward Elimination)
- 모델에서 변수(특성)를 하나씩 제거하며 최적의 특성 집합을 찾는 방법이다. 이 방법은 먼저 모든 특성을 포함한 모델을 학습한 후, 가장 중요하지 않거나 성능에 기여도가 낮은 특성을 하나씩 제거한다. 이 과정을 반복하여 최적의 특성 집합을 도출한다.
- 주요 로직은 아래와 같다.
- 초기 상태 설정: 모든 특성을 포함한 모델을 학습한다.
- 특성 평가: 각 특성이 모델 성능에 미치는 영향을 평가한다. 보통 p-value, AIC, BIC 등을 사용하여 특성을 평가한다.
- 특성 제거: 평가 기준에 따라 가장 중요도가 낮은 특성을 제거한다.
- 모델 재학습 및 평가: 하나의 특성을 제거한 후, 새로 학습된 모델을 평가하고, 제거된 특성을 제외한 나머지 특성에 대해서 다시 평가한다.
- 최적 특성 집합 도출: 모든 특성의 p-value가 일정 기준 이하로 작거나, 모델 성능이 더 이상 개선되지 않으면 종료한다.
- 예제 코드는 아래와 같다.
import pandas as pd
from sklearn.datasets import make_regression
from sklearn.linear_model import LinearRegression
from sklearn.feature_selection import SequentialFeatureSelector
# 예제 데이터 생성
X, y = make_regression(n_samples=100, n_features=10, noise=0.1, random_state=42)
df = pd.DataFrame(X, columns=[f'Feature{i+1}' for i in range(X.shape[1])])
df['Target'] = y # Target 열 추가
# 후방향 제거 적용
model = LinearRegression()
sfs = SequentialFeatureSelector(model, n_features_to_select=5, direction="backward")
sfs.fit(X, y)
# 선택된 특성 확인
selected_feature_indices = sfs.get_support(indices=True)
selected_feature_names = df.columns[:-1][selected_feature_indices] # Target 열열 제외
print("선택된 특성:", selected_feature_names.tolist())
3. 단계적 선택 (Stepwise Selection) 기법
- 단계적 선택은 순방향 선택과 후방향 제거를 조합한 방식으로, 특성을 하나씩 추가하거나 제거하면서 최적의 특성 집합을 찾는다. 이 방법은 특성 추가 및 제거를 동시에 고려하여 최적의 모델을 구축하는 데 유용하다.
- 주요 로직은 아래와 같다.
- 초기 상태 설정: 특성이 없는 상태에서 시작하거나 모든 특성을 포함한 상태에서 시작할 수 있다.
- 특성 추가 및 제거: 한번에 하나의 특성을 추가하거나 제거한다. 모델 성능을 평가하여 개선이 발생하면 해당 변경을 유지한다.
- 모델 평가: 추가된 특성과 제거된 특성을 고려하여 모델 성능을 평가한다. 평가 기준은 일반적으로 AIC, BIC, p-value 등의 기준을 사용한다.
- 과정 반복: 더 이상 모델 성능이 개선되지 않거나 종료 조건을 충족하면 반복을 멈춘다.
- 최적 특성 집합 도출: 선택된 특성 집합이 최종적으로 결정된다.
- 예제 코드는 아래와 같다.
from sklearn.datasets import make_regression
from sklearn.linear_model import LinearRegression
from sklearn.feature_selection import SequentialFeatureSelector
import pandas as pd
# 예제 데이터 생성
X, y = make_regression(n_samples=100, n_features=10, noise=0.1, random_state=42)
# 데이터프레임 생성
df = pd.DataFrame(X, columns=[f'Feature{i+1}' for i in range(X.shape[1])])
# 순방향 선택 적용
model = LinearRegression()
sfs_forward = SequentialFeatureSelector(model, n_features_to_select=7, direction="forward")
sfs_forward.fit(X, y)
# 순방향 선택 후 선택된 특성
selected_features_forward = sfs_forward.get_support(indices=True)
# 후방향 제거 적용 (순방향 선택 후 선택된 특성만 사용)
n_selected_features = len(selected_features_forward)
sfs_backward = SequentialFeatureSelector(model, n_features_to_select=n_selected_features - 2, direction="backward")
sfs_backward.fit(X[:, selected_features_forward], y) # 순방향 선택 후 선택된 특성만 사용
# 최종 선택된 특성
selected_features_final = sfs_backward.get_support(indices=True)
# 선택된 특성 출력
selected_feature_names = df.columns[selected_features_forward][selected_features_final]
print("최종 선택된 특성:", selected_feature_names.tolist())
4. 유전 알고리즘 (Genetic Algorithm, GA) 기법
- 유전 알고리즘은 생물의 자연 선택 과정을 모방하여 최적의 특성 조합을 찾는 방법이다. 랜덤하게 여러 개의 특성 집합을 생성하고, 교차 및 변이 연산을 수행하며 점진적으로 성능이 좋은 특성 집합을 찾는다.
- 주요 로직은 아래와 같다.
- 초기 상태 설정: 랜덤하게 여러 개의 특성 조합을 생성한다.
- 적합도 평가 (Fitness Evaluation): 생성된 개체(특성 조합)에 대해 모델을 학습하고 성능을 평가한다.
- 선택 (Selection): 성능이 좋은 개체를 선택하여 다음 세대에 전달한다.
- 교차 (Crossover): 선택된 개체들 간의 조합을 통해 새로운 특성 조합을 생성한다.
- 변이 (Mutation): 일부 특성을 무작위로 변경하여 새로운 개체를 추가한다.
- 과정 반복: 충분한 세대가 반복되거나 특정 종료 조건이 충족되면 최적의 특성 조합을 결정한다.
5. 재귀적 특성 제거 (Recursive Feature Elimination, RFE) 기법
- 재귀적 특성 제거(RFE)는 모델을 학습한 후, 중요도가 낮은 특성을 반복적으로 제거하여 최적의 특성 집합을 찾는 방법이다. 일반적으로 선형 회귀, 결정 트리 기반 모델과 함께 사용된다.
- 주요 로직은 아래와 같다.
- 초기 상태 설정: 모든 특성을 포함한 모델을 학습한다.
- 특성 중요도 평가: 모델의 특성 중요도를 평가하여 기여도가 낮은 특성을 식별한다.
- 특성 제거: 가장 중요도가 낮은 특성을 하나 제거한다.
- 과정 반복: 원하는 특성 개수에 도달할 때까지 반복한다.
- 최적 특성 집합 도출: 남아 있는 특성들이 최종 선택된 특성이다.
- 예제 코드는 아래와 같다.
import pandas as pd
from sklearn.datasets import make_regression
from sklearn.linear_model import LinearRegression
from sklearn.feature_selection import RFE
import numpy as np
# 예제 데이터 생성
X, y = make_regression(n_samples=100, n_features=10, noise=0.1, random_state=42)
df = pd.DataFrame(X, columns=[f'Feature{i+1}' for i in range(X.shape[1])])
df['Target'] = y # Target 열 추가
# 재귀적 특성 제거 적용
model = LinearRegression()
rfe = RFE(model, n_features_to_select=5)
rfe.fit(X, y)
# 선택된 특성 확인
selected_feature_indices = np.where(rfe.support_)[0]
selected_feature_names = df.columns[selected_feature_indices]
print("선택된 특성:", selected_feature_names.tolist())
2.3 임베디드 방법(Embedded Method)
임베디드 방법은 모델 학습 과정에서 변수 선택을 동시에 수행하는 방법이다. 학습 과정에서 변수의 중요도를 평가하여, 중요도가 낮은 변수를 제거한다. 모델에 내장된 특성 선택 방법을 사용하는 방식이다.
특징
- 모델 학습과 특성 선택 동시 수행: 모델을 학습하면서 변수 선택이 이루어지므로, 계산 효율적이고 과적합을 줄일 수 있다.
- 모델 의존적: 선택된 특성은 해당 모델에서 최적화된 것이다.
주요 기법
1. Lasso 회귀(Lasso Regression)
- Lasso는 L1 정규화 기법을 사용하여, 모델 학습 과정에서 중요하지 않은 변수의 가중치를 0으로 만들어 불필요한 변수를 제거한다.
- 예제 코드는 아래와 같다.
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import Lasso
import pandas as pd
import numpy as np
# California Housing 데이터 로드
california_housing = fetch_california_housing()
X, y = california_housing.data, california_housing.target
# Lasso 회귀 모델 학습
lasso = Lasso(alpha=0.01) # alpha는 정규화 강도를 조절하는 하이퍼파라미터
lasso.fit(X, y)
# 라쏘 회귀 계수 출력
lasso_coefficients = lasso.coef_
# 특성 중요도 평가: 계수가 0이 아닌 특성만 선택
selected_features = X[:, lasso_coefficients != 0]
# 선택된 특성들의 이름 출력
selected_feature_names = np.array(california_housing.feature_names)[lasso_coefficients != 0]
print("Selected features with Lasso Regression:", selected_feature_names)
2. 트리 기반 기법
- 결정 트리 계열의 모델들(예: RandomForest, XGBoost, LightGBM 등)은 각 특성의 중요도를 계산하여, 중요도가 낮은 특성을 제거하는 데 사용된다. 트리 모델에서 특성 중요도를 기반으로 변수를 선택할 수 있다.
- 예제 코드는 아래와 같다.
from sklearn.datasets import fetch_california_housing
from sklearn.ensemble import ExtraTreesRegressor
import pandas as pd
import numpy as np
# California Housing 데이터 로드
california_housing = fetch_california_housing()
X, y = california_housing.data, california_housing.target
# 트리 기반 모델을 활용한 특성 중요도 평가
model = ExtraTreesRegressor()
model.fit(X, y)
# 특성 중요도 평가
feature_importances = model.feature_importances_
# 특성 중요도가 1% 이상인 특성 선택
selected_features = X[:, feature_importances > 0.01]
# 특성 중요도가 1% 이상인 특성들의 이름 출력
selected_feature_names = np.array(california_housing.feature_names)[feature_importances > 0.01]
print("Selected features with importance > 0.01:", selected_feature_names)
3. 결론
특징 선택은 데이터 분석 및 머신러닝 모델링에서 매우 중요한 과정이다. 데이터를 다루는 초기 단게에서 모델의 성능을 최적화하고 과적합(overfitting)을 밪이하기 위해서는 유의미한 특징만을 선택하는 것이 필수적이다. 이를 통해 모델이 더욱 효율적으로 학습하고, 예측 성능을 향상시킬 수 있다.
'데이터 분석' 카테고리의 다른 글
데이터 전처리 (Data Preprocessing) (0) | 2025.03.12 |
---|---|
탐색적 데이터 분석 (EDA : Exploratory Data Analysis) (0) | 2025.03.10 |
범주형 데이터 처리 (0) | 2025.03.10 |
표준화(Standardization)와 정규화(Normalization) (0) | 2025.03.09 |
데이터 분석에서 왜도, 첨도, 로그 변환이 중요한 이유 (0) | 2025.03.09 |