Day to_day

[데이터 전처리] 데이터 인코딩의 종류와 활용 방법~! 본문

Machine Learning/머신러닝 기초

[데이터 전처리] 데이터 인코딩의 종류와 활용 방법~!

m_inglet 2023. 3. 31. 17:17
728x90
반응형

❗본 포스팅은 권철민 선생님의 '파이썬 머신러닝 완벽가이드' 강의와 '파이썬 라이브러리를 활용한 머신러닝' 서적을 기반으로 개인적인 정리 목적 하에 재구성하여 작성된 글입니다.

 

 

포스팅 개요

저번 포스팅에 이어서 데이터 인코딩에 대해서 적어보고 데이터 인코딩의 종류인 라벨 인코딩과 원-핫 인코딩에 대해서 자세히 알아보려고 한다.

 

 

데이터 인코딩의 목적

sci-kit learn의 ML은 문자열 값을 입력값으로 허용하지 않는다.

그렇기 때문에 모든 문자열 값은 인코딩을 해서 숫자형으로 변환해야 한다.

 

 

데이터의 표현 - 범주형 특성

범주형 데이터라는 것은 카테고리처럼 연속된 값이 아니고 값에 대소가 있지 않고, 중간값이 있는 게 아닌 데이터이다.

예를 들어 책, 옷, 하드웨어 이런 것은 책과 옷 사이에는 중간 값이 없고, 이 카테고리들 사이에는 순서가 없다. 책이 옷보다 크거나 작지 않고, 하드웨어는 책과 옷 사이에 있지 않다.

 

 

데이터 인코딩 - 레이블 인코딩

범주형 데이터를 숫자형으로 변환해 주기 위해서는 두 가지 방법이 있다.

'레이블 인코딩'과 '원-핫 인코딩'이다. 두 가지의 차이점과 코딩 구현 예제를 알아보겠다.

우선 레이블 인코딩은 어떤 카테코리자체를 숫자로 바로 변환하는 것이다. 

아래의 예시를 보면 상품 카테고리별로 숫자로 분류한 것을 볼 수 있다.

  • 상품 : Tv, 냉장고, 전자레인지, 컴퓨터…
  • 상품 분류: 0, 1, 2, 3,…
  • 유의할 점은 숫자 값의 크기가 모델에 영향을 미칠 수 있다.
# label encoding
# 범주형 데이터를 특정 숫자로 바꾸는 경우. 대신 숫자의 크기 때문에 모델에서 weight 값을 다르게 줄 수 있음 주의
from sklearn.preprocessing import LabelEncoder

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

encoder = LabelEncoder()
encoder.fit(items)
labels = encoder.transform(items)
print("transformed encoder: ", labels)
transformed encoder:  [0 1 4 5 3 3 2 2]

 

숫자로 변환한 범주형 데이터를 다시 원본 데이터 형태로 보고 싶을 땐 'classes_'를 통해 접근하면 된다.

원본 값에 접근하기 : classes_

print('encoding class: ', encoder.classes_)

[출력 결과]

encoding class:  ['TV' '냉장고' '믹서' '선풍기' '전자렌지' '컴퓨터']

 

 

데이터 인코딩 - 원 핫 인코딩

레이블 인코딩의 경우 주의해야 할 점이 숫자의 크기에 따라서 모델이 weight 값을 다르게 주어 판단할 수가 있었다.

그래서 '원-핫 인코딩' 변환법의 경우 하나만 1, 나머지는 0으로 바꿔준다. 좀 더 쉬운 설명을 위해 그림으로 그렸다.

 

코드로 구현하면 아래와 같다.

from sklearn.preprocessing import OneHotEncoder
import numpy as np

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

# 2차원 데이터로 변환해야함
items = np.array(items).reshape(-1, 1)

# One Hot Encoding 적용
ohe = OneHotEncoder()
ohe.fit(items)
oh_label = ohe.transform(items)

print(oh_label.toarray())
# 8개의 item을 원핫 인코딩을 통해 우위없이 범주형 데이터를 인코딩

[출력 결과]

인코딩한 결과를 array로 보면 아래와 같이 나온다. 각 카테고리를 1의 순서를 변경하면서 표현한 것이다.

[[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.]]

 

 

get_dummies로 쉽게 구현하기

pandas에 내장되어 있는 get_dummies를 이용하면 더욱 쉽게 구현이 가능하다.

# 더 쉽게 구현하기 get_dummies(items)
import pandas as pd

# DataFrame을 만들어 줄 때 딕셔너리 형태로 넣어주기
df = pd.DataFrame({'items':['TV','냉장고','전자렌지','컴퓨터','선풍기','선풍기','믹서','믹서']})
pd.get_dummies(df)

 

 

인코딩 적용 방법

데이터 인코딩 방법을 정리해 보자면 다음과 같다.

 

레이블 인코딩

  • LableEncoder 클래스 선언
  • 레이블 인코딩 fit()과 transform()을 이용하여 변환

 

원-핫 인코딩

 

1. OneHotEncoder 클래스 선언

  • 원-핫 인코딩 fit()과 transform()을 이용하여 반환. (인자로 2차원 ndarray 입력 필요)

2. pd.get_dummies(dataframe)을 이용

 

 

숫자로 표현된 범주형 데이터의 경우는?

어떤 설문지에서 대답이 0 (첫 번째 체크박스), 1(두 번째 체크박스), 2 (세 번째 체크박스) 등으로 있다고 하자. 그러면 이때는 숫자형으로 채워지지만 숫자의 크기에 의미를 갖는 것이 아니고, 연속형 데이터가 아닌 이산적인 데이터이다. 즉, 특성의 값이 숫자라고 해서 연속형 특성으로 다뤄져야 한다는 의미가 아닌 것이다.

 

만약 설문을 통해서 받은 데이터 그대로 get_dummies를 이용하여서 범주형 데이터를 숫자형으로 변환한다고 하자.

그러면 '범주형 특성' (양말, 여우, 상자)의 경우 잘 변환되었지만 '숫자 특성' (0,1,2)의 경우 그냥 그대로 변화 없이 반환되었다.

import pandas as pd
demo_df = pd.DataFrame({'숫자 특성': [0,1,2,1], 
                        '범주형 특성' : ['양말', '여우', '양말', '상자']})
print(pd.get_dummies(demo_df))

 

[출력 결과]

get_dummies로 숫자 특성의 범주형 데이터는 변하지 않았다.

    숫자 특성  범주형 특성_상자  범주형 특성_양말  범주형 특성_여우
0        0          0                 1                0
1        1          0                 0                1
2        2          0                 1                0
3        1          1                 0                0

 

해결 방법

숫자형을 문자타입으로 바꾸고(astype) → get_dummies 적용하기

# 숫자 특성의 범주형 데이터를 문자타입으로 바꾼다
demo_df['숫자 특성'] = demo_df['숫자 특성'].astype(str)
pd.get_dummies(demo_df)

 

 

728x90
반응형
Comments