/ STUDY

머신러닝 정리 (2)
지도학습 (2)

머신러닝 공부 관련 글

머신러닝 정리 (2) - 지도학습 (2)

본 문서는 [파이썬 라이브러리를 활용한 머신러닝] 책을 공부하면서 요약한 내용입니다.
또 데이터 청년 캠퍼스 수업과 학교 수업에서 배운 내용들도 함께 정리했습니다.
글의 순서는 [파이썬 라이브러리를 활용한 머신러닝]에 따라 진행됩니다.
코드는 밑에 링크에 공개되어있기 때문에 올리지않습니다.

소스 코드: https://github.com/rickiepark/introduction_to_ml_with_python

지도학습 (2)

  1. 결정 트리
  2. 결정 트리의 앙상블
  3. 배깅, 엑스트라 트리, 에이다부스트
    1. 배깅
    2. 엑스트라 트리
    3. 선형 모델
    4. 에이다부스트
  4. 커널 서포트 벡터 머신
  5. 신경망 (딥러닝)
  6. 분류 예측의 불확실성 추정
    1. 결정 함수
    2. 예측 확률
    3. 다중 분류에서의 불확실성

결정 트리

Decision Tree

결정 트리는 분류와 회귀 문제에서 사용되는 모델입니다.
스무고개처럼 예/아니오로 나눌 수 있는 조건을 통해서 결정에 다다르게 됩니다.
질문과 정답은 노드가 되고 특히 마지막 노드는 리프라고 합니다.

tree1

결정트리의 구조는 왼쪽 하단에 사진처럼 가장 위에는 Root node, 질문과 답을 연결하는 Edge, 내부의 Internal node, 마지막 노드는 Leaf node, 그리고 Depth로 구성됩니다.




결정 트리 만들기


결정 트리를 학습한다는 것은 정답에 가장 빨리 도달하는 예/아니오 질문 (TEST) 목록을 학습한다는 뜻입니다.
보통 데이터들은 예/아니오 특성으로 구분되지 않고 연속적인 특성을 가진 2차원 데이터 셋에서 보통 ‘특성 i는 값 a보다 큰가?’의 형태와 같은 테스트를 가집니다.

tree2

이 데이터들을 X[1]<=0.6인 테스트로 나누어 봅니다.

tree3

알고리즘은 가능한 모든 테스트에서 타깃 값에 대해 가장 많은 정보를 가진 것을 고르게 됩니다.

따라서 X[1]<=0.6인 테스트를 선택하게 됩니다.

tree5

결정 트리에서 각 테스트는 하나의 축을 따라 데이터를 나눕니다.
하나의 질문당 하나의 축을 만들어서 영역이 한 개의 타깃값을 가질 때까지 반복됩니다.

tree4

결정 트리의 멈춤 조건입니다.
즉, 미리 정의한 조건들이 없다면 가지를 만들 수 있을 때까지 만드는 것을 알 수 있습니다.
결정트리의 예측은 그 포인트가 어느 리프에 들어갈지 확인하는 것인데 분류는 타깃 값 중 다수인 것이 예측 결과가 되고 회귀의 경우 리프 노드의 훈련 데이터 평균값이 결과로 출력됩니다.




결정 트리 복잡도 제어하기


결정 경계가 클래스 포인트에 멀리 떨어진 이상치에 민감하게 되어 모든 리프 노드가 순수 노드가 될 때까지 진행하면 모델이 복잡해지고 과대적합이 발생합니다.
과대적합을 막기 위한 방법은 크게 사전가지치기, 사후 가지치기 두 가지입니다.
사전 가지치기는 이름에서 알 수 있듯이 모델을 만들 때 깊이나 리프의 개수 또는 테스트의 최소 개수를 미리 제한하는 것입니다.
미리 제한하기 때문에 정말로 중요한 포인트를 분류하지않을 수 있습니다.
사후 가지치기 역시 이름에서 알 수 있듯이 트리가 만들어진 뒤 포인트가 적은 노드를 삭제 혹은 병합하게 되는데 에러감소 프루닝, 룰 포스트 프루닝 같은 방법들이 있습니다.


참고
에러감소 프루닝

모든 노드를 프루닝 대상으로 고려
노드 제거 후 검증을 통해 제거 전, 후 정확도 비교
제거 전보다 정확도가 낮아지기 전까지 반복

룰 포스트 프루닝

의사결정 트리를 룰셋으로 변환 (룰은 루트부터 리프까지의 경로)
이 룰셋 속성들에 정확도를 떨어뜨리는 속성을 제거
프루닝 완료 후 정확도 순으로 정렬해 이 순서대로 적용



