티스토리 뷰

반응형

베이스라인 모델 전략 프로세스

 

데이터 불러오기 -> (기본적인) 피처 엔지니어링 -> 평가지표 계산 함수 작성 -> 모델 훈련 -> 성능 검증 -> 제출

 

베이스라인 모델에서 출발해 성능을 점차 향상시키는 방향으로 모델링

공유한 모델을 사용해도 되고, 직접 자신만의 모델을 만들어도 된다.

 

피처 엔지니어링

피처 엔지니어링 전에 두 데이터를 합쳤다가, 다 끝나면 도로 나눠준다.

훈련 데이터와 테스트 데이터 합치기-> 타입 변경이나 삭제, 추가 -> 데이터 나누기 순서

 

이상치 제거 

 

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 공식이다.

 

 

출처 : 머신러닝 딥러닝 문제해결 전략

반응형