관리 메뉴

TEAM EDA

[Kaggle] House Prices: Advanced Regression Techniques 본문

EDA Project/해외 공모전

[Kaggle] House Prices: Advanced Regression Techniques

김현우 2018. 11. 27. 08:38

이번 EDA 2기 첫 프로젝트로 진행했던 kaggle의 House Prices: Advanced Regression Techniques(https://www.kaggle.com/c/house-prices-advanced-regression-techniques)에 대한 분석 보고서입니다. 추가적으로 해당 내용에 대해 결측치 처리와 모델의 변수 중요도에 대한 해석이 들어간 자료는 [Kaggle] House Prices: Advanced Regression Techniques(2)를 참고하시기 바랍니다. 

 

 

집의 가격을 예측하는 문제로 사용한 모델은 ridge,lasso, Elastic Net, LightGBM, Xgboost입니다. 최종적으로 성적을 올리기위해 다른 사람들의 결과물을 반영해 추가적으로 앙생블을 해주었고 그 결과 12등으로 4311명 중에서 상위 1%이었습니다. 

 

대략적인 진행 과정은 아래와 같습니다. EDA를 통해서 의미있는 정보를 살펴보고, 전처리를 합니다. 그리고 변수들간의 관계를 이용해서 Feature Engineering을 해주고 각 모델의 가정에 맞게 모델들을 만들어 줍니다. 그리고 마지막에 kernel에 올라온 결과물들을 추가해서 Ensemble을 해줌으로서 최종 결과물을 만들어줍니다.

 

 

 

 

분석보고서이긴 하지만 대회의 특성 상 성적을 올리는 부분에 치중해있어서 이상치의 제거나 전처리과정에서 합리성이 떨어지는 부분이 있을 것입니다. 그러한 부분은 댓글로 추후 보고서 쓸 때 참고할 수 있도록 조언부탁드립니다.

 


 

1. 탐색적 데이터 분석(EDA)

 

1-1. 대회 목적

 

대회의 목적부터 살펴 보겠습니다. 대회의 목적은 집값을 정확하게 예측하는 것으로 평가기준으로 RMSLE를 사용합니다. 

 

 

RMSLE는 예측값과 실제값에 로그를 씌운후에 차이를 비교하는 방법입니다. RMSE를 사용하지 않고 Log를 씌우는 이유는 목적변수 집값의 범위가 넓어서 입니다. 

 

1-2. 변수 탐색

 

분석에 앞서서 가벼운 데이터 탐색 과정을 통해서 추후 어떠한 방향으로 분석을 진행해야할지 가이드 라인을 정해보도록 하겠습니다.

 

 

[그림1]을 보면 Train과 Test의 Shape는 각각 (1460, 81) , (1459,80)으로 생각보다 데이터가 크지는 않았습니다. 하지만 변수의 수가 많고 Train과 Test의 사이즈가 비슷하다 보니 적절한 Cross Validation전략과 Feature Selection을 하는 게 중요 해 보입니다.  

 

[그림2]를 보면 변수의 형태가 Object가 53%로 가장 많은것을 볼 수 있습니다. 그래서 적절한 Encoding 기법을 선택하는것이 이번 대회의 핵심포인트 중 하나라는것을 생각할 수 있습니다. 

 

변수의 형태를 좀 더 세부적으로 살펴보겠습니다. 이 과정에서는 3가지를 중점으로 변수를 살펴봤습니다. 

 

    1. 변수의 정의는 무엇인지
    2. 변수의 value는 무엇을 가지는지 
    3. 변수의 Unique value는 몇개인지 

이를 정리하여 엑셀파일로 정리한게 아래의 [표1]입니다. (첨부자료 Excel파일의 sheet1을 보시면 됩니다.)

 

이런 과정을 통해 확인할 수 있었던 점 두가지였습니다. 

 

    1. [표1]의 NA설명처럼 변수의 NA가 None을 의미하는 변수들이 존재한다.
    2. 아래의 [그림3] 원그래프처럼 int형 자료에 categorical변수가 섞여 있었고, 그 중에서도 순서를 가지는 Ordinal한 변수가 20개이다.

 

 

이를 통해 위에서 봤던 Object변수들 뿐만 아니라 추가적으로 Categorical변수들에 대해서도 적절한 전처리를 해줘야하고, None을 의미하는 결측치와 그렇지 않은 결측치를 분류해서 채워넣어야 하는 점을 고려하고 있어야합니다.

 

1-3. 시각화 - 반응 변수(SalePrice)

 

이제 각각의 변수들에 대해서 살펴보겠습니다. 먼저 Target Value인 집 값부터 보면 아래 [그림4], [표2]와 같습니다.

 

 

주목할 만한 점은 두가지였습니다.

 

    1. [그림4]를 보면 왼쪽으로 치우쳐져있는 분포를 나타낸다.
    2. [그림4]와 [표2]에서 참고할 수 있듯이 첨도와 왜도가 높다.

1-3. 시각화 - 수치형 변수들

 

다음으로는 SalePrice와 관련있는 변수들을 살펴보도록 하겠습니다. 

 

 

왼쪽의 그림처럼 SalePrice와 상관관계가 가장 높은 변수들을 뽑고, 그 순서대로 변수의 탐색을 진행하겠습니다. 여기서 주의할 점은 Pearson 상관관계가 아니라 Spearman 상관관계를 이용했는데, 그 이유는 Ordinal한 변수들도 숨어있기 때문입니다. Spearman은 아래의 그림처럼 선형회귀를 통해서 상관값을 구하는게 아니라 같이 증가하는지 감소하는지 여부를 통해서 값을 계산합니다. 그렇게에 Categorical한 변수에 대해서도 사용할 수 있습니다.

 

 

 

이를 위해 Object에서도 Ordinal한 변수들은 라벨인코딩을 진행하고 상관관계표를 만들었습니다. 물론 이렇게 하면 음수의 상관관계는 알 수 없어서 상관관계 값에 절댓값을 씌우고 진행했습니다.

 

 

먼저 [그림6]부터 살펴보겠습니다. OverallQual의 경우 집의 전반적인 가치를 의미하는 변수입니다. 가치가 높아지면 집의 가격이 높아지는것은 당연한 수순으로 상관관계 또한 0.79로 매우 높습니다. 하지만 위의 Boxplot을 보면 빨간색으로 표시한 부분은 그 정도가 너무 높거나 낮습니다. 이러한 부분은 기록해두었다가 확인해봐야 합니다. [그림7]의 GrLivArea는 거실의 크기가 얼마나 되는지를 의미하는 변수 입니다. 하지만 빨간색 상자에 감쌓여진 두개의 점은 거실의 크기가 제일 큼에도 불구하고 가격은 낮은것을 봐서는 무슨 특별한 이유가 있을 것 입니다. 

 

 

 

[그림8]의 GarageCars는 눈에 띄게 4의 값이 이상하게 느껴집니다. 하지만 위에서 봤던 이상치와는 다르게 4값 자체가 낮은걸로 봐서 특별한 이유가 있을 것으로 생각할 수 있습니다. 예를 들어서, 시골이어서 차를 수용할 공간이 많다든지 숙박업 같은 집이어서 차를 수용 할 공간이 많이 필요하다든지로 생각할 수 있습니다.

 

[그림9]의 경우 지어진 년도에 따른 SalePrice의 가격입니다. 대체적으로 선형성을 띄지만, 2000년 이후 최근에 지어진 집은 가격의 편차가 크고 1900년도 이전에 지어진 집은 이상치가 보입니다. YaerBuilt와 연관 된 변수인 Remodeling같은 변수가 존재하는걸로 봐서는 이상치들은 리모델링이 되어서 가격이 기존에 비해 비싸거나 한옥같이 특별한 집이어서 비쌀 수도 있습니다.

 

 

 

[그림10]의 GarageArea는 차고의 넓이를 의미하는데, GarageArea가 매우 큼에도 SalePrice가 낮은 부분이 있고, 중간임에도 SalePrice가 높은 부분이 있습니다. 아마 노란색 박스부분은 이상치로 생각되어지고, GarageArea가 큰 부분은 애초에 집의 크기가 넓든지 시골이 든지 하는 의미가 있을 것 같습니다. 

 

[그림11]의 FullBath는 완전한 욕실의 갯수를 의미합니다. 완전한 욕실이라고 말한 이유는 변수중에 HalfBath같이 반쪽짜리 욕실도 있기 때문입니다. 그렇기 때문에 FullBath가 0이어도 HalfBath같은 다른 변수들에 의해 FullBath가 0임에도 다른 값들보다 크게 나타났을거로 예상되어 집니다.

 

 

 

[그림12]는 TotalBsmtSF는 Basement Area의 square feet를 표시 한 값입니다. 재밌는것은 선형성을 띄고 있지만, 노란색 박스로 친 basement Area가 없는 부분이 보입니다. 

 

[그림13]은 [그림12]와 굉장히 유사한 모습을 보입니다. 이상치의 부분도 비슷한 위치에 있고, 위의 [그림10]GarageArea의 Scatter plot에서 봤던 크기가 큼에도 불구하고 가격이 낮은 이상치가 [그림12]와 [그림13]에서도 동일하게 나타는것을 확인할 수 있습니다.

 

1-3. 시각화 - 범주형 변수들

 

다음으로는 수치형데이터가 아닌 범주형데이터의 시각화 모습입니다. 아래에는 6개의 그림만 모습을 나타냈지만 실제로는 모습 범주형 데이터에 대해 시각화를 하고 아래와 같은 인사이트를 얻었습니다.

 

 

 

    1. Neighborhood, Condition1, Condition2와 같은 변수들은 각각의 값들끼리 중앙값의 차이가 크다. 
    2. Condition1과 Condition2를 보면 Normal의 편차가 굉장히 큰게 이를 더 세분화 시킬 수 없을까 고민. 
    3. Neighborhood를 보면 다른 범주형 변수들에 비해 이상치가 생기면 심하게 생기는 것을 확인할 수 있음. 왜 이렇게 생겼는지, 어떻게 대처해야할지 고민.

 

 

1-4. 결측치 확인

 

결측치를 확인 한 부분입니다. 

 

 

 

 

위의 [그림14]를 보면  각 Column별 결측치의 비율을 확인 할 수 있습니다. PoolQC, MiscFeature, Alley, Fence의 경우 80% 이상이 결측치 이고, 초록박스로 쳐진 두개의 박스는 변수명이 비슷하고 결측치 비율이 똑같은 걸로 봐서 결측치끼리 상관성이 있는 것을 볼 수 있습니다. 결측치가 생긴 이유는 위의 [표1]변수의 세부 정보 표에서 봤듯이 아래 2가지를 잘 구분해서 처리해줘야 합니다.

  1. Null : 값이 존재하지 않아서 결측치
  2. Na : 표기의 실수나 어떠한 일로 인하여 값이 존재하지만 결측치로 표기.

 

1-5. 훈련데이터와 평가데이터 비교

 

마지막으로, Train과 Test의 분포를 확인 한 부분입니다. 모든 변수에 대해서 비교해봤을 때, Train과 Test의 분포는 거의 동일하였습니다. 그래서 이 부분에서는 Train에 오버피팅(Overfitting)되는 위험은 없을 것이라 생각하고 넘어갔습니다.

 

 

2. 데이터 전처리(Data Preprocessing)

 

 

 

2-1. 크로스 벨리데이션(CV) 설정

 

경진대회에서는 LB(Leader Board Score)보다 중요한게 CV(Cross Validation Score) 입니다. 그 이유는 두가지 입니다. 첫번째로, LB의 점수를 Test Set의 20% 밖에 사용하지 않는 다는 점( House Prices에서는 다른 대회랑은 다르게 50%를 사용하였습니다.) 두번째로, 리더보드 제출 횟수의 제한때문에 자체적으로 모델을 평가할 만한 검증시스템이 준비되어야 합니다. 그래서 먼저 신뢰 할 만한 CV을 구축하고 이상치를 제거했을 때 CV이 좋아지면 이상치를 제거하고, CV가 나빠지면 이상치를 냅두는 형식으로 사용했습니다.

 

대표적인 CV전략은 아래 [그림16]처럼 3가지가 있습니다. 

 

 

 

위의 [그림16]은 대표적인 CV 전략입니다. HoldOut 방식을 사용하지 않은것은 Train과 Test의 년도가 이어지는 형태가 아니라 섞여있는 형태였기 때문에 HoldOut방식은 정보의 손실을 야기할 수 있다고 판단하였습니다. 다음으로 KFOLD방식과 LOOCV방식을 모두 사용해봤고 더 나은 결과를 주는 KFOLD방식을 선택하였습니다. 

 

2-2. 전처리 - 반응변수(SalePrice)

 

그 다음으로는 다음 3가지 이유에 의해서 SalePrice에 로그를 취해 정규분포를 만들었습니다.

 

    1. 평가기준이 RMSLE
    2. 선형회귀 모델(릿지,라쏘)은 반응변수가 정규분포일 때 더 잘 작동.
    3. 스케일을 맞춰주면 편차에 의한 오차를 줄여줄 수 있음.

 

 

 

 

 

그 결과 위의 그림처럼 QQ 그래프를 봤을때, 정규성이 훨씬 좋아진것을 볼 수 있습니다. 추가로 상위 2개, 하위 5개의 값은 심한 이상치를 보이는 것을 추가로 확인할 수 있습니다.

 

2-2. 전처리 - 범주형 변수(Categorical Variable) : Encoding

 

데이터 형태에는 object가 많이 있습니다. 이러한 값은 컴퓨터가 인식하지 못하기 때문에 Encoding 작업이 필요합니다. One-hot, label, frequency 총 3가지의 방법을 적용해보고 가장 점수가 좋은 One-hot을 사용했습니다. 추가적으로 데이터의 특성에 맞게 순위형변수는 label을 그렇지 않은 변수는 one-hot과 Frequency를 이용해서 시도해봤으나 단순 One-hot보다 성능이 나빴습니다. 아마 label 인코딩의 경우는 1, 2, 3, 4 --- 이런식으로 인코딩을 하기 때문에 숫자의 크고 작음을 인식하는데 기존의 변수는 이렇게 순서대로 SalePrice가 크지 않아서 같습니다. 추가적으로 같은 퀄리티를 가져도 A변수에서는 SalePrice가 낮게 나오고, B변수에서는 높게 나오고 하는 차이점을 보여서 one-hot 인코딩이 성능이 더 좋게 나온 것 같습니다. 

 

 

3. 변수생성(Feature Engineering)

 

피쳐엔지니어링은 모델의 성능에 가장 직접적인 영향을 끼치는 중요한 부분입니다. 총 4가지 방법(변수의 사칙연산, 통계값, 범주화, 스케일링)을 통해서 새로운 변수를 추가하고 정제해줬습니다.

 

3-1. 변수의 사칙연산

 

아래의 변수들은 3가지 과정에 의해서 만들어줬습니다. 먼저 데이터를 읽어보고 

  1. Total_Bathrooms처럼 관련이 있는 변수들을 합치는 방법. 
  2. 상관성이 높은 변수들끼리 더하거나 곱하거나 하는 방식으로 다중공선성을 줄이는 방법.
  3. GrLivArea_OverallQual 같이 중요한 변수들(GrLivArea와 OverallQual)끼리 곱해서 가중치를 높이는 방법.

 

 

 변수 이름  설명
 Total_sqr_footage  BsmtFinSF1 + BsmtFinSF2 + 1stFlrSF + 2ndFlrSF
 Total_Bathrooms  FullBath + 0.5xHalfBath + BsmtFullBath + 0.5xBsmtHalfBath
 Total_porch_sf  OpenPorchSF + 3SsnPorch + EnclosedPorch + ScreenPorch + WoodDeckSF
 TotalHouse  TotalBsmtSF+1stFlrSF+2ndFlrSF
 TotalArea  TotalBsmtSF+1stFlrSF+2ndFlrSF+GarageArea
 GrLivArea_OverallQual  GrLivArea * OverallQual
 LotArea_OverallQual  LotArea * OverallQual

 

3-2. 통계값

 

통계적인 변수들은 나를 대표할 만한 변수들을 파악해서 만들어줬습니다. 나와 비슷한 가치를 가지는 집에 사는 사람들(OverallQual) 혹은 나와 비슷한 위치의 집에 사는 사람들(Neighborhood)의 평균,최소,최대,중위값을 이용해 변수를 만들어줬지만 Overfitting되는 경향을 보여서 사용하지는 않았습니다. 아무래도 위 [그림14]에 Neighborhood 변수의 Boxplot에서 봤듯이 같은 이웃을 가져도 이상치가 있거나 분산이 큰 경우가 있었습니다. 그러한 값들 때문에 Overfitting이 생긴거로 판단되고 이를 보정하기 위해서 다른 중요한 변수는 OverallQual이나 크기와 같은 변수들을 추가했지만 좋아지지는 않았습니다. 

 

 변수 이름  설명
 overall_statistical  나와 동일한 품질의 집을 가진 사람들의 평균,최소,최대,중위 집값
 neighborhood_statistical  나와 근처의 사는 사람들의 평균,최소,최대,중위 집값

 

3-3. 범주화

 

변수들 중 일부는 품목이 존재해야 값을 가지는 변수이었습니다. 예를들어 garage가 있어야 garageArea, garageQual 등등이 존재해서 있고 없고의 차이에 따라 과적합 되는 경우가 발생 할 가능성이 높았습니다. 이를 방지해 주기 위해 따로 있고 없고라는 변수를 만들어줘서 편향을 줄이려고 하였고 실제로 모델의 성능이 좋아졌습니다.

 

 변수 이름  설명
 haspool  풀이 있으면 1, 그렇지 않으면 0
 hasgarage  차고가 있으면 1, 그렇지 않으면 0
 hasbsmt  Basement가 있으면 1, 그렇지 않으면 0
 hasfireplace  소방시설이 있으면 1, 그렇지 않으면 0

 

3-4. 스케일링(Box-cox)

 

마지막으로 Box-cox정규화를 통해 스케일링을 해주었습니다. 그 이유는 분산을 줄여주기 위한 목적도 있고 log화를 통해 값의 크기가 줄어진 SalePrice와 크기를 비슷하게 맞춰주려는 의도도 있었습니다.

 

 변수 이름  Skew
 MiscVal  21.942472
 PoolArea  18.682408
 haspool  16.169674
 LowQualFinSF  12.067635

 

위의 보이는것과 같이 왜도가 높은 값들에 Box-Cov 처리를 해줌으로써 정규화를 해줬습니다.

 

 

4. 모델(Model)

 

모델로는 총 5개 Ridge, Lasso, ElasticNet, XGBoost, LightGBM을 사용했습니다. 

 

Ridge와 Lasso의 경우 데이터의 크기(1460)에 비해 변수들의 갯수가 80개 이상으로 많은 상황에서 변수들을 제거하려는 용도로 적합했습니다. GBM모델들은 Colsample이라는 기능을 통해서 변수들의 일부분만을 가지고 모델을 학습하기 때문에 현 데이터에서 가장 문제되는 다중공선성을 피할 수 있다고 판단했습니다. ElasticNet은 처음 들어보지만 많은 사람들이 사용하길래 사용했습니다. 추가적으로 ElasticNet에 대해 찾아 본 결과 L1정규화와 L2정규화를 함께 사용하는 모델인데 데이터셋과 같이 변수의 크기가 충분히 클 때 잘 작동한다고 합니다. 

 

4-1. Ridge

 

 

 

 

Ridge rmsle : 0.11082247

 

 

 

 

 

 위의 그림은 Ridge Regression의 변수 중요도를 살펴 본 그림입니다. 하지만 Ridge Regression은 변수를 모두 끌어 안고 가기 때문에 One-hot-encoding을 통해 변수가 많이 늘어 난 상황에서 해석하기가 힘든 단점이 있습니다. 

 

 

4-2. Lasso

 

 

 

Lasso rmsle : 0.11044071

 

 

 

 위의 Ridge Regression의 대안인 Lasso Regression의 그래프 입니다. 그래프에서 보이듯이 상위 하위에 Neighborhood와 OverallCond이 많이 보이는 것을 확인 할 수 있습니다. 


 

4-3. ElasticNet

 

ElasticNet rmsle : 0.1102891

 

4-4. XGBoost

 

XGBoost rmsle : 0.1133072

 

4-5. LightGBM

 
LightGBM rmsle : 0.1150742

 

 

 추가적으로 Gain Importance로 변수 중요도를 살펴봤을 때, Lasso와는 조금 다른 형태를 보이는 것을 확인 할 수 있습니다. Lasso의 경우 자주 보였던 Neighborhood나 OverallCond가 덜 중요한 변수쪽으로 가고, Area나 Year과 관련 된 변수가 중요하다고 판단되어짐을 볼 수 있습니다.

 

 

 

 

 

5. 앙생블(Ensemble)

 

5-1. Stacking

 

Stacking은 [그림21]처럼 모델로 예측한 값을 Feature처럼 이용해서 반응 변수(SalePrice)를 학습할 때 사용하는 방법입니다. 위에서 총 5개의 모델로 예측한 값을 만들었고 단순히 5개의 예측값만을 가지고 Target을 예측 시도, 기존의 변수들과 함께 예측 시도 두가지 방법으로 접근하였습니다.

 

 

 

5-2. Average

 

Average는 모델의 예측값을 (가중 혹은 단순)평균 내 줌으로써 성능을 향상시키는 방법입니다. 아래 [그림22]와 같이 13,18,11보다 가중 평균 낸 16.8이 정답 17에 더 가까운것과 같은 방식입니다. 먼저 단순평균으로 스코어가 얼마나 향상 혹은 떨어졌는지 확인하고 모델의 스코어에 맞게끔 가중치를 달리 해 주는 방식을 선택하였습니다. 

 

 

 

6. 결론(Conclusion)

 

위의 방법론을 적용했을 때, 최종 점수는 약 0.118로 상위 17%의 성적이었습니다. 이를 더 올리기 위해서 상위점수의 커널들에서 사용한 전처리 기법과 변수 생성 기법, 모델들을 참고해 다른 모델들을 만든 다음에 기존의 모델과 앙생블을 해줬더니 최종 0.10963으로 상위 1%의 성적을 기록할 수 있었습니다. 추가적으로 해당 내용에 대해 결측치 처리와 모델의 변수 중요도에 대한 해석이 들어간 자료는 [Kaggle] House Prices: Advanced Regression Techniques(2)를 참고하시기 바랍니다. 

 

 

코드(커널) 

https://www.kaggle.com/chocozzz/beginner-challenge-house-prices

 

참고자료 

https://www.slideshare.net/yeonminkim/pycon-korea-2018-kaggle-tutorialkaggle-break

Kaggle 우승작으로 배우는 머신러닝 탐구생활 

https://www.kaggle.com/nextbigwhat/eda-for-categorical-variables-a-beginner-s-way
https://www.kaggle.com/jens0306/easy-prediction-using-lightgbm-model
https://www.kaggle.com/hemingwei/top-2-from-laurenstc-on-house-price-prediction/notebook

https://brunch.co.kr/@itschloe1/11

https://brunch.co.kr/@gimmesilver/26