본문 바로가기

Hello MLop/ML

MLop_ML_XGBoost_커플 성사 여부 예측

20221115

28일차


오늘 해볼 알고리즘은 

XGBoost(eXtreme Gradient Boosting)을 사용한 커플 성사 여부 예측이다.

 

데이터는 kaggle에서 가져왔으며

먼저 XGBoost에 대하여 알아보자.

 


XGBoost(eXtreme Gradient Boosting)

 

먼저 전체적인 개념을 이해하기 앞서

우리는 Gradient Boosting의 개념을 먼저 잡는게 개인적으로 중요하다고 생각한다.

 

개인적으로 나는 발전을 시켜야 했을까?

어떤 포인트가 한계라고 느끼게 했을까?

그럼 어떤 방식으로 바뀌었길레 발전이 되었나? 를 중요하게 생각한다.

 


전체적인 흐름을 보자.

 

💡 결정트리모델은 각 특징을 조건으로 구분하여

트리 모양으로 나눈 후 결과를 도출한다.

 

하지만 트리 하나만으로는 정확도 그리 높지 않으니

여러개의 트리를 조합하는 방식으로 결과를 뽑게 되었다.

그렇게 나온게 랜덤포레스트 방식이다.

 

💡 여러개의 트리를 만들어 결과를 도출하는 방식을

앙상블 방식이라고 하는데

 

이는 크게 배깅(Bagging)과 부스팅(Boosting)이 있다.

 

간단하게 설명하면

 

배깅(Bagging)은 여러개의 트리를 만들고 그 결과를 취합하여 가장 높은 항목을 선택한다.

배깅의 대표 랜덤포레스트!

 

부스팅(Boosting)은 하나의 트리를 가지고 지속적으로 성능을 높이는(부스팅) 방법이다. 

 부스팅의 대표 그래디언트 부스팅!

 

여기서 주목해야 하는게 부스팅 방식,

하나의 트리를 가지고 지속적으로 성능을 높이는 방법

 

🤔 그럼 랜덤 포레스트처럼 그래디언트부스팅 모델도 많이 모아서 분석하면 더 좋지 않을까?

 

해서 나온게 우리가 오늘 실습할

 

XGBoost(eXtreme Gradient Boosting)이다.

 


데이터를 불러오자.

 

이번 데이터는 컬럼의 수가 많으므로

pd.options.display.max_columns = 40

옵션을 적용하여 전체 컬럼을 봐야한다.

 


 

.info() 도 찍어서 결측치도 확인해 보고  데이터타입은 어떻게 분포되어 있는지 확인한다.

 

총 colum의 목록 및 해석이다.

 

.describe()도 확인해 이상치 및 어떤 특수한 상황이 있는지 체크한다.

 


결측치를 체크해보자.

.isna()를 사용하여  체크할 수 있다.

 

각 결측치 개수의 평균이 출력되었다.

 

여기서 우리는 살릴 컬럼

아주 사소하게 결측치가 들어있는 컬럼의

과감하게 삭제하기로 했다.

 

선택받은 컬럼을 subset으로 묶어주고 부분집합 처리를 해주어

df.dropna를 했다.

 

💡 .dropna()

 

axis 의 defalt값은 0이기 때문에

자동적으로 (axis = 0)에 있는 결측치를 삭제한다.

 


그리고 전체데이터에서 위의 컬럼을 뺀 나머지의 컬럼의 결측치

우리가 인지할 수 있는 -99라는 값을 넣어준다.

 

 

그리고 다시 전체 데이터의 결측치를 확인해보면

전부 처리가 됬음을 알 수 있다.

 


가지고 있는 독립변수들, 즉 컬럼들을 좀 더 가공해서 더 유의미하게 만들고 컬럼의 수도 줄이는 작업을

피처 엔지니어링이라고 한다.

Feature Engineering

 

💡

Feature = 특징들, 독립변수들Engineering = 공학, 새롭게 만든다.

 


나이 차이를 의미하는 age_gap 함수를 선언한다.

 

로직은  이러하다.

