타이타닉 프로젝트에서 남의 노트북을 배껴서 답안을 제출해 본 다음 내가 처음으로 선택해서 분석해 본 두 번째 프로젝트였다. 사이킷런을 적용해 본다는 재미도 있었지만 역시나 아직 내공이 부족한 상태에서 단순히 알고리즘을 적용해 보는 것만으로는 정확도를 80% 이상 얻어내는 것이 어려웠다.
아래 내용에서 내가 두 번째 프로젝트의 정확도를 80% 이상으로 끌어올리기 위해 시도해 본 방법들을 소개한다.
한편 어떤 방법을 사용할 것인가에 못지않게 중요한 것이 어떻게 평가할 것인가인데 실수값을 예측하는 회귀 문제의 경우 실제값과 예측값의 차이를 평균절대오차(Mean Absolute Error, MAE)나 평균제곱오차(Mean Square Error, MSE), 평균제곱근오차(Root Mean Square Error, RMSE) 등으로 평가할 수 있다.
특히 실제값과 예측값 차이를 제곱하고 이를 평균한 MSE는 오차가 제곱되는 만큼 이상치에 민감할수 있는데 그결과값에 대한 해석이 값이 작을수록 좋은 것이라는 알고리즘 간 상대적 평가만 가능하지 그래서 이 수치가 얼마나 좋은 모델인가에 대한 절대적인 기준에서 해석하기 어려운 것이 사실이다... 그래서 일단 이번 프로젝트에서는 평가기준을 좀 더 직관적으로 와닿기 쉬운 MAE를 그대로 사용하기로 했다.
수치형 데이터를 예측할 때 머신러닝 지도학습 가운데 회귀 알고리즘을 사용하는데 앞서 사용한 의사결정나무, 랜덤 포레스트, XGBoost 회귀에 이어 선형회귀 알고리즘을 적용해 보기로 했다. 선형회귀 알고리즘은 간단히 말하면 데이터에 가장 잘 맞는 선(line) 혹은 선형 방정식을 찾는 것이다.
역시 사이킷런의 선형회귀 알고리즘을 불러와 트레이닝 데이터를 훈련하고 테스트 데이터로 예측해 테스트 데이터의 실제값과 오차를 확인해 보자. 사이킷런의 선형회귀 알고리즘은 최적화해 볼만한 하이퍼 파라미터가 단순한데 선형 방정식에 상수항을 넣을 것인지 말 것인지를 나타내는 fit_intercept와 알고리즘 자체로 입력값을 스케일링할 수 있는 normalize 정도가 있다.
리니어 리그레션 알고리즘을 적용한 결과
선형 회귀를 적용한 결과 MAE가 2,105로 랜덤 포레스트을 적용했을 때 나온 베스트 결과인 1,516보다 오차가 크다. 앞서 사용한 알고리즘들과 함께 선형회귀 알고리즘도 포함해 LTV 이상치 처리, 종속변수 LTV 스케일링, 앙상블을 적용해 테스팅 해보았다.
2) LTV 아웃라이어 제거
예측 목표가 되는 LTV값 자체를 씨본 라이브러리를 활용해 살펴보면 LTV가 2만 달러 이하에 집중적으로 분포되어 있고 사분범위의 최대값(16,414)을 벗어나는 이상치 데이터가 많음을 알 수 있었다. 이상치 데이터는 819개로 전체 데이터의 약 10%에 해당한다.
데이터의 도메인 영역에 따라 획득할 수 있는 데이터의 값과 성격이 다르기 때문에 이상치를 처리하는 절대적인 기준은 없다고 하는데 그렇다면 과연 이 10% 데이터를 제거하는 게 적절할까? 이상치 데이터만 모아서 보면 원본 데이터에 비해 LTV 평균 자체는 8,000에서 25,573으로 훌쩍 높아졌지만 독립변수들 가운데 상관관계가 있었던 Monthly Premium Auto와 Total Claim Amount 등 금액과 관련된 항목의 평균이 살짝 높아졌을 뿐 보험가입 기간이나 보험개수, 컴플레인 수 등에 있어 별 다른 차이는 없었다.
해당 데이터만으로는 LTV가 왜 그렇게 높은 지 별다른 이유가 없어 보인다. 그렇다면 이상치 데이터 819개를 제거한 데이터에 의사결정나무, 랜덤포레스트, XGBoost, 선형회귀 4개 알고리즘을 모두 적용해 보자. 그 결과 랜덤포레스트 모델이 MAE가 약 362로 가장 낮으며 이는 이상치 제거 후 새로운 LTV 평균인 6,279달러의 약 5%에 해당하는 오차이다.
이상치를 제거한 후 베스트모델(랜덤포레스트)의 실제값과 예측값 분포
3) 종속변수인 LTV값 스케일링
스케일링은 데이터가 한 쪽으로 심하게 치우친 분포를 보이거나 컬럼 항목의 데이터 값들이 서로 크기가 달라 회귀 모델에 영향을 줄 수 있을 때 이러한 분포나 값의 크기의 영향을 줄이기 위해 사용하는 방법이다. 일반적으로 스케일링은 독립변수들에 대해 사용하는데 문제는 종속변수인 LTV 값의 분포가 심하게 한 쪽으로 치우친 경우 스케일링을 사용할 수 있을까하는 것이다.
예측 목표가 되는 LTV 값 자체를 스케일링 처리를 하게 되면 예측값이 아주 작거나 크게 나올 것이기 때문이다. 일단 LTV에 로그함수를 사용해 한 쪽으로 치우친 분포를 개선하고 이를 활용해 트레이닝하고 여기서 나온 값에 다시 반대가 되는 지수함수 처리를 함으로써 LTV 예측값을 만들고 실제값과 오차를 계산해보자.
원래 LTV 분포 vs. 로그변환 처리 후 LTV 분포
이렇게 모델링을 하니 4개 모델 모두 MAE가 약 7000정도로 지수함수를 잘못 쓴 건지? 방법이 잘못된 것인지 오차가 이전보다 훨씬 더 커졌다..
4) 앙상블(보팅)
앙상블은 기본적으로 하나의 모델을 사용하는 것보다 여러 개 모델을 조합해 사용할 때 조금 더 신뢰성 높은 결과를 얻을 수 있다는 생각에서 출발한 방법이다. 앞서 나온 랜덤 포레스트나 XGBoost가 바로 의사결정나무를 앙상블 기법으로 사용한 모델이라 할 수 있다.
앙상블 기법은 그 방법에 따라 배깅(Baggin), 부스팅(Boosting), 그리고 보팅으로 나눌 수 있는데 배깅이나 부스팅이 같은 알고리즘(학습기)를 여러 번 사용해 결과를 얻어내는 방식인 반면, 보팅은 서로 다른 알고리즘의 결과를 결합함으로써 결과를 보완하는 방식이다.
보팅이 최적의 결과를 얻어내는 방식은 다수의 학습기가 결정한 예측값을 최종값으로 하는, 즉 다수결 방식인 하드보팅과 학습기들의 각 레이블값 결정 확률을 평균한 뒤 가장 확률이 높은 레이블 값을 최종값으로 하는 소프트보팅 방식이 있다. 분류 문제일 경우 이렇고, 예측하는 값이 회귀 모델의 경우에는 각 학습기의 예측값을 평균하게 된다.
그렇다면 선형회귀, 의사결정나무, 랜덤포레스트, XGBoost를 모두 적용해 보팅 방식으로 예측을 해보자. 예측결과는 (실망스럽게도) 1,645로 LTV 이상치를 제거하지 않은 상태에서 랜덤 포레스트의 오차가 1,516로 가장 작았는데 보팅 방법을 써도 이보다 나아지지는 않았다.
결과적으로 현재로써 모델의 정확도를 높이는 가장 좋은 방법은 이상치 데이터를 제거하는 것이였다. 아직은 머신러닝을 시작한 지 얼마 되지 않아 부족한 것도 많고 답답한 것도 많지만 개별 알고리즘에 대한 공부와 사이킷런의 세부 기능 등에 대해 계속해서 공부하고 포스팅 해나갈 예정이다.