결정 트리는 다음과 같이 만들 수 있고 정확도를 확인할 수 있습니다.
Default값은 모든 리프가 순수 노드가 되는 모델을 만들기 때문에 훈련 세트의 정확도가 100%가 됩니다.
하지만 트리가 무한정 깊어지고 복잡해지고 일반화가 잘 되지 않습니다.

from sklearn.tree import DecisionTreeClassifier

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)))

훈련 세트 정확도: 1.000
테스트 세트 정확도: 0.937


과대적합 때문에 반드시 훈련 세트의 정확도가 테스트 정확도와 비례하지 않아서 max_depth와 같은 파라미터를 통해 과대적합을 줄이고 테스트 세트 정확도를 높일 수 있습니다.



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)))

훈련 세트 정확도: 0.988
테스트 세트 정확도: 0.951




결정 트리 분석


결정 트리를 생성하고 시각화하기 위해서는 다음과 같은 모듈이 필요합니다.

# 트리 모델 생성
from sklearn.tree import DecisionTreeClassifier 

# 트리의 시각화_1
from sklearn.tree import export graphviz 

# 트리의 시각화_2 (.dot 파일을 만들지 않아도 가능)
from sklearn.tree import plot_tree 


그래프를 시각화하는 코드는 다음과 같이 쓸 수 있습니다.

# graphviz 이용
from sklearn.tree import export_graphviz

export_graphviz(tree, out_file="tree.dot", class_names=["악성", "양성"],
                feature_names=cancer.feature_names, impurity=False, filled=True)

#plot_tree
from sklearn.tree import plot_tree

plot_tree(tree, class_names=["악성", "양성"], feature_names=cancer.feature_names,
         impurity=False, filled=True, rounded=True, fontsize=4)

filled=True를 넣어주면 다음과 같이 색상이 들어가는 트리 모델을 얻을 수 있습니다.

tree8




트리의 특성 중요도


tree.feature_importane를 통해 특성 중요도를 알 수 있습니다.
특성 중요도는 0부터 1 사이에 존재하는데 0은 전혀 사용되지 않은 특성, 1은 완벽하게 타깃 클래스를 예측한 특성을 의미합니다.
특성 중요도가 낮다는 유용하지 않다가 아닌 모델이 만들어질 때 특성을 선택하지 않았거나 특성과 중복되는 정보가 있다는 것을 의미합니다.
전체 합은 1이 되고 따라서 특성중요도는 ‘이 모델이 만들어지는데 어떤 특성의 비율이 높은가?’ 정도의 해석이라고 생각하면 될 것 같습니다.
Worst_radius만 보고 ‘반지름이 크면 양성이다?’ 를 알 수 없는 것처럼 특성 중요도는 어떤 클래스를 지지하는지 알려주지 않습니다.

결정 트리의 회귀도 분류와 비슷하게 적용됩니다. 단, 결정 트리를 회귀 모델로 사용하게 되면 훈련 데이터 범위 밖의 정보가 없어서 그 부분에 대한 예측이 불가능하게 됩니다.

tree9

다음 모델은 트리 복잡도에 제한을 두지않아서 훈련 데이터는 완벽하게 예측하지만 데이터 범위 밖으로 나가면 마지막 포인트로 예측값을 출력합니다. 따라서 트리 모델은 가격의 등락과 같은 예측을 할 때는 좋은 예측 모델을 만들 수 있지만 시계열 데이터에서는 데이터가 가진 시간 범위 밖의 예측은 안되기 때문에 잘 맞지 않습니다.



장단점과 매개변수


장점

해석력이 높습니다.
데이터의 스케일에 구애받지 않습니다.
정규화나 표준화 같은 전처리 불필요합니다. 특성의 스케일이 다르거나 이진특성, 연속적인 특성이 혼합되어도 잘 작동합니다.

단점

과대적합되는 경향이 있어 일반화 성능이 좋지 않습니다.
축 평행을 구분하여 일부 관계에서 모델링이 어려움이 있습니다.
훈련 데이터에 대한 약간의 변경은 전체 결정논리에 큰 변화를 야기하여 샘플에 민감합니다.


매개변수 설명
min_samples_split - 노드를 분할하기 위한 최소한의 샘플 데이터수 → 과적합을 제어하는데 사용
- Default = 2 → 작게 설정할 수록 분할 노드가 많아져 과적합 가능성 증가
min_samples_leaf - 리프노드가 되기 위해 필요한 최소한의 샘플 데이터수
- min_samples_split과 함께 과적합 제어 용도
- 불균형 데이터의 경우 특정 클래스의 데이터가 극도로 작을 수 있으므로 작게 설정 필요
max_features - 최적의 분할을 위해 고려할 최대 feature 개수
- Default = None → 데이터 세트의 모든 피처를 사용
- int형으로 지정 →피처 갯수 / float형으로 지정 →비중
- sqrt 또는 auto : 전체 피처 중 √(피처개수) 만큼 선정
- log : 전체 피처 중 log2(전체 피처 개수) 만큼 선정
max_depth - 트리의 최대 깊이
- default = None
→ 완벽하게 클래스 값이 결정될 때 까지 분할 또는 데이터 개수가 min_samples_split보다 작아질 때까지 분할
- 깊이가 깊어지면 과적합될 수 있으므로 적절히 제어 필요
max_leaf_nodes 리프노드의 최대 개수

