데이터 전처리
ML 알고리즘은 데이터에 기반하고 있기 때문에 어떤 데이터를 입력하느냐에 따라 결과는 천차만별이다.
그래서 ML 알고리즘을 적용하기 전에 데이터에 대해 미리 처리해야 할 기본 사항이 있다.
예를 들어 결측치의 경우 고정된 다른 값으로 변환해야 한다. 만약 결측치가 대부분을 이루는 변수라면 사용하지 않는 것이 바람직하다.
NULL값이 애매하게 존재하는 경우가 가끔 존재 하는데, 해당 변수의 변수 중요도가 높고 결측치를 평균이나 중간값으로 대체 하였을 때, 결과 왜곡될 가능성이 높다면 다른 대체 데이터를 선정해야 한다.
그리고 머신러닝 알고리즘은 문자열 값을 그대로 입력값으로 받을 수 없다. 그래서 모든 문자열은 인코딩 시켜 주어야 한다. 문자열 변수는 보통 카테고리형 변수와 텍스트형 변수로 나뉜다. 특히 텍스트형 변수는 벡터화 시켜야 한다.
데이터 인코딩
머신러닝을 위한 대표적인 인코딩 방식은 레이블 인코딩
과 원-핫 인코딩
이 있다.
레이블 인코딩
카테고리 피처를 숫자 값으로 변환 하는 것
예를 들어 상품 데이터의 상품 구분이 TV, 냉장고, 전자레인지, 컴퓨터, 선풍기, 믹서기 라면,
TV : 1, 냉장고: 2, 전자레인지:3 , 컴퓨터 : 4 , 전자레인지 : 5 , 믹서기 : 6 과 같은 숫자형 값으로 변환하는 것을 말한다.
from sklearn.preprocessing import LabelEncoder
items=['TV','냉장고','전자렌지','컴퓨터','선풍기','선풍기','믹서','믹서']
# LabelEncoder를 객체로 생성한 후, fit()과 transform()으로 레이블 인코딩 수행.
encoder = LabelEncoder()
encoder.fit(items)
labels = encoder.transform(items)
print('인코딩 변환값:', labels)
인코딩 변환값: [0 1 4 5 3 3 2 2]
출력 값을 살펴보면 TV는 0, 냉장고는 1, 전자레인지는 4, 컴퓨터는 5, 선풍기는 3, 믹서기는 2로 변환 된 것을 알 수 있다.
레이블 인코딩은 간단하게 문자열 값을 숫자형 카테고리 값으로 변환한다. 하지만 레이블 인코딩이 일괄적인 숫자값으로 변환이 되면서 몇몇 ML 알고리즘에는 이를 적용할 경우 예측 성능이 떨어지는 경우가 발생 할 수 있다.
냉장고가 1, 믹서기가 2로 변환되면, 1보다 2가 더 큰 값이므로 특정 ML알고리즘에서 가중치가 더 부여 되거나 더 중요하게 인식할 수있다.
이러한 특성 때문에 레이블 인코딩은 선형 회귀와 같은 ML 알고리즘에는 적용하면 안된다.
트리 계열의 ML 알고리즘은 숫자의 이러한 특성을 반영하지 않으므로 별 문제 없다.
원-핫 인코딩
원-핫 인코딩은 레이블 인코딩의 숫자 값 변환의 문제점을 해결하기 위한 인코딩 방식이다.
원-핫 인코딩은 피처 값의 유형에 따라 새로운 피처를 추가해 고유 값에 해당하는 칼럼에만 1을 표시하고 나머지 칼럼에는 0을 표시하는 방식이다. 아래 표를 참고하자
TV가 0, 냉장고 1, 믹서 2, 선풍기 3, 전자레인지 4, 컴퓨터가 5로 인코딩돼 있음을 알 수 있다.
Pandas의 get_dummies()
를 이용하면 사이킷런의 OneHotEncoder()와 다르게 문자열 카테고리 값을 숫자 형으로 변환할 필요 없이 바로 변환할 수 있다.
import pandas as pd
df = pd.DataFrame({'item':['TV','냉장고','전자렌지','컴퓨터','선풍기','선풍기','믹서','믹서'] })
pd.get_dummies(df)
피처 스케일링
서로 다른 변수의 값 범위를 일정한 수준으로 맞추는 작업을 피처 스케일링이라고 한다. 대표적인 방법으로 표준화
와 정규화
가 있다.
표준화(Standardization)
- 값의 범위를 평균 0, 분산 1이 되도록 반환
- 머신러닝 모델에서 scale이 큰 feature의 영향이 커지는 것을 방지
- 딥러닝에서 Local Minima에 빠질 위험 감소(학습 속도 향상)
- 정규분포를 표준정규분포로 변환하는 것과 같음.
$\frac {x-\mu} {\sigma} \space \space \space (\mu:평균, \sigma: 표준편차)$
정규화(Normalization)
- 값의 범위(scale)를 0~1 사이의 값으로 바꾸는 것
- 머신러닝에서 scale이 큰 feature의 영향이 비대해지는 것을 방지
- 딥러닝에서 Local Minima에 빠질 위험 감소(학습 속도 향상)
${x-x_{min} \over x_{max}-x_{min}}$
사이킷런에서 서포트 벡터 머신이나 선형 회귀, 로지스틱 회귀는 데이터가 가우시안 분포를 가지고 있다고 가정하고 구현됐기 때문에 사전에 표준화를 하는 것은 예측 성능 향상에 중요한 요소가 될 수 있다.
코드를 통해 살펴보자
StandardScaler
from sklearn.datasets import load_iris
import pandas as pd
# 붓꽃 데이터 셋을 로딩하고 DataFrame으로 변환합니다.
iris =load_iris()
iris_data = iris.data
iris_df = pd.DataFrame(data=iris_data, columns=iris.feature_names)
print('feature 들의 평균 값')
print(iris_df.mean())
print('\nfeature 들의 분산 값.')
print(iris_df.var())
feature 들의 평균 값
sepal length (cm) 5.843333
sepal width (cm) 3.057333
petal length (cm) 3.758000
petal width (cm) 1.199333
dtype: float64
feature 들의 분산 값.
sepal length (cm) 0.685694
sepal width (cm) 0.189979
petal length (cm) 3.116278
petal width (cm) 0.581006
dtype: float64
from sklearn.preprocessing import StandardScaler
#StandardScaler객체 생성
scaler = StandardScaler()
#StandardScaler로 데이터 셋 변환. fit()과 transform() 호출.
scaler.fit(iris_df)
iris_scaled=scaler.transform(iris_df)
#transform()시 스케일 변환된 데이터 셋이 Numpy ndarray로 반환돼 이를 DataFrame으로 변환
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
print('feature 들의 평균 값')
print(iris_df_scaled.mean())
print('\nfeature 들의 분산 값.')
print(iris_df_scaled.var())
feature 들의 평균 값
sepal length (cm) -1.690315e-15
sepal width (cm) -1.842970e-15
petal length (cm) -1.698641e-15
petal width (cm) -1.409243e-15
dtype: float64
feature 들의 분산 값.
sepal length (cm) 1.006711
sepal width (cm) 1.006711
petal length (cm) 1.006711
petal width (cm) 1.006711
dtype: float64
모든 칼럼 값의 평균이 0에 아주 가까운 값으로, 그리고 분산은 1에 아주 가까운 값으로 변환됐음을 알 수 있다.
MinMaxScaler
MinMaxScaler는 데이터값을 0과 1사이의 범위 값으로 변환합니다. (음수 값이 나오면 –1에서 1값으로 변환합니다.)
데이터의 분포가 가우시안 분포가 아닐 경우에 Min, Max Scaler을 적용해 볼 수 있습니다. 다음 코드를 통해 MinMaxScaler를 알아보자.
from sklearn.preprocessing import MinMaxScaler
#MinMaxScaler객체 생성
scaler = MinMaxScaler()
#MinMaxScaler로 데이터 셋 변환. fit()과 transform() 호출.
scaler.fit(iris_df)
iris_scaled = scaler.transform(iris_df)
#transform() 시 스케일 변환된 데이터 셋이 NumPy ndarray로 반환돼 이를 DataFrame로 변환
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns = iris.feature_names)
print('feature 들의 최솟값')
print(iris_df_scaled.min())
print('\nfeature 들의 최댓값.')
print(iris_df_scaled.max())
feature 들의 최솟값
sepal length (cm) 0.0
sepal width (cm) 0.0
petal length (cm) 0.0
petal width (cm) 0.0
dtype: float64
feature 들의 최댓값.
sepal length (cm) 1.0
sepal width (cm) 1.0
petal length (cm) 1.0
petal width (cm) 1.0
dtype: float64
모든 피처에 0에서 1사이의 값으로 변환되는 스케일링이 적용됐음을 알 수 있다.
'머신러닝' 카테고리의 다른 글
numpy, pandas 기초 (0) | 2020.08.20 |
---|---|
타이타닉 생존자 예측 -사이킷런 (0) | 2020.08.19 |
사이킷런의 Model Selection 모듈 (0) | 2020.08.19 |
사이킷런 기반의 프레임 워크 (0) | 2020.08.19 |
사이킷런을 이용한 머신러닝 (0) | 2020.08.19 |