인공지능

[빅데이터 직무연구회] 3주차 모임 정리

Chipmunks 2018. 5. 4.
728x90

빅데이터 직무연구회. 3주차 모임 정리


모임 요일 : 5월 3일 목요일 저녁 6시

분류용 선형 모델

  • 선형 모델은 분류에도 널리 사용
  • 고차원에서의 분류 선형 모델은 매우 강력해 진다. 특성이 많아지면 과대적합되지 않도록 하는 것이 중요하다.
  • 이진 분류(Binary Classification)

  • 선형 회귀와 아주 비슷함.
  • 예측한 값을 임계치 0과 비교함.
    1. 계산한 값이 0보다 작으면 클래스를 -1
    2. 예측하고 0보다 크면 +1 이라고 예측
  • 회귀용 선형 모델에서는 출력 y이 특성의 선형 함수다.
  • 분류용 선형 모델에서는 결정 경게가 입력의 선형 함수다.
  • 선형 분류기는 선, 평면, 초평면을 사용해서 두 개의 클래스를 구분하는 분류기

< 선형 모델을 학습시키는 알고리즘 >
  • 특정 계수와 절편의 조합이 훈련 데이터에 얼마나 잘 적합하는지 측정
  • 규제와 그 방식
  • 알고리즘 마다 측정 방법이 다름. 수학적 이유로 w와 b를 조정하는 것은 불가능
  • 앞 목록의 첫 번째 항목(손실 함수)에 대한 차이는 크게 중요치 않음

< 가장 널리 알려진 두 개의 선형 분류 알고리즘 >

  1. 로지스틱 회귀 : 이름에 회귀가 들어가지만, 분류 알고리즘
  2. 선형 서포트 벡터 머신

< 규제 방법 >

  • 둘 다 규제의 강도를 결정하는 매개변수 C 있음.
  • C의 값이 높아지면 규제가 감소
    • 개개의 데이터 포인트를 정확히 분류함
  • C의 값을 낮추면 계수 벡터(w)가 0에 가까워지도록 만듦
    • 데이터 포인트 중 다수에 맞추려 함


다중 클래스 분류용 선형 모델

  • 로지스틱 회귀는 소프트맥스(softmax) 함수를 사용한 다중 클래스 분류 알고리즘 지원
  • 그 외 대부분의 선형 분류 모델은 태생적으로 이진 분류만을 지원
  • 다중 클래스 분류용으로 확장하는 보편적인 기법은 일대다(one-vs.-rest, one-vs.-all) 방법
    • 각 클래스를 다른 모든 크랠스와 구분하도록 이진 분류 모델 학습
    • 클래스의 수만큼 이진 분류 모델 생성
    • 가장 높은 점수를 내는 분류기의 클래스를 예측값
    • 각 클래스가 계수 벡터(w)와 절편(b) 하나씩 가짐
    • 다음 공식의 결과값이 가장 높은 클래스가 해다 데이터의 클래스 레이블로 분류


  • 다중 클래스 로지스틱 회귀는 일대다 방식과 조금 다름.
  • 공식은 다음과 같음

    • K개의 클래스에 대한 각각의 계수 W를 데이터 포인트에 곱하여 지수함수를 적용한 합
    • 클래스 c에 대한 값을 나누어 계산
    • 수식의 간소함을 위해 절편(b)는 계수 벡터 W에 포함되어 있는 것으로 나타냄
    • 따라서 다중 클래스 로지스틱 회귀에서도 클래스마다 계수 벡터와 절편이 있음


장단점과 매개변수

< 매개변수 >

  • 회귀 모델
    • alpha
  • 분류 모델
    • C
  • alpha 증가, C 감소 : 모델이 단순해짐 ( 특별히 회귀 모델에서 조정이 중요 )
  • 보통 로그 스케일(자릿수가 바뀌도록 10배씩 변경)로 최적치 정함
  • L1과 L2 중 어떤 규제 사용할지 중요
    • L1 규제 : 중요한 특성이 많지 않을 때
      • 몇 가지 특성만 사용하므로 중요한 특성이 무엇이고 그 효과가 어느 정도인지 말해주기 쉬움
    • L2 규제 : 그렇지 않다면


