유진의 코딩스토리
Python ML 실습 [자전거 대여 수요 예측 - 회귀 모델] 본문
자전거 대여 수요를 예측하는 모델을 만들기 위해서 먼저 kaggle에서 데이터셋을 가져온다.
https://www.kaggle.com/c/bike-sharing-demand/overview
kaggle에서 설명해주는 각 feature에 대한 설명이다.
- datetime - 년월일 + timestamp
- season -
1 = spring, 2 = summer, 3 = fall, 4 = winter1 = winter, 2 = spring, 3 = summer, 4 = fall - holiday - whether the day is considered a holiday (공휴일 유무)
- workingday - whether the day is neither a weekend nor holiday (평일인지 주말인지)
- weather - 1: Clear, Few clouds, Partly cloudy, Partly cloudy (매우 좋은 날)
2: Mist + Cloudy, Mist + Broken clouds, Mist + Few clouds, Mist (약간 구름이 끼고, 안개가 끼는 날)
3: Light Snow, Light Rain + Thunderstorm + Scattered clouds, Light Rain + Scattered clouds (약간의 눈과 비, 흐린 날)
4: Heavy Rain + Ice Pallets + Thunderstorm + Mist, Snow + Fog (폭우, 우박, 뇌우, 눈,안개) - temp - temperature in Celsius (온도섭씨)
- atemp - "feels like" temperature in Celsius (체감온도?)
- humidity - relative humidity (상대습도)
- windspeed - wind speed (풍속)
- casual - number of non-registered user rentals initiated (예약하지 않고 자전거를 대여한 수)
- registered - number of registered user rentals initiated (예약을 한 후 자전거를 대여한 수)
- count - number of total rentals (자전거 대여 총 수)
season의 경우 데이터를 탐색하다가 오류가 있어 수정했다.
그래프를 보면 season이 1인 경우는 1~3월, 2인 경우는 4~6월, 3인 경우는 7~9월, 4인 경우는 10~12월이다.
1 = winter, 2 = spring, 3 = summer, 4 = fall 라고 정정하기는 했지만 뚜렷하게 계절감이 드러나게 범주화하지는 않은 듯하므로 month를 범주화한 정도로만 생각하면 될 듯하다.
weather의 경우 1에서 4로 갈수록 날씨가 안좋은 방향으로 생각하면 될 듯하다.
데이터셋 불러오기
데이터 탐색
info()
10886개의 행과 12개의 열로 구성되어있으며 결측값은 없으므로 따로 결측값 처리할 일은 할 필요없다.
datetime이 object 형태로 되어있다. 이를 datetime형식으로 변환해야함을 확인한다.
season, holiday, workingday, weather의 경우 라벨 인코딩된 범주형 feature으로 int형식으로 된 것을 확인할 수 있다.
그러므로 추후 순서가 반영된 것을 없애기 위해 원-핫인코딩을 해야한다고 염두에 둔다.
나머지 숫자형 데이터로는 temp, atemp, humidity, windspeed, casual, registered, count이 있다.
describe()
datetime 컬럼 처리
datetime에서 년도, 월, 일, 시간을 추출 한다.
이를 위해서는 dt연산자를 이용해서 날짜 요소를 추출하는 방법이 있고
apply를 이용해서 각 행마다 lambda함수를 활용해서 날짜요소를 추출하는 방법도 있다.
필요없는 컬럼은 삭제해준다.
casual, registered는 총 대여건수인 count를 세부적으로 나눈 것이므로 자전거 대여의 예약여부는 해당 모델에서 크게 상관없는 것으로 판단하여 삭제한다.
datetime의 경우 year, month, day, hour 과 같이 날짜 요소를 추출했으므로 중복되는 datetime은 삭제해준다.
시각화
seaborn countplot
먼저 seaborn의 countplot을 사용하여 각 범주형 변수들의 인자별 빈도수를 시각화한 그래프이다.
범주형 데이터의 인자별 빈도가 크게 차이나는 feature는 weather, holiday, workingday이다.
weather : 1 > 2 > 3 > 4 순으로 빈도가 높으며 날씨가 좋은날일수록 데이터가 많고 매우 안좋은 날은 거의 0에 가까울정도로 적은 데이터를 갖고 있음을 확인할 수 있다.
holiday : 공휴일이 아닌 날이 더 많은 것을 알 수 있다.
workingday : 일하는 날이 일하지 않는 날보다 절반이상 많은 것을 확인할 수 있다.
seaborn barplot
- year : 2011년보다 2012년도에 자전거 대여 수요량이 더 많음
- month : 겨울에 가장 자전거 대여 수요량이 낮고 날이 따뜻해질수록 자전거 대여량이 늘어나는 것을 볼 수 있다. 그러다가 날이 다시 추워지는 11월부터 다시 자전거 대여 수요량이 낮아지는 것을 확인할 수 있다.이는 season을 통해 더 자세히 계절에 따른 자전거 대여 수요량의 변화를 확인할 수 있다.
- day : 일의 경우 자전거 수요량에 크게 차이가 나지 않은 것을 확인할 수 있다.(뚜렷하게 찾을 만한 특징은 없다)
- hour : 0시 ~ 6시까지의 새벽시간대에 가장 뚜렷하게 자전거 대여량이 적으며 아침 8시, 오후 5시,6시에 급격하게 자전거 대여량이 늘어나는 것을 보아 출퇴근 시간대에 자전거 대여량이 많음을 알 수 있다.
- season : 1 > 4 > 2 > 3 순으로 자전거 대여 수요량이 낮은 것을 확인할 수 있다.이는 1~3월, 다음으로는 10~12월에 순으로 자전거 대여량이 적은 것을 보아 날씨가 추울 수록 자전거 대여량이 적은 것을 알 수 있다.
- weather : 1 > 2 > 4 > 3 순으로 기본적으로 날씨가 좋은 날에 자전거 대여량이 많다. 특이한 점은 날씨가 매우 안좋은 4가 날씨가 덜 안좋은 3에 비해 자전거 대여량이 많은 것이다.
- holiday : 휴일인 날과 휴일이 아닌 날은 자전거 대여 수요량에 큰 차이는 없었지만 휴일이 아닌 날이 휴일인 날에 비해 훨씬 많은 것을 고려하면 상대적으로 적은 휴일인 날에 자전거 대여량이 많은 것을 알 수 있다.
- workingday : 일하는 날과 아닌 날에도 자전거 대여 수요량에는 큰 차이가 없지만 일하는 날이 쉬는 날에 비해 훨씬 많은 것을 고려하면 상대적으로 적은 쉬는 날에 자전거 대여량이 많은 것을 알 수 있다.
seaborn boxplot
모델 학습 / 평가
MSE는 오차에 제곱을 한 값으로 원래의 데이터보다 단위가 크므로 실제 오차의 크기를 직관적으로 파악하기 어렵다는 단점이 있다. 그래서 루트를 씌운 RMSE를 통해 원래의 데이터 단위로 환원하여 해석이 쉬워진다는 장점이 있다.
RMSLE는 실제값과 예측값을 로그변환한 후 RMSE를 해준 값이다. 로그변환으로 인해 outlier에 덜 민감하다는 장점이 있으며 예측값이 실제값보다 작을 때 더 큰 패널티를 부여한다는 특징이 있다.
MSE, MAE는 함수로 제공하지만 RMSE, RMAE는 따로 함수로 제공하지 않기 때문에 따로 sqrt한 함수를 정의해준다.
원-핫 인코딩, 스케일링 없이 기본 전처리만 진행한 후 모델을 학습한 후 성능을 평가해보았을 때의 성능 평가 지표는 다음과 같이 나왔다.
하지만 비교 대상 없이 하나의 평가지표만을 가지고는 좋은 성능의 모델인지 판단하기 어렵다.
그러므로 실제로 예측값과 실제값을 비교해보면서 얼마나 잘 예측했는지를 확인해보자.
실제값, 예측값 비교
실제값을 real_count, 예측값을 predicted_count , 실제값과 예측값의 차이의 절대값을 diff에 넣어 result_df라는 데이터프레임을 만들어 예측값과 실제값의 차이인 diff의 값이 가장 큰 순서대로 top n개를 출력하는 함수를 정의해보았다.
위 결과값은 diff가 가장 큰 순서대로 top5개까지 출력해보았다.
그 결과 가장 예측에 실패했을 경우 실제값과 예측값의 차이가 568로 거의 예측을 못하는 수준의 결과임을 확인할 수 있었다. 결론적으로 현재까지의 과정으로는 모델을 학습하기 아직 이르고 추가적인 튜닝을 거쳐야한다는 것을 알 수 있다.
스케일링
이를 위해 앞에서 살펴봤던 데이터의 describe를 보면 target값인 count의 경우 min, max를 보면
다른 컬럼들은 약 1~100까지의 범위를 가지는 것에 비해 약 1~1000까지로 범위가 매우 큰 것을 볼 수 있다.
target변수의 스케일링이 필요해보인다.
이처럼 회귀모델의 경우 종종 Target변수를 스케일링을 해줘야할 때가 생긴다.
타겟 변수를 스케일링해야 하는 경우
▶ Target 값의 범위가 매우 클 때 :
위 경우와 같이 target값의 범위가 다른 값들에 비해 너무 클 경우 큰 값이 모델에 의해 과대적합될 가능성이 있다.
▶ 타겟 값의 크기에 민감한 Linear Regression, Lasso, Ridge와 같은 모델의 경우 :
이러한 모델들은 가중치를 최적화할 때 target 값이 너무 크면 과도한 가중치를 학습할 수 있다.
▶ MSE 손실함수를 사용하는 경우 :
MSE는 오차에 제곱을 한 값이라 target 값이 크면 손실 함수 값이 매우 커질 수 있다.
▶ 다른 특성(Features)들과 타겟 값의 크기 차이가 클 때 :
위 경우와 같이 target 변수가 다른 feature에 비해 매우 큰 값을 가질 경우, 모델이 다른 특성을 적절히 학습하지 못할 수 있다.
target값의 분포
target변수의 분포도를 보면 x값이 증가할수록 기하급수적으로 감소하는 경향을 보인다. 즉, 한쪽으로 많이 skewed된 모습 을 볼 수 있는데 이럴 경우 log변환을 통해 skewed된 분포를 어느정도 완화하여 정규분포의 모습으로 정규화를 할 수 있다.
log변환
log변환을 하고난 후 어느정도 정규분포의 형태를 띄는 것을 확인할 수 있다.
모델 학습 / 평가
target값이 count를 로그 변환한 후 다시 모델을 학습하고 평가를 진행해보자.
여기서 주의할 점은 로그 변환한 경우 모델을 학습한 후 평가를 진행하기 전 다시 지수 변환을 통해 원래의 scale로 변환해주는 작업이 필요하다.
(로그함수의 역함수는 지수함수..)
성능 결과를 확인해봤을 때 RMSLE의 경우 값이 더 내려갔지만 RMSE, MAE의 경우는 더 큰 값을 갖는다.
스케일링을 적용했지만 더 나은 성능을 보인다고 하기 어려웠다.
원-핫 인코딩
이를 위해 다시 데이터프레임을 살펴보았다.
데이터프레임을 살펴보았을 때 year이나 humidity같은 경우 다른 데이터들에 비해 scale이 굉장히 크다.
각 feature별로 회귀계수 시각화
Linear Regression 모델의 회귀계수를 내림차순으로 정렬하여 seaborn의 barplot을 이용해 시각화해보았다.
다중선형회귀모델에서 회귀계수가 크다는 것은 해당 독립변수가 종속변수에 미치는 영향이 크다는 것을 뜻한다. 즉, 위 그래프에서 볼 수 있다시피 year값의 경우 해당 feature가 모델에 과하게 영향을 미치고 있다는 뜻인데 year와 같이 년도를 의미하는 feature가 모델에 과하게 영향을 미치는 것이 이상하지 않는가..!
year의 값이 다른 feature에 비해 큰 값을 가지므로 종속변수에 가장 영향을 많이 미치는 것으로 파악할 수 있다.
이러한 경우 표준화,정규화를 통해 스케일링하거나 원-핫 인코딩을 통해 0,1로 범주화하는 방법이 있다.
year의 경우 2011년, 2012년 2가지도 범주화된 범주형이다. 그외에도 month, day, hour, weather, season 등 범주형 컬럼들은 원-핫 인코딩을 진행하고 나머지 temp, atemp, weendspeed, humidity 등 숫자형 컬럼들은 standardScaler를 진행할 예정이다.
MinMaxscaler
숫자형 데이터를 MinMaxscaler 모듈을 통해 정규화를 진행한다.
머신러닝에서는 학습에 사용할 feature들이 비슷한 영향력을 갖도록 MinMaxscaler를 통해 범위를 [0,1]로 비슷하게 맞춰는 작업이 필요하다. 특히 다중선형회귀에서의 여러 feature들의 값의 범위 차이가 많이 날 경우 feature들의 영향력이 공정하지 않아 모델의 성능에 영향을 준다.
One-Hot Encode
get_dummies()를 이용해서 다음 범주형 컬럼들을 원-핫 인코딩을 진행해준다.
데이터셋 분할
학습데이터셋 70%, 테스트데이터셋 30%으로 분리한다.
'Azure 실습 > Azure machine learning' 카테고리의 다른 글
Python ML 실습 [와인 분류 - 분류 모델] (0) | 2024.10.17 |
---|---|
Azure ML Designer 실습 [군집 모델] (0) | 2024.10.11 |
Azure ML Designer 실습 2 [자전거 대여 수요 예측 - 회귀 모델] (0) | 2024.10.10 |
Azure ML Designer 실습 [로켓 발사 여부 예측 - 분류 모델] (0) | 2024.10.08 |