머신러닝 | 의사결정나무와 랜덤 포레스트 | Decision Tree, DT | Random Forest, RF | Ensemble (앙상블) | Bagging(배깅) = Bootstrapping + Aggregating | 타이타닉 데이터 실습 예시 | 지도학습 | 회귀, 분류 분석

    728x90

     

    1. 의사결정나무 (Decision Tree, DT)

     

    ▶ 의사결정나무

    : 의사결정 규칙을 나무 구조로 나타내어 전체 자료를 몇 개의 소집단으로 분류하거나 예측을 수행하는 분석 방법

    : 의사결정 '분류' 나무가 있고, 의사결정 '회귀' 나무가 있음

    : 의사결정나무의 가지가 끝까지 자라게 되면 해당 데이터에 대한 과적합으로 이어질 수 있음

     

    ▶ 의사결정나무 실습

    * 타이타닉 데이터셋

    : 성별 기준으로 생존 여부 구분하기

     

    [타이타닉 데이터셋 다운로드]

    https://www.kaggle.com/c/titanic/data

     

    Titanic - Machine Learning from Disaster | Kaggle

     

    www.kaggle.com

    # 라이브러리 가져오기
    import pandas as pd
    
    # 타이타닉 데이터 읽어오기
    # 데이터는 캐글에서 다운받을 수 있음
    titanic_df = pd.read_csv('titanic/train.csv')
    #titanic_df.head(3)
    
    # Sex 데이터 인코딩 하기 (male : 0, female : 1)
    def get_sex(x):
        if x == 'male':
            return 0
        elif x == 'female':
            return 1
        
    # Sex컬럼에 get_sex 함수 적용해서 sex_en컬럼 만듦
    titanic_df = titanic_df.assign(sex_en = titanic_df['Sex'].map(get_sex))
    #titanic_df.head(3)
    
    # 의사결정모델 학습하기
    from sklearn.tree import DecisionTreeClassifier
    
    X = titanic_df[['sex_en']]
    y = titanic_df['Survived']
    
    model_dt = DecisionTreeClassifier(max_depth=3)
    model_dt.fit(X, y)
    
    print(model_dt.feature_importances_)
    
    # graphviz로 의사결정나무 시각화하기
    from sklearn.tree import export_graphviz
    import graphviz
    
    
    tree_dot = export_graphviz(model_dt,
                               feature_names=['sex_en'],
                               class_names=['Survived', 'Not Survived'],
                               filled=True)
    
    dt_graph = graphviz.Source(tree_dot, format='png')
    dt_graph

     

     

    [ graphviz 설치 방법_참고 게시글]

    https://free-eunb.tistory.com/14

     

    [파이썬,머신러닝] graphviz 설치/실행 에러 해결

    Decision tree를 하는 과정에서 graphviz관련 오류가 날 때가 있습니다. 1. ModuleNotFoundError: No module named 'graphviz' 에러 파이썬에서 해당 라이브러리가 설치되지 않았다는 것을 의미합니다. 그럼 설치해주

    free-eunb.tistory.com

     

    ▶ 의사결정나무 명칭

    • 루트 노트(Root Node) : 의사결정나무의 시작점. 최초의 분할 조건
    • 리프 노트(Leaf Node) : 루트 노드로부터 파생된 중간 혹은 최종 노드

    • 분류 기준(criteria) : 남성인 경우 0, 여성인 경우 1로 인코딩.
                                       남성인 경우 좌측 노드로, 여성인 경우 우측 노드로 분류
    • 불순도(impurity) 
      • 지니계수(gini) : 0과 1사이의 값을 가짐.
        • 0은 완벽한 순도(모든 샘플이 하나의 클래스),
        • 1은 완벽한 불순도(노드의 샘플이 균등하게 분포)
      • 리프 노드로 갈수록 불순도가 작아지는(한 클래스로 분류가 잘 되는) 방향으로 나무가 자람
    • 샘플(samples) : 해당 노드의 샘플 개수(891개의 관측치)
    • 값(value) : y변수에 대한 배열
      • y = 0 : 549명이 죽음
      • y = 1 : 342명이 살았음
    • 클래스(class)
      • 가장 많은 샘플을 차지하는 클래스를 표현
      • 위에서는 주황색(y = 1 다수), 파란색(y = 0 다수)을 표현

    2. 랜덤 포레스트 (Random Forest, RF)

     

    ▶ 랜덤 포레스트

    : 의사결정나무의 경우, 과적합과 불안정성의 문제가 있음

    : 이를 해결하기 위해 나무(tree)를 여러 개 만들어 숲(forest)을 만든 뒤 다수결 법칙에 따라 결론을 냄

     

    ▶ 배깅(Bagging)의 원리

    • 머신러닝의 문제는 언제나 '데이터의 부족'
    • 이를 해결하기 위해 Bootstrapping + Aggregating 방법론 사용
      • Bootstrapping : 데이터를 복원 추출해서 유사하지만 다른 데이터 집단을 생성하는 것
      • Aggregating : 데이터의 예측, 분류 결과를 합치는 것
      • Ensemble(앙상블) : 여러 개의 모델을 만들어 결과를 합치는 것

     

    ▶ Tree를 Forest로 만들기

    : 여러 개의 데이터 샘플에서 각자 의사결정트리를 만들어서 다수결 법칙에 따라 결론을 냄

    ▶ 랜덤 포레스트 특징

    • 장점
      • Bagging 과정을 통해 과적합을 피할 수 있음
      • 이상치에 견고하고, 데이터 스케일링이 불필요
      • 변수 중요도를 추출하여 모델 해석에 중요한 특징을 파악할 수 있음
    • 단점
      • 컴퓨터 리소스 비용이 큼
      • 앙상블 모형이기 때문에 해석을 하는 데에는 조금 어려움
    • Python 패키지
      • sklearn.ensemble.RandomForestClassifer
      • sklearn.ensemble.RandomForestRegressor

     

    ▶ 랜덤 포레스트 실습

    * 타이타닉 데이터셋

    : 생존율을 가장 잘 예측하는 주요 변수 찾아내기

    # 라이브러리 가져오기
    import pandas as pd
    import matplotlib.pyplot as plt 
    import seaborn as sns
    from sklearn.preprocessing import LabelEncoder
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import accuracy_score, f1_score
    
    # 타이타닉 데이터 읽어오기
    titanic_df = pd.read_csv('titanic/train.csv')
    
    # 타이타닉 데이터 복사본 만들기
    titanic_df2 = titanic_df.copy()
    
    
    # 타이타닉 데이터 전처리
    
    # 성별을 남자는 0, 여자는 1로 인코딩해주는 함수
    def get_sex(x):
        if x == 'male':
            return 0
        elif x == 'female':
            return 1
    
    # 성별 인코딩 함수를 Sex컬럼에 적용해 sex_en 컬럼 새로 만들기
    titanic_df2 = titanic_df2.assign(sex_en = titanic_df2['Sex'].apply(get_sex))
    
    # SibSp컬럼과 Parch컬럼을 합해서 Family컬럼 만들기
    # 가족이 없는 사람(Family컬럼이 0인 사람)도 자기 자신은 탑승했으니 +1 해줌
    titanic_df2 = titanic_df2.assign(Family = titanic_df2['SibSp']+titanic_df2['Parch']+1)
    
    # Age컬럼에 있는 결측치는 나이의 평균값으로 채워주지
    Age_mean = titanic_df2['Age'].mean()
    titanic_df2 = titanic_df2.assign(Age_sc = titanic_df2['Age'].fillna(Age_mean))
    
    # Embarked컬럼의 승선 항구는 각각 0,1,2로 레이블인코딩 해주기
    le = LabelEncoder()
    titanic_df2['Embarked'] = le.fit_transform(titanic_df2['Embarked'])
    
    # 분석에 사용할 컬럼만 뽑아서 타이타닉 데이터프레임 만들기
    titanic_df2 = titanic_df2[['Survived', 'Pclass', 'sex_en', 'Age_sc', 'Family', 'Fare', 'Embarked']].reset_index(drop=True)
    
    
    # 랜덤 포레스트 모델링
    
    model_rf = RandomForestClassifier(random_state=42)
    
    X = titanic_df2[['sex_en', 'Pclass', 'Fare', 'Age_sc']]  # 가장 높은 스코어가 나오는 X변수 조합 찾기(자유롭게 바꿔보기)
    y = titanic_df2['Survived']
    
    X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                        test_size=0.3,
                                                        shuffle=True,
                                                        stratify=y,
                                                        random_state=42)
    
    model_rf.fit(X_train, y_train)
    y_pred = model_rf.predict(X_test)
    
    
    # 정확도(Accuracy)와 f1-score를 출력하는 함수 만들기
    def get_score(model_name, y_true, y_pred):
        acc = accuracy_score(y_true, y_pred)
        f1 = f1_score(y_true, y_pred, average='weighted')
        print(model_name, ':', 'acc 스코어: ', acc, ',', 'f1 스코어: ', f1)
    
    
    # 모델링 결과 출력
    get_score('rf', y_test, y_pred)

    일단 이제까지 한 것 중에 제일 높게 나온 스코어 박제

    728x90

    댓글