본문 바로가기
Python/Machine Learning

[ML]_데이터 전처리 >> 데이터 인코딩(Label & One-Hot)

by ssolLEE 2023. 8. 28.
반응형

  • 이 공부는 다음 멋진 책과 함께 합니다. 위키북스와 저자님 너무나도 감사합니다. 

데이터에 대해서 공부하면서 느낀 점이 있습니다. 

데이터만 "멀쩡"하면, 우선 시작은 할 수 있겠다!!!!

하지만 생각보다 "멀쩡"한 데이터는 많이 없습니다. 

일부 데이터값이 없는 경우도 꽤 있었습니다. 

이럴 땐 어떻게 해야 할까요? 무작정 없앨까요? 아니면 적당히 모른척 값을 채워넣어볼까요?(ㅎㅎ)

이미 탐색적 데이터 분석(EDA)을 하며 이러한 데이터값을 처리하는 것을 경험하셨을 것입니다. 

 

우리는 머신러닝을 하는 만큼, 머신러닝에서 주의해야할 것을 알아야겠죠? 

 

사이킷런의 머신러닝 알고리즘은 문자열 값을 입력값으로 허용하지 않기 때문에, 모든 문자열 값은 인코딩되어서 숫자 형으로 변환해야 합니다. 우리는 이번 포스팅에서 인코딩 방식을 알아보고자 합니다. 

 

레이블 인코딩 - 범주형 변수의 문자형을 수치형으로 변환

  • LabelEncoder 클래스로 레이블 인코딩을 구현합니다. 
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, 믹서는 2, 선풍기는 3, 전자레인지는 4, 컴퓨터는 5로 문자형이 수치형으로 변환되었습니다. 
  • 문자열이 많아질 경우에는 다음의 코드를 입력하여 문자열 값을 확인할 수 있고, 0부터 순서대로 나열되어 있습니다.
print("인코딩 클래스 : ", encoder.classes_)

>> 인코딩 클래스 :  ['TV' '냉장고' '믹서' '선풍기' '전자레인지' '컴퓨터']
  • 디코딩도 가능합니다.
print('디코딩 원본값: ', encoder.inverse_transform([4, 5, 3, 1, 0, 0, 2]))

>>> 디코딩 원본값:  ['전자레인지' '컴퓨터' '선풍기' '냉장고' 'TV' 'TV' '믹서']
  • 하지만 레이블 인코딩으로 인해서 머신러닝 알고리즘의 예측 성능이 떨어지는 경우도 있습니다. 
    • 반환되는 숫자 값의 크고 작음의 특성이 작용하여, 큰 숫자에 가중치가 더 부여되거나 더 중요하게 인식할 가능성이 있습니다.
  • 따라서 레이블 인코딩은 선형회귀와 같은 머신러닝 알고리즘에는 적용하지 않습니다. 
  • 트리 계열의 머신러닝 알고리즘은 숫자의 이러한 특성을 반영하지 않아 레이블 인코딩을 사용해도 됩니다. 
  • 이러한 레이블 인코딩의 문제점을 해결한 것인 원-핫 인코딩입니다. 

 

원-핫 인코딩  - 표현하고 싶은 인덱스 = 1, 그 외 = 0

  • OneHotEncoder 클래스로 원-핫 인코딩을 구현합니다.
  • LabelEncoder와 다른 점은 
    • 입력값으로 2차원 데이터가 필요
    • 변환한 값이 희소 행렬 형태이므로 이를 다시 toarray()를 이용하여 밀집 행렬로 변환
from sklearn.preprocessing import OneHotEncoder
import numpy as np

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

# 2차원 ndarray로 변환
items = np.array(items).reshape(-1, 1)

# 원-핫 인코딩 적용
oh_encoder = OneHotEncoder()
oh_encoder.fit(items)
oh_labels = oh_encoder.transform(items)

# OneHotEncoder로 변환한 결과를 toarray()로 밀집 행렬로 변환
print("원-핫 인코딩 데이터")
print(oh_labels.toarray())
print('원-핫 인코딩 데이터 차원')
print(oh_labels.shape)

  • 딱 자기 위치에만 1이 써져 있는 것 보이시나요? 
  • 8개의 레코드와 1개의 칼럼을 가진 원본 데이터가 결과적으로 8개의 레코드와 6개의 칼럼을 가진 데이터로 변환되었습니다. 
  • 판다스에서는 원-핫 인코딩을 더 쉽게 지원하는 API가 있습니다. **get_dummies()**
import pandas as pd
df = pd.DataFrame({'items' : ['TV', '냉장고', '전자레인지', '컴퓨터', '선풍기', '선풍기', '믹서', '믹서']})
pd.get_dummies(df)

그 외의 인코딩

  • 카운트 인코딩 : 각 범주의 갯수를 집계한 후 그 값을 인코딩
  • 대상 인코딩
    • 범주형 자료의 값들을 훈련 데이터에서 목표에 해당하는 값으로 바꿔주는 방식
    • 원-핫 인코딩의 변수값이 많아지는 문제를 해결