티스토리 뷰
베이스라인 모델 전략 프로세스
데이터 불러오기 -> (기본적인) 피처 엔지니어링 -> 평가지표 계산 함수 작성 -> 모델 훈련 -> 성능 검증 -> 제출
베이스라인 모델에서 출발해 성능을 점차 향상시키는 방향으로 모델링
공유한 모델을 사용해도 되고, 직접 자신만의 모델을 만들어도 된다.
피처 엔지니어링
피처 엔지니어링 전에 두 데이터를 합쳤다가, 다 끝나면 도로 나눠준다.
훈련 데이터와 테스트 데이터 합치기-> 타입 변경이나 삭제, 추가 -> 데이터 나누기 순서
이상치 제거
weather가 4인 데이터는 이상치다.
# 훈련 데이터에서 weather가 4가 아닌 데이터만 추출
train = train[train['weather'] != 4]
데이터 합치기
훈련 데이터와 테스트 데이터에 같은 피처 엔지니어링을 적용하기 위해 concat()으로 합친다.
all_data_temp = pd.concat([train, test])
all_data_temp
훈련데이터는 10886, 테스트는 6493 이므로 17379행.
weather가 4인 데이터를 제거했으니 17378행이 된다.
실행하면 인덱스가 6492까지밖에 안 보인다. 실제로는 0부터 10885까지 매기고 다시 0부터 매긴 결과
원래 데이터의 인덱스를 무시하고 이어 붙이려면 ignore_index=True
all_data = pd.concat([train, test], ignore_index=True)
all_data
인덱스가 0부터 17,377까지 잘 나타난다.
테스트 데이터의 casual, registerd 피처와 count 타깃값이 없으므로 NaN으로 표시된다.
파생 피처(변수) 추가
from datetime import datetime
# 날짜 피처 생성
all_data['date'] = all_data['datetime'].apply(lambda x: x.split()[0])
# 연도 피처 생성
all_data['year'] = all_data['datetime'].apply(lambda x:
x.split()[0].split('-')[0])
# 월 피처 생성
all_data['month'] = all_data['datetime'].apply(lambda x:
x.split()[0].split('-')[1])
# 시 피처 생성
all_data['hour'] = all_data['datetime'].apply(lambda x:
x.split()[1].split(':')[0])
# 요일 피처 생성
all_data['weekday'] = all_data['date'].apply(lambda dateString :
datetime.strptime(dateString,"%Y-%m-%d").weekday())
날짜, 연도, 월, 시, 요일의 추가
day,minute,second는 피처 생성 X
datetime 피처를 datetime 타입으로 바꾸면 쉽게 가져올 수 있다.
# datetime 타입으로 바꾸기
all_data['datetime'] = pd.to_datetime(all_data['datetime'])
all_data['year'] = all_data['datetime'].dt.year # 연도
all_data['month'] = all_data['datetime'].dt.month # 월
all_data['hour'] = all_data['datetime'].dt.hour # 시간
all_data["weekday"] = all_data['datetime'].dt.weekday # 요일
필요 없는 피처 제거
casual, registered는 테스트 데이터에 없으므로 제거.
datetime 피처 및 date는 다른 정보들에도 있어 제거
season 피처가 month의 대분류기 때문에 month도 제거
windspeed 피처도 상관관계가 없어 제거
drop_features = ['casual', 'registered', 'datetime', 'date', 'month', 'windspeed']
all_data = all_data.drop(drop_features, axis=1)
<class 'pandas.core.frame.DataFrame'>
Int64Index: 17378 entries, 0 to 6492
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 datetime 17378 non-null object
1 season 17378 non-null int64
2 holiday 17378 non-null int64
3 workingday 17378 non-null int64
4 weather 17378 non-null int64
5 temp 17378 non-null float64
6 atemp 17378 non-null float64
7 humidity 17378 non-null int64
8 windspeed 17378 non-null float64
9 casual 10885 non-null float64
10 registered 10885 non-null float64
11 count 10885 non-null float64
dtypes: float64(6), int64(5), object(1)
memory usage: 1.7+ MB
에서
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 17378 entries, 0 to 17377
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 season 17378 non-null int64
1 holiday 17378 non-null int64
2 workingday 17378 non-null int64
3 weather 17378 non-null int64
4 temp 17378 non-null float64
5 atemp 17378 non-null float64
6 humidity 17378 non-null int64
7 count 10885 non-null float64
8 year 17378 non-null object
9 hour 17378 non-null object
10 weekday 17378 non-null int64
dtypes: float64(3), int64(6), object(2)
memory usage: 1.5+ MB
로 바뀌었다.
피처 선택이란?
모델링 시 데이터의 특징을 잘 나타내는 주요 피처만 선택하는 작업을 피처 선택(feature selection)이라고 한다..
피처 선택은 머신러닝 모델 성능에 큰 영향을 준다.
타깃값 예측과 관련 없는 피처가 많다면 오히려 예측 성능이 떨어진다.
피처 선택 방법에 정답은 없다!
탐색적 데이터 분석, 피처 중요도(feature importance), 상관관계 매트릭스 등을 활용해 종합적으로 판단해야 한다.
여기까지가 피처 엔지니어링
데이터 나누기
모든 피처 엔지니어링을 적용했으므로 훈련 데이터와 테스트 데이터를 다시 나눈다.
# 훈련 데이터와 테스트 데이터 나누기 ①
X_train = all_data[~pd.isnull(all_data'count'])]
X_test = all_data[pd.isnull(all_data['count'])]
# 타깃값 count 제거 ②
X_train = X_train.drop(['count'], axis=1)
X_test = X_test.drop(['count'], axis=1)
y = train['count'] # 타깃값 ③
타깃값이 있으면 훈련, 없으면 테스트 데이터다.
count가 null이 아니면 훈련 데이터
이렇게 나눈 X_train과 X_test에는 타깃값인 count도 포함되어 있으므로 제거
그리고 타깃값인 train count는 변수 y에 따로 할당
평가 지표 계산 함수 작성
import numpy as np
def rmsle(y_true, y_pred, convertExp=True):
# 지수변환 ①
if convertExp:
y_true = np.exp(y_true)
y_pred = np.exp(y_pred)
# 로그변환 후 결측값을 0으로 변환 ②
log_true = np.nan_to_num(np.log(y_true+1))
log_pred = np.nan_to_num(np.log(y_pred+1))
# RMSLE 계산 ③
output = np.sqrt(np.mean((log_true - log_pred)**2))
return output
y_true와 y_pred를 인수로 전달하면 rmsle 수치를 반환한다.
1. 만약에 convertExp=True 라면, 입력 데이터를 지수변환. 지수변환 하는 이유는 타깃값으로 count가 아닌 log(count)를 사용하기 때문. 로그 변환 후에 사용한다.
정규분포를 따른다면 count 값을 그대로 사용해도 된다.
2. np.log(y_true+1)로 로그 값으로 변환하고, output 계산
3. np.nan_to_num() 함수는 Nan 결측값을 모두 0으로 바꾸는 기능
4. output은 RMSLE 공식이다.
출처 : 머신러닝 딥러닝 문제해결 전략