< 장점 >

  • 학습 속도가 빠르다
  • 예측도 빠르다
  • 매우 큰 데이터셋과 희소한 데이터셋에도 잘 작동한다
    • 대용량 데이터셋일 시, LogisticRegression과 Ridge에 solver='sag' 옵션을 준다.
      • sag : Stochastic Average Gradient descent(확률적 평균 경사 하강법)
      • 경사 하강법과 비슷하다.
      • 반복이 진행될 때 이전에 구한 모든 경사의 평균을 사용하여 계수를 갱신
      • 대안으로 SGDClassifier 와 SGDRegressor 사용 가능
        • SGD : Stochastic Gradient Descent(확률적 경사 하강법)
  • 회귀와 분류에서 예측이 어떻게 만들어 지는지 비교적 쉽게 이해 가능
  • 샘플에 비해 특성이 많을 때 잘 작동

=> 속도와 메모리 사용에 제약이 있는 애플리케이션이라면 선형 모델이 적합


< 단점 >

  • 특성들이 서로 깊게 연관되어 있을 때 계수를 분석하기 어려울 수 있음
  • 저차원 데이터셋에서는 다른 모델들의 일반화 성능이 더 좋음


2.3.4 나이브 베이즈 분류기

  • 선형 모델과 매우 유사함.
  • 선형 분류기보다 속도가 빠르지만, 일반화 성능이 조금 뒤짐
  • 각 특성을 개별로 취급해 파라미터를 학습
  • 각 특성에서 클래스별 통계를 단순하게 취합
  • GaussianNB, BernoulliNB, MultinomialNB 등이 있음
    • GaussianNB : 연속적인 어떤 데이터에 적용
      • 각 특성의 표준편차와 평균을 계산하여 저장
    • BernoulliNB : 이진 데이터
      • 각 클래스의 특성 중 0이 아닌 것이 몇 개인지 셈
    • MultinomialNB : 카운트 데이터 (예. 문장에 나타난 단어의 횟수)
      • 클래스별로 특성의 평균을 계산하여 저장
    • BernoulliNB, MultinomialNB는 대부분 텍스트 데이터를 분류할 때 사용
  • 예측 시, 데이터 포인트를 클래스의 통계 값과 비교해 가장 잘 맞는 클래스를 예측값
  • 예측 공식은 선형 모델과 형태가 같음
    • coef_ : 기울기 w가 아님. 특성 카운트 수를 로그 변환한 형태
    • intercept_ : 클래스 카운트 수를 로그 변환한 형태


장단점과 매개변수

< 매개변수 >

  • MultinomialNB, BernoulliNB 는 모델의 복잡도를 조절하는 alpha 매개변수
    • 알고리즘이 모든 특성에 양의 값을 가진 가상의 데이터 포인트를 alpha 개수만큼 추가
    • => 통계 데이터를 완만하게 만들어 줌
    • 모델의 복잡도는 낮아짐
    • 성능 향상에 크게 기여하지 않음
    • 조정하면 어느 정도는 정확도를 높일 수 있음

< 특징 >

  • Multinomial, BernoulliNB : 텍스트 같은 희소한 데이터를 카운트 하는데 사용
  • MultinomialNB : 보통 0이 아닌 특성잉 비교적 많은 데이터셋 (큰 문서들)에서 BernoulliNB 보다 성능이 높음
  • GussianNB
    • 매우 고차원인 데이터셋에 사용 가능

< 장단점 >

  • 훈련과 예측속도 빠름
  • 훈련 과정 이해하기 쉬움
  • 희소한 고차원 데이터셋에 잘 작동
  • 비교적 매개변수에 민감하지 않음


