2023. 11. 18. 21:22ㆍ개발/💠 Alchemist
< 캐글 자전거 대여 수요 예측 >
https://www.kaggle.com/c/bike-sharing-demand
Bike Sharing Demand | Kaggle
www.kaggle.com
1. 데이터 세트 로딩 및 데이터 전처리, 모델 import
데이터 세트, 모델 import
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning)
bike_df = pd.read_csv('./bike_train.csv')
print(bike_df.shape)
bike_df.head()
datatime 칼럼 - 연도, 월, 일, 시간으로 분리
# 문자열을 datetime 타입으로 변경
bike_df['datetime'] = bike_df.datetime.apply(pd.to_datetime)
# datetime 타입에서 년, 월, 일, 시간 추출
bike_df['year'] = bike_df.datetime.apply(lambda x : x.year)
bike_df['month'] = bike_df.datetime.apply(lambda x : x.month)
bike_df['day'] = bike_df.datetime.apply(lambda x : x.day)
bike_df['hour'] = bike_df.datetime.apply(lambda x : x.hour)
bike_df.head(3)
필요 없는 칼럼 ( datetime, casual, registered ) 삭제
drop_columns = ['datetime', 'casual', 'registered']
bike_df.drop(drop_columns, axis=1, inplace=True)
카테고리형 피처들 시각화
fig, axs = plt.subplots(figsize=(16, 8), ncols=4, nrows=2)
cat_features = ['year','month','season','weather','day', 'hour', 'holiday', 'workingday']
# cat_features에 있는 모든 칼럼별로 개별 칼럼값에 따른 count의 합을 barplot으로 시각화
for i, feature in enumerate(cat_features):
row = int(i/4)
col = i % 4
# 시본의 barplot을 이용해 칼럼값에 따른 count의 합을 표현
sns.barplot(x=feature, y='count', data=bike_df, ax=axs[row][col])
2. 회귀 모델 학습/예측 및 평가 -> 데이터세트 개선
RMSLE, MSE, RMSE - 회귀 모델 예측 성능 평가 함수
from sklearn.metrics import mean_squared_error, mean_absolute_error
# log값 변환 시 NaN 등의 이슈로 log()가 아닌 log1p()를 이용해 RMSLE 계산
def rmsle(y, pred):
log_y = np.log1p(y)
log_pred = np.log1p(pred)
squared_error = (log_y - log_pred) ** 2
rmsle = np.sqrt(np.mean(squared_error))
return rmsle
# 사이킷런의 mean_square_error()를 이용해 RMSE 계산
def rmse(y, pred):
return np.sqrt(mean_squared_error(y, pred))
# MSE, RMSE, RMSLE를 모두 계산
def evaluate_regr(y, pred):
rmsle_val = rmsle(y, pred)
rmse_val = rmse(y, pred)
# MAE는 사이킷런의 mean_absolute_error()로 계산
mae_val = mean_absolute_error(y, pred)
print('RMSLE: {0:.3f}, RMSE: {1:.3F}, MAE: {2:.3F}'.format(rmsle_val, rmse_val, mae_val))
회귀 모델 적용 및 예측 성능 평가
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.linear_model import LinearRegression, Ridge, Lasso
# target, feature 칼럼 설정
y_target = bike_df['count']
X_features = bike_df.drop(['count'], axis=1, inplace=False)
# 학습 / 테스트 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(X_features, y_target, test_size=0.3, random_state=0)
# 선형 회귀 모델 적용
lr_reg = LinearRegression()
lr_reg.fit(X_train, y_train)
pred = lr_reg.predict(X_test)
# 예측 성능 평가
evaluate_regr(y_test, pred)
오류값 확인
def get_top_error_data(y_test, pred, n_tops=5):
# DataFrame의 칼럼으로 실제 대여 횟수(count)와 예측값을 서로 비교할 수 있도록 생성
result_df = pd.DataFrame(y_test.values, columns=['real_count'])
result_df['predicted_count'] = np.round(pred)
result_df['diff'] = np.abs(result_df['real_count'] - result_df['predicted_count'])
# 예측값과 실제값의 차이가 가장 큰 데이터 순으로 출력
print(result_df.sort_values('diff', ascending=False)[:n_tops])
get_top_error_data(y_test, pred, n_tops=5)
실제값(real_count)과 비교해봤을 때 오류값(diff)이 꽤나 크다는 것을 알 수 있다
오류값이 클 땐 가장 먼저 Target값이 왜곡된 형태를 띄고 있는지 확인해봐야 한다
Target값의 분포 형태 확인
y_target.hist()
Target 값이 0~200 사이에 몰려있는 왜곡된 분포 형태를 띄고 있다
Target값 정규 분포 형태로 변화
y_log_transform = np.log1p(y_target)
y_log_transform.hist()
데이터의 왜곡 정도가 많이 회복됨
Target 칼럼(count)값을 log1p로 로그 변환 후 모델 학습 및 예측
# 타겟 칼럼인 count값을 log1p로 로그 변환
y_target_log = np.log1p(y_target)
# 로그 변환된 y_target_log를 반영해 학습/테스트 데이터 세트 분할
X_train, X_test, y_train, y_test = train_test_split(X_features, y_target_log, test_size=0.3, random_state=0)
# 선형 회귀 모델 학습 및 예측
lr_reg = LinearRegression()
lr_reg.fit(X_train, y_train)
pred = lr_reg.predict(X_test)
# 테스트 데이터 세트의 Target값은 로그 변환되었으므로 다시 expm1을 이용해 원래 스케일로 변환
y_test_exp = np.expm1(y_test)
회귀 모델 예측 성능 평가
# 예측값 역시 로그 변환된 타겟 기반으로 학습돼 예측됐으므로 다시 expm1로 스케일 변환
pred_exp = np.expm1(pred)
# 선형 회귀 모델 예측 성능 평가
evaluate_regr(y_test_exp, pred_exp)
RMSLE 오류는 감소했지만 RMSE는 오히려 증가함
피처 인코딩
# 피처의 회귀 계숫값 시각화
coef = pd.Series(lr_reg.coef_, index = X_features.columns)
coef_sort = coef.sort_values(ascending = False)
sns.barplot(x=coef_sort.values, y=coef_sort.index)
카테고리형 피처 원-핫 인코딩 진행
# 'year', 'month', 'day', 'hour' 등의 카테고리형 피처들을 One Hot Encoding
X_features_ohe = pd.get_dummies(X_features, columns=['year','month','day','hour','holiday','workingday','season','weather'])
원-핫 인코딩 후 예측 성능 평가
# 원-핫 인코딩이 적용된 피처 데이터 세트 기반으로 학습/예측 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X_features_ohe, y_target_log, test_size=0.3, random_state=0)
# 모델과 학습/테스트 데이터 세트를 입력하면 성능 평가 수치를 반환
def get_model_predict(model, X_train, X_test, y_train, y_test, is_expm1=False):
model.fit(X_train, y_train)
pred = model.predict(X_test)
if is_expm1 :
y_test = np.expm1(y_test)
pred = np.expm1(pred)
print('###',model.__class__.__name__,'###')
evaluate_regr(y_test, pred)
# 모델별로 평가 수행
lr_reg = LinearRegression()
ridge_reg = Ridge(alpha=10)
lasso_reg = Lasso(alpha=0.01)
for model in [lr_reg, ridge_reg, lasso_reg]:
get_model_predict(model, X_train, X_test, y_train, y_test, is_expm1=True)
원-핫 인코딩 진행 후 예측 성능값이 많이 향상되었음
회귀 계수 상위 20개 추출
# 회귀 계수 상위 20개 피처 시각화 - 왜 알아야할까?
coef = pd.Series(lr_reg.coef_, index=X_features_ohe.columns)
coef_sort = coef.sort_values(ascending=False)[:20]
sns.barplot(x=coef_sort.values, y=coef_sort.index)
회귀 트리를 이용한 회귀 예측 수행
# 회귀 트리를 이용한 회귀 예측
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from xgboost import XGBRegressor
from lightgbm import LGBMRegressor
# 랜덤 포레스트, GBM, XGBoost, LightGBM model별로 평가 수행
rf_reg = RandomForestRegressor(n_estimators=500)
gbm_reg = GradientBoostingRegressor(n_estimators=500)
xgb_reg = XGBRegressor(n_estimators=500)
lgbm_reg = LGBMRegressor(n_estimators=500)
for model in [rf_reg, gbm_reg, xgb_reg, lgbm_reg]:
# XGBoost의 경우 DataFrame이 입력될 경우 버전에 따라 오류 발생 가능, ndarrayfh qusghks
get_model_predict(model, X_train.values, X_test.values, y_train.values, y_test.values, is_expm1=True)
회귀 예측 성능이 개선됨
'개발 > 💠 Alchemist' 카테고리의 다른 글
💠 AIchemist 7주차 💠 (0) | 2023.11.22 |
---|---|
💠 회귀 - 캐글 주택 가격: 고급 회귀 기법 💠 (0) | 2023.11.21 |
💠 AIchemist 6주차 💠 (0) | 2023.11.08 |
💠 머신러닝 회귀 모델 💠 (4) | 2023.11.07 |
💠 AIchemist 5주차 💠 (0) | 2023.11.07 |