데이터분석

데이터 스케일링 및 모델 특성 선택법

장수우 2024. 11. 6. 00:11

데이터 스케일링은 변수들이 서로 다른 범위를 가질 때 분석이나 모델 성능에 영향을 줄 수 있으므로,
중요한 전처리 과정입니다. 거리 기반 알고리즘이나 신경망 모델에서는 스케일링이 큰 효과를 발휘합니다.

주로 세 가지 상황에서 많이 사용합니다.

- 변수 간 크기 차이가 큰 경우

  • 데이터에 있는 변수들이 서로 다른 단위를 가지고 있을 때 스케일링을 적용하면 분석이 용이해집니다.
    나이(10~80)와 연간 수입(수백만 원 단위)처럼 값의 범위가 크게 차이 나는 경우가 대표적입니다.

- 거리 기반 알고리즘을 사용할 때

  • K-최근접 이웃(KNN), K-평균 군집화(K-means)와 같은 거리 기반 알고리즘은 각 변수의 범위가 다르면 성능이
    저하될 수 있습니다. 스케일링을 통해 모든 변수의 범위를 동일하게 맞춰주는 것이 중요합니다.

- 경사하강법을 사용하는 모델을 학습할 때

  • 선형 회귀, 로지스틱 회귀, 신경망 등 경사하강법 기반 모델은 변수 범위에 따라 학습 속도가 달라지거나 최적의 해를 찾기 어려워질 수 있습니다. 스케일링을 통해 모델이 더 빠르고 안정적으로 학습할 수 있습니다.

스케일링 기법

 

1. 표준화 (Standardization)

표준화는 데이터의 평균을 0, 표준편차를 1로 조정하여, 데이터가 정규 분포를 따르도록 변환하는 기법입니다.

from sklearn.preprocessing import StandardScaler
import pandas as pd

# 예시 데이터
data = pd.DataFrame({
    'age': [25, 45, 32, 40, 23, 37],
    'income': [50000, 52000, 60000, 64000, 58000, 61000]
})

# 표준화 적용
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)

# 결과를 데이터프레임으로 변환
data_scaled_df = pd.DataFrame(data_scaled, columns=data.columns)

print(data_scaled_df)

2. 정규화 (Normalization)

정규화는 데이터를 [0, 1] 범위로 변환하는 방법입니다. 특히 값이 0에서 양수로만 구성된 경우 유용합니다.

from sklearn.preprocessing import MinMaxScaler

# 정규화 적용
scaler = MinMaxScaler()
data_normalized = scaler.fit_transform(data)

# 결과를 데이터프레임으로 변환
data_normalized_df = pd.DataFrame(data_normalized, columns=data.columns)

print(data_normalized_df)

3. 로그 변환 (Log Transformation)

데이터가 한쪽으로 치우쳐 있거나 이상치가 많을 때 로그 변환을 적용하면 분포를 정규에 가깝게 만들 수 있습니다.

로그 변환은 연봉이나 거래액과 같이 값의 차이가 클 때 유용합니다.

import numpy as np

# 로그 변환 적용 (0 이상의 값만 가능)
data['income_log'] = np.log1p(data['income'])  # log1p는 log(1 + x)로 0일 때도 처리 가능

print(data[['income', 'income_log']])

로그 변환을 통해 큰 값을 축소하여 분포를 조정할 수 있습니다.
변수 간의 상대적 크기 차이를 줄이고, 데이터가 비대칭일 때 정규 분포에 가까워지도록 할 수 있습니다.

 


특성선택

특성 선택은 모델 성능을 높이고, 분석을 더 쉽게 하기 위해 중요한 특성만 선택하여 분석에 사용하는 과정입니다. 모든 특성이 분석에 유효하지 않거나 오히려 성능에 부정적인 영향을 미칠 수 있기 때문에, 특성 선택을 통해 분석 효율성을 높일 수 있습니다.

 

특성 선택이 유용한 상황

  • 높은 차원의 데이터:
    데이터의 특성이 너무 많으면 차원의 저주 문제가 발생할 수 있습니다. 이때, 중요한 특성만 선택하면 모델의 성능을 높일 수 있습니다.
  • 노이즈가 많은 데이터:
    일부 특성은 노이즈 역할을 하여 모델 성능을 떨어뜨립니다. 이런 특성을 제거하면 분석 결과가 정확해질 수 있습니다.
  • 해석 가능한 모델을 원하는 경우:
    특성 수가 줄어들면 모델이 더 간결해지고, 분석 결과의 해석이 쉬워집니다.

주요 특성 선택 방법

1. 상관관계 기반 특성 선택

상관관계 기반 특성 선택은 변수 간의 상관관계를 분석하여 다중공선성이 높은 변수를 제거하거나, 종속 변수와의 관계가 강한 변수를 선택하는 방법입니다. 이 방법은 데이터가 연속형일 때 특히 유용하며, 해석이 용이하다는 장점이 있습니다.

 

주요 방법

  • 피어슨 상관계수 (Pearson Correlation):
    두 연속형 변수 간의 선형 상관관계를 평가합니다. -1에서 1 사이의 값을 가지며, 1에 가까울수록 강한 양의 선형 관계, -1에 가까울수록 강한 음의 선형 관계를 나타냅니다.
  • 스피어만 상관계수 (Spearman Correlation):
    순위에 기반한 상관관계로, 데이터가 정규 분포를 따르지 않거나 비선형 관계일 때 유용합니다.
  • 모든 특성 간의 상관 행렬을 계산합니다.
  • 상관계수가 일정 임계값 이상인 경우(예: 0.7 이상), 다중공선성이 높은 변수 중 하나를 제거합니다.
  • 종속 변수와의 상관계수를 기준으로 상관이 높은 변수를 우선 선택합니다.

 

