반응형
Index
활용하고자 하는 데이터를 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으로 확인할 수도 있다)
fig, axes = plt.subplots(1, 2, figsize=(10, 2))
sns.histplot(house_df['SalePrice'], kde=True, ax=axes[0])
# 로그 변환
log_SalePrice = np.log1p(house_df['SalePrice'])
sns.histplot(log_SalePrice, kde=True, ax=axes[1])
- 여러 종류의 피쳐중에서 숫자형이면서 Skewed 되어있는 피쳐들 위주로 스케일링하기. Skew 의 정도를 일일히 histogram 볼 수 없으니 아래와 같이 skew 매서드를 활용할 수도 있다.
from scipy.stats import skew
# object가 아닌 숫자형 피처의 칼럼 index 객체 추출.
features_index = house_df.dtypes[house_df.dtypes != 'object'].index
# house_df에 칼럼 index를 [ ]로 입력하면 해당하는 칼럼 데이터 세트 반환. apply lambda로 skew( ) 호출
skew_features = house_df[features_index].apply(lambda x : skew(x))
# skew(왜곡) 정도가 1 이상인 칼럼만 추출.
skew_features_top = skew_features[skew_features > 1]
print(skew_features_top.sort_values(ascending=False)[:5])
house_df[skew_features_top.index] = np.log1p(house_df[skew_features_top.index])
2-1. StandardScaler
- 사이킷런의 StandardScalar 클래스는 평균이 0, 분산이 1 인 정규분포를 따르도록 변환해준다.
- 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)
2-2. MinMaxScaler
- 0~1 사이의 값으로 맞추고자 할 때 사용
from sklearn.preprocessing import MinMaxScaler
scaler=MinMaxScaler()
scaler.fit(iris_df)
iris_scaled=scaler.transform(iris_df)
iris_df_scaled=pd.DataFrame(data=iris_scaled, columns=iris_data_name)
#print(iris_df_scaled.min(), iris_df_scaled.max())
3. Oversampling & Under Sampling
- 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)은 떨어진다.
from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=0)
X_train_over, y_train_over = smote.fit_resample(X_train, y_train)
print('SMOTE 적용 전 학습용 피처/레이블 데이터 세트: ', X_train.shape, y_train.shape)
print('SMOTE 적용 후 학습용 피처/레이블 데이터 세트: ', X_train_over.shape, y_train_over.shape)
print(type(X_train_over),type(y_train_over))
print('SMOTE 적용 후 레이블 값 분포: \n', y_train_over.value_counts())
# SMOTE 사용 후 Label 1에 해당하는 학습데이터가 Label 0 수준으로 증가함 확인
4. (선형)회귀모델에서의 정규화
- 선형회귀는 피쳐와 타겟의 분포가 정규분포인 형태를 매우 선호한다. 특히 타겟의 분포가 Skewed 되어있으면 예측 성능이 안좋아진다.
- 일반적으로 중요한 피쳐들 + 타겟에 대해 스케일링/정규화 작업을 수행한다.
- *피처 데이터의 스케일링 : ① 평균0,분산1인 표준정규분포 정규화 혹은 0~1 사이값으로 표준화 ② 표준,정규화 된것을 다시 다항특성을 적용하여 변환 ③ 로그변환 (주로 사용)
- *타겟 데이터의 스케일링 : 로그변환
- 스케일링으로 로그변환이 주로 사용되는 이유는, 정규분포 변환은 원본으로의 원복이 힘든 반면 로그변환은 넘파이의 log1p() 함수로 정규화 하고, 원복시에 expn1() 함수로 간단히 원상복구 할 수 있기 때문이다.
from sklearn.preprocessing import StandardScaler, MinMaxScaler, PolynomialFeatures
# method는 표준 정규 분포 변환(Standard), 최대값/최소값 정규화(MinMax), 로그변환(Log) 결정
# p_degree는 다향식 특성을 추가할 때 적용. p_degree는 2이상 부여하지 않음.
def get_scaled_data(method='None', p_degree=None, input_data=None):
if method == 'Standard':
scaled_data = StandardScaler().fit_transform(input_data)
elif method == 'MinMax':
scaled_data = MinMaxScaler().fit_transform(input_data)
elif method == 'Log':
scaled_data = np.log1p(input_data)
else:
scaled_data = input_data
# scaled_data 로 scale 된 이후에도 다항변환 할 수 있도록 코딩
if p_degree != None:
scaled_data = PolynomialFeatures(degree=p_degree,
include_bias=False).fit_transform(scaled_data)
return scaled_data
반응형
'Study > ML' 카테고리의 다른 글
6. 앙상블(Ensemble) - 보팅(Voting),배깅(Bagging) (0) | 2023.05.28 |
---|---|
5. 분류(Classification) - Decision Tree (0) | 2023.05.27 |
4. 성능 평가 (Evaluation) - Classification 평가방법 (0) | 2023.05.27 |
2. 교차검증 (Cross-Validation) (1) | 2023.05.26 |
1. 머신러닝 개요 (2) | 2023.05.26 |
댓글