Snoopy [ML] 20. 데이터 전처리 (9) - 인코딩(Ordinary-Encoding, label-Encoding, One-hot-Encoding)
머신러닝과 딥러닝/ML 개념정리

[ML] 20. 데이터 전처리 (9) - 인코딩(Ordinary-Encoding, label-Encoding, One-hot-Encoding)

Sooyoon Jeong 2022. 11. 14.

멋쟁이 사자처럼 AI스쿨 7기 오늘코드 박조은 강사님의 수업자료를 바탕으로 포스팅하였습니다.


인코딩이란?

categorical Feature를 numerical feature로 변환하는 것이다.

 

 

왜 인코딩이 필요할까?

1️⃣ 머신러닝에서는 문자형 변수가 있으면 오류가 발생하며, 문자형 변수를 수치형 변수로 바꿔주어야 한다.

      (선형회귀 모델, 딥러닝 모델등은 문자형 변수 사용 불가)

2️⃣ 데이터 시각화에 유리하다.

 

범주형 변수를 수치형 변수로 바꿔는 인코딩 방법에는 여러가지가 있다.

가장 대표적인 것이

 

1. Ordinal-Encoding

2. One-hot-Encoding

 

Ordinal Encoding은

a <- 1

b <- 2

이런 식으로 들어가는 순서형 인코딩으로, 순서가 있는 데이터라면 사용하기에 적합하지만

순서가 없는 데이터라면 의도치 않은 연산이 발생할 수 있다. (a + b 는 3이 아니다.)

 

이런 경우에는 one-hot-encoding을 사용한다.

 

정리하자면,

one-hot-encoding은 순서가 없는 명목형 데이터에 적용하는 인코딩 기법으로 결과가 matrix 2차원 행렬 형태로 나온다.

Ordinal Encoding 순서가 있어도 되는 명목형 데이터이며, category 타입으로 변경해주는 인코딩 기법으로 결과가 벡터 1차원 형태로 나온다.

 

원핫인코딩은 여러 컬럼을 생성하여 1과 0으로 값을 채워 넣는다면
ordinal 인코딩은 하나의 컬럼에다가 1부터 순차적으로 값을 채워 넣는다.


Ordinal-encoding?

catergoy 데이터 타입으로 변경하는 인코딩 기법

 

ordinal encoding 활용 방법

train["새로운 변수명"] = train["적용할 변수명"].astype("category").cat.codes
test["새로운 변수명"] = test["적용할 변수명"].astype("category").cat.codes

 

장점

직관적이다.

복잡하기 않고 간단하다.

 

단점

데이터에 추가적인 가치를 더해주지 않는다.

잘못된 의미(순서)를 부여할 수 있다.

 

라벨인코딩과 오디널 인코딩의 차이

아래 링크에 잘 정리가 되어 있다.

 

라벨인코딩이랑 오디널 인코딩은 이름만 다르고 거의 똑같은 기능이다.

https://techblog-history-younghunjo1.tistory.com/99

 

sklearn을 활용한 label encoder

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
le.fit(["paris", "paris", "tokyo", "amsterdam"])

print(list(le.classes_))
print(["tokyo", "tokyo", "paris"])
print(le.transform(["tokyo", "tokyo", "paris"]))

list(le.inverse_transform([2, 2, 1]))

sklearn을 활용한 ordinal encoder

from sklearn.preprocessing import OrdinalEncoder
enc = OrdinalEncoder()
X = [['male', 'from US', 'uses Safari'], 
     ['female', 'from Europe', 'uses Firefox']]
enc.fit(X)
print(enc.transform([['female', 'from US', 'uses Safari']]))
print(enc.categories_)

 

label encoder와 ordinal encoder의 입력값의 차이?

기능의 차이는 별로 없어보이는데 왜 sklearn에는 두 기능 모두를 만들어놨을까?

 

Ordinal Encoding은 Label Encoding과 달리 변수에 순서를 고려한다는 점에서 큰 차이를 갖는다.

Label Encoding이 알파벳 순서 혹은 데이터셋에 등장하는 순서대로 매핑하는 것과 달리

Oridnal Encoding은 Label 변수의 순서 정보를 사용자가 지정해서 담을 수 있다.

 

label : 입력이 1차원 y 값

ordinal: 입력이 2차원 X값

 

X => 독립변수, feature, 2차원 array 형태, 학습할 피쳐 예) 시험의 문제,

