ABC 부트캠프/머신러닝

19일차 - 지도학습 2

멋진단지 2023. 4. 12. 02:21

나이브 베이즈 분류기

  • 선형 모델과 매우 유사한 분류기.
  • 각 특성을 개별로 취급해 파라미터 학습.
  • 각각의 통계를 다 내어 취합하는 방식.

 

  • GaussianNB
    • 연속적인 데이터에서도 적용 가능
    • 텍스트 데이터 분류에 주로 사용
  • BernoulliNB
    • 이진 데이터에 적용 가능
    • 텍스트 데이터 분류에 주로 사용
  • MultinomialNB
    • 카운트 데이터에 적용 가능.
    • 카툰트 데이터 -> 개수를 나타내는 정수형 특성 (문장에 나타난 단어의 횟수)

 

 

 

 

+ 파이썬 Numpy의 axis를 이용한 덧셈

  • axis를 이용하여 배열의 축을 이용한 덧셈

 

axis가 증가할 수록 안쪽으로 들어감.

 

 

  • 매개변수
    • 매개 변수 조절만으로 정확도를 높일 수 있음.
    • alpha: 모델의 복잡도를 조절 (alpha가 크면 완만해지고 복잡도 낮아짐.)
  • 장, 단점
    • 선형 모델로는 학습시간이 너무 오래 걸리는 매우 큰 데이터셋에 적합.
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("특성 카운트:", counts)

 

 

print("np.unique(y)=", np.unique(y))
# np.unique(y)= [0 1]

print("y == 0:", y == 0)
print("y == 1:", y == 1)
# y == 0: [ True False  True False]
# y == 1: [False  True False  True]

print("X[y == 0]:\n", X[y == 0])
print("X[y == 1]:\n", X[y == 1])

 

 

 

 


결정 트리 (Diecision Tree)

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

 

 

 

과대적합을 막는 전략

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

cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
    cancer.data, cancer.target, stratify=cancer.target, random_state=42)

tree = DecisionTreeClassifier(random_state=0)
tree.fit(X_train, y_train)
print("훈련 세트 정확도: {:.3f}".format(tree.score(X_train, y_train)))
print("테스트 세트 정확도: {:.3f}".format(tree.score(X_test, y_test)))

과대적합 상태

훈련 세트 정확도는 100이지만

테스트 세트 정확도가 많이 차이남 -> 과대적합 상태.

 

 

 

사전 가지치기 예제

tree = DecisionTreeClassifier(max_depth=4, random_state=0)
tree.fit(X_train, y_train)
print("훈련 세트 정확도: {:.3f}".format(tree.score(X_train, y_train)))
print("테스트 세트 정확도: {:.3f}".format(tree.score(X_test, y_test)))

훈련 세트 정확도는 떨어졌지만

테스트 세트 정확도가 올라갔음! 

 

 

for i in range(1,10):
    tree = DecisionTreeClassifier(max_depth=i, random_state=0)
    tree.fit(X_train, y_train)
    print("Test Set Accuracy({}):{:.3f}".format(i,tree.score(X_test, y_test)))

for문을 이용하여 depth의 값을 변경해 정확도가 가장 높은 depth 값 찾기.

 

 

 

 

from sklearn.tree import export_graphviz

# 트리를 시각화.
# .dot -> 노드 사이의 연결을 저장해놓은 텍스트 파일
export_graphviz(tree, out_file="tree.dot", class_names=["악성","양성"],
    feature_names=cancer.feature_names, impurity=False, filled=True)
import graphviz
with open("tree.dot", encoding = "UTF-8") as f:
    dot_graph = f.read()
display(graphviz.Source(dot_graph))
from sklearn.tree import plot_tree
plt.figure(figsize=(12,6))
plot_tree(tree, class_names=["악성","양성"], feature_names=cancer.feature_names,
          impurity=False, filled=True, rounded=True, fontsize=6)
plt.show()

  • 트리를 시각화한다면 알고리즘 예측 과정을 이해시킬 수 있음.
  • 비 전문가에게 머신러닝 알고리즘 설명하기에 좋음.

 

 

 

 

특성 중요도

  • 0: 전혀 사용되지 않음
  • 1: 완벽하게 타깃 클래스 예측
  • 특성 중요도 전체 합: 1

 

L1 모델은 중요도 0을 다 지워버림.

 

 

 

 

특성과 클래스 간의 분석

  • class , target, label 다 비슷한 말.
    • ex) 악성, 양성
  • 선형 모델의 계수와는 달리 특성의 중요도는 항상 양수
  • 특성이 어떤 클래스를 지지하는지 알 수 없음.
  • worst radius(높은 반지름)이 중요하다는 것을 알 수 있음.
  • 높은 반지름이 양성, 악성을 의미하는지 알 수 없음.

 

이런 그래프로는 결정 트리를 사용하기 어려움.

 

선형 모델은 훈련 데이터 밖의 포인터에 대해 예측을 할 수 있음.

