머신러닝 - 원-핫 인코딩(One-Hot Encoding)
목차
본 글에서는 머신러닝에서 원-핫 인코딩이 무엇인지 설명합니다.
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( )
를 이용하면 숫자형 값으로 변환 없이도 바로 변환이 가능함을 알 수 있습니다.