여기서 max_depth, max_leaf_nodes,min_samples_leaf 중 하나만 지정해도 과대적합을 막는데 충분한 역할을 합니다.




결정 트리의 앙상블

Ensemble

앙상블은 여러 머신러닝 모델을 연결하여 더 강력한 모델을 만드는 기법입니다.
책에서는 결정 트리의 앙상블로 한정하고 가장 많이 쓰이는 랜덤포레스트나 부스팅 모델은 트리 기반 모델이지만 앙상블은 다른 분류 모델을 결합하여 사용할 수도 있습니다.

  • Voting – 서로 다른 알고리즘을 가진 분류기를 결합
  • Bagging – 각각의 분류기는 모두 같은 유형의 알고리즘 기반, 모델을 다양하게 만들기 위해 데이터를 재구성 (랜덤포레스트)
  • Boosting – 맞추기 어려운 데이터에 대해 좀 더 가중치를 두어 학습 (Adaboost, Gradient Boosting)
  • Stacking – 모델의 output 값을 새로운 독립변수로 사용

ensemble1

앙상블의 조건입니다.



랜덤 포레스트


랜덤 포레스트는 조금씩 다른 결정 트리의 묶음입니다.
데이터의 일부에 과대적합되는 경향을 이용하여 서로 다른 방향으로 과대적합된 트리를 많이 만들어 그 결과를 평균냄으로써 예측 성능은 유지되면서 결과적으론 과대적합이 줄어드는 아이디어에 기초합니다.
결정 트리를 많이 만들면서 각 트리는 타깃 예측을 잘 해야 하고 다른 트리와 구별되어야 합니다.
따라서 무작위성을 주입하는데 트리를 만들 때 사용하는 데이터 포인트를 무작위로 선택하거나 분할 테스트에서 특성을 무작위로 선택하는 방법을 이용합니다.



랜덤 포레스트 구축


from sklearn.ensemble import RandomForestClassifier (or RandomForestRegressor)
n_estimators로 생성할 트리의 개수를 정합니다.
부트스트랩 샘플은 n_samples개의 데이터 포인트 중에서 n_samples 횟수만큼 무작위로 중복 가능하게 반복 추출하는 것을 의미합니다.
따라서 데이터 셋이 원래 크기와 같지만 누락되거나 중복되는 데이터가 만들어집니다.

ensemble2


각 노드에서 전체 특성을 대상으로 최선의 테스트를 찾는 것이 아닌 알고리즘이 각 노드에서 후보 특성을 무작위로 선택한 후 이 후보들 중에서 최선의 테스트를 찾습니다. (max_features)
부트스트랩 샘플링을 통해 트리가 조금씩 다른 데이터셋을 이용해 만들어지도록 합니다.
각 노드에서 특성의 일부만 사용하기 때문에 트리의 각 분기는 각기 다른 특성 부분 집합을 사용됩니다.

max_features=n_features는 특성 선택에 무작위성이 들어가지 않습니다. (부트스트랩 샘플링에는 무작위성 그대로 입니다.)
max_feature=1 트리의 분기는 테스트할 특성을 고를 필요가 없게 되고 무작위로 선택한 특성의 임계값 찾기만 하면 됩니다.
max_feature이 커지면 랜덤 포레스트 트리들은 매우 비슷하고 가장 두드러진 특성으로 데이터에 잘 맞춰질 것이고 작으면 트리들은 서로 많이 달라지고 각 트리는 데이터에 맞추기 위해 깊이가 깊어지게 됩니다.

랜덤 포레스트 예측의 경우 알고리즘이 모델에 있는 모든 트리의 예측을 만듭니다.
회귀의 경우 이 예측들을 평균하여 최종 예측을 만듭니다.
분류의 경우 약한 투표 전략을 사용합니다.
약한 투표 전략은 각 알고리즘이 가능성 있는 출력 레이블의 확률을 제공하고 예측한 확률을 평균으로 가장 높은 확률을 가진 클래스가 예측값이 됩니다.
참고로 강한 투표 전략은 다수의 분류기가 결정한 예측값을 최대로 하는 것을 말합니다.


ensemble3




랜덤 포레스트 분석


랜덤 포레스트 훈련 모델

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)

ensemble4