2.3.5 결정 트리

  • 분류와 회귀 문제에 널리 사용하는 모델
  • 예/아니오 질문을 이어 나가며 학습
  • 트리의 노드 : 질문이나 정답을 담은 네모 상자
  • 리프 : 마지막 노드
  • 에지 : 질문의 답과 다음 질문을 연결
  • 결정 트리를 학습 : 정답에 가장 빨리 도달하는 예/아니오 질문 목록을 학습한다는 뜻
  • 질문들 : 테스트
  • 트리 만드는 알고리즘 : 가능한 테스트에서 타깃값에 대해 가장 많은 정보를 가진 것
  • 2차원 데이터셋과 같은 연속된 특성 : 특성 i는 값 a보다 큰가? 와 같은 형태
  • 루트 노드 : 맨 위의 노드
  • 순수 노드 : 타깃 하나로만 이뤄진 리프 노드
  • 한 개의 타깃값을 가질 때 까지 반복
  • 회귀의 경우 리프 노드의 훈련 데이터 평균값이 데이터 포인트의 출력이 됨


결정 트리의 복잡도 제어하기

  • 이상치 하나에 너무 민감함
< 과대적합을 막는 전략 >
  1. 사전 가지치기 : 트리 생성을 일찍 중단
    1. 트리의 최대 깊이 제한
    2. 리프의 최대 개수 제한
    3. 노드가 분할하기 위한 포인트의 최소 개수 지정
  2. (사후) 가지치기 : 데이터 포인트가 적은 노드를 삭제하거나 병합


결정 트리 분석

  • graphviz 모듈로 시각화
  • 많은 수의 데이터가 흐르는 경로를 찾아보는 것이 좋음


트리의 특성 중요도

특성 중요도 : 트리를 만드는 결정에 각 특성이 얼마나 중요한지 평가. 0과 1 사이의 숫자


외삽(Extrapolation) : 훈련 데이터의 범위 밖의 포인트에 대해 예측할 수 없음. 모든 트리 기반 회귀 모델의 특성. 단순히 마지막 포인트를 이용해 예측하느게 전부


장단점과 매개변수

< 매개변수 >
  • 사전 가지치기
    • max_depth
    • max_leaf_nodes
    • min_samples_leaf


< 장점 >

  • 쉽게 시각화 가능
  • 데이터 스케일에 구애받지 않음
  • 특성의 정규화나 표준화 같은 전처리 과정 필요 없음
  • => 스케일이 서로 다르거나 이진 특성과 연속적인 특성이 혼합되어 있을 때도 잘 작동


< 단점 >

  • 사전 가지치기 해도 과대적합되는 경향이 있음.
  • 일반화 성능이 좋지 않음

=> 대안으로 앙상블 방법이 있음


2.3.6 결정 트리의 앙상블

앙상블(Ensemble) : 여러 머신러닝 모델을 연결해 더 강력한 모델을 만드는 기법
  • 랜덤 포레스트(random forest) 결정 트리
  • 그래이언트 부스팅(gradient boosting) 결정 트리


랜덤 포레스트

조금씩 다른 여러 결정 트리의 묶음. 훈련 데이터에 과대적합되는 경향을 회피함


  • 각 트리는 비교적 예측이 가능, 데이터의 일부에 과대적합하는 경향을 가짐
  • 서로 다른 방향으로 과대적합된 트리를 많이 만듦.
  • 그 결과를 평균냄으로써 과대적합된 양을 줄이는게 가능


결정 트리를 랜덤으로 만드는 방법

  • 데이터 포인트를 무작위로 선택하는 방법
  • 분할 테스트에서 특성을 무작위로 선택하는 방법

랜덤 포레스트 구축

  • 생성할 트리의 개수를 정해야 함
    • RandomForest Regressor, RandomForectClassifier : n_estimators 매개변수
  • 무작위로 몇 개의 특성을 고를지 조정 가능
    • max_features
      • max_features 값이 클 때 : 랜덤 포레스트의 트리들은 매우 비슷해짐. 가장 두드러진 특성을 이용해 데이터에 잘 맞춰짐
      • max_features 값이 작을 때 : 랜덤 포레스트의 트리들은 많이 달라짐. 각 트리는 데이터에 맞추기 위해 깊이가 깊어짐
  • 모든 트리의 예측을 만듦.
  • 예측들을 평균하여 최종 예측을 만듦
  • 분류 : 약한 투표 전략
    • 각 알고리즘이 가능성 있는 출력 레이블의 확률을 제공함으로써 간접적인 예측
    • 트리들이 예측한 확률을 평균내어 가장 높은 확률을 가진 클래스가 예측값이 됨


