생각하는 감쟈

[Python] 4-3) 머신러닝 - 결정트리.. 본문

Language/Python

[Python] 4-3) 머신러닝 - 결정트리..

생각하는 감쟈🥔 2023. 4. 13. 10:19

 

 

 

 

21일차 (23.04.10)

 


✔3DAY

나이브베이즈 분류기

결정 트리

결정 트리 분석

결정 트리의 앙상블

출처 입력


나이브 베이즈

  • 선형 모델과 매우 유사한 분류기
  • 선형 분류가 보다 훈련 속도가 빠른 장점
    • 선형 분류기
    • 알번화 성능

 

나이즈 베이즈 분류기의 원리

  • 각 특성을 개별로 취급해 파리미터 학습
  • 각 특성에서 클래스별 통계를 단순하게 취급하는 방식

 

scikit-learn 구현된 3가지 나이브 베이즈 분류기

  • GaussianNB
    • 연속적인 어떤 데이터도 적용 가능
    • 텍스트 데이터 분류에 주로 사용
  • BernoulliNB
    • 이진 데이터에 적용 가능
    • 텍스트 데이터 분류에 주로 사용
  • MultinomialNB
    • 카운트 데이터에 적용 가능
    • 카운트 데이터
      • 개수를 나타내는 정수형 특성

 

x = np.array([[0,1,0,1],
              [1,0,1,1],
              [0,0,0,1],
              [1,0,1,0]])
y = np.array([0,1,0,1])
 
counts ={}
for label in np.unique(y):
    counts[label] = x[y==label].sum(axis=0)
print("특성 카운트 :\n{}".format(counts))
 
특성 카운트 :
{0: array([0, 1, 0, 2]), 1: array([2, 0, 2, 1])}
 

np.unique는 중복제거, label은0과 1

배열 y에 == 0,1 연산 시 0,2와 1,3반환

 


결정 트리

  • 분류와 회귀 문제에 널리 사용하는 모델
  • 결정에 다다르기 위해 예/아니오 질문을 이어나가면서 학습

 

결정 트리의 학습

  • 정답에 가장 빨리 도달하는 질문 목록을 학습하는 것

 

테스트

  • 결정 트리의 질문들
    • 2차원 데이터 셋과 같이 연속적 데이터 형태
    • 연속적인 잘 인반화 되었는지 테스트하래 사용되는 데이터

 

가능한 모든 데이터에서 타깃값에 대해 가장 많은 정보를 가진 것 선탣

  • 첫 번쨰로 선택된 테스트
    • 데이터셋을 x[1]=0.0596에서 수평으로 나누는 것이 가장 많은 정보 포함
    • 이 직선이 클래스 0에 포인트와 클래스 1에 속한 포인트 분할
  • 루트 노드
    • 맨 위의 노드
    • 클래스 0의 포인트 75개, 클래스 1의 포인트 75개를 포함한 전체 데이터 셋
mglearn.plots.plot_tree_progressive()
 

가능한 모든 테스트에서 타깃값에 대해 가장 맋은 정보를 가짂 것 선택

  • 첫 번째로 선택된 테스트
    • 데이터셋을 x[1]=0.0596에서 수평으로 나누는 것이 가장 맋은 정보 포함
    • 이 직선이 클래스 0에 속핚 포인트와 클래스 1에 속핚 포인트 분핛 – 루트 노드(root node)
  • 루트 노드(root node)
    • 맨 위의 노드
    • 클래스 0의 포인트 75개, 클래스 1의 포인트 75개를 포함핚 전체 데이터셋

아래 영역에는 아직 클래스 0에 속한 포인트 포함

  • 위 영역에는 클래스 1에 속한 포인트 포함
  • 두 영역에서 가장 좋은 테스트를 찾는 과정 반복
    • 모델을 더 정확하게 할 수 있음

 

가장 많은 정보를 담을 수 있더럭 x[0] 값을 기준으로 횐쪽과 오른쪽 분할

  • 깊이 2인 감정트리기 만든 결정 경계

 

각 ㄴ\노드가 테스트 하나씩을 가진 이진 결정 트리 생성

  • 각 테스트는 하나의 축을 따라 데이터를 둘로 나누는 것
  • 계층적으로 영역을 분할해가는 알고리즘
  • 각 테스트는 하나의 특성에 대해선 이루어짐
    • 나누어진 영역은 항상 축에 평행한 모양

 

