Python(Colab) 랜덤 포레스트 (Random Forest)

2023. 6. 16. 17:39파이썬/머신러닝 및 딥러닝

✔ 랜덤 포레스트

- 의사결정나무는 매우 훌륭한 모델이지만, 학습데이터에 오버피팅하는 경향이 있다.
- 가지치기 같은 방법을 통해 부작용을 최소화 할 수 있지만, 한계가 있다.
- 학습을 통해 구성해 놓은 다수의 나무들로부터 분류 결과를 취합해서 결론을 얻는 방식의 모델

랜덤포레스트는 !



cf) 앙상블 모델 

여러개의 머신러닝 모델을 이용해서 최적의 답을 찾아내는 기법

 

 

데이터로 실습

 

 

목표: 어떤 컬럼이 예약 취소율과 관련이 있을 지

 

1.기초설정

 

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
 
hotel_df = pd.read_csv('/content/drive/MyDrive/KDT-1/머신러닝과 딥러닝/hotel.csv')
 
hotel_df
 
 

 

✔컬럼 설명

* hotel : 호텔 종류
* is_canceled : 취소 여부
* lead_time : 예약 시점으로 부터 체크인이 될때 까지 기간(얼마나 미리 예약 했는지)
* arrival_date_year: 예약 연도
* arrival_date_month : 예약 월
* arrival_date_week_number : 예약 주
* arrival_date_day_of_month : 예약 일
* stays_in_weekend_nights : 주말 포함 숙박일
* stays_in_week_nights  : 평일 포함 숙박일
* adults : 성인 인원* children : 어린이 인원
* babies : 아기 인원
* meal :  식사 형태
* country : 지역
* distribution_channel : 유입 경로
* is_repeated_guest : 재방문 고객 여부
* previous_cancellations : 이전 예약 취소 여부
* previous_bookings_not_canceled :  예약을 취소하지 않고 정상 숙박한 횟수
* reserved_room_type : 예약 객실 타입
* assigned_room_type : 실제 배정된 객실 타입
* booking_changes: 예약 후 서비스가 몇번 변경되었는지
* deposit_type: 요금 납부 방식
* days_in_waiting_list: 예약을 위해 기다린 날짜
* customer_type: 고객 타입
* adr : 특정일에 높아지거나 낮아지는 가격
* required_car_parking_spaces : 주차공간 필요 여부
* total_of_special_requests : 별도의 요청 사항
* reservation_status_date: 예약한 날짜
* name : 이름
* email : 이메일
* phone-number : 핸드폰 번호
* credit_card : 신용카드 번호

 

2. 필요없는 컬럼 제거하기

개인정보 제거하기

hotel_df.drop(['credit_card','phone-number','email','name','reservation_status_date'],axis=1,inplace=True)

 

 

 

3.관련있어보이는 컬럼 찾기 (이상치 확인)

 

후보1)  lead_time : 예약 시점으로 부터 체크인이 될때 까지 기간(얼마나 미리 예약 했는지)

sns.displot(hotel_df['lead_time'])
 

 

sns.boxplot(hotel_df['lead_time'])
 

 

 

후보2) distribution_channel : 유입 경로

sns.barplot(x=hotel_df['distribution_channel'],y=hotel_df['is_canceled'])
 
오차율이 높은 관계로 한번 개수 확인

hotel_df['distribution_channel'].value_counts()

 

 

후보3) hotel : 호텔 종류 

sns.barplot(x=hotel_df['hotel'],y=hotel_df['is_canceled'])
 

 

후보4)  arrival_date_year: 예약 연도

sns.barplot(x=hotel_df['arrival_date_year'],y=hotel_df['is_canceled'])
 

 

 

 

후보5 arrival_date_month : 예약 월

plt.figure(figsize=(15,5))
sns.barplot(x=hotel_df['arrival_date_month'],y=hotel_df['is_canceled'])
 
 
1월부터 정리가 되지 않았음

 

✔ 1월부터 나오게 정렬하기

# 월 별로 정렬하기

plt.figure(figsize=(15,5))
sns.barplot(x=hotel_df['arrival_date_month'],y=hotel_df['is_canceled'], order=month)
 

 

 

후보6) is_repeated_guest : 재방문 고객 여부

sns.barplot(x=hotel_df['is_repeated_guest'],y=hotel_df['is_canceled'])
 

 

 

후보7) deposit_type: 요금 납부 방식

sns.barplot(x=hotel_df['deposit_type'],y=hotel_df['is_canceled'])
 

 

오차율이 높은 관계로 한번 개수 확인

hotel_df['deposit_type'].value_counts()

 

 

plt.figure(figsize=(20,30))
sns.heatmap(hotel_df.corr(),cmap='coolwarm', vmax=1,vmin=-1,annot=True)

#vmax, vmin= -1 ~ 1 사이로 정렬 해달라
#annot=True : 박스안에 해당 숫자를 넣는 것
 

 

 

hotel_df.isna().mean()

 

 

파생변수 설정 

1. 사람인원수

2. 총 숙박일

hotel_df['people'] = hotel_df['adults'] + hotel_df['children']+ hotel_df['babies']
hotel_df['total_nights'] =  hotel_df['stays_in_weekend_nights'] + hotel_df['stays_in_week_nights']

 

 

arrival_date_month의 value 값을 개월로 바꾸기

#방법 1
 
hotel_df['arrival_date_month'].apply(lambda x : 'spring' if x in ['March','April','May'] else 'summer' if x in ['June','July','Augest'] else 'fall' if x in ['September','Octorber','November'] else 'winter')
 
 
 
