Python(Colab) 의사 결정 나무(Decision Tree)

2023. 6. 13. 11:18파이썬/머신러닝 및 딥러닝

 ✔ 의사 결정 나무 

- 데이터를 분석하여 그 사이에 존재하는 패턴을 예측 가능한 규칙들의 조합으로 나타내며
  그 모양이 나무와 유사하다하여 의사 결정 나무라고 부른다.


특징)

1. 분류와 회귀 모두 가능하다.

2. 지니계수(Gennie Index) : 0에 가까울수록 클래스에 속한 불순도가 낮다

3. 엔트로피(Entropy): 결정을 내릴만한 충분한 정보의 데이터가 없다고 보는 것

4. 과대적합(overfitting): 훈련데이터에서는 정확하나, 테스트 데이터에서는 성과가 나쁜 현상 
                                      훈련 데이터가 적거나, 노이즈가 있을 때 또는 알고리즘 자체가 나쁠때 발생
                                      의사 결정 나무에서는 나무 가지가 많거나, 크기가 클 때 발생


cf) 과대 적합을 회피하기 위한 대책
                     1) 사전 가지치기: 나무가 다 자라기전에 알고리즘을 멈추는 법
                     2) 사후 가지치기: 의사 결정 나무를 다 돌린 후 밑에서부터 가지를 쳐나가는 작업

 

데이터로 실습

 

1. 기초 설정

 

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
 
bike_df = pd.read_csv('/content/drive/MyDrive/KDT-1/머신러닝과 딥러닝/bike.csv')
 
데이터 설명

* datetime  : 등록날짜
* count : 대여 개수
* holiday : 휴일 여부  
* workingday : 평일 여부
* temp  :  기온
* feels_like: 체감온도
* temp_min : 최저온도
* temp_max : 최고온도
* pressure : 기압
* humidity : 습도
* wind_speed : 풍속  
* wind_deg : 풍향
* rain_1h : 강수량
* snow_1h : 강설량
* clouds_all :  구름의 양
* weather_main : 오늘 날씨

 

데이터 전처리

 

2. 이상치 확인

sns.boxplot(y=bike_df['count'])
 

 

3. 관련이 있어보이는 컬럼 찾기

후보1) feel_like= 체감온도

sns.scatterplot(x='feels_like',y='count',data=bike_df,alpha=0.3)
 

 

후보2) pressure = 기압

sns.scatterplot(x='pressure',y='count',data=bike_df,alpha=0.3)
 

 

후보3) wind_speed = 풍속

sns.scatterplot(x='wind_speed',y='count',data=bike_df,alpha=0.3)
 

 

후보4) wind_deg = 풍향

sns.scatterplot(x='wind_deg',y='count',data=bike_df,alpha=0.3)

 

 

 

 

4. 결측치 확인

rain_1h: 강수량 / snow_1h 강설량이 NaN이 있다

bike_df.isna().sum()
 

 

 

 

5. 결측치 처리

강수량 강설량의 NaN은 0으로 대체

bike_df = bike_df.fillna(0)
bike_df.isna().sum()
 

 

6. datetime 컬럼 타입 변경 

object -->  datetime으로 

bike_df['datetime'] =  pd.to_datetime(bike_df['datetime'])
bike_df.info()
 
 

 

 

7. datetime의 값 파생 변수로 분리하기

year, month, hour , date(ex)2018-01-01 4가지 파생변수 만들기

bike_df['year'] = bike_df['datetime'].dt.year
bike_df['month'] = bike_df['datetime'].dt.month
bike_df['hour'] = bike_df['datetime'].dt.hour
bike_df['date'] = bike_df['datetime'].dt.date
 

 

8.그래프로 시각화하여 확인

 

1) 날짜별 대여 개수 (date / count)

plt.figure(figsize=(14,4))
sns.lineplot(x='date',y='count',data=bike_df)
plt.xticks(rotation=45)
plt.show()
 

 

🔴그래프의 이상함을 파악 (2020/01~07)사이에 데이터가 이상하다

 

9. 2020년도 데이터 확인 