결정 트리 모델은 훈련 데이터 범위 밖의 포인터에 대해 예측을 할 수 없음.

외삽(extrapolation) 불가

훈련 데이터의 범위 밖의 포인터에 대해 예측을 할 수 없음.

 

 

 

 

컴퓨터 메모리 가격 동향 데이터셋

  • 컴퓨터 메모리 가격 동향 데이터셋을 이용한 예제
  • X축: 날짜
  • Y축: 해당 년도의 랠(RAM) 1메가바이트당 가격

 

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

2000년도 이전 데이터셋을 이용한 학습

두 가지 모델 비교

DecisionTreeRegressor

LinearRegression 

import os
ram_prices = pd.read_csv(os.path.join(mglearn.datasets.DATA_PATH,"ram_price.csv"))
plt.yticks(fontname="Arial")
plt.semilogy(ram_prices.date, ram_prices.price)
plt.xlabel("년")
plt.ylabel("가격($/Mbyte)")

로그 스케일로 그린 램 가격 동향

 

 

 

from sklearn.tree import DecisionTreeRegressor
from sklearn.linear_model import LinearRegression

data_train = ram_prices[ram_prices.date<2000]
data_test = ram_prices[ram_prices.date >= 2000]

X_train = data_train.date.to_numpy()[:, 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.to_numpy()[:, 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.semilogy(data_train.date, data_train.price, label="train data")
plt.semilogy(data_test.date, data_test.price, label="test data")
plt.semilogy(ram_prices.date, price_tree, linestyle="dashed", label="tree prediction")
plt.semilogy(ram_prices.date, price_lr, linestyle="dashed", label="lr prediction")
plt.legend()

2000년 이전 데이터로 학습, 2000년 이후 데이터로 테스트

트리는 있는 데이터로 학습하기 때문에 다음 데이터는 예측 불가능.

선형 모델은 실제 2000년 이전으로 학습했어도 그 뒤 내용을 예측 가능함.

 

트리 예측은 외부 데이터 예측은 불가능, 데이터 안에서 예측할 수 있음.

 

 

 

 

결정 트리에서 복잡도 조절 매개변수

  • 트리가 완전히 만들어지기 전에 멈추게 하는 사전 가지치기 매개 변수
  • 한 가지만 사용해도 과대적합 방지 가능
    • max_depth
    • max_leaf_nodes
    • min_samples_leaf

 

 

단점

일반화 성능이 좋지 않음 -> 사전 가지치기를 사용함에도 불구하고 과대적합되는 경향

앙상블 기법이 좋음...

 

 

 

 

 


결정 트리의 앙상블

  • 앙상블: 여러 머신러닝 모델을 연결하여 더 강력한 모델을 만드는 기법.
    • 랜덤 포레스트(Random Forest) 결정 트리
    • 그래디언트 부스팅(Gradient Boosting) 결정 트리

 

 

 

 

랜덤 포레스트

  • 여러 결정 트리의 묶음.
  • 훈련 데이터에 과대적합 되는 문제 회피 가능
  • 결정 트리의 주요 단점인 과대적합을 피할 수 있음. → (원래 트리) 결정적인 한 데이터로 정확도가 바뀔 수 있음.

 

1. 생성할 트리의 개수 

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

 

2. 부트스트랩 샘플(bootstrap sample) 생성

  • n_samples 개의 데이터 포인트 중에서 무작위로 n_samples 횟수 만큼 반복 추출.

 

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

 

 

  • 핵심 매개변수
    • max_features 
    • 트리의 깊이는 낮게 설정해주는 것이 좋음.

 

회귀: 예측들을 평균하여 최종 예측 생성

분류: 약한 투표 전략 사용, 각 알고리즘이 가능성 있는 출력 레이블의 확률을 제공.

 

 

 

 

 

 

랜덤 포레스트 분석

two_moon 데이터셋 활용

noise -> 불규칙한 자연 데이터 넣어주기.

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)

5개의 트리들을 다 합친 것이 랜덤 포레스트이다.

실제 응용에서는 수백, 수천개 트리를 사용하므로 더 부드러운 결정 경계 생성 가능.

 

 

 

 

유방암 데이터셋

100개의 트리로 이루어진 랜덤 포레스트 적용하기.

 

 

랜덤 포레스트보다 단일 트리가 적합한 경우

  • 의사 결정 과정을 간소하게 표현하려면 단일 트리 사용 가능.
    • 수백개의 트리를 분석하기는 어려움.
    • 특성의 일부만 사용하므로 결정 트리보다 더 깊어지는 경향이 있음
  • 비 전문가에세 예측 과정을 시각적으로 보여주기 위한 목적.

 

언어처리로는 부적합함.

텍스트 데이터 같은 고차원 데이터는 선형 모델이 좋음.

빠르게 처리  → 선형모델

적합한 정보 → 랜덤 포레스트