부트스트랩 샘플링 때문에 한쪽 트리에 나타나는 훈련 포인트가 다른 트리에는 포함되지 않을 수 있어 각 트리는 불완전하지만 랜덤포레스트의 결과는 좋은 결정경계를 보여줍니다.


ensemble5

단일 트리와 다르게 랜덤 포레스트에서 가장 특성 중요도가 높은 특성은 worst perimeter입니다.
랜덤 포레스트에서 더 많은 특성이 0 이상의 중요도를 갖고 따라서 더 넓은 시각으로 데이터를 바라볼 수 있습니다.


X_train, X_test, y_train, y_test = train_test_split(
    cancer.data, cancer.target, random_state=0)
forest = RandomForestClassifier(n_estimators=100, random_state=0)
forest.fit(X_train, y_train)

print("훈련 세트 정확도: {:.3f}".format(forest.score(X_train, y_train)))
print("테스트 세트 정확도: {:.3f}".format(forest.score(X_test, y_test)))

훈련 세트 정확도: 1.000
테스트 세트 정확도: 0.972


랜덤 포레스트에선 훈련 데이터 정확도가 100% 이지만 단일 트리에 비해서 테스트 정확도가 상승한 것을 확인 할 수 있습니다.




장단점과 매개변수


장점

매개변수 튜닝을 많이 하지 않습니다.
데이터의 스케일에 구애받지 않습니다.
단일 트리의 단점을 보완하고 장점을 그대로 가지고 있습니다.

단점

랜덤 포레스트의 트리는 특성의 일부만 사용하므로 결정 트리보다 더 깊어지는 경향이 있습니다.
다른 random_state를 지정하면 전혀 다른 모델이 만들어집니다.
텍스트 데이터와 같은 차원이 높고 희소한 데이터에 잘 작동하지 않습니다.
선형 모델에 비해 많은 메모리를 사용하며 훈련과 예측이 느림


매개변수 설명
n_estimators - 결정트리의 갯수를 지정
- Default = 10 (0.22버전부터 100)
- 무작정 트리 갯수를 늘리면 성능 좋아지는 것 대비 시간이 걸릴 수 있음
min_samples_split - 노드를 분할하기 위한 최소한의 샘플 데이터수 → 과적합을 제어하는데 사용
- Default = 2 → 작게 설정할 수록 분할 노드가 많아져 과적합 가능성 증가
min_samples_leaf - 리프노드가 되기 위해 필요한 최소한의 샘플 데이터수
- min_samples_split과 함께 과적합 제어 용도
- 불균형 데이터의 경우 특정 클래스의 데이터가 극도로 작을 수 있으므로 작게 설정 필요
max_features - 최적의 분할을 위해 고려할 최대 feature 개수
- Default = ‘auto’ (결정트리에서는 default가 none이었음)
- int형으로 지정 →피처 갯수 / float형으로 지정 →비중
- sqrt 또는 auto : 전체 피처 중 √(피처개수) 만큼 선정 (RandomForestClassifier-sqrt(n_feature), RandomForestRegressor-n_feature)
- log : 전체 피처 중 log2(전체 피처 개수) 만큼 선정
max_depth - 트리의 최대 깊이
- default = None
→ 완벽하게 클래스 값이 결정될 때 까지 분할 또는 데이터 개수가 min_samples_split보다 작아질 때까지 분할
- 깊이가 깊어지면 과적합될 수 있으므로 적절히 제어 필요
max_leaf_nodes 리프노드의 최대 개수

N_estimatiors는 클수록 좋고 max_features와 max_depth와 같은 사전 가지치기 옵션은 단일 트리와 같이 주어집니다.




그레이디언트 부스팅 회귀 트리


gradient


이름은 회귀이지만 회귀와 분류 모두 사용됩니다. (GradientBoostingClassifier, GradientBoostingRegressor)
그레이디언트 부스팅은 이전 트리의 오차를 보완하는 방식으로 순차적으로 트리를 만듭니다.
따라서 기본적으로 무작위성이 없습니다.
대신 강력한 사전 가지치기가 사용되고 깊지 않은 트리를 사용합니다.
각 트리는 데이터의 일부에 대해서만 예측을 잘 수행하여 트리가 많이 추가될수록 성능이 향상됩니다.
이때 손실 함수를 정의하고 경사 하강법을 사용해서 다음 값을 보정합니다.

gradient1



random_state=0 만 입력했을 때

from sklearn.ensemble import GradientBoostingClassifier

X_train, X_test, y_train, y_test = train_test_split(
    cancer.data, cancer.target, random_state=0)

gbrt = GradientBoostingClassifier(random_state=0)
gbrt.fit(X_train, y_train)

print("훈련 세트 정확도: {:.3f}".format(gbrt.score(X_train, y_train)))
print("테스트 세트 정확도: {:.3f}".format(gbrt.score(X_test, y_test)))

