일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 삼성 SDS 서포터즈
- 파이썬 SQL 연동
- Deep Learning for Computer Vision
- 브라이틱스 스태킹
- michigan university deep learning for computer vision
- 파이썬 내장 그래프
- 브라이틱스 서포터즈
- 머신러닝
- Brightics AI
- 분석 툴
- paper review
- 데이터 분석 플랫폼
- 브라이틱스 AI
- 데이터 분석
- 딥러닝
- Brightics 서포터즈
- pymysql
- Brightics EDA
- 범주형 변수 처리
- 비전공자를 위한 데이터 분석
- Brigthics Studio
- 서포터즈 촬영
- 삼성 SDS
- Python
- Brightics studio
- 검증 평가 지표
- 브라이틱스 분석
- 브라이틱스 프로젝트
- Random Forest
- Activation Function
- Today
- Total
하마가 분석하마
[machine learning class] 5. 범주형 변수 처리-2 본문
범주형 변수를 다룰 때 고려해야 할 것 중 하나는 새로운 혹은 희귀한 범주이다. 이러한 범주는 학습 데이터에는 나타나지 않고 평가 데이터에서 새로 나타날 수 있다. 이 경우 평가 시에 모델이 오류를 발생할 것이다. 이를 방지하기 위해 새로운 범주를 추가할 수 있다. 이 새로운 범주를 '희귀(rare) 범주'라고 한다. 희귀 범주는 자주 나타나지 않고, 여러 범주를 포함할 수 있다.
학습 데이터에 없었던 새로운 범주가 나타났을 때 처리하는 다른 방법은 nearest neighbor 모델을 사용하여 기존 범주 중 가장 비슷한 범주를 예측하는 것이다. 이 경우, 새로운 범주가 기존 범주 중 하나의 값으로 대체된다.
앞선 파트의 결측치 대체 부분에서 필자의 경험을 서술해 놓았다.
새로운 범주를 다룰 때 이러한 방식이 모델의 성능을 꼭 향상시킨다고 장담할 수는 없다. 직접 적용해보기 전에는 어떤 방식이 도움이 되는지 알 수 없다.
평가 데이터가 고정되어 있다면 평가 데이터를 학습 데이터에 추가하여 피쳐에 존재하는 모든 범주를 미리 찾을 수 있다. 이는 모델 성능 향상을 위해 학습 데이터와 검증 데이터를 동시에 사용하는 준지도 (semi-supervised) 학습과 비슷하다. 이 방식을 사용하면 학습 데이터에 없지만 평가 데이터에 나타나는 희귀 범주 값을 처리할 수 있어 더 안정적인 모델을 만들 수 있다.
평가 데이터를 학습 데이터에 추가하면 오버피팅을 야기하지 않을까? 그럴 수도 있고 아닐 수도 있다. 또한 교차검증을 사용하여 각 폴드의 검증 데이터에 평가 데이터와 동일한 전처리를 적용함으로써 오버피팅을 방지할 수 있다.
위 방식은 코드를 통하여 더 쉽게 이해할 수 있을 것이다. 코드를 살펴보자.
## 학습 데이터에는 존재하지 않거나 희귀하지만 시험 데이터에만 존재하는 범주를 학습하기 위해 학습 데이터와 시험 데이터를 합치기
import pandas as pd
from sklearn import preprocessing
# 학습 데이터를 불러온다.
train = pd.read_csv('cat_train.csv')
# 평가 데이터를 불러온다.
test = pd.read_csv('cat_test.csv')
# 테스트 데이터에는 타겟 열이 없으므로 가짜 타겟 열을 생성한다.
test.loc[:, 'target'] = -1
# 학습 데이터와 평가 데이터를 결합한다.
data = pd.concat([train, test]).reset_index(drop = True)
# 인코딩 할 피쳐의 목록을 만든다.
# id와 target은 포함해서는 안된다.
features = [x for x in train.columns if x not in ['id', 'target']]
# 모든 피쳐에 대해 계산한다.
for feat in features:
# 각 피쳐에 대해 새로운 LabelEncoder 객체를 생성한다.
lbl_enc = preprocessing.LabelEncoder()
# 범주형 변수들이므로, 문자열로 fillna()를 호출한 후
# 모든 정수이든지 실수이든지 모두 문자열로 변환된다.
temp_col = data[feat].fillna('NONE').astype(str).values
# 학습 데이터와 평가 데이터를 합쳤으므로 fit_transform을 사용하여 한 번에 변환한다.
data.loc[:, feat] = lbl_enc.fit_transform(temp_col)
# 합쳤던 학습 데이터와 시험 데이터를 다시 나눈다.
train = data[data.target != -1].reset_index(drop = True)
test = data[data.target == -1].reset_index(drop = True)
이는 시험 데이터가 미리 주어진 경우 사용할 수 있다. 즉, 실시간 환경에서는 사용할 수 없다는 뜻이다. 실시간으로 입력되는 정보를 바탕으로 분석을 진행한다고 했을 때 학습 데이터와 평가 데이터는 합칠 수 없다. 입력되기 전까지의 데이터를 바탕으로 카테고리를 구성했기에 새로운 데이터가 원래 없던 카테고리를 포함한다면 모델은 새로운 카테고리를 인식하지 못하고 예측에 실패할 것이다. 이와 같은 상황은 "알 수 없는 (NONE)" 범주를 사용하여 방지할 수 있다.
이는 자연어 처리와 유사하다. 자연어 처리에서는 언제나 고정된 어휘를 바탕으로 모델을 만들고, 어휘의 양이 증가함에 따라 모델의 크기도 커진다. 버트(BERT)와 같은 트랜스포머 모델은 영어의 경우 약 3만 단어로 학습한다. 그리고 새로운 단어가 나오면 UNK (알 수 없음)으로 표기한다.
따라서 시험 데이터에서 새로 추가되는 범주를 다루기 위해서는 첫째, 시험 데이터의 범주가 학습 데이터의 범주와 동일하다고 가정하거나, 둘째, 희귀 혹은 알 수 없는 범주를 학습 과정에 추가할 수 있다.
깃허브 코드는 이진 분류 학습의 예에서 범주형 변수 처리에 따른 성능을 보기 위해 로지스틱과 랜덤 포레스트 알고리즘을 적용해 본다. 천천히 따라 해 보기 바란다.
필자는 'NONE' 범주를 만들어 사용해 본 적이 없다. 대부분의 공모전이 평가 데이터가 따로 있었고, 지금까지의 프로젝트 및 공모전에서 범주형 데이터가 다양하게 나온 적이 없었기 때문이다. 다음 기회에 '준지도 학습'과 'NONE' 범주를 사용하여 분석을 해봐야겠다.
https://github.com/rch1025/Machine-learning-class
rch1025/Machine-learning-class
Several concepts and several tips that are important for data analysis can be learned. I studied based on 'Machine Learning Master Class'. - rch1025/Machine-learning-class
github.com
'Machine learning class' 카테고리의 다른 글
[machine learning class] 6. feature engineering (0) | 2021.03.07 |
---|---|
[machine learning class] 5. 범주형 변수 처리-3 (2) | 2021.03.03 |
[machine learning class] 5. 범주형 변수 처리-1 (0) | 2021.02.26 |
[machine learning class] 4. 프로젝트 관리 (0) | 2021.02.23 |
[machine learning class] 3. 검증 및 평가 메트릭-3 (0) | 2021.02.22 |