22.11.07.
먼저 kaggle titanic 데이터를 GridSearch와 RandomizedSearch까지 마무리 했다.
그 후, bike sharing 데이터를 통해 회귀 예측을 해보기 위한 과정을 시작했다.
결과 attribute
Bestestimator : 어떤 분류기가 가장 좋은 성능을 내는지 알려준다.
Bestscore : 가장 좋은 성능을 낸 점수를 알려준다.
Cvresults : (cross validation의) 전체 report를 출력해준다. 어떤 조각이 어떤 성능을 냈는지를 알려준다.
hold-out validation과의 차이
hold-out validation? 하나의 test-set을 만들어 검증하는 것. 평상시에 하듯 데이터를 train set과 test set으로 나누는 것!
hold-out-validation 은 한번만 나눠서 학습하고 검증하기 때문에 빠르다는 장점이 있다. 하지만 신뢰가 떨어진다는 단점이 있다. hold-out-validation 은 당장 비즈니스에 적용해야 하는 문제에 빠르게 검증해보고 적용해 보기에 좋다고 한다!
EDA 과정 중
전처리 과정 중
이상치 및 결측치 처리
그래프를 잘 그려보고 잘 파악하자. 이런 경우 오류 데이터라고 파악할 수 있겠다.
windspeed에 따른 대여 횟수의 scatterplot이다. 당연히 바람이 세게 불면 자전거를 빌리는 사람이 적을 것이라고 생각했고, 그래프를 보면, 바람이 세질수록, 대여 횟수의 최댓값이 작아지는 것은 확연하게 확인할 수 있다.
그러나, 점 하나하나가 데이터임을 명심하고 살펴보면, 풍속이 느리지만 자전거의 대여 횟수가 적은 데이터도 매우 많이 존재한다. 상관관계가 우리가 생각하던 대로 나오지 않은 것.
따라서 regplot을 그려보면 다음과 같은 형태다.
혹시 0으로 표시되어있는 결측치 때문인가 하여 결측치를 제거하고도 그려보았다.
wind_test = train.copy()
wind_test = wind_test.drop(wind_test[wind_test['windspeed'] == 0].index)
sns.regplot(data = wind_test, x='windspeed', y='count')
그래도 같다. 우리가 생각하던 경향과는 완전히 다른 추세선을 보이고 있다. 맨 위의 값들만 있으면 모르겠는데, 그 밑의 값들이 많이 존재하여 회귀선이 우리 생각과 다르게 나온다.
지금 우리가 사용하고 있는 RandomForestRegressor가 선형회귀 모델을 제작한다면, 저 regplot의 라인의 기울기가 windspeed에 대한 기울기(계수)가 되는 것 아닌가? 그렇다면 오히려 windspeed는 피쳐에서 제외하는게 맞는 것 아닌가? 아 너무 헷갈린다. 모르겠다.
그래서 feature에서 windspeed만 빼고 돌려봤다. 그리고 제출까지 해보았다.
0.002점 좋아진다.. 흠...
! 근데 지금 생각해보면, 결국 그래프가 저렇게 나왔다는 건, 바람이 세게 불면 사람들이 적게 빌리는 것은 맞지만, 바람이 적게 분다고 많이 빌리지도 않는다는 것!
바람이 세게 불면 대여가 줄어들기야 하겠지만, 그렇다고 해서 바람의 세기와 대여횟수 사이엔 상관관계가 없다는 것! 실제로 windspeed와 count 사이의 pearson 상관계수를 구해보면, 0.101369라는 작은 값이 나온다.
내가 생각했던 가설과 다르다고 해서 그냥 의미 없는 고민을 한 거구나! 데이터를 그대로 보지 않고 그냥 내 생각과 다르다고 이게 잘못되었다고 생각한건가? 그래프를 보던 상관계수를 보던 바람세기와 대여횟수의 관계는 바람이 셀수록 대여가 주는 것이 아니다! 내 상식과 내 마음대로 데이터를 곡해해서 해석하지 말아야겠다.
결론은 저걸 받아들이고, feature로 사용할지 안할지를 잘 선택하면 되겠다!
그럼 차라리 지난번에 한번 했던 것 처럼, 풍속이 몇 이상인지 아닌지를 0과 1로 구분해주는 컬럼을 만드는 건?
날씨에 따른 대여 수를 살펴보았다.
sns.barplot(data= train, x='weather', y='count',ci=None)
1~4로 갈수록 날씨가 좋지 않은 것인데, 날씨가 폭우 또는 폭설을 의미하는 4일때가 3일때보다 평균 대여수가 많다.
그래서 날씨가 4인 날을 살펴봤더니, 딱 하루, 그것도 딱 한시간이다.
따라서 평균 대여수가 날씨가 3인 날보다 더 많은 것이라고 예측해볼 수 있다.
그러면 여기서 남는 의문은, 과연 이 날씨가 4일때의 데이터를, 학습에 사용하는것이 맞는가..? 라는 의문이 남는다. 잘못된 일반화와 학습이 진행되는 건 아닐까..!
결론은 나지 않았지만, 지금 생각하기엔 ordinal encoding으로 되어있기에, 1~3까지의 경향이 충분히 반영된다면 4일때의 데이터를 빼고 학습시켜도 되지 않을까? 잘은 모르겠다..
월별 대여수의 그래프를 살펴보았다.
sns.barplot(data = train, x='month', y='count')
나름 의미있는 데이터인것 같아 보인다.
그러나, 년도에 따라 색상이 나누어지게 하여 살펴보았다.
sns.barplot(data = train, x='month', y='count', hue ='year')
년도에 따라서 월별 대여수가 너무 차이가 많이 난다. 2012년이 2011년에 비해 확연히 많다. 심지어는 2011년의 12월 데이터와 2012년의 1월 데이터가 유사하다.
즉, 같은 달인데에도 연도에 따라 값이 차이가 많이 나기 때문에 오히려 성능을 저하시킬 수 있다. 따라서 피쳐에서 제외해주는 것이 좋다.
월별 경향은 분명히 존재하는 것 같으니, 이를 사용하고 싶다면 연-월 이라는 피쳐를 만들어 사용하는 방법도 있겠다. 약간 태블로에서의 불연속형 월과 연속형 월의 차이같은 느낌!
Day를 살펴보면, train 데이터에는 1일부터 19일까지, test 데이터에는 20일부터 의 데이터만 존재한다. 따라서 day를 피쳐로 사용해 학습을 해봤자 그다지 도움이 되지 않는다는 것을 알 수 있고, 피쳐에서 제외해준다.
그리고 이는 train 과 test set을 day를 기준으로 나누었음을 짐작할 수 있게 해준다!
나는 사실 day는 뭐 크게 영향이 없을 것 같아 피쳐에서 제외했고, month는 season과 어느정도 겹치는 부분 아닌가 해서 제외했는데.. 우연히 제거해야하는 것들을 제거한 셈..!
오늘의 가장 어려웠던 것..!
abs(y_train - y_valid_pred).mean()
from sklearn.metrics import mean_absolute_error
mean_absolute_error(y_train, y_valid_pred)
((y_train - y_valid_pred) ** 2).mean()
from sklearn.metrics import mean_squared_error
mean_squared_error(y_train, y_valid_pred)
np.sqrt(((y_train - y_valid_pred) ** 2).mean())
((np.log1p(y_train) - np.log1p(y_valid_pred)) ** 2).mean() ** 0.5
# log1p는 1을 더한 후 로그를 취해주는 함수
# 또는
from sklearn.metrics import mean_squared_log_error
rmsle = np.sqrt(mean_squared_log_error(y_train, y_valid_pred))
rmsle
RSME와 유사하나, 실제값과 예측값 대신 해당 값들에 1을 더하고 로그를 취한 값을 사용.
1을 더해주는 이유?
로그 함수의 그래프. x 가 1보다 작으면 로그 값이 음수가 나온다. 따라서 1을 더해서 로그를 씌운 결과가 음의 무한대로 발산하는 것을 방지!
라고 하는데, 솔직히 바로 납득은 안간다. 좀 더 써보고 공부해봐야 왜 로그를 씌워서 사용하는지 알 것 같다.
4번은 사실 수업들으면서 헷갈렸던 부분이라 확실하지는 않다. 큰 값과 작은 값의 기준도 모호하긴 하고, 그래도 일단은 이런 식으로 알고 있으면 될 것 같다.
RMSLE는 log 기반이므로 수치가 작은 값들에 대해 더 크게 나타나는 효과를 가진다.
약간 결은 다르지만,
위에서 MSE는 잔차의 제곱으로 나타내므로, 실제값과 예측값의 차가 큰 값에 대해 더 크게 나타나는 효과를 가졌었다. RMSE도 당연히 마찬가지고!
MAE는 절댓값을 이용하므로 값의 크기에 따른 가중치가 없다!
RMSLE는 다른 오차들과는 다르게 상대적 오차((실제값 + 1) / (예측값 + 1)) 를 나타내기 때문에, 잔차(실제값 - 예측값)의 크기에 따른 가중치는 특정할 수 없겠다. 그것보다는 값들 자체의 절대적인 수치가 작을때 RMSLE가 커진다고 받아들였다.
오늘의 결론 :
EDA를 정말 꼼꼼히 잘 해보는게 머신러닝에 있어서 아주 중요함을 느낀 하루.
기타
더 공부해볼 것
참고자료.
요즘 항상 너무 늦게 시작해서, 시간이 없다는 핑계로 자세히 공부 안하고 넘어가는데...
반성하자!
회귀의 평가지표에 대한 자세한 내용을 더 공부해보고 싶다. 자료가 별로 없나..? 통계학 쪽인가..?
결측치와 이상치 처리를 어떻게 해봐야 할 지도 생각해봐야겠고
어떤 피쳐를 사용하는게 옳은지에 대한 판단도 더 연습해봐야 한다!
그리고 아까도 생각했지만, 정리 하나하나에 매몰되지 말고, 오늘 수업 전체의 흐름을 생각하자!
다시 전체 한번 훑어보고 머릿속으로 정리하고 자자.
학교 원드라이브 계정이 변경된다고 그러더니, 동기화 오류가 났다. 필기 날라가진 않겠지?..