훈련 세트 정확도: 1.000
테스트 세트 정확도: 0.965


random_state=0, max_depth=1 을 입력했을 때

gbrt = GradientBoostingClassifier(random_state=0, max_depth=1)
gbrt.fit(X_train, y_train)

print("훈련 세트 정확도: {:.3f}".format(gbrt.score(X_train, y_train)))
print("테스트 세트 정확도: {:.3f}".format(gbrt.score(X_test, y_test)))

훈련 세트 정확도: 0.991
테스트 세트 정확도: 0.972


random_state=0, learning_rate=0.01을 입력했을 때

gbrt = GradientBoostingClassifier(random_state=0, learning_rate=0.01)
gbrt.fit(X_train, y_train)

print("훈련 세트 정확도: {:.3f}".format(gbrt.score(X_train, y_train)))
print("테스트 세트 정확도: {:.3f}".format(gbrt.score(X_test, y_test)))

훈련 세트 정확도: 0.988
테스트 세트 정확도: 0.965


훈련 세트의 정확도가 100%로 과대적합이 된 모델은 max_depth나 learning_rate로 보완할 수 있습니다.
Random_state는 고정시켜야 같은 모델이 나오는 것을 볼 수 있습니다.
Learning_rate는 오차에 곱을 해서 예측값을 업데이트 해주는 값입니다.

gradient2

gradient3

랜덤 포레스트에 비해 그레이디언트 부스팅은 특성들이 더 적습니다.
안정성에서는 랜덤 포레스트가 더 좋지만 그레이디언트가 성능적으로 더 좋은 모습을 보여줄수 있습니다.


참고
XGBoost

XGBoost는 데이터 별 오류를 다음 round 학습에 반영 시킨다는 측면에서 기존 Gradient Boosting과 큰 차이는 없음
Gradient Boosting과 달리 학습을 위한 목적식(loss function)에 Regularization term이 축가되어 모델이 과적합 되는 것을 방지해줌
Regularization term을 통해 XGBoost는 복잡한 모델에 패널티를 부여함


gradient4


LighGBM

XGBoost와 다르게 lear-wise loss 사용 (loss를 더 줄일 수 있음)
XGBoost 대비 2배 이상 빠른 속도 (동일 파라미터 기준)
과대적합에 민감하여, 대량의 학습데이터를 필요로 함


gradient5




장단점과 매개변수


장점

이진 특성이나 연속적인 특성에도 잘 작동합니다.
데이터의 스케일에 구애받지 않습니다.

단점

매개변수의 조정이 필수입니다.
휸련시간이 깁니다.
차원이 높고 희소한 데이터에 잘 작동하지 않습니다.

N_estimators가 클수록 랜덤 포레스트는 좋았지만 그래이디언트 부스팅에서는 과대적합될 가능성이 높아집니다.
N_estimator을 정하고 난 뒤에 learning_rate를 정하게 되는데 learning_rate를 낮추면 비슷한 복잡도의 모델을 만들기 위해 더 많은 트리를 추가해야합니다.


매개변수 설명
n_estimators - 트리의 개수를 지정
- 커지면 모델이 복잡해지고 과대적합 가능성 높아짐
learning_rate - 관례상 n_estimators를 맞추고 learning_rate를 찾음
- 이전 트리의 오차를 보정하는 정도
n_iter_no_change / validation_fraction -조기 종료를 위한 매개변수 (default값: n_iter_no_change =None (조기 종료 x), validation_fraction=0.1)
- validation_fraction 비율만큼 검증 데이터로 사용하여 n_iter_no_change 만큼 반복하여 향상되지 않으면 훈련 종료
max_depth / max_leaf_nodes -각 트리의 복잡도를 낮춤
- max_depth는 보통 매우 작게 설정하며 트리의 깊이가 5보다 깊어지지 않게 함




배깅, 엑스트라 트리, 에이다부스트

Bagging

from sklearn.ensemble import BaggingClassifier
배깅은 중복을 허용한 랜덤샘플링으로 만든 훈련 세트를 사용해 분류기를 각기 다르게 학습합니다.
랜덤포레스트는 배깅의 일종이지만 설명변수도 무작위로 선택하는 것이 차이가 있습니다.
predict_proba() 지원하면 메서드를 통해 확률값을 평균하여 예측을 수행합니다. (지원하지 않는다면 가장 빈도가 높은 클래스 레이블)
oob_score=True로 지정하면 매개변수는 부트스트래핑에 포함되지 않은 샘플로 훈련된 모델을 평가할 수 있습니다. (OOB 오차, default=False)

from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import BaggingClassifier
bagging = BaggingClassifier(LogisticRegression(), n_estimators=100, oob_score=True, n_jobs=-1, random_state=42)
bagging.fit(Xc_train, yc_train)