장단점과 매개변수

< 매개변수 >
  1. n_estimators
    • 클 수록 좋음.
    • 더 많은 트리를 평균하면 과대적합을 줄여 더 안정적인 모델을 만듦
    • 더 많은 메모리와 긴 훈련 시간으로 이어짐.
    • "가용한 시간과 메모리 만큼 많이" 만들 것
  2. max_features
    • 각 트리가 얼마나 무작위가 될지를 결정함
    • 작은 max_features는 과대 적합을 줄여줌.
    • 일반적으로 기본값을 쓰는 것이 좋은 방법
    • 분류 : max_features = sqrt(n_features)
    • 회귀 : max_features = n_features
  3. max_depth, max_leaft_noes : 훈련과 예측에 필요한 메모리와 시간을 단축할 수 있음

< 장점 >
  • 회귀와 분류에 있어 현재 가장 널리 사용되는 머신러닝 알고리즘
  • 성능이 매우 뛰어남.
  • 매개변수 튜닝을 따로 안해도 잘 작동함
  • 데이터의 스케일을 맞출 필요도 없음


< 단점 >

  • 비전문가에게 예측 과정을 시각적으로 보여주기 힘듦
  • 대용량 데이터셋에서 모델을 만들 때 다소 시가니 걸림.
    • CPU 코어가 많다면 손쉽게 병렬 처리 가느
    • n_jobs 매개변수
      • n_jobs = -1 : 컴퓨터의 모든 코어를 사용
  • random_state 를 설정하지 않으면 전혀 다른 모델이 나타남
  • 텍스트 데이터와 같이 매우 차원이 높고 희소한 데이터에는 잘 작동하지 않음
    • 선형 모델이 더 적합함
  • 많은 메모리를 사용하며 훈련과 예측이 느림


그래디언트 부스팅 회귀 트리

  • 회귀와 분류 모두 사용 가능
  • 이전 트리의 오차를 보완하는 방식으로 순차적으로 트리를 만듦
  • 무작위성이 없음
  • 강력한 사전 가지치기가 사용
  • 보통 하나에서 다섯 정도의 깊지 않은 트리 사용
  • 메모리를 적게 사용하며 예측도 빠름
  • 얕은 트리 같은 간단한 모델(약한 학습기weak learner)을 많이 연결하는 것
  • 트리가 많이 추가될 수록 성능이 좋아진다.
  • learning_rate : 이전 트리의 오차를 얼마나 강하게 보정할 것인지를 제어


장단점과 매개변수

< 매개변수 >

  • n_estimators
    • n_estimators가 클수록 모델이 복잡해지고 과대적합될 가능성이 높아짐
    • 일반적으로 가용한 시간과 메모리 한도에서 n_estimators를 맞춤
  • learning_rate
    • n_estimators를 맞춘 후 적절한 learning_rate를 찾음
  • 위 두 매개변수는 매우 깊게 연관
    • learning_rate를 낮추면 비슷한 복잡도의 모델을 만들기 위해 더 많은 트리를 만들어야 함
  • max_deapth, max_leaft_nodes : 그래디언트 부스팅 모델 특성 상 매우 작게 설정함. 트리의 깊이가 5보다 깊어지지 않게 함.


< 장점 >

  • 지도 학습에서 가장 강력하고 널리 사용하는 모델 중 하나
  • 트리 기반 모델의 특성 상 특성의 스케일을 조정하지 않아도 됨
  • 트리 기반 모델의 특성 상 이진 특성이 연속적인 특성에서도 잘 동작


< 단점 >

  • 매개변수를 잘 조정해야 함
  • 훈련 시간이 김
  • 트리 기반 모델의 특성 상 희소한 고차원 데이터에는 잘 작동하지 않음