각 분할된 영역이 한 개의 타깃값을 가질 떄 까지 반복

  • 분할된 영역
    • 결정트리의 리프 노드
  • 타깃값
    • 하나의 클래스
    • 하나의 회귀 분석 결과
  • 순수 노드
    • 타깃 하나로만 이뤄진 리프 노드

 

새로운 데이터 포인트에 대한 예측

  • 주어진 데이터 포인트가 특성을 분활한 영역들 중 어디에 놓아는지 확인
  • 그 영역의 타깃값 중 다수인 것이 예측 결과
    • 순수 노드인 경우 하나
  • 루트 노드에서 시작
    • 데스트 결과에 따라 왼쪽 또는 오른쪽 트리 탐색

 

트리 생성기 모든 리프 노드가 순수 노드가 될 떄까지 진행 불가

  • 모델이 매우 복잡해짐
  • 훈련 데이터에 과대적합 될 수 있음

 

순수 노드로 이루어진 트리

  • 훈련 세트에 100%정확하게 맞다는 의미
  • 훈련 세트의 모든 데이터 포인트는 정황한 클래스의 리프 노드에 있음

 

과대 적합 그래프

  • 특정 케이스에 너무 꼭 맞음

 

글래스 1로 결정된 영역이 클래스 0의 포인트로 둘러싸인 모습

  • 그 반대 모습도 있음
  • 바람직한 결정 경계의 모습이 아님
  • 결정 경계가 클래슥의 포인드들에서 멀리 떨어진 이상치 하나에 너무 민감

 

과대적합을 막는 전략은 크게 두가지

  • 사전 가지치기
    • 트리 생성을 일찍 중단하는 전략
      • 1 : 트리의 최대 깊이나 리프의 최대 갯수를 제한
      • 2 : 노드가 분할하기 위한 포인트의 최고 개수를 지정
  • 사전 가지치기
    • 트리를 만든 후 데이터 포인트가 적은 노드를 삭제하거나 병합하는 전략

 


결정 트리 분석

 

시각화

장점

  • 알고리즘의 예측 과정의 이해
  • 비 전문가에게 머신러닝 알고리즘 설명하기에 좋음

 

단점

  • 깊이가 4단계나 되어도 매우 복잡해 짐
  • 트리의 깊이가 10단계 되면 한 눈에 보기가 힘듬

 

데아터가 많이 흐르는 경로를 관찰

  • 앞 결정 트리 그래프의 각 노드의 값
    • sample : 각 노드의 있는 샘플의 수
    • value : 클래스 당 샘플의 수

 

전체 트리를 분석하기는 어려움

  • 트리가 어떻게 작동하는지 요약하는 속성 사용 가능
  • 특성 중요도 서절
    • 0과 1사이의 숫자
      • 0 : 전혀 사용하지 않음
      • 1 : 완벽하게 타깃 클래스 예측
      • 특성 중요도 전체 합 : 1'

 

가장 중요한 특성의 분석

  • 첫 전쨰 노드에서 사용한 특성
  • 두 클래스 잘 분류 하고 있음

 

featue_importance, 값이 낮다고 해서 쓸모 없는 것은 아님

  • 트리가 그 특성을 선택하지 않았을 뿢
  • 다른 특성이 동일한 정보를 자나고 있었을 수 있다.

 

import os
ram_prices = pd.read_csv(os.path.join(mglearn.datasets.DATA_PATH, 
"ram_price.csv"))
plt.yticks(fontname = "Arial") # 한글 폰트가 지수에 음수를 표시하지 못하므로
ytick의 폰트를 바꾸어 줍니다.
plt.semilogy(ram_prices.date, ram_prices.price)
plt.xlabel("년")
plt.ylabel("가격 ($/Mbyte)")
 

출력 결과 분석

날짜 특성 하나맊으로 2000년도 후의 가격 예측 –

  • 2000년도 이젂 데이터셋을 이용핚 학습
  • 2가지 모델 비교
      • DecisionTreeRegressor
      • LinearRegression –
  • 가격을 로그 스케일로 변경
    • 비교적 선형적인 관계
    • DecisionTreeRegressor에는 차이 없음
    • LinearRegression에는 큰 차이 발생
  • 모델의 훈렦 이후 예측 수행
    • 로그 스케일을 되돌리기 위해 지수 함수 적용
  • 그래프의 표현을 위해 젂체 데이터 셋에 대해 예측 수행
    • 실제 테스트 데이터셋과 비교 목적