print("훈련 세트 정확도: {:.3f}".format(bagging.score(Xc_train, yc_train)))
print("테스트 세트 정확도: {:.3f}".format(bagging.score(Xc_test, yc_test)))
print("OOB 샘플의 정확도: {:.3f}".format(bagging.oob_score_))

훈련 세트 정확도: 0.953
테스트 세트 정확도: 0.951
OOB 샘플의 정확도: 0.946


배깅은 랜덤포레스트와 달리 max_samples에 부트스트랩 샘플의 크기를 정할 수 있습니다.
또한 로지스틱 회귀가 들어갈 수도 있고 결정 트리가 들어갈 수도 있습니다.




Extra Tree

후보 특성을 무작위로 분할한 다음 최적의 분할을 찾습니다.
엑스트라 트리도 랜덤 포레스트와 비슷하지만 splitter=‘random’을 사용합니다. 랜덤 포레스트는 splitter=‘best’가 고정입니다.
Splitter=‘best’의 의미는 모든 변수의 정보 이득을 계산하고 그중 가장 설명력이 높은 변수를 선택하는 것입니다.
또한 부트스트랩 샘플링을 적용하지 않습니다.
무작위성을 증가시키면 모델 편향은 늘어나지만 분산이 감소하는 모습을 보입니다.
개별 트리는 매우 복잡하지만 결정 경계는 안정적입니다.
계산 비용은 위 splitter에서의 feature의 차이 때문에 랜덤 포레스트보다 적지만 일반화 성능을 높이려면 많은 트리를 만들어야합니다.

from sklearn.ensemble import ExtraTreesClassifier
xtree = ExtraTreesClassifier(n_estimators=100, n_jobs=-1, random_state=0)
xtree.fit(Xc_train, yc_train)