from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC

X, y = mglearn.datasets.make_forge()

fig, axes = plt.subplots(1, 2, figsize=(10, 3))

for model, ax in zip([LinearSVC(), LogisticRegression()], axes):
    clf = model.fit(X, y)
    mglearn.plots.plot_2d_separator(clf, X, fill=False, eps=0.5, ax=ax, alpha=.7)
    mglearn.discrete_scatter(X[:, 0], X[:, 1], y, ax=ax)
    ax.set_title("{}".format(clf.__class__.__name__))
    ax.set_xlabel("특성 0")
    ax.set_ylabel("특성 1")
axes[0].legend()
Out[37]:
<matplotlib.legend.Legend at 0x10eb65278>
In [38]:
mglearn.plots.plot_linear_svc_regularization()
In [39]:
from sklearn.datasets import load_breast_cancer
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)
logreg = LogisticRegression().fit(X_train, y_train)
print("훈련 세트 점수: {:.3f}".format(logreg.score(X_train, y_train)))
print("테스트 세트 점수: {:.3f}".format(logreg.score(X_test, y_test)))
훈련 세트 점수: 0.953
테스트 세트 점수: 0.958
In [40]:
logreg100 = LogisticRegression(C=100).fit(X_train, y_train)
print("훈련 세트 점수: {:.3f}".format(logreg100.score(X_train, y_train)))
print("테스트 세트 점수: {:.3f}".format(logreg100.score(X_test, y_test)))
훈련 세트 점수: 0.969
테스트 세트 점수: 0.965
In [41]:
logreg001 = LogisticRegression(C=0.01).fit(X_train, y_train)
print("훈련 세트 점수: {:.3f}".format(logreg001.score(X_train, y_train)))
print("테스트 세트 점수: {:.3f}".format(logreg001.score(X_test, y_test)))
훈련 세트 점수: 0.934
테스트 세트 점수: 0.930
In [42]:
plt.plot(logreg.coef_.T, 'o', label="C=1")
plt.plot(logreg100.coef_.T, '^', label="C=100")
plt.plot(logreg001.coef_.T, 'v', label="C=0.01")
plt.xticks(range(cancer.data.shape[1]), cancer.feature_names, rotation=90)
plt.hlines(0, 0, cancer.data.shape[1])
plt.ylim(-5, 5)
plt.xlabel("특성")
plt.ylabel("계수 크기")
plt.legend()
Out[42]:
<matplotlib.legend.Legend at 0x10ef6e898>
In [43]:
for C, marker in zip([0.001, 1, 100], ['o', '^', 'v']):
    lr_l1 = LogisticRegression(C=C, penalty="l1").fit(X_train, y_train)
    print("C={:.3f}인 l1 로지스틱 회귀의 훈련 정확도: {:.2f}".format(C, lr_l1.score(X_train, y_train)))
    print("C={:.3f}인 l1 로지스틱 회귀의 테스트 정확도: {:.2f}".format(C, lr_l1.score(X_test, y_test)))
    plt.plot(lr_l1.coef_.T, marker, label="C={:.3f}".format(C))

plt.xticks(range(cancer.data.shape[1]), cancer.feature_names, rotation=90)
plt.hlines(0, 0, cancer.data.shape[1])
plt.xlabel("특성")
plt.ylabel("계수 크기")

plt.ylim(-5, 5)
plt.legend(loc=3)
C=0.001인 l1 로지스틱 회귀의 훈련 정확도: 0.91
C=0.001인 l1 로지스틱 회귀의 테스트 정확도: 0.92
C=1.000인 l1 로지스틱 회귀의 훈련 정확도: 0.96
C=1.000인 l1 로지스틱 회귀의 테스트 정확도: 0.96
C=100.000인 l1 로지스틱 회귀의 훈련 정확도: 0.99
C=100.000인 l1 로지스틱 회귀의 테스트 정확도: 0.98
Out[43]:
<matplotlib.legend.Legend at 0x110d2ae10>
In [44]:
from sklearn.datasets import make_blobs