from sklearn.linear_model import LinearRegression
 
from sklearn.tree import DecisionTreeRegressor

data_train = ram_prices[ram_prices.date < 2000]
data_test = ram_prices[ram_prices.date >= 2000]
X_train = data_train.date[:, np.newaxis]

y_train = np.log(data_train.price)
tree = DecisionTreeRegressor().fit(X_train, y_train)
linear_reg = LinearRegression().fit(X_train, y_train)

X_all = ram_prices.date[:, np.newaxis]
pred_tree = tree.predict(X_all)
pred_lr = linear_reg.predict(X_all)

price_tree = np.exp(pred_tree)
price_lr = np.exp(pred_lr)
 
plt.yticks(fontname = "Arial")
plt.semilogy(data_train.date, data_train.price, label="훈련 데이터")
plt.semilogy(data_test.date, data_test.price, label="테스트 데이터")
plt.semilogy(ram_prices.date, price_tree, label="트리 예측")
plt.semilogy(ram_prices.date, price_lr, label="선형회귀 예측")
plt.legend()
 

선형모델은 직선으로 데이토 표시

  • 훈련데이터와 테스트 데이터에 있는 미세한 굴곡을 매끈하게 표시
  • 2000년도 이후를 정확히 예측

 

트리모델은 훈련 데이터를 완벽하게 예측

  • 트리의 복잡도에 제한을 두지 않아서 전체 데이터셋 모두 기억
  • 데이터 범위 밖으로 나가면 단순히 마지막 포인트를 이용한 예측
    • 훈련 데이터 밖의 새로운 데이터를 예측할 능력이 없음
    • 모든 트리 기반 모델의 공통적 단점

 

결정 트리에서 모델 복잡도를 조절하는 매개변수

  • 트리가 완전히 만들어지기 전에 멈추게 하는 사전 가지치기 매개 변수
    • max_depth
    • max_leaf_nodes
    • min_sample_leaf

 

 

결정트리의 장점

  • 생성된 모델을 쉽게 시각화 가능
    • 비교적 작은 트리인 경우 비전문자도 이해하기 쉬움
  • 데이터 분할 시 데이터의 스케일에 구애 밪디 않음
    • 각 특성이 개별적으로 처리
    • 특성의 정규화나 표준화 같은 전처리 불필요
    • 특성의 스케일이 서로 다르거나 특성이 혼합된 경우도 잘 작동함
      • 이진 특성과 연속적인 특성 등

 

결정트리 단점

  • 일반화 성능이 좋지 않음
    • 사전 가지치기를 사용함에도 불구하고 과대적합되는 경향
  • 단일 결정 트리의 대안
    • 앙상블 기법

 


결정 트리의 앙상블

 

앙상블

  • 전체적인 어울림이나 통일성, 조화로움
  • 여러 머신러닝 모델을 연결하여 더 강력한 모델을 만드는 기법
  • 머신러닝에 있는 많은 종류의 앙상블 모델
    • 두 앙상블 모델이 분류와 회귀 문제에 효과적

 

가장 효과적인 2가지 앙상블 모델

  • 랜덤 포레스트 결정트리
  • 그래디언트 부스팅 결정트리
    • 둘 다 모델을 구성하는 기본 요소로 결정 트리 사용

 

훈련 데이터에 과대적합 되는 문제 회피 가능

  • 결정 트리의 주요 단점인 과대적합을 피할 수 있음
  • 다른 결정 트리의 묶음 형태

 

랜덤 포레스트 구현 전략

  • 결정 트리를 많이 생성하는 전략
    • 각 트리는 티겟 예측을 잘해야 함
    • 다른 트리와 서로 구별되어애 함
  • 랜덤 포레스트 의미
    • 트리들이 서로 달라지도록 트리 생성 시 무작위성 주입
  • 트리를 랜덤하게 만드는 방법
    • 트리를 만들 때 사용하는 데이터 푀인트를 무작위로 선택하는 방법
    • 분할 테스트에서 특성을 무작위로 선택하는 방법

 

생성할 트리의 개수를 정해야 함

  • RandomForestRegressor나 RandomForestClassifier의 n_estimators 파라미터
  • 트리가 10개 필요하다고 가정
  • 트리들은 완젂히 독립적으로 생성해야 함
  • 알고리즘은 각 트리가 고유하게 만들어지도록 무작위 선택 진행

 

