데이터 전처리
데이터 전처리 Data Preprocessing
-
어떤 데이터를 입력으로 가지느냐에 따라 결과가 크게 달라짐 (Garbage In, Garbage Out)
사이킷런 ML 알고리즘을 적용하기 전 처리할 기본 사항
-
결손값, NaN, Null 허용 안됨
-
문자열값 허용 안됨
결손값, NaN, Null 처리
-
결손값등이 얼마 되지 않는 다면 피처의 평균값 등으로 간단히 처리
-
결손값등이 대분이라면 해당 피처 Drop
-
결손값등이 일정 수준 이상되는 경우 일정 수준의 기준이 없어 선택이 어려움
-
중요도가 높은 피처이고 단순히 평균값등로 대체할 경우 예측 왜곡이 심할 수 있다면 상세히 검토해 더 정밀한 대체 값을 선정 해야 함
문자열값 처리
-
모든 문자열은 인코딩돼서 숫자로 변환
-
문자열 피처는 카테고리형 피처와 텍스트 피처를 의미
-
카테고리형 피처는 코드 값으로 표현
-
텍스트형 피처는 피처 벡터화(feature vectorization)등의 기법으로 벡터화
-
불필요한 피터 예를 들어 ID나 주민번호 같은 행 실별 피처 같은 경우 삭제 처리
데이터 인코딩
-
레이블 인코딩(Label encoding)
-
원-핫 이코딩(One Hot encoding)
레이블 인코딩
-
카테고리 피처를 코드형 숫자 값으로 변환 하는 것
-
상품데이터의 상품구분이 휴대폰, TV, 컴퓨터 값이면 휴대폰:1, TV:2, 컴퓨터:3
-
사이킷런의 LabelEncoder 클래스로 구현
import numpy as np
from sklearn.preprocessing import LabelEncoder
items = ['휴대폰', 'TV', '컴퓨터']
encoder = LabelEncoder()
encoder.fit(items)
labels = encoder.transform(items)
print(labels)
[2 0 1]
# classes_ 0번부터 순서대로 변환된 인코딩 원본값
print('encoding class', encoder.classes_)
encoding class ['TV' '컴퓨터' '휴대폰']
print('decoding values', encoder.inverse_transform([0, 1, 2]))
decoding values ['TV' '컴퓨터' '휴대폰']
레이블 인코딩 주의 사항
-
몇몇 ML 알고리즘에는 숫자 값의 크고 작음에 대한 특성이 작용 해 예층 성능이 떨어짐
-
회귀와 같은 ML 알고리즘에서는 휴대폰:1, TV:2, 컴퓨터:3 숫자 값에 따른 순서나 중요도로 인식 됨
-
트리 계열의 ML 알고리즘은 숫자의 이러한 특성을 반영하지 않음
-
이러한 문제점을 해결하기 위한 인코딩 방식이 원-핫 인코딩
원-핫 인코딩(One-Hot Encoding)
-
피처 값의 유형에 따라 새로운 피처를 추가해 고유 값에 해당하는 칼럼에만 1을 표시
-
원본데이터 => 원-핫 인코딩으로 변환
-
단점 : 무수한 0의 난발
사이킷런의 LabelEncoder 클래스로 구현
from sklearn.preprocessing import OneHotEncoder
items
['휴대폰', 'TV', '컴퓨터']
# 숫자로 변환
encoder = LabelEncoder()
encoder.fit(items)
labels = encoder.transform(items)
print(labels)
[2 0 1]
# 2차원 데이터로 변환
# reshape(-1,n), reshape(n,-1)의 의미 https://rfriend.tistory.com/345
labels = labels.reshape(-1, 1) # shape(3, 1)
labels
array([[2],
[0],
[1]], dtype=int64)
# 원-핫 인코딩 적용
oh_encoder = OneHotEncoder()
oh_encoder.fit(labels)
oh_labels = oh_encoder.transform(labels)
oh_labels.toarray()
array([[0., 0., 1.],
[1., 0., 0.],
[0., 1., 0.]])
# 판다스로 원-핫 인코딩 적용
import pandas as pd
df = pd.DataFrame(items)
pd.get_dummies(df)
0_TV | 0_컴퓨터 | 0_휴대폰 | |
---|---|---|---|
0 | 0 | 0 | 1 |
1 | 1 | 0 | 0 |
2 | 0 | 1 | 0 |
피처 스케일링(feature scaling) 과 정규화
-
피처 스케일링 : 서로 다른 변수의 값 범위를 일정한 수준으로 맞추는 작업
-
대표적 방법 : 표준화(Standardization)와 정규화(Normalization)
-
사이킷런의 StandardScaler, MinMaxCaler 모듈
표준화
-
피처 각각이 평균이 0이고 분산이 1인 가우시안 정규 본포를 가진 값으로 변환
정규화
-
서로 다른 피처의 크기를 통일하기 위해 크기를 변환해 주는 개념
-
피처 A(거리) : 0~ 100KM, 피처 B(금액) : 0 ~ 100,000,000 => 최소 0 ~ 최대 1 값으로 변환
백터 정규화(선형대수 개념의 정규화)
-
사이킷런의 Nomalizer 모듈
-
세개의 피처 x, y, z가 있다면 x_new/(|x,y,z|)
StandardScaler
-
표준화 지원 클래스
-
사이킷런의 서포트 백터 머신(SVM), 선형회귀(Linear Regression), 로지스틱 회귀(Logistic Regression)는 가우시안 분포라고 가정하고 구현된 알고리즘
from sklearn.datasets import load_iris
import pandas as pd
# 붗꽃 데이터 세트 로딩
iris = load_iris()
# iris
iris_data = iris.data
#iris_data
iris.feature_names
['sepal length (cm)',
'sepal width (cm)',
'petal length (cm)',
'petal width (cm)']
iris_df = pd.DataFrame(data=iris_data, columns=iris.feature_names)
iris_df.head()
sepal length (cm) | sepal width (cm) | petal length (cm) | petal width (cm) | |
---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 |
1 | 4.9 | 3.0 | 1.4 | 0.2 |
2 | 4.7 | 3.2 | 1.3 | 0.2 |
3 | 4.6 | 3.1 | 1.5 | 0.2 |
4 | 5.0 | 3.6 | 1.4 | 0.2 |
# StandardScaler 표준화
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(iris_df)
iris_scaled = scaler.transform(iris_df) # numpy.ndarray로 저장됨
# Numpy => DataFrame
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
iris_df_scaled.head()
sepal length (cm) | sepal width (cm) | petal length (cm) | petal width (cm) | |
---|---|---|---|---|
0 | -0.900681 | 1.019004 | -1.340227 | -1.315444 |
1 | -1.143017 | -0.131979 | -1.340227 | -1.315444 |
2 | -1.385353 | 0.328414 | -1.397064 | -1.315444 |
3 | -1.506521 | 0.098217 | -1.283389 | -1.315444 |
4 | -1.021849 | 1.249201 | -1.340227 | -1.315444 |
iris_df_scaled.mean()
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
iris_df_scaled.var()
sepal length (cm) 1.006711
sepal width (cm) 1.006711
petal length (cm) 1.006711
petal width (cm) 1.006711
dtype: float64
MimMaxScaler
-
0 ~ 1 사이의 값으로 변환
-
음수 값이 있으면 -1 ~ 1 사이의 값으로 변환
# MinMaxScaler 정규화
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaler.fit(iris_df)
iris_scaled = scaler.transform(iris_df)
# numpy => DataFrame
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
iris_df_scaled.head()
sepal length (cm) | sepal width (cm) | petal length (cm) | petal width (cm) | |
---|---|---|---|---|
0 | 0.222222 | 0.625000 | 0.067797 | 0.041667 |
1 | 0.166667 | 0.416667 | 0.067797 | 0.041667 |
2 | 0.111111 | 0.500000 | 0.050847 | 0.041667 |
3 | 0.083333 | 0.458333 | 0.084746 | 0.041667 |
4 | 0.194444 | 0.666667 | 0.067797 | 0.041667 |
iris_df_scaled.min(), iris_df_scaled.max()
(sepal length (cm) 0.0
sepal width (cm) 0.0
petal length (cm) 0.0
petal width (cm) 0.0
dtype: float64,
sepal length (cm) 1.0
sepal width (cm) 1.0
petal length (cm) 1.0
petal width (cm) 1.0
dtype: float64)