Categorical Variables란?
설문조사의 항목처럼 제한된 가짓수로 선택지를 숫자로 대체 표현가능한 변수.
변수에 대해 범주를 만들어 그 안에 포함시켜 분류하기 위해.
예로, survey에서 "never"==0, "rarely"==1, "most days"==2, "every day"==3, 이렇게 표현 가능
Categorical Variables를 다루는 3가지 방법
1. Drop Categorical Variables (the easiest way)
이 방법은 해당 column들이 유용하지 않은 정보를 포함할 때만 쓸모있음.
2. Label Encoding
각각 다른 정수를 부여하여 구별시키기
위의 예의 경우 never부터 every day 항목까지 순차적으로 정렬할 수 있음. 순위를 부여할 수 있다는 의미.
모든 categorical variables가 뚜렷한 순서를 가지진 않지만
위와 같이 순위를 가진다면 "ordinal variable"이라고도 이야기할 수 있음.
ordinal variable이란 값이 완벽하지 않아도 그 범주 내에 있으면 그 값으로 처리한 후 순위를 매길 수 있는 변수.
decision trees나 random forest처럼 트리 기반의 모델에서는 ordinal variable인지 확인 후 label encoding 하는 게 좋음.
3. One-Hot Encoding
각 변수에 대해 새로운 column을 만들어서 그 변수의 존재 유무를 나타냄
순위를 매길 수 없는 categorical variable에서 사용하는 방법.
요런 변수를 nominal variables라고 일컬음.
변수 가짓수가 너무 많으면 그닥 좋은 방법이 아님. 일반적으로 15개 미만일 때 사용.
Example
1st. train_data에서 모든 categorical variables의 리스트를 가져오기
각 column의 data type(dtype)으로 확인해봄.
"object" dtype은 해당 column이 text를 가지고 있다는 의미.
아래의 코드는 text를 보유한 column의 이름을 출력해줌.
# Get list of categorical variables
s = (X_train.dtypes == 'object')
object_cols = list(s[s].index)
print("Categorical variables:")
print(object_cols)
2nd. MAE 계산 함수 정의해두기
이후에 적용할 방법들에 대해서 MAE 계산 함수를 써보며 어느 방법이 더 나은지 확인할 수 있도록
3rd-1. Drop Columns included Categorical Variables
"object" dtype의 column을 drop하고 싶을 땐
"select_dtypes(exclude=['object'])" 메소드를 사용
drop_X_train = X_train.select_dtypes(exclude=['object'])
drop_X_valid = X_valid.select_dtypes(exclude=['object'])
print("MAE from Approach 1 (Drop categorical variables):")
print(score_dataset(drop_X_train, drop_X_valid, y_train, y_valid))
3rd-2. Label Encoding
Scikit-learn의 LabelEncoder 모듈을 가져와서 사용
categorical variable을 가진 각 column에 개별적으로 label encoder를 적용함
!!핵심코드!!
from sklearn.preprocessing import LabelEncoder
label_encoder = LabelEncoder()
X[col] = label_encoder.transform(X[col])
from sklearn.preprocessing import LabelEncoder
# Make copy to avoid changing original data
label_X_train = X_train.copy()
label_X_valid = X_valid.copy()
# Apply label encoder to each column with categorical data
label_encoder = LabelEncoder()
for col in object_cols: #object_cols -> good_label_cols
label_X_train[col] = label_encoder.fit_transform(X_train[col])
label_X_valid[col] = label_encoder.transform(X_valid[col])
print("MAE from Approach 2 (Label Encoding):")
print(score_dataset(label_X_train, label_X_valid, y_train, y_valid))
위의 코드 예제는 서로다른 정수를 각각의 값들을 무작위 지정함. 하나하나 하는 customizing 하는 것보단 나음.
그러나 더 성능을 높이고 싶다면, ordinal variable일 때 정보가 가미된 label(informed label)을 적용하면 좋음.
컴퓨터 종류에 대한 text 정보는 출시연도에 따라 정수로 순번을 매길 수 있음. 무작위로 지정하는 것보다 나음.
해당 column에 어떤 text들이 들어있는지 알고 싶으면 X["column이름"].unique()를 쓰면 됨.
그럼 리스트 형식으로 안에 들어있는 값들을 나열해서 보여줌
그런데 다음 사진과 같이 train_data와 valid_data의 내용이 다를 수 있음. train_data에서만 나타날 떼!!
이러면 encoder는 error를 냄. valid_data에서 처음 만난 값에 대한 integer 정보가 없으니까.
위의 사진에서는 train_data에 valid_data의 'RRAn'과 'RRNn' 값이 없음.
이럴 땐 customizing으로 하나하나 정수값을 지정하거나 drop column을 해야하겠지요...
그래서 good_label_cols를 따로 모아보고, bad_label_cols도 따로 모아봄.
bad_label_cols는 버려야할 column들이니 이후에 쓰지 않도록 주의하자!
encoder에는 good_label_cols만 쓰시고!
# All categorical columns
object_cols = [col for col in X_train.columns if X_train[col].dtype == "object"]
# Columns that can be safely label encoded
good_label_cols = [col for col in object_cols if
set(X_train[col]) == set(X_valid[col])]
# Problematic columns that will be dropped from the dataset
bad_label_cols = list(set(object_cols)-set(good_label_cols))
print('Categorical columns that will be label encoded:', good_label_cols)
print('\nCategorical columns that will be dropped from the dataset:', bad_label_cols)
# Drop categorical columns that will not be encoded
label_X_train = X_train.drop(bad_label_cols, axis=1)
label_X_valid = X_valid.drop(bad_label_cols, axis=1)
3rd-3. One-Hot Encoding
Scikit-learn의 OneHotEncoder 모듈을 가져와서 사용
여기에는 customizing해야 할 매개변수가 많이 있음.
- handle_unknown='ignore' : train_data에 표현되지 않은 class를 가진 valid_data로 인해 직면할 error를 방지
- sparse=False : encoded column들이 numpy array(sparse matrix)로 표현되는 걸 보장해줌.
- X_train[object_cols], 꼭 categorical_variable이 포함된 column들에만 위의 모듈을 써야함!
- one-hot encoding은 index를 지우기에 꼭 다시 되붙여주어야 함. (X_train.index)
- one-hot 처리 완료된 column을 본 데이터에 삽입하기 전에, 본 데이터에 남아있는 text로된 column을 먼저 삭제한 뒤 합병해야 함!
from sklearn.preprocessing import OneHotEncoder
# Apply one-hot encoder to each column with categorical data
OH_encoder = OneHotEncoder(handle_unknown='ignore', sparse=False)
OH_cols_train = pd.DataFrame(OH_encoder.fit_transform(X_train[object_cols]))
OH_cols_valid = pd.DataFrame(OH_encoder.transform(X_valid[object_cols]))
# One-hot encoding removed index; put it back
OH_cols_train.index = X_train.index
OH_cols_valid.index = X_valid.index
# Remove categorical columns (will replace with one-hot encoding)
num_X_train = X_train.drop(object_cols, axis=1)
num_X_valid = X_valid.drop(object_cols, axis=1)
# Add one-hot encoded columns to numerical features
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)
print("MAE from Approach 3 (One-Hot Encoding):")
print(score_dataset(OH_X_train, OH_X_valid, y_train, y_valid))
+) One-Hot Coding을 하기 전 거쳐야할 단계
1. Cardinality(값의 종류, 가짓수)가 너무 큰 지 보기
해당 column을 one-hot으로 바꾸기엔 Cardinality가 너무 많은지 확인하기
-> 그런 column은 제외하자
2. 내가 필요한 특정 column을 one-hot으로 바꾸는데 몇 개의 column이 필요한지 알아보자
# Get number of unique entries in each column with categorical data
object_nunique = list(map(lambda col: X_train[col].nunique(), object_cols))
d = dict(zip(object_cols, object_nunique))
# Print number of unique entries by column, in ascending order
sorted(d.items(), key=lambda x: x[1])
#하나의 리스트 안에 (column이름, cardinality)가 cardinality를 기준으로 오름차순으로 정렬된 리스트를 반환
high_cardinality_numcols=0
num_cols_neighborhood = 0
for col,cardi in sorted(d.items(), key=lambda x: x[1]):
if cardi>9: #check num of columns that cardinality is greater than 10
high_cardinality_numcols += 1
if col == 'Neighborhood': #check cardinaility of column I need
num_cols_neighborhood = cardi
'Machine Learning > [Kaggle Course] ML (+ 딥러닝, 컴퓨터비전)' 카테고리의 다른 글
[Kaggle Course] Cross-Validation(교차검증) (0) | 2020.10.23 |
---|---|
[Kaggle Course] Pipelines + How to make and submit CSV in Kaggle (0) | 2020.10.21 |
[Kaggle Course] Missing Values (0) | 2020.10.11 |
[Kaggle Course] Introduction (0) | 2020.10.11 |
Intro to AutoML (0) | 2020.10.08 |