bike_df[bike_df['year'] == 2020].groupby('month')['count'].mean()
 
 
2020년도 4월 데이터가 없다
결측치가 크고 예측하기 힘들기 때문에 다른 컬럼을 찾아보자

 

 

10. 코로나 기준으로 date를 바꾸기

2020-04-01 이전 : precovid

2021-04-01 이전 : covid

2021-04-01 이후 : postcovid

#방법 1
 
def covid(date):
    if str(date) < '2020-04-01':
        return 'precovid'
    elif str(date) < '2021-04-01':
        return 'covid'
    else:
        return 'postcovid'
 
bike_df['date'].apply(covid)
 
#방법 2
 
bike_df['covid'] = bike_df['date'].apply(lambda date: 'precovid' if str(date) < '2020-04-01'
                                                             else 'covid' if str(date) <'2021-04-01' else 'postcovid')

 

 

11. season이라는 파생 변수 만들기

3~5월 spring

6~8월 summer

9~11월 fall

12~2월 winter

bike_df['season'] = bike_df['month'].apply(lambda x: 'winter' if x == 12 else 'fall' if x >= 9 else 'summer' if x >= 6 else 'spring' if x >= 3 else 'winter')
 
 
#확인
bike_df[['month','season']]
 

 

12. day_night 파생 변수 만들기 

bike_df['day_night'] = bike_df['hour'].apply(lambda x: 'night' if x >= 21
                                             else 'late evening' if x >= 19
                                             else 'early evening' if x >= 17
                                             else 'late afternoon' if x >= 16
                                             else 'early afternoon' if x >= 13
                                             else 'late morning' if x >= 11
                                             else 'early morning' if x >= 5
                                             else 'night')
 

 

 

13. 머신러닝에 독립변수로 사용할 데이터타입 변경

 

 

#컬럼 별 개수 확인
 
for i in ['weather_main','covid','season','day_night']:
    print(i,bike_df[i].nunique())
 
#원 핫 인코딩
bike_df = pd.get_dummies(bike_df,['weather_main','covid','season','day_night'])
원 핫 인코딩을 진행하기전에 데이터의 분류의 개수를 파악하는 것이 좋다.

 

 

14. 학습 데이터 + 검증 데이터 분리하기

from sklearn.model_selection import train_test_split
 
X_train, X_test, y_train, y_test = train_test_split(bike_df.drop('count',axis=1),bike_df['count'],test_size=0.2,random_state=10)

 

 

15. 의사결정 나무 사용해서 학습 시키기

from sklearn.tree import DecisionTreeRegressor
 
#하이퍼 파라미터로 random_state 미리 적용 
dt = DecisionTreeRegressor(random_state=10)
 
#학습데이터 학습
dt.fit(X_train,y_train)
 
#검증데이터 테스트
pred1 = dt.predict(X_test)

 

16. 결과 검증 

오차율 확인 (기준 : RMSE)

from sklearn.metrics import mean_squared_error
 
mean_squared_error(y_test,pred1,squared=False)

 

 

 

17. 선형 회귀랑 비교하기 

 

from sklearn.linear_model import LinearRegression
 
lr = LinearRegression()
 
lr.fit(X_train,y_train)
 
pred2 = lr.predict(X_test)
 
mean_squared_error(y_test,pred2,squared=False)
 

 

18. 비교

# 의사결정나무 rmse 오차율 :228.42843328100884
# 선형회귀 rmse 오차율 :228.26128192004947

 

19. 의사결정나무에 하이퍼 파라미터 적용

dt = DecisionTreeRegressor(random_state=10, max_depth=50, min_samples_leaf=30)
✔ 하이퍼 파라미터

random_state: 학습,검증데이터가 변하지 않게 고정

max_depth: 데이터를 최대 50번 분리한다

min_samples_leaf = 남은 데이터가 30개 일시 알고리즘 종료

 

 

19.Tree 그래프로 확인

from sklearn.tree import plot_tree
 
plt.figure(figsize=(24,12))
plot_tree(dt,max_depth=5, fontsize=12, feature_names=X_train.columns)
plt.show()
 
 
 
max_depth:  최대 층을 설정해주는 것 
feature_names: 어떤 컬럼의 데이터가 영향력이 있는지 표시

 

 

728x90