1 개요
특정 값이 아니라 어떤 선택지에 대한 답을 받았을 때 이를 어떻게 처리할 것인가. 쉽게 말하자면, 문자데이터를 받았을 때 어떻게 머신러닝 기계가 알아먹을 언어로 바꾸어 넣어줄 수 있을까.
1.1 방법
어떤 방법이 좋은진 상황에 따라 다르다. 복잡하고 정교하게 설계된 방법이라고 해서 다 옳진 않다.
- 버리기.
- 가장 간편한 방법인데, 이 안에 중요한 데이터가 들어있다면 좋은 선택은 아니다.
- 순서 부여하기.
- 특정 빈도나 점수화가 가능한 대답의 경우엔 이에 해당하는 라벨링으로 바꾸어주는 방법.
- 원핫 인코딩(One-Hot Encoding).
- 그런데, 빨강, 초록 등의 중립적인 값은 어떻게 처리해야 하는가? 이런 경우엔 선택지에 따라 열을 세분화하여 해당값을 갖는 경우에만 1을 부여하는 등의 방식을 사용한다.
- - 그러나 너무 많은 범주가 있는 경우엔 잘 먹히지 않는 전략이다. 범주가 15개가 넘는다면 권장되지 않는다.[1]
- - 15개 이상의 항목을 가진 경우, 순서부여하기로 처리하고 이 둘을 합치는 전략도 있다.- 너무 많은 열이 만들어지면 데이터 자체가 너무 커진다.
2 방법
2.1 버리기
# df를 사용한다.
# df의 select_dtypes 메서드를 사용한다.
drop_X_train = X_train.select_dtypes(exclude=['object']) # object타입은 데이터를 하나라도 포함한 경우.
drop_X_valid = X_valid.select_dtypes(exclude=['object'])
# exclude를 이용해 해당 데이터를 제외한다.
2.2 순서 부여하기
2.3 One-Hot Encoding
특정 데이터에서 텍스트를 포함한 열을 구분해낸다.
# df를 사용한다.
s = (X.dtypes == 'object') # 판단근거들을 X에 담아 타입을 검사한다.
object_cols = list(s[s].index) # 해당 열을 담는다.
....하는 방법이 있지만 사이킷런에선 이런 기능을 이미 제공하고 있다.
2.3.1 적용할지 말지
선택지가 15개가 넘어가는 경우엔 버리는 게 낫다.
# df의 기능을 이용한다.
high_cardinality_cols = [col for col in object_cols if X_train[col].nunique() > 15]
# 선택지가 15개 초과된 행을 리스트로 반환한다.
# 해당 리스트의 행을 버리면 ok. 혹은 15개 미만만 살린다.
low_cardinality_cols = [col for col in object_cols if X_train[col].nunique() < 15]
2.3.2 적용
from sklearn.preprocessing import OneHotEncoder
# 각각의 열에 One-Hot Encoding을 적용한다.
OH_encoder = OneHotEncoder(handle_unknown='ignore', sparse=False)
OH_cols_train = pd.DataFrame(OH_encoder.fit_transform(X_train[object_cols])) # object_cols 대신 위에서 작성한 low_cardinality_cols를 사용하는 게 편하다.
OH_cols_valid = pd.DataFrame(OH_encoder.transform(X_valid[object_cols])) # 도대체 fit과 그냥 트렌스폼은 뭐가 다른걸까..?
# 인덱스를 넣어준다. One-Hot Encoder는 인덱스를 없애고 값만 반환하기 때문.(근데, 필요한가 이게;? 어차피 그냥 넣을 값인데.)
OH_cols_train.index = X_train.index
OH_cols_valid.index = X_valid.index
# 새로운 열을 만들 뿐, 기존 데이터는 없다.
# 기존의 데이터에서 원-핫 인코딩 한 열은 지워주자.
num_X_train = X_train.drop(object_cols, axis=1)
num_X_valid = X_valid.drop(object_cols, axis=1)
# 기존 데이터와 원핫 인코딩 결과를 합쳐준다.
OH_X_train = pd.concat([num_X_train, OH_cols_train], axis=1)
OH_X_valid = pd.concat([num_X_valid, OH_cols_valid], axis=1)