메인 콘텐츠로 이동하기
  1. 블로그 글/

머신러닝 - 원-핫 인코딩(One-Hot Encoding)

·4 분

본 글에서는 머신러닝에서 원-핫 인코딩이 무엇인지 설명합니다.

One-Hot Encoding #

원-핫 인코딩은 피처 값의 유형에 따라 새로운 피처를 추가해 고유 값에 해당하는 칼럼에만 1을 표시하고 나머지 칼럼에는 0을 표시하는 방식입니다. 즉, 행 형태로 돼 있는 피처의 고유 값을 열 형태로 차원을 변환한 뒤, 고유 값에 해당하는 칼럼에만 1을 표시하고 나머지 칼럼에는 0을 표시합니다. 다음 그림에 원본 데이터를 원-핫 인코딩으로 변환하는 모습을 나타냈습니다.

Original Data
Product Category
TV
fridge
microwave
computer
fan
fan
mixer
mixer
One-Hot Encoding
Product Category_TV Product Category_computer Product Category_fan Product Category_fridge Product Category_microwave Product Category_mixer
1 0 0 0 0 0
0 0 0 1 0 0
0 0 0 0 1 0
0 1 0 0 0 0
0 0 1 0 0 0
0 0 1 0 0 0
0 0 0 0 0 1
0 0 0 0 0 1

먼저 원본 데이터는 8개의 레코드로 돼 있으며 고유 값은 [’TV’ ‘computer’ ‘fan’ ‘fridge’ ‘microwave’ ‘mixer’]로 모두 6개입니다. 앞의 레이블 인코딩 예제를 참조하면 TV가 0, computer 1, fan 2, fridge 3, microwave 4, mixer가 5로 인코딩돼 있음을 알 수 있습니다. 0부터 5까지 6개의 상품 분류 고유 값에 따라 상품분류 피처를 6개의 상품 분류 고유 값 피처로 변환합니다.즉, TV를 위한 상품 분류_TV, computer를 위한 상품 분류_computer, fan을 위한 상품 분류_fan, fridge를 위한 상품 분류_fridge, microwave를 위한 상품 분류_microwave, mixer를 위한 상품 분류_mixer 6개의 피처로 변환하는 것입니다. 그리고 해당 레코드의 상품 분류가 TV인 경우는 상품 분류_TV 피처에만 1을 입력하고 나머지 피처는 모두 0입니다. 마찬가지로 해당 레코드의 상품 분류가 fridge라면 상품 분류_fridge 피처에만 1을 입력하고 나머지 피처는 모두 0이 되는 것입니다. 즉, 해당 고유 값에 매칭되는 피처만 1이 되고 나머지 피처는 0을 입력하며, 이러한 특성으로 원-핫(여러 개의 속성 중 단 한 개의 속성만 1로 표시) 인코딩으로 명명하게 됐습니다.

Scikit-learn Implementation #

원-핫 인코딩은 사이킷런에서 OneHotEncoder 클래스로 변환이 가능합니다. 단, LabelEncoder와 다르게 약간 주의할 점이 있습니다. 입력값으로 2차원 데이터가 필요하다는 것과, OneHotEncoder를 이용해 변환한 값이 희소 행렬(Sparse Matrix) 형태이므로 이를 다시 toarray( ) 메서드를 이용해 밀집 행렬(Dense Matrix)로 변환해야 한다는 것입니다. OneHotEncoder를 이용해 앞의 데이터를 원-핫 인코딩으로 변환해 보겠습니다.


from sklearn.preprocessing import OneHotEncoder
import numpy as np
items=['TV', 'fridge', 'microwave', 'computer', 'fan', 'fan', 'mixer', 'mixer']
# Converting to 2 dimension ndarray
items =np.array(items).reshape(-1 , 1)
# Applying One-Hot Encoding
oh_encoder = OneHotEncoder() 
oh_encoder.fit(items)
oh_labels = oh_encoder.transform(items)
# The result of the conversion using OneHotEncoder is a sparse matrix, so we use toarray() to convert it into a dense matrix.  
print('One-Hot Encoded data:')
print(oh_labels.toarray())
print('Dimensions of One-Hot Encoded data:')
print(oh_labels.shape)
 One-Hot Encoded data:
[[1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 0. 1. 0.]
 [0. 1. 0. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0.]
 [0. 0. 0. 0. 0. 1.]
 [0. 0. 0. 0. 0. 1.]]
Dimensions of One-Hot Encoded data:
(8, 6)

8개의 레코드와 1개의 칼럼을 가진 원본 데이터가 8개의 레코드와 6개의 칼럼을 가진 데이터로 변환됐습니다. TV가 0, computer 1, fan 2, fridge 3, microwave 4, mixer가 5로 인코딩됐으므로 첫번째칼럼이 TV, 두 번째 칼럼이 computer, 세 번째 칼럼이 fan, 네 번째 칼럼이 fridge, 다섯 번째 칼럼이 microwave, 여섯 번째 칼럼이 mixer를 나타냅니다. 따라서 원본 데이터의 첫 번째 레코드가 TV이므로 변환된 데이터의 첫번째 레코드의 첫번째 칼럼이 1이고 나머지칼럼은 모두 0이됩니다. 위 예제 코드의 변환절차는 다음 그림과 같이 정리할 수 있습니다.

Original Data
Product Category Price
TV 1,000,000
fridge 1,500,000
microwave 200,000
computer 800,000
fan 100,000
fan 100,000
mixer 50,000
mixer 50,000

Original Data
Product Category Price
0 1,000,000
3 1,500,000
4 200,000
1 800,000
2 100,000
2 100,000
5 50,000
5 50,000

One-Hot Encoding
Product Category_TV Product Category_computer Product Category_fan Product Category_fridge Product Category_microwave Product Category_mixer Price
1 0 0 0 0 0 1,000,000
0 0 0 1 0 0 1,500,000
0 0 0 0 1 0 200,000
0 1 0 0 0 0 800,000
0 0 1 0 0 0 100,000
0 0 1 0 0 0 100,000
0 0 0 0 0 1 50,000
0 0 0 0 0 1 50,000

판다스에는 원-핫 인코딩을 더 쉽게 지원하는 API가 있습니다. get_dummies( ) 를 이용하면 됩니다. 사이킷런의 OneHotEncoder와 다르게 문자열 카태고리 값을 숫자 형으로 변환할 필요 없이 바로 변환할 수 있습니다.

import pandas as pd
df = pd.DataFrame({'item':['TV', 'fridge', 'microwave', 
                           'computer', 'fan', 'fan',
                           'mixer', 'mixer']})
pd.get_dummies(df)
item_TV item_computer item_fan item_fridge item_microwave item_mixer
0 True False False False False False
1 False False False True False False
2 False False False False True False
3 False True False False False False
4 False False True False False False
5 False False True False False False
6 False False False False False True
7 False False False False False True

get_dummies( ) 를 이용하면 숫자형 값으로 변환 없이도 바로 변환이 가능함을 알 수 있습니다.