활용하고자 하는 데이터를 EDA 등의 과정을 통해 탐색하고 이해했다면, 이 데이터를 기계학습 모델에 사용하기 적합하도록 데이터의 질을 높여주는 과정이 전처리(Pre-processing) 이다.
기본적인 전처리 과정에는 Noise 혹은 Null 값처리, 인코딩(Encoding), 스케일링(Scaling) 및 정규화(Normalization) 과정 등이 있다.
PCA 등의 차원축소 기법, Feature Selection 및 Extraction 등에 대해서는 후속 포스팅에서 정리하겠다.
1. 데이터 인코딩 (Encoding)
데이터 인코딩은 기계학습에서 활용할 알고리즘에 적합한 형태로 데이터를 변환하는 것을 의미하며, 대게는 문자형/범주형 데이터를 숫자형으로 변환하는 과정을 말한다.
1-1. 레이블 인코딩
카테고리(범주형) 피쳐를 코드형 숫자로 변환하는 것
숫자로 변환하다 보니 '크고 작음' 으로 인한 우선순위 발생 등의 부작용이 생김. 따라서 회귀모델보다는 트리형태 알고리즘에 주로 사용한다.
LabelEncoder 클래스를 활용하여 인코딩, 디코딩을 수행할 수 있다.
from sklearn.preprocessing import LabelEncoder
items=['TV','냉장고','컴퓨터','믹서','믹서','믹서','핸드폰']
encoder = LabelEncoder()
# 피처값을 인코딩할때 fit 과 transform 을 사용
encoder.fit(items)
labels = encoder.transform(items)
# labels = encoder.fit_transform(items) 이렇게 한번에 쓸수도 있음
print('인코딩 변환값:',labels)
# 인코딩 후에는 classes_ 속성값에 0부터 순서대로 저장됨
print('인코딩 클래스:',encoder.classes_)
# 디코딩
print('디코딩:',encoder.inverse_transform([4,1,2]))
1-2. 원-핫 인코딩 (OneHotEncoder)
레이블 인코딩의 숫자특성으로 인한 문제점 해결
행 형태의 피쳐 고유값을 열 형태로 전환한뒤, 고유값만 1처리하여 2차원 메트릭스로 만든다.
변환된 값은 희소행렬(Sparse Matrix) 이기 때문에, toarray() 매서드를 이용해 밀집행렬(Dense Matrix) 변환 해줘야함
사이킷런에 OneHotEncoder 클래스가 있지만 fit_transform 하고 밀집행렬 변환해주기까지 번거롭기에, 아래 코드와 같이 주로 Pandas 모듈의 get_dummies 라는 API 를 활용한다.
get_dummies로 반환되는 값은 위에 그림과 같은 모습의 DataFrame 이다.
# Pandas 에서 간단하게 OneHotEncoder 를 활용하는 API 소개
# get_dummies
import pandas as pd
df = pd.DataFrame({'item':['TV','냉장고','컴퓨터','믹서','믹서','믹서','핸드폰']})
pd.get_dummies(df)
2. 피쳐 스케일링 (Feature Scaling) - 표준화, 정규화
피쳐간에 상대적인 값 차이가 너무 크다면, 피쳐의 크기가 피쳐 중요도가 될 수 있기에 일정한 크기로 맞추는 작업
대표적인 두 방법 ①표준화(Standardization)는 N(0,1) 정규화를 하는것, ②정규화(Normalization)는 모두 같은 크기/범위로 맞춰주는 것
★주의할 점 : Scaling 시에는 fit 은 학습데이터에만, 테스트 데이터에는 transform만 해야한다. fit 은 스케일링을 위한 기준정보(평균,최대/최소 등)를 설정하는 과정이기 때문에, 학습/테스트 따로하면 스켈링 기준이 다르게 된다.→ 따라서, 스케일링은 가능하면 data split 이전에 하는게 맞다
회귀문제에서는 타겟의 분포가 Skewed 되어있는지 꼭 확인하고 정규화 해줘야한다. (Skewness는 아래와 같이 Histogram으로 확인할 수도 있다)
SVM,선형회귀,로지스틱회귀는 데이터가 정규분포를 띈다는 가정하에 구현되었기에 표준화가 매우 중요하다.
대부분의 회귀문제에서는 타겟이 Skewed 되있다면 로그 정규화를 진행한다.
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(iris_df)
# scaler 로 transform 하면 Numpy 의 ndarray 형태로 반한됨.
iris_scaled = scaler.transform(iris_df)
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris_data_name)
Oversampling 과 Under Sampling 은 불균형한 데이터셋의 불균형을 완화해주는 기법이다.
데이터 유실 문제로 대게의 경우에는 Oversampling 이 사용되는데, Oversampling은 적은 라벨의 데이터를 많은 라벨 수준으로 증식 시켜주는 방식이다. Oversampling 에 대표적인 방법이 SMOTE 이다.
Data Augmentation 과의 차이? 비슷한 맥락에서 사용할 수도 있지만 Oversampling 은 불균형 데이터셋을 맞춰 적은 클래스 데이터가 학습이 안되는걸 방지하는 목적에 가깝고, Augmentation은 주로 딥러닝 모델에서 더 강력한 모델을 만들기 위해 가지고 있는 데이터를 변형시켜 증식하는 목적이다.
3-1. SMOTE
SMOTE는 Synthetic Minority Over-sampling Technique의 약자로 대표적인 오버 샘플링 기법 중 하나이다.낮은 비율로 존재하는 클래스의 데이터를 최근접 이웃 K-NN 알고리즘알고리즘을 활용하여 새롭게 생성하는 방법이다.
가상의 데이터를 증식하는 방식이기때문에, 검증/테스트셋에는 사용하면 안되며, 학습데이터에만 사용해야한다.
SMOTE 활용코드. 통상적으로 Oversample 하면 재현율(Recall)은 올라가고 정밀도(Precision)은 떨어진다.
댓글