y => 종속변수, label, target, 정답, 1차원 벡터 예) 시험의 답안

 

X는 보통 2차원으로 대문자로 표기하고 y 는 소문자로 표기하는 것이 관례처럼 사용되고 있다.

그런데, 딥러닝에서는 x를 보통 소문자로 사용하는데 아마도 추측하기로는 x에 꼭 2차원만 들어가는게 아니라서인 것 같다.

2차원 이상도 들어간다. 예) 이미지


원 핫 인코딩?

범주형 데이터를 수치형 데이터로 전처리할 때 자주 사용되는 인코딩 기법으로

한 개의 1과 수 많은 0의 값으로 데이터를 구별하는 인코딩이다.

 

pandas와 sklearn을 활용하여 원 핫 인코딩을 진행할 수 있는데,

수치데이터와 범주형 데이터를 함께 넣어도 수치형 데이터는 그대로 범주형 데이터에 대해서만 인코딩을 해주기 때문에 pandas를 사용하는 것이 편리하다.

 

다만 pandas를 이용해 원 핫 인코딩을 할 경우 train과 test의 columns 개수, 명이 같은지 반드시 확인해야 한다.

pandas의 get_dummies를 사용해서 인코딩을 하면 train, test를 따로 인코딩을 하게 됩니다.
train 학습한 것을 기반으로 test와 동일하게 피처를 생성해주어야 하는데, 이게 조금 다를 수 있습니다.
판다스로 train, test 각각 인코딩 했다면 피처의 수, 종류가 다를 수 있습니다.

그런데 학습, 예측을 할 때는 동일한 피처를 입력해주어야 합니다. 개수도 동일해야 합니다.

pandas로 인코딩한다면 set(train.columns) - set(test.columns) 이런식으로 비교해서 맞춰주어야 합니다.
또 train 에만 등장하는 피처가 있다면 test에도 동일하게 만들어주어야 합니다.

가장 간단한 것은 concat을 사용하는 방법입니다.
없는 값은 nan으로 들어가게 되고 다시train, test를 나눠주면 됩니다.

=> 처음부터 concat을 사용하고 나중에 나눠주면 이런 문제를 해결할 수 있지만
=> 그런데 test 에만 등장하는 데이터를 피처로 사용하지 말라는 정책이 있을 때 이 방법은 규칙위반일수 있다.

 

장점

feature의 모든 정보를 유지한다.

 

단점

feature에 너무 많은 고유값이 있는 경우 feature를 너무 많이 사용하게 된다.

(feature가 많아지면 자원이 많이 소요된다)

 

pd.get_dummies()

pandas.get_dummies(data, prefix=None, 
prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False, dtype=None)

 

주요 파라미터

1) data: array-like, Series, or DataFrame

원 핫 인코딩을 적용할 데이터

 

2) prefix: str, list of str, or dict of str, default None

인코딩 한 값을 데이터프레임에 추가할 때 사용할 문자열

 

3) prefix_sep:

prefix를 추가하는 경우 사용할 구분 기호

※ default = ' '

 

4) dummpy_na

NaN 값도 포함시킬지 여부

※ default = None

 

5) columns

대상 컬럼

 

6) drop_first

첫 번째 컬럼을 drop 시킬지 여부 지정

 

7) dtype

새로 생성되는 columns의 데이터 타입 지정

 

sklearn을 이용한 인코딩

from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder()
X = [['male', 'from US', 'uses Safari'],
     ['female', 'from Europe', 'uses Firefox']]
enc.fit(X)
enc_out = enc.transform([['female', 'from US', 'uses Safari'],
               ['male', 'from Europe', 'uses Safari']]).toarray()
print(enc_out)
print(enc.get_feature_names_out())
pd.DataFrame(enc_out, columns=enc.get_feature_names_out())

ohe = OneHotEncoder(handle_unknown='ignore')
train_ohe = ohe.fit_transform(train[["MSZoning", "Neighborhood"]]).toarray()
test_ohe= ohe.transform(test[["MSZoning", "Neighborhood"]])
pd.DataFrame(train_ohe, columns=ohe.get_feature_names_out())

 

🔗 참고자료

AIS7기 오늘코드 박조은 강사님 강의자료

https://pandas.pydata.org/docs/reference/api/pandas.get_dummies.html

 

댓글