본문 바로가기

AI Study/Machine Learning

데이터 전처리 기본 (1) - data encoding

 

데이터 전처리(Data Preprocessing)

  • ML AL이 data에 기반하므로, 데이터를 어떻게 처리하느냐에 따라 결과가 달라질 수 있음.
  • sklearn의 ML AL을 적용하기 전 반드시 해야할 전처리
    • 결손값 처리. NaN, Null값은 허용되지 않는다.
      • feature값 중 Null 값이 얼마 되지 않음 -> 평균값 등으로 대체
      • feature값 중 Null 값이 대부분 -> 해당 feature를 drop하는 것이 좋음
    • 문자열
      • sklearn의 ML AL은 문자열값을 입력값으로 허용하지 않음
      • 모든 문자열 값은 인코딩하여 숫자형으로 변환해야 함
      • 문자열 피처 : 카테고리형 피처 / 텍스트형 피처(피처 벡터화로 벡터화 수행하거나 불필요한 경우 삭제)
        • ex) 주민번호, 단순 문자열 : 인코딩 하지 않고 삭제하는 것이 Good. 식별자 feature는 단순한 data row를 식별하는 용이고, 예측에는 중요하지 않기 때문.
 

데이터 인코딩

  • 대표적인 인코딩 방식 : Label encoding / One Hot encoding
  • 레이블 인코딩(Label encoding) : category feature를 코드형 숫자값으로 변환하는 것
    • 숫자의 크고 작음이 있기에 Tree 계열 AL을 제외하면 가중치가 적용되어 문제가 될 수 있음
    • Label Encoding의 문제점을 해결한 것이 One Hot Encoding임
 

Label encoding

  • 간단하게 문자열 값을 숫자형 카테고리값으로 변환함
  • 숫자값의 크고 작음이 있기에, 레이블 인코딩을 할 경우 몇몇 ML AL에서는 예측 성능이 떨어질 수 있음.
    • 믹서가 2, 냉장고가 1로 인코딩되면 2>1 이므로 가중치가 믹서에 부여될 수 있음.
    • 냉장고와 믹서의 숫자 변환 값은 단순 코드지 숫자 값에 따른 순서나 중요도로 인식되어서는 안됨.
      -> 이를 해결하려고 나온 것이 One Hot Encoding
    • Tree 계열의 ML AL은 숫자의 이러한 특성을 반영하지 않으므로 Label Encoding OK
  • sklearn의 label encoding은 LabelEncoder Class로 구현함.
  • Label Encoder를 객체로 생성한 후 -> fit(), transform()을 호출해 레이블 인코딩을 수행
 

여기서 fit / transform을 사용하는데 목적은?

  • fit()은 데이터 변환을 위한 기준 정보 설정(예를 들면 data set의 max/min 값 설정 등)을 적용해줌.
  • transform()은 설정된 정보를 이용해 데이터를 변환함.
 
In [25]:
from sklearn.preprocessing import LabelEncoder

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

# LabelEncoder를 객체로 생성한 후 , fit( ) 과 transform( ) 으로 label 인코딩 수행. 
encoder = LabelEncoder()
encoder.fit(items) 
labels = encoder.transform(items)
print('인코딩 변환값:',labels)
 
인코딩 변환값: [0 1 4 5 3 3 2 2]
 
In [26]:
# .classes_ 속성은 0번부터 순서대로 변환된 인코딩 값에 대한 원본값을 가지고 있음 
# 따라서 이를 통해 TV가 0, 냉장고 1, 믹서 2, 선풍기 3, 전자레인지 4, 컴퓨터가 5로 인코딩되었음을 알 수 있음. 
print('인코딩 클래스:',encoder.classes_)
 
인코딩 클래스: ['TV' '냉장고' '믹서' '선풍기' '전자렌지' '컴퓨터']
 
In [27]:
# inverse_transform()을 통해 인코딩된 값을 다시 디코딩할 수 있음 
print('디코딩 원본 값:',encoder.inverse_transform([4, 5, 2, 0, 1, 1, 3, 3]))
 
디코딩 원본 값: ['전자렌지' '컴퓨터' '믹서' 'TV' '냉장고' '냉장고' '선풍기' '선풍기']
 
In [28]:
# 이렇게 거꾸로 인코딩 결과를 통해 원본 추척도 가능.
print('디코딩 원본 값:',encoder.inverse_transform([0,1,2,3,4,5]))
 
디코딩 원본 값: ['TV' '냉장고' '믹서' '선풍기' '전자렌지' '컴퓨터']

 

 

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

  • feature 값의 유형에 따라 새로운 feature를 추가해 고유 값에 해당하는 column에만 1을 표시, 나머지 column에는 0을 표시하는 방식
  • 즉, 행 형태로 되어있는 feature의 고유 값을 열 형태로 차원을 변환함 -> 고유값에 해당하는 column에만 1, 나머지 column에는 0을 표시
  • One-Hot Encoding은 sklearn에서 OneHotEncoder Class로 쉽게 변환 가능
  • 주의할 점
    1. OneHotEncoder로 변환하기 전에 모든 문자열 값이 숫자형 값으로 변환되어야 함 (LabelEncoder가 선행되는 것임)
    2. 입력 값으로 2차원 데이터가 필요함
 
In [29]:
from sklearn.preprocessing import OneHotEncoder
import numpy as np

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

# 먼저 숫자값으로 변환을 위해 LabelEncoder로 변환합니다. 
encoder = LabelEncoder()
encoder.fit(items)
labels = encoder.transform(items)

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

# 원-핫 인코딩을 적용합니다. 
oh_encoder = OneHotEncoder()
oh_encoder.fit(labels)
oh_labels = oh_encoder.transform(labels)
print('원-핫 인코딩 데이터')
print(oh_labels.toarray())
print()
print('원-핫 인코딩 데이터 차원')
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. 0. 1. 0. 0.]
 [0. 0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0.]]

원-핫 인코딩 데이터 차원
(8, 6)
 

get_dummies = 손쉬운 버전의 One-Hot Encoding

  • 위에 어려운 거 말고 이거 알아두면 편리함.
  • pandas의 get_dummies : One-Hot Encoding을 더 쉽게 제공함
  • LabelEncoding 과정 거칠 필요 없이 (문자열 카테고리 값을 숫자 형으로 변환할 필요 없이) 바로 사용 가능
 
In [30]:
import pandas as pd

df = pd.DataFrame({'item':['TV','냉장고','전자렌지','컴퓨터','선풍기','선풍기','믹서','믹서'] })
pd.get_dummies(df)
 
Out[30]:
  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 0 1 0 0
6 0 0 1 0 0 0
7 0 0 1 0 0 0