부트스트랩 샘플 생성

  • n_samples개의 데이터 포인트 중에서 무작위로 n_samples 횟수 만큼 반복 추출
    • 한 샘플이 여러 번 중복 추출 될 수 있음
  • 이 데이터셋은 원래 데이터셋 크기와 동일
    • 데이터 포인트는 누락될 수 있음 (약 1/3 정도)
    • 데이터 포인트는 중복될 수 있음

 

랜덤 포레스트의 트리가 조금씩 다른 데이터셋을 이용해 생성

  • 각 노드에서 특성의 일부만 사용
    • 트리의 각 분기는 각기 다른 특석 부분 집합을 사용
  • 이러한 방식으로 랜덤 포레스트의 모든 트리가 서로 달라지도록 생성

 

 

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_moons

X, y = make_moons(n_samples=100, noise=0.25, random_state=3)
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, 
random_state=42)
forest = RandomForestClassifier(n_estimators=5, random_state=2)
forest.fit(X_train, y_train)
 
fig, axes = plt.subplots(2,3, figsize=(20,10))
for i, (ax, tree) in enumerate(zip(axes.ravel(), forest.estimators_)):
 ax.set_title("트리 {}".format(i))
 mglearn.plots.plot_tree_partition(X, y, tree, ax=ax)
 
mglearn.plots.plot_2d_separator(forest, X, fill=True, ax=axes[-1, -1], 
alpha=.4)
axes[-1, -1].set_title("랜덤 포레스트")
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
 

확연히 다른 모양의 다섯개 트리의 결정 경계

  • 부트스트랩 샘플링 떄문에 각 트리는 불완전
  • 한 쪽 트리에 나타는 훈련 포인드가 다른 트리에 없을 수 있음

랜덤 포레스트

  • 개개의 트리보다 덜 과대적합, 평균을 이용해 훨씬 더 좋은 결정 경계 생성
  • 실제 응용에서는 수백, 수천개 트리를 사용하므로 더 부드러운 결정 경계 생성 가능

 

랜덤 포레스트 장점

  • 회귀와 분류에 있어서 랜덤 포레스트
    • 현재 가장 널리 사용도고 머신러닝 알고리즘
    • 성능이 매우 뛰어나고 매개변수 튜닝을 많이 하지 않아도 작동
    • 데이터의 스케일으 맞출 필요 없음
    • 단일 트리의 단점을 보완하고 장점을 유지
  • 랜덤 포레스트 보다 단일 트리가 적합한 경우
    • 의사 결정 과정을 간소하게 표현하려면 단일 트리 사용 가능
      • 수백개의 트리를 분석하기는 어려움
      • 특성의 일부만 사용하므로 결정트리보다 더 깊어지는 경향이 있음
    • 비전문가에게 예측과정을 시각적으로 보여주기 위한 목적

 

랜덤 포레스트 단점

  • 선형모델보다 많은 메모리 사용
    • 훈련과 예측이 느린편
    • 속도와 메모리 사용에 제약이 있는 응용
      • 선형 모델 적합

 

데이터셋 처리

대량의 데이터셋에서는 시간이 걸릴 수 있음

  • CPU 코어가 많다면 손 쉽게 병렬처리 가능
  • 멀티 코어 프로세서일 경우 n_jobs 매개변수 이용
    • 코어 수 지정 가능
    • 요즘 거의 모든 컴퓨터가 코어가 둘 이상
  • 사용하는 CPU 코어 개수에 비례해서 속도 향상
    • 코어를 2개 사용하면 랜덤 포레스트의 훈련 속도도 두배 빨라짐
  • n_jobs 매개변수를 코어 개수보다 크게 지정하는 것은 도움되지 않음
    • n_jobs=-1로 지정 시 컴퓨터의 모든 코어를 사용

 

 

 

 

.

.

어허 이게 맞나

왜 이론수업이 되어가니...

어려워욧.....

 

 

 

 

#ABC부트캠프 #부트캠프 #유클리드소프트 #파이썬 #고용노동부 #한국산업인력공단 #청년친화형 #ESG지원사업 #대전 #서포터즈 #python #Ai #Bigdata #cloud #대외활동 #대학생 #daily

 

Comments