생각하는 감쟈
[Python] 4-3) 머신러닝 - 결정트리.. 본문
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'
- 0과 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
'Language > Python' 카테고리의 다른 글
[Python] 5-1) 딥러닝 흐름 (0) | 2023.06.10 |
---|---|
[Python] 4-4) 머신러닝 - 그래디언트,커널 (1) | 2023.06.10 |
[Python] 4-2) 머신러닝 - 지도학습 알고리즘 (1) | 2023.04.13 |
[Python] 4-1) 머신러닝 기초 (0) | 2023.04.06 |
[Python] 3-2) 정규표현식, 워드클라우드 (0) | 2023.04.06 |