-99결측치를 의미

 

내 나이가 결측치이면 return 결측치

상대 나이가 결측치이면 return 결측치

 

성별이 female일 경우 return 상대나이 -  내 나이  ▶ 상대의 나이가 나보다 얼마나 많은지

성별이 male일  경우 return 내 나이 - 상대나이 ▶ 내 나이가 상대보다 얼마나 많은지

 

 


df에 'age_gap'컬럼을 만들고

그  데이터는 df에 위 함수 age_gap을 열방향으로 적용한다.

 

그럼 'age_gap'으로 실행된 값들이 전부 소수점이 포함된 상태로 저장된다.

왜냐하면 'age'와 'age_o'컬럼의 데이터 타입이 float이였기 때문.

 

따라서 전부 int로 만들거나 절대값을 씌워 소숫점을 없애야 하는데

절대값을 씌워보자.

 

abs()를 이용해 전부 절대값 처리가 된 결과를출력에서 확인할 수 있다.

 


인종을 데이터로 가지고 있는 'race', 'race_o'컬럼에 

unique()를 적용해 확인

 

만약 결측치가 나오면 결측치로 두고

만약 내 인종과 상대방의 인종이 같으면 1

그 이외의 것들은 전부 -1로 주는

same_race라는 함수를 선언한다.

 

'same_race'컬럼에 전체 데이터에 same_race함수를 적용하면

-1과  1로만 이루어진 컬럼이 생성된것을 확인 할 수 있다.

 


그럼 이제 같은 인종이라는 것에 대한 선호도 컬럼 'importance_same_race'

위에서 구한 'same_race'컬럼을 접목 시킬 수 있다.

 


 

결측치는 그대로 두고

'same_race' * 'importance_same_race' 하여

same_race_point (같은 인종일때의 선호도 점수) 함수를 선언해서값을 구해 저장해 주자.

 


위와 같이 구하고

컬럼들을 조회해 보면?

 

위와 같이 나의 인종, 상대방 인종, 인종이 같은지 다른지, 같은 인종일때의 중요도, 같은 인종일때의 중요도 점수

데이터들이 쭉 나오는것을 확인할 수 있다.

 


전처리를 하다보니 이번 데이터의 규칙성을 발견했다.

 

우리는 중요도(importance) * 점수(score) 를 함수로 만들어주고

칼럼에 변환된 값들을 저장해준다.

 

그럼 나머지 column들을 그룹화해서

전부다 처리할수 없을까?란 생각이 드는것이다.

 


슬라이싱을 해보니 공통된 기준으로 묶어줄 수 있었고

 

이를 카테고리화 해서  변수로 저장해 주었다.

 

partner_imp ▶ 상대방의 선호도

partner_rate_me ▶ 본인에 대한 상대방의 평가

my_imp ▶ 본인의 선호도

my_rate_partner ▶ 상대방에 대한 본인의 평가

 


그럼 이제 상대방에 관한것과 본인에 관한것을 둘로 나눠

새로운 리스트로 만들어 주자.

 

그럼 이제 위에서 선언한 rating함수에 지정한 i, j, k들을 넣어서 작동 시키면!

 

'attrative_m', 'sincere_partner_m', 'intelligence_m', 'funny_m', 'ambition_m', 'shared_interests_m'

컬럼으로 저장된것을 알 수 있다!

 


마지막으로 남은 object컬럼 3가지는 get_dummies 처리 해주었다.

 


이제 평가를 하기위해 훈련셋과 시험셋을 나눠주고

모델링까지 해준다.

 


모델에 트레인 셋을 학습시키고

X_test는 모델에 예측

 

평가를 위해 3가지  임포트 해주었다.

 

accuracy_score ▶ 정확도 확인confusion_matrix ▶ 혼동 행렬, 지도 학습으로 훈련된 분류 알고리즘의 성능을 시각화 할 수 있는 표classification_report ▶ 분류 알고리즘 평가 지표 

 


 

accuracy_score

 

테스트 결과 86% 정답률을 확인

 