X, y = make_blobs(random_state=42)
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
plt.xlabel("특성 0")
plt.ylabel("특성 1")
plt.legend(["클래스 0", "클래스 1", "클래스 2"])
Out[44]:
<matplotlib.legend.Legend at 0x10ef9f630>
In [45]:
linear_svm = LinearSVC().fit(X, y)
print("계수 배열의 크기: ", linear_svm.coef_.shape)
print("절편 배열의 크기: ", linear_svm.intercept_.shape)
계수 배열의 크기:  (3, 2)
절편 배열의 크기:  (3,)

mglearn.discrete_scatter(X[:, 0], X[:, 1], y) line = np.linespace(-15 ,15) for coef, intercept, color in zip(linear_svmcoef, linear_svmintercept, mglearn.cm3.colors): plt.plot(line, -(line * coef[0] + intercept) / coef[1], c=color) plt.yli,(-15, 15) plt,xlim(-10, 8) plt.xlabe("특성 0") plt.ylabel("특성 1") plt.legend("클래스 0", "클래스 1", "클래스 2", "클래스 8 경계", "클래스 1 경계", '클래스 2 경계'

In [46]:
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
line = np.linspace(-15, 15)
for coef, intercept, color in zip(linear_svm.coef_, linear_svm.intercept_, mglearn.cm3.colors):
    plt.plot(line, -(line * coef[0] + intercept) / coef[1], c=color)
plt.ylim(-10, 15)
plt.xlim(-10, 8)
plt.xlabel("특성 0")
plt.ylabel("특성 1")
plt.legend(['클래스 0', '클래스 1', '클래스 2', '클래스 0 경계', '클래스 1 경계', '클래스 2 경계'], loc=(1.01, 0.3))
Out[46]:
<matplotlib.legend.Legend at 0x10edbaa58>
In [47]:
mglearn.plots.plot_2d_classification(linear_svm, X, fill=True, alpha=.7)
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
line = np.linspace(-15, 15)
for coef, intercept, color in zip(linear_svm.coef_, linear_svm.intercept_, mglearn.cm3.colors):
    plt.plot(line, -(line * coef[0] + intercept) / coef[1], c=color)
plt.legend(['클래스 0', '클래스 1', '클래스 2', '클래스 0 경계', '클래스 1 경계', '클래스 2 경계'], loc=(1.01, 0.3))
plt.xlabel("특성 0")
plt.ylabel("특성 1")
Out[47]:
Text(0,0.5,'특성 1')
In [48]:
# 나이브 베이즈 분류기
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])
In [49]:
# 클래스별로 0이 아닌 원소를 세는 과정
counts = {}
for label in np.unique(y):
    # 클래스마다 반복
    # 특성마다 1이 나타난 횟수를 센다.
    counts[label] = X[y == label].sum(axis=0)
print("특성 카운트:\n{}".format(counts))
특성 카운트:
{0: array([0, 1, 0, 2]), 1: array([2, 0, 2, 1])}
In [50]:
# graphviz 패키지 설치되어있어야 함
mglearn.plots.plot_animal_tree()
In [51]:
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
In [52]:
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
In [53]:
from sklearn.tree import export_graphviz
export_graphviz(tree, out_file="tree.dot", class_names=["악성", "양성"],
               feature_names=cancer.feature_names,
               impurity=False, filled=True)
In [54]:
import graphviz

with open("tree.dot") as f:
    dot_graph = f.read()
