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은 완벽한 불순도(노드의 샘플이 균등하게 분포)
- 리프 노드로 갈수록 불순도가 작아지는(한 클래스로 분류가 잘 되는) 방향으로 나무가 자람
- 지니계수(gini) : 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)
댓글