confusion_matrix

 

 

혼동행렬 시각화후 확인

 

TP는 True positive의 약자로, 실제 True인데, 분류모델에서 예측이 True라고 판단된 경우이다.
TN는 True negative의 약자로, 실제 False인데, 분류모델에서 예측이 False라고 판단된 경우이다.
FP는 False positive의 약자로, 실제 False인데, 분류모델에서 예측이 True라고 판단된 경우이다. # 1종 오류
FN는 False negative의 약자로, 실제 True인데, 분류모델에서 예측이 False라고 판단된 경우이다. # 2종 오류

 

 

위의 모델은 

86%(TP + TN)정도가 올바르게 판단했고

14%(FP + FN) 정도가 헷갈렸다라고 판단할 수 있다.

 

 

classification_report

 

precision 정밀도

 

다른것은 다 볼 필요없다.

분자 = TP분모 = TP + FP

 

TP는 올바르게 판단 한것

FP는 헷갈린것

 

그럼 FP가 커지면 커질수록 정밀도는 낮아진다. # 정밀도는 1로 본다.why? 1과 멀어지기 때문


recall 재현율

분자 = TP  분모 = TP + FN

 

TP는 올바르게 판단 한것

FN는 헷갈린것

 

그럼 FN 커지면 커질수록 재현율 낮아진다. # 재현율은 1로 본다.

why? 1과 멀어지기 때문


f-score F-1 점수

쉽게 설명하면 FNFP의 비율이 50:50에 얼마나 가깝냐를 나타내는 점수이다.

 


 

그리드 서치란?

 

하이퍼 파라미터가 무었인지 알것이다.

 

모델을 학습하는데 

최고의 조건으로 바꿔줘서

최상의 결과물을 얻는 셋팅인데,

 

그리드 서치란 이러한 최상의 조건을 찾는 과정이다.

 

다시말해 내가 튜닝할  파라미터 값을 여러개 정해두고

컴퓨터에게 뭐가 가장 좋은 파라미터가  되겠어?  계산해봐!

그리고 알려줘 하는것이다.

 

그럼 XGBoost에서는 어떤 파라미터를 손대야 할까?

 


 

learning_rate : 경사하강법에서 '매개변수'얼만큼씩 이동해 가면서 최소의 오차를 찾을지 비율

 

💡 경사하강법?

XGBoost앙상블 방법중에서도 부스팅 방식을 사용하기 때문에

경사하강법(Gradient descent)을 사용하여 최적의 학습을 진행하는데

 

오차(=기울기)에 대한 미분계수를 통해 매개 변수이동 방향보폭을 결정한다.

 


max_depth (최대 깊이)

각 트리의 최대 깊이 제한

 

subsample 

오버피팅을 방지하기 위해 모델을 학습시킬때 데이터를 제한함

 

n_estimators (전체 트리 개수)

전체 트리 개수 제한

 


위와 같이 그리드 서치에 사용할 파라미터를 만들어 준다.

 


사이키런에서 GridSearchCV를 임포트 해주고

modelXGBClassifier() # =XGB 분류기 지정

 

gs_model = GridSearchCV(model, parameter, n_jobs=-1, scoring='f1',cv=5)

▶ gs_model에 위의 설정한 파라미터로 분류해주겠다라는 의미

 

gs_model에 훈련셋을 학습 시켜주면?

 

학습된 훈련셋의 최적의 결과는

아래의 파라미터일때 나왔습니다. 라는 출력이 나온다.

 


위의 그리드 서치로 얻은 파라미터를 적용해서

어떤 변수가 영향력을 끼치는지 알 수 있다.

 


model.feature_importances_메서드를 적용시키면 아래와 같은 배열이 나오는데

 

이를 데이터프레임으로 바꿔서 feature_imp라는 변수에 저장하고

 

 

.sort_values(by='values', ascending=False) 를 해주면
영향력이 순서대로 출력된다.
 

이를 시각화 해주면

위와 같이 어떤 변수가 영향력이 있는지 한눈에 알아보기 쉽다.