print("훈련 세트 정확도: {:.3f}".format(xtree.score(Xc_train, yc_train)))
print("테스트 세트 정확도: {:.3f}".format(xtree.score(Xc_test, yc_test))

훈련 세트 정확도: 1.000
테스트 세트 정확도: 0.972




Adaptive Boosting

이전의 모델이 잘못 분류한 샘플에 가중치를 높여서 다음 모델을 훈련합니다.
훈련된 각 모델은 성능에 따라 가중치 부여합니다.
예측을 만들 때는 모델이 예측한 레이블을 기준으로 모델의 가중치를 합산하여 가장 높은 값을 가진 레이블을 선택합니다.
AdaBoostClassifier은 기본값으로 DecisionTreeClassifier(max_depth=1)를 갖습니다.
AdaBoostRegressor은 기본값으로 DecisionTreeRegressor(max_depth=3)을 갖습니다. (base_estimator을 이용하여 다른 모델 지정 가능)


ada1

에이다 부스팅의 원리와 수식

ada2


예측정확도와 가중치의 곱의 합이 되어 높은 정확도를 만들게 됩니다.

from sklearn.ensemble import AdaBoostClassifier
ada = AdaBoostClassifier(n_estimators=100, random_state=42)
ada.fit(Xc_train, yc_train)

print("훈련 세트 정확도: {:.3f}".format(ada.score(Xc_train, yc_train)))
print("테스트 세트 정확도: {:.3f}".format(ada.score(Xc_test, yc_test)))

훈련 세트 정확도: 1.000
테스트 세트 정확도: 0.986



커널 서포트 벡터 머신

커널 서포트 벡터 머신은 보통 SVM이라고 한다.
입력 데이터에서 단순한 초평면으로 정의되지 않는 더 복잡한 모델을 만들 수 있도록 확장한 것이다.
분류와 회귀 모두 사용 가능하다. (SVC는 분류, SVR은 회귀)

from sklearn.svm import LinearSVC #선형 모델
LinearSVC(max_iter=)

from sklearn.svm import SVC
SVC(kernel='',C=,gamma=) # kernel, C, gamma 파라미터 존재
선형 모델과 비선형 특성

선형 모델은 직선으로만 데이터 포인트를 나눌 수 있어 밑에 같은 데이터는 잘 들어맞지 않는다.
SVM 모델은 3차원에서 2차원으로 투영해본다면 더이상 선형 모델이 아니다.

커널 기법

커널 기법은 실제로 데이터를 확장하지 않고 확장된 특성에 대한 데이터 포인트들의 거리를 계산한다.
$ (특성1)^2 * (특성2)^5 $하는 다항식 커널이 있고 가우시안 커널로 불리우는 RBF 커널이 있다.
가우시안 커널은 차원이 무한한 특성 공간에 매핑하는 것이다.
모든 차수의 모든 다항식을 고려하지만 특성의 중요도는 고차항이 될수록 줄어든다.

SVM 이해하기

두 클래스 사이에 경계한 데이터 포인트들을 서포트 벡터라고 한다.
새로운 데이터 포인트에 대해 예측하려면 각 서포트 벡터와의 거리를 측정한다.
서포트 벡터의 중요도는 훈련 과정에서 학습하는데 dual_coef_ 속성에 저장된다.

가우시안 커널 공식 사진

가우시안 커널에 의해 계산되며 $ X_1, X_2 $는 데이터 포인트이며 $ ||X_1 - X_2|| $는 유클리디안 거리이고 $Γ$ 은 가우시안 커널의 폭을 제어하는 매개변수이다.

SVM 매개변수 튜닝

$Γ$는 가우시안 커널 폭의 역수에 해당하는데 하나의 훈련 샘플이 미치는 영향의 범위를 결정한다.(1~0 사이의 범위이다.)
작은 값은 넓은 영역을 뜻하고, 큰 값은 영향이 미치는 범위가 제한적이다.
즉 커널의 반경이 클수록 훈련 샘플의 영향 범위도 커진다.
작은 $Γ$ 값은 모델의 복잡도를 낮출 수 있다.
C 매개 변수는 규제 매개변수이다. dual_coef_값을 제한합니다.
작은 C는 매우 제약이 큰 모델을 만들고 각 데이터 포인트의 영향력이 작다.
C를 증가시키면 이 포인트들이 영향을 크게 줘서 결정 경계를 휘게 만든다.

SVM을 위한 데이터 전처리

커널 SVM에서는 데이터셋의 특성 자릿수가 완전히 다르면 영향을 크게 미친다.
따라서 특성 값을 평균이 0이고 단위 분산이 되도록 하거나, 0과 1 사이로 맞추는 방법을 많이 사용한다.(StandardScaler와 MinMaxScalar)

장단점과 매개변수

SVM은 저차원과 고차원의 데이터에 모두 잘 작동하지만 샘플이 많으면 잘 맞지 않는다.
또한 전처리와 매개변수 설정에 신경을 많이 써야하는데 그래서 랜덤 포레스트나 그레이디언트 부스팅과 같은 전처리가 거의 필요 없는 트리 기반 모델이 선호된다.
SVM은 분석도 어려워서 예측이 어떻게 결정되었는지 설명하기가 난해하다.
하지만 모든 특성이 비슷한 단위이고 스케일이 비슷하다면 시도해볼 만하다.
중요한 매개변수는 C이고 어떤 커널을 사용할지와 각 커널에 따른 매개변수이다.
RBF는 $Γ$ 매개변수를 갖지만 다른 커널 종류도 많다.

신경망 (딥러닝)

다층 퍼셉트론은(MLP)는 간단하게 분류와 회귀에서 쓰일 수 있다.

신경망 모델

MLP는 여러 단계를 거처 결정을 만들어내는 선형 모델의 일반화된 모습이다.

선형 회귀 모델의 예측 공식 사진

$\hat Y $는 x[0]에서 x[p]까지의 입력특성과 학습된 계수의 가중치의 합이다.

퍼셉트론 사진

왼쪽 노드는 입력 특성을 나타내며 연결선은 학습된 계수를 표현하고 오른쪽 노드는 입력의 가중치 합, 즉 출력을 나타낸다.
MLP는 가중치 합을 만드는 과정이 여러 번 반복되며 먼저 중간 단계를 구성하는 은닉 유닛을 계산하고 이를 이용하여 최종 결과를 산출하기 위해 다시 가중치 합을 계산한다.

다중 퍼셉트론 사진

각 은닉 유닛의 가중치 합을 계산한 후 결과에 비선형 함수인 렐루나 하이퍼볼릭 탄젠트, 시그모이드 함수를 적용합니다.

회귀 분석 사진

w는 입력 x와 은닉층 h 사이의 가중치이고, v는 은닉층 h와 출력 $\hat Y$ 사이의 가중치입니다.
w와 v는 훈련 데이터에서 학습하고 x는 입력 특성이며 $ \hat Y $는 계산된 출력, h는 중간 계산값 입니다.

신경망 튜닝

더 복잡도가 낮은 모델을 만들고 싶다면 hidden_layer_size를 통해 은닉 유닛의 개수를 줄인다.
은닉 유닛을 추가하거나, 은닉층을 추가하거나 활성화함수를 바꾸면 더 매끄러운 결정 경계를 얻을 수도 있다.
선형 분류와 리지 회귀 처럼 L2 페널티를 사용해서 가중치를 0에 가깝게 감소시킬 수도 있다.(default는 매우 낮다)
신경망에서는 학습을 시작하기 전에 가중치를 무작위로 설정하며 이 무작위한 초기화가 모델의 학습에 영향을 준다.
따라서 같은 매개변수를 사용하더라도 초깃값이 다르면 모델이 많이 달라질 수 있다.
신경망도 입력 특성이 평균은 0 분산이 1이 되도록 변형하는 것이 좋다.
은닉 유닛에서 작은 가중치를 가진 특성은 모델에 덜 중요하다고 추론할 수 있다.

from sklearn.neural_network import MLPClassifier # MLP분류
MLPClassifier(solver='',activation='',random_state=,hidden_layer_sizes=[,],max_itter=,alpha=) 
#solver에 최적화 알고리즘,activation에 활성화 함수 ,hidden_layer_size로 은닉 유닛의 개수 설정(default=100),max_itter은 반복 횟수,alpha는 L2 페널티
장단점과 매개변수

머신러닝 알고리즘을 뛰어넘는 성능을 보일 수 있지만 학습이 오래걸리고 데이터 전처리를 주의해서 해야한다.
모든 특성이 같은 의미를 가지면 SVM, 다른 종류의 특성이라면 트리 기반 메딜이 더 잘 작동할 수 있다.

신경망의 복잡도 추정

가장 중요한 매개변수는 은닉층의 개수와 각 은닉층의 유닛 수이다.
복잡도에 관해 연관된 측정치는 학습된 가중치 또는 계수의 수이다.
특성이 100개 은닉 유닛 100개인 이진 분류라면 입력층과 첫 번째 은닉층 사이에는 편향을 포함하여 $ 100 * 100 + 100 = 10100 $개의 가중치가 있습니다.
은닉층과 출력층 사이에 $ 100 * 1 + 1 = 101 $개의 가중치가 더 있어 가중치는 10201개 이다.
이렇게 가중치는 은닉층을 추가할수록 훨씬 커지게 된다.
매개변수를 조정하는 일반적인 방법은 충분히 과대적합되어 문제를 해결할만한 큰 모델을 만든 뒤 훈련 데이터가 충분히 학습될 수 있다고 생각되면 신경망 구조를 줄이거나 규제 강화를 위해 alpha 값을 증가시켜 일반화 성능을 향상시킨다.
층의 개수, 층당 유닛 개수, 규제, 비선형성으로 모델 구성을 할 수 있으며, solver 매개변수를 통해서 학습시키는 방법을 지정할 수 있다.
solver의 경우 기본값은 adam이고 데이터 스케일에 민감하다.
lbfgs는 안정적이지만 규모가 크면 시간이 오래 걸린다
sgd는 momentum과 nesterovs_momentom의 영향을 받는데 다른 여러 매개변수와 함께 튜닝하여 최선의 결과를 만들 수 있다.

분류 예측의 불확실성 추정

decision_function과 predict_proba로 추정 할 수 있다.

결정 함수

decision_function의 반환값의 크기는 (n_samples,)이며각 샘플이 하나의 실수 값을 반환한다.
모델이 데이터 포인트가 양성 클래스인 클래스 1에 속한다고 믿는 정도이다.
즉, 음수값은 다른 클래스에 속함을 의미한다.
값의 범위는 데이터와 모델 파라미터에 따라 달라지게 된다.

예측 확률

predict_proba의 출력은 각 클래스에 대한 확률이고 이진 분류에서 이 값의 크기는 항상 (n_samples,2)이다.
두 클래스의 확률 합은 1이므로 두 클래스 중 하나는 50% 이상의 확신을 가질 것이고 그 클래스가 예측값이 된다.
데이터에 있는 불확실성이 얼마나 이 값에 잘 반영되는지는 모델과 매개변수 설정에 달렸다.
그래서 과대적합된 모델 혹은 잘못된 예측도 예측의 확신이 강한 편이다.
복잡도가 낮을 수록 예측에 불확실성이 더 많다.
불확실성과 모델의 정확도가 동등하면 이 모델이 보정되었다고 한다.

다중 분류에서의 불확실성

다중 분류에서도 decision_funcion과 predict_proba를 사용할 수 있다.
decision_function에서는 (n_samples, n_classes)가 결과값이 된다.
글 클래스에 대한 확신 점수를 담고 그 수치가 크면 그 클래스일 가능성이 크다.
데이터 포인트마다 점수들에서 가장 큰 값을 찾아 예측 결과를 재현할 수 있다.
predict_proba는 (n_samples,n_classes)가 출력값이 된다.
마찬가지로 각 데이터 포인트에서 클래스 확률의 합은 1이다.
argmax 함수를 적용해서 예측 결과를 재현할 수 있지만 클래스가 문자열이거나 정수형을 사용하지만 연속적이지 않고 0부터 시작하지 않을 수 있다.
따라서 predict 결과와 decision_function, predict_proba의 결과를 비교하기 위해서는 분류기의 classes_ 속성을 사용해 클래스의 실제 이름을 얻어야 한다.