#방법 2
season_dic = { 'spring':[3,4,5], 'summer':[6,7,8], 'fall':[9,10,11], 'winter':[12,1,2]}
 
new_season_dic = {}

for i in season_dic:
    for j in season_dic[i]:
        new_season_dic[calendar.month_name[j]] = i

hotel_df['season'] = hotel_df ['arrival_date_month'].map(new_season_dic)

 

expected_room_type을 0,1로 바꾸기(예약했던적이 있는지 없는지)

 

# 예약 객실과 실제 배정 객실이 같을 경우 true/false가 나오는데 astype으로 int화 시키면 0,1로 된다.
hotel_df['expected_room_type'] = (hotel_df['reserved_room_type']  == hotel_df['assigned_room_type']).astype(int)
 

 

 

 

취소율 구하기

 

hotel_df['cancel_rate'] = hotel_df['previous_cancellations'] / (hotel_df['previous_cancellations'] + hotel_df['previous_bookings_not_canceled'])
 
 
hotel_df['cancel_rate'].value_counts()
 

 

 

#타입이 obj인 컬럼만 빼오기
obj_list = []

for i in hotel_df.columns:
    if hotel_df[i].dtype == 'O':
        obj_list.append(i)
 
obj_list
 

 

각 컬럼별 분류개수 보기

for i in obj_list:
    print(i,hotel_df[i].nunique())
 

 

 

학습데이터 검증데이터 나누기

독립변수: 나머지 컬럼들

종속변수: 취소율

from sklearn.model_selection import train_test_split
 
X_train, X_test , y_train, y_test = train_test_split(hotel_df.drop('is_canceled',axis=1), hotel_df['is_canceled'],test_size=0.3,random_state=12345)

 

모델 학습시키기 (분류의 배깅 모델 사용 예정)

 

from sklearn.ensemble import RandomForestClassifier
 
rf= RandomForestClassifier()
 
rf.fit(X_train,y_train)
 
pred1= rf.predict(X_test)
 
# 예측 결과를 %로 보고싶을 때
proba1 = rf.predict_proba(X_test)
proba1
 

 

                                                                                0일확률 vs 1일 확률

 

 

테스트 데이터를 예측한 결과를 보고싶다.

 

# 첫번째 테스트 데이터에 대한 예측 결과
proba1[0]
 

 

# 모든 테스트 데이터에 대한 취소 확률을 찍어보고싶다.
proba1[:,1]
 

 

 

결과검증 지표 

 

✔ ROC Curve

- 이진 분류 의 성능을 측정하는 도구
- 민감도, 특이도로 그려지는 곡선을 의미


✔특이도(FPR False Positive Rate)



✔민감도(True Positive Rate)



✔AUC(Area Under the ROC Curve)  ROC커브와 직선 사이의 면적을 의미

 

결과검증 적용

 

정확도 / 혼돈행렬 / T사이킷런  / ROC

from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, roc_auc_score
 
 
accuracy_score(y_test,pred1)
# 약 86% 정답률
 

 

 

confusion_matrix(y_test,pred1)

 

 

 

 

print(classification_report(y_test,pred1))

 

 

 

 

하이퍼 파라미터 수정하고 정확도 올려보기

max_depth =  30 (30층까지 가지를 내린다.)
random_state = 12345(데이터 고정)
rf2= RandomForestClassifier(max_depth=30, random_state=12345)

rf2.fit(X_train,y_train)
proba2 = rf2.predict_proba(X_test)


roc_auc_score(y_test,proba2[:,1])

 

 

🔴최적의 파라미터 찾기🔴

 

GridSearchCV

원하는 모든 하이퍼 파라미터를 적용하여 최적의 값을 찾아준다.

 

 

설정법

from sklearn.model_selection import GridSearchCV
 
# 객체를 생성
# 갯수를 맞춰줄 필요가 없다.

params = {
    'max_depth': [None, 10, 30 ,50],
    'min_samples_split': [2,3,5,7,10]
}

 

 

학습하기

 

rf3= RandomForestClassifier(random_state=12345)
 
#cv = 5 5조각으로 쪼개서 검사
grid_df = GridSearchCV(rf3,params,cv=5)
 
grid_df.fit(X_train,y_train)
cv = 총 데이터를 n 조각으로 쪼개서 검사한다.
#최적의 파라미터 확인하기
grid_df.best_params_

 

 

✔  피쳐 중요도 (feature Importances)

* Decision Tree에서 노드를 분기할 때 해당 피쳐가 클래스를 나누는데 얼마나 영향을 미쳤는지를 표기하는 척도    

 

proba3 = rf3.predict_proba(X_test)
proba3
 

 

roc_auc_score(y_test,proba3[:,1])
 

 

rf3.feature_importances_
 
 
 
✔ feature_importances_

결정트리에서 노드가 분기될때 얼마나 영향을 미쳤는지 표기하는 척도

 

 

데이터 프레임으로 영향력 확인하기

 

feat_imp = pd.DataFrame({
    'features': X_train.columns,
    'importance': rf3.feature_importances_
})
 

 

총 결과 깔끔히 보기

 

 
feat_imp = pd.DataFrame({
    'features': X_train.columns,
    'importance': rf3.feature_importances_
})
 
top10 = feat_imp.sort_values('importance',ascending=False).head(10)
top10
 

 

plt.figure(figsize=(5,10))
sns.barplot(x='importance',y='features', data=top10)

 

728x90