본문 바로가기

ML with SckitLearn

데이터 전처리하기 : 레이블 인코딩 (Label Encoding), 원-핫 인코딩(One-Hot Encoding), get_dummies()를 Pandas에서 사용하기

반응형

데이터 전처리(Data Processing)는 ML알고리즘만큼 중요합니다. ML 알고리즘을 데이터에 기반하고 있기 때문에 어떤 데이터를 입력으로 가지느냐에 따라 결과도 크게 달라질 수 있습니다. (Garbage In, Garbage Out)

 

기본적으로 결손값, 즉 NaN, Null 값은 허용되지 않습니다. 따라서 이러한 Null 값은 고정된 다른 값으로 변환해야 합니다. Null 값을 어떻게 처리해야 할지는 경우에 따라 다릅니다. 피처 값 중 Null 값이 얼마 되지 않는다면 피처의 평균값 등으로 간단히 대체할 수 있습니다. 하지만 Null 값이 대부분이라면 오히려 해당 피처는 Drop 하는 것이 좋습니다.

 

가장 결정이 힘든 부분이 Null값이 일정 수준 이상 되는 경우입니다. 정확히 몇 퍼센트까지를 일정 수준 이상이라고 한다는 기준은 없습니다. 하지만 해당 피처가 중요도가 높은 피처이고 Null을 단순히 평균값으로 대체할 경우 예측 왜곡이 심할 수 있다면 업무 로직 등을 상세히 검토해 더 정밀한 대체 값을 선정해야 합니다.

 

사이킷런의 알고리즘은 문자열 값을 입력 값으로 허용하지 않습니다. 그래서 모든 문자열 값은 인코딩 돼서 숫자 형으로 변환해야 합니다. 문자열 피처는 일반적으로 카테고리형 피처와 텍스트형 피처를 의미합니다. 카테고리형 피처는 코드 값으로 표현하는 게 더 이해하기 쉬울 것 같습니다. 텍스트형 피처는 피처 벡터화등의 기법으로 벡터화하거나 불필요한 피처라고 판단되면 삭제하는 게 좋습니다.

 

예를 들어 주민번호나 단순 문자열 아이디와 같은 경우 인코딩하지 않고 삭제하는 게 더 좋습니다. 이러한 식별자 피처는 단순히 데이터 로우를 식별하는 용도로 사용되기 때문에 예측에 중요한 요소가 될 수 없으며 알고리즘을 오히려 복잡하게 만들고 예측 성능을 떨어뜨리기 때문입니다.

 

신러닝을 위한 대표적인 인코딩 방식은 레이블 인코딩(Label Encoding)과 원-핫 인코딩이 있습니다.

 

 

 

 


레이블 인코딩 (Label Encoding)

레이블 인코딩은 카테고리 피처를 코드형 숫자 값으로 변환하는 것입니다.

from sklearn.preprocessing import LabelEncoder

items=['TV', '냉장고', '전자레인지', '컴퓨터', '선풍기', '믹서', '믹서']
encoder = LabelEncoder()
encoder.fit(items)
labels = encoder.transform(items)
print(labels)

#[0 1 4 5 3 2 2]

 

위 경우는 데이터가 작아서 문자열 값이 어떤 값으로 인코딩됐는지 직관적으로 알 수 있지만, 많은 경우에 이를 알지 못할 수가 있으므로, classes_속성 값을 사용하면 됩니다.

print(encoder.classes_)

#['TV' '냉장고' '믹서' '선풍기' '전자레인지' '컴퓨터']

위의 값을 보면 TV가 0, 냉장고가 1..... 컴퓨터가 5입니다.

 

print(encoder.inverse_transform([4,5,2,0,1,3]))

#['전자레인지' '컴퓨터' '믹서' 'TV' '냉장고' '선풍기']

inverse_transform으로 각 주소에 맞는 문자열을 알 수 있습니다.

 

레이블 인코딩은 간단하게 문자열 값을 숫자형 카테고리 값으로 변환합니다. 하지만 레이블 인코딩이 일괄적으로 숫자 값으로 변환이 되면서 몇몇 ML알고리즘에는 이를 적용할 경우 예측 성능이 떨어지는 경우가 발생할 수 있습니다.  숫자로 되어 있어 잘못하면 가중치로 인식하여 값에 왜곡이 생기게 됩니다.

 

이러한 특성 때문에 레이블 인코딩은 선형 회귀와 같은 ML알고리즘에는 적용하지 않습니다. 트리 계열의 ML 알고리즘은 숫자의 이러한 특성을 반영하지 않으므로 레이블 인코딩도 별문제가 없습니다.

 


원-핫 인코딩(One-Hot Encoding)

피처 값의 유형에 따라 새로운 피처를 추가해 고유 값에 해당하는 칼럼에만 1을 표시하고 나머지 칼럼에는 0을 표시하는 방식입니다. 즉, 행 형태로 돼 있는 피처의 고유 값을 열 형태로 차원을 변환한 뒤, 고유 값에 해당하는 칼럼에만 1을 표시하고 나머지 칼럼에는 0을 표시합니다.

 

 

원-핫 인코딩은 사이킷런ㅇ서 OneHotEncoder클래스로 쉽게 변환이 가능합니다. 주의할 점으로 변환하기 전 모든 문자열 값이 숫자형 값으로 변환돼야 하며, 입력 값으로 2차원 데이터가 필요하다는 점입니다.

 

from sklearn.preprocessing import OneHotEncoder
import numpy as np

items = ['TV', '냉장고', '전자레인지', '컴퓨터', '선풍기', '믹서', '믹서']

#Step1: 모든 문자를 숫자형으로 변환합니다.
encoder = LabelEncoder()
encoder.fit(items)
labels = encoder.transform(items)

#Step2: 2차원 데이터로 변환합니다.
labels = labels.reshape(-1, 1)

#Step3: One-Hot Encoding 적용합니다.
oh_encoder = OneHotEncoder()
oh_encoder.fit(labels)
oh_labels = oh_encoder.transform(labels)
print(oh_labels.toarray())
print(oh_labels.shape)

결과

[[1. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 0.]
 [0. 0. 0. 0. 0. 1.]
 [0. 0. 0. 1. 0. 0.]
 [0. 0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0.]]
(7, 6)

 


PANDAS에서의 원-핫 인코딩(One-Hot Encoding)

get_dummies()를 사용하면 간단하게 원-핫 인코딩을 더 쉽게 진행할 수 있습니다.

import pandas as pd

items = ['TV', '냉장고', '전자레인지', '컴퓨터', '선풍기', '믹서', '믹서']
df = pd.DataFrame({'item':items})
print(pd.get_dummies(df))

 

   item_TV  item_냉장고  item_믹서  item_선풍기  item_전자레인지  item_컴퓨터
0        1         0        0         0           0         0
1        0         1        0         0           0         0
2        0         0        0         0           1         0
3        0         0        0         0           0         1
4        0         0        0         1           0         0
5        0         0        1         0           0         0
6        0         0        1         0           0         0

 

반응형