display(graphviz.Source(dot_graph))
worst radius <= 16.795samples = 426value = [159, 267]class = 양성worst concave points <= 0.136samples = 284value = [25, 259]class = 양성Truetexture error <= 0.473samples = 142value = [134, 8]class = 악성Falseradius error <= 1.048samples = 252value = [4, 248]class = 양성worst texture <= 25.62samples = 32value = [21, 11]class = 악성smoothness error <= 0.003samples = 251value = [3, 248]class = 양성samples = 1value = [1, 0]class = 악성samples = 4value = [1, 3]class = 양성samples = 247value = [2, 245]class = 양성worst smoothness <= 0.179samples = 12value = [3, 9]class = 양성worst symmetry <= 0.268samples = 20value = [18, 2]class = 악성samples = 10value = [1, 9]class = 양성samples = 2value = [2, 0]class = 악성samples = 3value = [1, 2]class = 양성samples = 17value = [17, 0]class = 악성samples = 5value = [0, 5]class = 양성worst concavity <= 0.191samples = 137value = [134, 3]class = 악성worst texture <= 30.975samples = 5value = [2, 3]class = 양성samples = 132value = [132, 0]class = 악성samples = 3value = [0, 3]class = 양성samples = 2value = [2, 0]class = 악성
In [55]:
print("특성 중요도:\n{}".format(tree.feature_importances_))
특성 중요도:
[0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.01019737 0.04839825
 0.         0.         0.0024156  0.         0.         0.
 0.         0.         0.72682851 0.0458159  0.         0.
 0.0141577  0.         0.018188   0.1221132  0.01188548 0.        ]
In [56]:
def plot_feature_importances_cancer(model):
    n_features = cancer.data.shape[1]
    plt.barh(range(n_features), model.feature_importances_, align='center')
    plt.yticks(np.arange(n_features), cancer.feature_names)
    plt.xlabel("특성 중요도")
    plt.ylabel("특성")
    plt.ylim(-1, n_features)
plot_feature_importances_cancer(tree)
In [57]:
tree = mglearn.plots.plot_tree_not_monotone()
display(tree)
Feature importances: [0. 1.]
X[1] <= -5.814samples = 100value = [50, 50]samples = 25value = [25, 0]TrueX[1] <= 5.348samples = 75value = [25, 50]Falsesamples = 50value = [0, 50]samples = 25value = [25, 0]
In [58]:
import pandas as pd
import os
ram_prices = pd.read_csv(os.path.join(mglearn.datasets.DATA_PATH, "ram_price.csv"))

plt.semilogy(ram_prices.date, ram_prices.price)
plt.xlabel("년")
plt.ylabel("가격 ($/Mbyte)")
Out[58]:
Text(0,0.5,'가격 ($/Mbyte)')
/usr/local/lib/python3.6/site-packages/matplotlib/mathtext.py:849: MathTextWarning: Font 'default' does not have a glyph for '-' [U+2212]
  MathTextWarning)
/usr/local/lib/python3.6/site-packages/matplotlib/mathtext.py:850: MathTextWarning: Substituting with a dummy symbol.
  warn("Substituting with a dummy symbol.", MathTextWarning)
In [59]:
from sklearn.tree import DecisionTreeRegressor
# 2000년 이전을 훈련 데이터로, 2000년 이후를 테스트 데이터로 만듭니다.
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)
In [60]:
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()
Out[60]:
<matplotlib.legend.Legend at 0x1112c76d8>
/usr/local/lib/python3.6/site-packages/matplotlib/mathtext.py:849: MathTextWarning: Font 'default' does not have a glyph for '-' [U+2212]
  MathTextWarning)
/usr/local/lib/python3.6/site-packages/matplotlib/mathtext.py:850: MathTextWarning: Substituting with a dummy symbol.
  warn("Substituting with a dummy symbol.", MathTextWarning)
In [61]:
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)
Out[61]:
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
            max_depth=None, max_features='auto', max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, n_estimators=5, n_jobs=1,
            oob_score=False, random_state=2, verbose=0, warm_start=False)
In [62]:
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)
Out[62]:
[<matplotlib.lines.Line2D at 0x11148bef0>,
 <matplotlib.lines.Line2D at 0x11103e390>]
In [63]:
# 유방암 데이터셋에 100개의 트리로 이뤄진 랜덤 포레스트 적용
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
In [64]:
plot_feature_importances_cancer(forest)
In [65]:
# 그래디언트 부스팅 회귀 트리
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.958
In [66]:
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
In [67]:
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
In [68]:
gbrt = GradientBoostingClassifier(random_state=0, max_depth=1)
gbrt.fit(X_train, y_train)

plot_feature_importances_cancer(gbrt)


댓글