지루한 이론과 설치가 끝나고 드디어 실습이다.
이번 글에서는 sklearn에서 제공하는 보스턴 주택 가격 데이터를 이용해 xgboost 모델을 학습시키고 예측하기까지 해 볼 예정이다.
개발 환경
설치가 완료된 이상 대부분 개발환경의 제약은 받지 않으나 내가 개발한 환경은 다음과 같다.
- AWS Linux
- python 3.6.10
준비하기
- 이전 글에서 설치한 xgboost용 python을 활성화해준다.
source <설치경로>/bin/activate
- sklearn, pandas, matplotlib, graphviz를 설치하지 않은 경우 설치해준다.
pip install sklearn pandas matplotlib graphviz
앞에 sudo를 붙이거나 가상 환경을 활성화시키지 않은 상태로 설치하는 실수는 하지 말자.
실습하기
Full 코드를 한줄한줄 실행해보며 이해해보는 것을 추천한다.
데이터 준비하기
우리가 사용할 데이터는 sklearn에서 제공해주는 보스턴의 주택 가격 데이터이다.
이 데이터를 통해 주택 가격을 예측해보는 xgboost 모델을 만들어보자.
from sklearn.datasets import load_boston
boston = load_boston()
위 코드를 입력하면 저장된 서버에서 데이터를 읽어와 boston이라는 변수에 저장해준다.
데이터 탐색하기
가져온 데이터가 어떻게 생겼는지 확인해보자.
읽어온 데이터는 dictionary(딕셔너리) 형태이기 때문에 keys() 메서드로 키를 확인할 수 있다.
print(boston.keys())
>>> dict_keys(['data', 'target', 'feature_names', 'DESCR'])
boston.data.shape이라는 값을 통해 데이터 셋의 사이즈를 확인해볼 수 있다.
print(boston.data.shape)
>>> (506, 13)
(506, 13)을 리턴하는 것을 확인할 수 있는데,
506개의 데이터(주택수)와 13개의 칼럼(특성)으로 이루어졌다는 것을 의미한다.
feature_names를 통해 피쳐의 이름을 가져올 수 있다.
print(boston.feature_names)
>>> ['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO' 'B' 'LSTAT']
이름 가지고는 잘 모르겠으니 DESCR으로 설명을 보자
print(boston.DESCR)
>>>
Boston House Prices dataset
===========================
Notes
------
Data Set Characteristics:
:Number of Instances: 506
:Number of Attributes: 13 numeric/categorical predictive
:Median Value (attribute 14) is usually the target
:Attribute Information (in order):
- CRIM per capita crime rate by town
- ZN proportion of residential land zoned for lots over 25,000 sq.ft.
- INDUS proportion of non-retail business acres per town
- CHAS Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
- NOX nitric oxides concentration (parts per 10 million)
- RM average number of rooms per dwelling
- AGE proportion of owner-occupied units built prior to 1940
- DIS weighted distances to five Boston employment centres
- RAD index of accessibility to radial highways
- TAX full-value property-tax rate per $10,000
- PTRATIO pupil-teacher ratio by town
- B 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town
- LSTAT % lower status of the population
- MEDV Median value of owner-occupied homes in $1000's
:Missing Attribute Values: None
:Creator: Harrison, D. and Rubinfeld, D.L.
This is a copy of UCI ML housing dataset.
http://archive.ics.uci.edu/ml/datasets/Housing
This dataset was taken from the StatLib library which is maintained at Carnegie Mellon University.
The Boston house-price data of Harrison, D. and Rubinfeld, D.L. 'Hedonic
prices and the demand for clean air', J. Environ. Economics & Management,
vol.5, 81-102, 1978. Used in Belsley, Kuh & Welsch, 'Regression diagnostics
...', Wiley, 1980. N.B. Various transformations are used in the table on
pages 244-261 of the latter.
The Boston house-price data has been used in many machine learning papers that address regression
problems.
**References**
- Belsley, Kuh & Welsch, 'Regression diagnostics: Identifying Influential Data and Sources of Collinearity', Wiley, 1980. 244-261.
- Quinlan,R. (1993). Combining Instance-Based and Model-Based Learning. In Proceedings on the Tenth International Conference of Machine Learning, 236-243, University of Massachusetts, Amherst. Morgan Kaufmann.
- many more! (see http://archive.ics.uci.edu/ml/datasets/Housing)
Attribute Information 아래에 각 칼럼명에 대한 설명이 나와 있다. 자세한 내용은 직접 번역해서 읽어보길..
데이터 변환하기
학습을 시키기 위해서는 내가 필요한 데이터 형태로 변환을 해주어야 한다.
XGBoost에서는 DMatric형태로 데이터를 입력할 수 있는데, 이는 메모리에 효율적이고 학습에 빠르게 구현되어있다고 한다. 예전에 강의 들을 때 triplet 표현식으로 구현되어있다고 들었었는데, 공홈에서는 그런 내용이 안 보인다.
우선 Pandas dataframe 형태로 변환해보자.
import pandas as pd
data = pd.DataFrame(boston.data)
data.columns = boston.feature_names
그리고 출력
data.head()
>>> (다음 표)
아까 보았던 칼럼명들과 그에 해당하는 값이 있다.
그런데 정작 예측할 가격이 없다. 이는 boston.target에 있으니, 이 값을 한 개의 칼럼으로 추가해주자.
data['PRICE'] = boston.target
info() 메서드를 통해서 데이터 프레임의 각 값이 어떤 타입을 사용하고 있는지 확인할 수 있다.
data.info()
>>>
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 506 entries, 0 to 505
Data columns (total 14 columns):
CRIM 506 non-null float64
ZN 506 non-null float64
INDUS 506 non-null float64
CHAS 506 non-null float64
NOX 506 non-null float64
RM 506 non-null float64
AGE 506 non-null float64
DIS 506 non-null float64
RAD 506 non-null float64
TAX 506 non-null float64
PTRATIO 506 non-null float64
B 506 non-null float64
LSTAT 506 non-null float64
PRICE 506 non-null float64
dtypes: float64(14)
memory usage: 55.4 KB
우리가 예측할 가격을 포함해서 모든 칼럼이 float64로 되어있다.
describe() 메서드를 통해 값들의 대략적인 통계를 보자.
data.describe()
>>> 다음표
XGBoost에 들어갈 인풋 데이터를 준비할 때 주의할 점은 categorical value를 onehot 인코딩을 통해서 직접 변환해주어야 하는데, 이 예제에서는 해당사항이 없다.
추가적인 정보로 xgboost는 null(NA) 값을 내부적으로 처리해주는 로직이 있어 별도로 처리하지 않아도 된다.(권장되는지는 모르겠다.)
이제 DMatrix형태로 변환해보자.
import xgboost as xgb
from sklearn.metrics import mean_squared_error
import pandas as pd
import numpy as np
필요 모듈들을 임포트 시키고
X, y = data.iloc[:,:-1],data.iloc[:,-1]
X와 y로 나눈 뒤
data_dmatrix = xgb.DMatrix(data=X,label=y)
dmatrix로 변환해준다.
학습하기
이제 학습을 시킬 차례다. 그런데 위에서 언급한 말을 정정해야 할 것 같다.
XGBoost에서는 DMatric형태로 데이터를 입력할 수 있는데,
XGBoost에서는 DMatric형태나 sklearn에서 지원하는 형태로 데이터를 입력할 수 있다.
정정한 이유는 xgboost가 sklearn estimate wrapper 형태로'도' 지원되기 때문이다.
다만, 이 형태로 학습을 시킬 때의 속도와 메모리 효율성은 DMatrix일 때보다 떨어진다.
우리는 간단한 예제 이기 때문에 sklearn wrapper 형태의 api를 사용해볼 예정이다.
우선 train, test 셋을 80:20 비율로 나누고,
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=123)
우리가 예측할 범위는 (0~무한대)인 특정 값이므로 regressor가 어울리니 regressor를 생성해준다.
(파라미터에 대한 설명은 이글 참고)
xg_reg = xgb.XGBRegressor(objective ='reg:linear', colsample_bytree = 0.3, learning_rate = 0.1, max_depth = 5, alpha = 10, n_estimators = 10)
그리고 fit() 메서드를 호출해 학습시켜준다.
xg_reg.fit(X_train,y_train)
예측하기
학습이 완료되었으면 이제 test 데이터로 예측을 해보자.
precit 메서드에 테스트 데이터를 넣어 호출하면 예측치가 나온다.
preds = xg_reg.predict(X_test)
실제 값과 얼마나 차이가 날까? RMSE로 측정해보자.
rmse = np.sqrt(mean_squared_error(y_test, preds))
print("RMSE: %f" % (rmse))
>>> RMSE: 10.569356
음.. 10.5 정도가 나왔다. RMSE가 낮으면 더 좋은 모델인데, 엄청 좋은 것 같진 않다.
xgb는 cross validation을 기본적으로 제공해주니 더 좋은 모델을 다시 한번 만들어 보자
Cross Validation으로 학습하고 예측 결과 비교하기
우선 cv로 학습은 다음과 같이 하면 된다.
(파라미터에 대한 설명은 이글 참고)
params = {"objective":"reg:linear",'colsample_bytree': 0.3,'learning_rate': 0.1,'max_depth': 5, 'alpha': 10}
cv_results = xgb.cv(dtrain=data_dmatrix, params=params, nfold=3,num_boost_round=50,early_stopping_rounds=10,metrics="rmse", as_pandas=True, seed=123)
cv결과는 cv_results에 매 스탭마다 저장되어있다.
확인해보자.
cv_results.head()
>>> (아래 표)
이런 식으로 모두 저장되는데 마지막에 저장된 test-rmse-mean이 우리가 확인해볼 결과이다.
마지막 값을 확인해보자.
print((cv_results["test-rmse-mean"]).tail(1))
>>> 49 3.975679
>>> Name: test-rmse-mean, dtype: float64
약 4.0 이 나왔다! 10.5보다 훨씬 개선된 결과이다!
모델 시각화하기
모델 시각화를 하기 위해서는 matplotlib이 설치되어있어야 한다.
tree 시각화는 다음과 같은 코드로 할 수 있다.
import matplotlib.pyplot as plt
xgb.plot_tree(xg_reg,num_trees=0)
plt.rcParams['figure.figsize'] = [40, 10]
plt.show()
>>> (다음 그림)
Boostring 방식으로 학습했기 때문에, step 마다 하나의 tree가 생성된다.
즉 위와 비슷한 tree가 step 수만큼 더 있는 것이다.
num_trees=0 이 부분을 수정하면 다른 step에 생성된 tree들도 확인해볼 수 있다.
다음으로 feature importance 확인하기.
graphviz가 설치되어있어야 한다.
xgb.plot_importance(xg_reg)
plt.rcParams['figure.figsize'] = [10, 10]
plt.show()
>>> (다음 그림)
위로 갈수록 feature의 중요도가 높고 아래로 갈수록 중요도가 낮다.
100%는 아니지만 xgb에서 중요한 feature가 다른 모델에서도 중요한 경우가 많다.
xgb는 이렇게 간단하게 시각화하고 결과를 뽑을 수 있기에,
초벌 모델링을 xgb로 하고 중요한 feature를 확인하는데 쓰기도 한다.
이상으로 XGBoost tutorial을 진행해보았다.
다음 글에서는 실전용 데이터로 학습과 시행착오들을 어떻게 겪어 나가는지 과정을 포스팅해 볼 예정이다.
Reference
'ML | DL | Big data > ML' 카테고리의 다른 글
VAR(Vector Auto Regression)을 이용한 다변량 시계열 분석 및 예측 (6) | 2020.09.26 |
---|---|
시계열 예측을 지도 학습으로 바꾸는 방법 - Time Series to Supervised Learning with Sliding window (1) | 2020.09.11 |
Python Prophet - 자동차 판매량 시계열 데이터 예측하기(Time Series Forecasting) (3) | 2020.08.28 |
XGBoost (3) - Python 가상 환경에 설치하기 (0) | 2020.07.13 |
XGBoost (2) - Parameter 이해와 현업자의 설정 방법 (2) | 2020.07.09 |
XGBoost (1) - 입문용 예제로 개념 쉽게 이해하기 (0) | 2020.07.08 |
댓글