import pandas as pd

# 예시 데이터 생성
data = pd.DataFrame({
    'feature1': [1, 2, 3, 4, 5],
    'feature2': [2, 4, 6, 8, 10],  # feature1과 높은 상관관계
    'feature3': [5, 3, 4, 2, 1],
    'target': [1, 0, 1, 0, 1]
})

# 상관 행렬 계산
correlation_matrix = data.corr()
print("상관 행렬:\n", correlation_matrix)

# 상관계수 임계값을 설정하여 다중공선성이 높은 변수 제거
threshold = 0.7
correlated_features = set()
for i in range(len(correlation_matrix.columns)):
    for j in range(i):
        if abs(correlation_matrix.iloc[i, j]) > threshold:
            colname = correlation_matrix.columns[i]
            correlated_features.add(colname)

print("다중공선성이 높은 특성:\n", correlated_features)

# 상관관계가 낮은 특성만 남기기
data_selected = data.drop(columns=correlated_features)
print("선택된 데이터:\n", data_selected)

 

2. 모델 기반 특성 선택 (Feature Importance)

모델 기반 특성 선택은 학습된 모델을 통해 각 특성의 중요도를 평가하여, 중요한 특성만 선택하는 방법입니다.
특히 비선형 관계나 고차원 데이터에서 효과적입니다.

 

주요 방법

  • 트리 기반 모델 (Tree-Based Models):
    랜덤 포레스트, 결정 트리와 같은 트리 기반 모델은 특성의 중요도를 계산할 수 있습니다. 이러한 모델들은 비선형
    관계도 고려하므로, 다양한 데이터에서 특성 중요도를 평가하는 데 유리합니다.
  • 선형 모델 (Linear Models):
    선형 회귀나 로지스틱 회귀와 같은 선형 모델은 각 특성의 가중치 계수를 통해 중요도를 평가할 수 있습니다.
  • L1 규제 (Lasso):
    L1 규제를 사용하는 Lasso 회귀는 가중치가 0인 특성을 자동으로 제거하여 중요한 특성만 남깁니다.
  • 모델을 학습하여 특성 중요도를 계산합니다.
  • 특정 임계값 이상인 중요도를 가진 특성만 선택하거나, 상위 몇 개의 특성만 선택합니다.
## 랜덤포레스트 예시
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
import pandas as pd

# 예시 데이터 생성
X, y = make_classification(n_samples=100, n_features=10, random_state=42)
data = pd.DataFrame(X, columns=[f'feature_{i}' for i in range(10)])

# 랜덤 포레스트 모델 학습
model = RandomForestClassifier(random_state=0)
model.fit(X, y)

# 특성 중요도 추출
feature_importances = pd.Series(model.feature_importances_, index=data.columns)
selected_features = feature_importances[feature_importances > 0.1]  # 중요도 기준으로 특성 선택

print("특성 중요도:\n", feature_importances)
print("선택된 특성:\n", selected_features)

 

3. 순차 특성 선택 (Sequential Feature Selection)

순차 특성 선택은 모델 성능이 가장 좋아지는 조합을 찾기 위해 특성을 하나씩 추가하거나 제거하며 최적의 특성 집합을 찾아가는 방법입니다.

전진선택법, 후진제거법, 단계적 선택법을 주로 사용합니다.

## 후진 제거법
from sklearn.feature_selection import SequentialFeatureSelector
from sklearn.linear_model import LinearRegression
from sklearn.datasets import make_regression
import pandas as pd

# 데이터 생성
X, y = make_regression(n_samples=100, n_features=10, noise=0.1, random_state=42)
data = pd.DataFrame(X, columns=[f'feature_{i}' for i in range(10)])

# 후진 제거법을 적용한 순차 선택
model = LinearRegression()
sfs = SequentialFeatureSelector(model, n_features_to_select=5, direction='backward')
sfs.fit(X, y)

# 선택된 특성
selected_features = data.columns[sfs.get_support()]
print("선택된 특성:\n", selected_features)

-------------------------

## 전진 선택법
sfs_forward = SequentialFeatureSelector(model, n_features_to_select=5, direction='forward')
sfs_forward.fit(X, y)

# 선택된 특성
selected_features_forward = data.columns[sfs_forward.get_support()]
print("선택된 특성 (전진 선택):\n", selected_features_forward)

 단계적 선택법 (Stepwise Selection)

  • 절차:
    1. 전진 선택을 통해 특성을 하나씩 추가합니다.
    2. 각 단계에서 새로 추가된 특성 및 기존 특성의 기여도를 평가합니다.
    3. 기여도가 낮은 특성이 발견되면 해당 특성을 제거하고, 새로운 특성을 추가하는 과정을 반복합니다.
    4. 더 이상 추가할 특성이 없거나, 성능이 더 이상 개선되지 않으면 중단합니다.
  • 단계적 선택법은 전진 선택법과 후진 제거법을 결합한 방법입니다. 전진 선택을 통해 특성을 추가하면서도, 추가된 특성 중 기여도가 낮아진 특성이 발견되면 이를 제거합니다.
반응형