20일차 - 지도학습 3

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

    • 여러 개의 결정 트리를 묶어 강력한 모델을 만드는 앙상블 기법 중 하나.
    • 이름은 회귀지만 회귀와 분류에 모두 사용 가능

     

    • 장점
      • 지도학습에서 가장 강력함.
      • 가장 널리 사용하는 모델 중의 하나
      • 특성의 스케일 조정이 불필요 -> 정규화 불필요.
    • 단점
      • 매개변수를 잘 조정해야 한다는 것.
      • 긴 훈련 시간.
      • 트리 기반 모델을 사용.  -> 희소한 고차원 데이터는 부적합. (특성이 많고 값이 별로 없는 데이터셋)

     

    매개변수

    • n_estmators: 트리의 개수 지정
      • 너무 클 경우 모델이 복잡해지고 과대적합 가능성
    • learning_rate: 이전 트리의 오차 보정 강도 조절.
      • 메모리 한도에서 n_estimators 부터 설정.
      • 이후 적절한 learning_rate 설정.
      • 학습률이 크면 트리를 강하게 보정하여 복잡한 모델 생성. → 학습률을 오히려 낮추는 것이 좋음.
    • max_depth: 각 트리의 복잡도를 낮추는 매개변수.
      • 깊이는 5보다 깊어지지 않는 게 좋음.

     

     

     

     

    GredientBoostingClassifier 사용하기

    • 유방암 데이터셋 활용
    from sklearn.datasets import load_breast_cancer
    from sklearn.model_selection import train_test_split
    from sklearn.ensemble import GradientBoostingClassifier
    
    cancer = load_breast_cancer()
    
    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)))

    과대적합 상태.

     

     

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

     

     

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

     

     

    def plot_feature_importances_cancer(model):
        n_features = cancer.data.shape[1]
        plt.barh(np.arange(n_features), model.feature_importances_, align="center")
        plt.yticks(np.arange(n_features), cancer.feature_names)
        plt.xlabel("feature_important")
        plt.ylabel("feature")
        plt.ylim(-1, n_features)
    gbrt = GradientBoostingClassifier(random_state = 0, max_depth= 1)
    gbrt.fit(X_train, y_train)
    
    plot_feature_importances_cancer(gbrt)

     

     

     


    학습 데이터셋

    # from preamble import *
    from sklearn.model_selection import train_test_split
    from sklearn.datasets import make_moons
    from sklearn.datasets import load_breast_cancer
    
    Xm, ym = make_moons(n_samples = 100, noise = 0.25, random_state = 3)
    Xm_train, Xm_test, ym_train, ym_test = train_test_split(
    Xm, ym, stratify = ym, random_state = 42)
    
    cancer = load_breast_cancer()
    Xc_train, Xc_test, yc_train, yc_test = train_test_split(
    cancer.data, cancer.target, random_state = 0)

     

     

     

     


    배깅(Bagging)

    • 중복을 허용한 랜덤 샘플링으로 만든 훈련 세트를 사용하여 분류기를 각기 다르게 학습.
    from sklearn.linear_model import LogisticRegression
    from sklearn.linear_model import LinearRegression
    from sklearn.ensemble import BaggingClassifier
    
    bagging = BaggingClassifier(LogisticRegression(solver = 'liblinear'),
                               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_))

     

    from sklearn.tree import DecisionTreeClassifier
    bagging = BaggingClassifier(DecisionTreeClassifier(), n_estimators = 5,
                               n_jobs = -1, random_state = 42)
    
    bagging.fit(Xm_train, ym_train)

     

    fig, axes = plt.subplots(2, 3, figsize = (20, 10))
    
    for i, (ax, tree) in enumerate(zip(axes.ravel(), bagging.estimators_)):
        ax.set_title("Tree {}".format(i))
        mglearn.plots.plot_tree_partition(Xm, ym, tree, ax = ax)
        
    mglearn.plots.plot_2d_separator(bagging, Xm, fill = True, ax = axes[-1, -1], alpha = .4)
    axes[-1, -1].set_title("Bagging")
    mglearn.discrete_scatter(Xm[:, 0], Xm[:, 1], ym)
    plt.show()

     

    bagging = BaggingClassifier(DecisionTreeClassifier(), 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_))

     

     

     

     


    엑스트라 트리(Extra-Trees)

    • 후보 특성을 무작위로 분할한 다음 최적의 분할을 찾음.
    from sklearn.ensemble import ExtraTreesClassifier
    xtree = ExtraTreesClassifier(n_estimators = 5, n_jobs = -1, random_state = 0)
    xtree.fit(Xm_train, ym_train)
    
    fig, axes = plt.subplots(2, 3, figsize = (20, 10))
    for i, (ax, tree) in enumerate(zip(axes.ravel(), xtree.estimators_)):
        ax.set_title("tree {}".format(i))
        mglearn.plots.plot_tree_partition(Xm, ym, tree, ax = ax)
        
    mglearn.plots.plot_2d_separator(xtree, Xm, fill = True, ax = axes[-1, -1], alpha = .4)
    axes[-1, -1].set_title("Extra tree")
    mglearn.discrete_scatter(Xm[:, 0], Xm[:, 1], ym)
    plt.show()

     

     

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

     

     

    n_features = cancer.data.shape[1]
    plt.barh(range(n_features), xtree.feature_importances_, align="center")
    plt.yticks(np.arange(n_features), cancer.feature_names)
    plt.xlabel("Feature important")
    plt.ylabel("Feature")
    plt.ylim(-1, n_features)
    plt.show()

     

     

     

     


    에이다부스트(AdaBoost)

    • 그레디언트 부스팅과는 달리 이전의 모델이 잘못 분류한 샘플에 가중치를 높여 다음 모델을 훈련.
    from sklearn.ensemble import AdaBoostClassifier
    ada = AdaBoostClassifier(n_estimators = 5, random_state = 42)
    ada.fit(Xm_train, ym_train)
    
    fig, axes = plt.subplots(2, 3, figsize = (20, 10))
    for i, (ax, tree) in enumerate(zip(axes.ravel(), ada.estimators_)):
        ax.set_title("Tree {}".format(i))
        mglearn.plots.plot_tree_partition(Xm, ym, tree, ax = ax)
        
    mglearn.plots.plot_2d_separator(ada, Xm, fill = True, ax = axes[-1, -1], alpha = .4)
    axes[-1, -1].set_title("AdaBoost")
    mglearn.discrete_scatter(Xm[:, 0], Xm[:, 1], ym)
    plt.show()

     

     

     

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

     

     

     

    plt.barh(range(n_features), ada.feature_importances_, align = "center")
    plt.yticks(np.arange(n_features), cancer.feature_names)
    plt.xlabel("Feature important")
    plt.ylabel("Feature")
    plt.ylim(-1, n_features)
    plt.show()

     

     

     

     


    히스토그램 기반 부스팅

    from sklearn.ensemble import HistGradientBoostingClassifier
    hgb = HistGradientBoostingClassifier(random_state = 42)
    hgb.fit(Xm_train, ym_train)
    
    mglearn.plots.plot_2d_separator(hgb, Xm, fill = True, alpha = .4)
    plt.title("HistGradientBoosting")
    mglearn.discrete_scatter(Xm[:, 0], Xm[:, 1], ym)
    plt.show()

     

     

     

    hgb = HistGradientBoostingClassifier(random_state = 42)
    hgb.fit(Xc_train, yc_train)
    
    print("훈련 세트 정확도: {:.3f}".format(hgb.score(Xc_train, yc_train)))
    print("테스트 세트 정확도: {:.3f}".format(hgb.score(Xc_test, yc_test)))

     

    from sklearn.inspection import permutation_importance
    
    result = permutation_importance(hgb, Xc_train, yc_train,
                                   n_repeats = 10, random_state = 42, n_jobs = -1)
    
    plt.barh(range(n_features), result.importances_mean, align="center")
    plt.yticks(np.arange(n_features), cancer.feature_names)
    plt.xlabel("Feature important")
    plt.ylabel("Feature")
    plt.ylim(-1, n_features)
    plt.show()


    커널 서포트 백터 머신 (SVM)

    • 입력 데이터에서 단순한 초평면으로 정의되지 않는 더 복잡한 모델을 만들 수 있도록 확장한 지도 학습 모델.
    from sklearn.datasets import make_blobs
    X, y = make_blobs(centers = 4, random_state = 8)
    y = y % 2
    
    mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
    plt.xlabel("Feature 0")
    plt.ylabel("Feature 1")

     

    분류를 위한 선형 모델은 직선으로만 데이터 포인트를 나눌 수 있어서 이런 데이터셋에서는 맞지 않음.

     

     

     

    from sklearn.svm import LinearSVC
    linear_svm = LinearSVC(max_iter = 5000, tol=1e-3).fit(X, y)
    
    mglearn.plots.plot_2d_separator(linear_svm, X)
    mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
    plt.xlabel("Feature 0")
    plt.ylabel("Feature 1")

     

     

     

     

    X_new = np.hstack([X, X[:, 1:] ** 2])
    from mpl_toolkits.mplot3d import Axes3D, axes3d
    figure = plt.figure()
    
    # 3차원 그래프
    if matplotlib.__version__ >= "3.4":
        # Axes3D가 자동으로 그램에 추가되는 방식은 matplotlib 3.4 버전에서
        # deprecated 되었습니다.
        # 이와 관련된 경고를 피하려면 auto_add_to_figure = False로 지정하고
        # figure.add_axes(ax)로 직접 추가하세요.
        
        ax = Axes3D(figure, elev = - 512, azim = -26, auto_add_to_figure = False)
        figure.add_axes(ax)
        
    else:
        ax = Axes3D(figure, elev = -152, azim = -26)
        
    mask = y == 0
    ax.scatter(X_new[mask, 0], X_new[mask, 1], X_new[mask, 2], c='b',
               cmap = mglearn.cm2, s = 60, edgecolor = 'k')
    ax.scatter(X_new[~mask, 0], X_new[~mask, 1], X_new[~mask, 2], c='b', marker = '^',
               cmap = mglearn.cm2, s = 60, edgecolor = 'k')
    
    ax.set_xlabel("Feature 0")
    ax.set_ylabel("Feature 1")
    ax.set_zlabel("Feature 1 ** 2")

     

     

     

    linear_svm_3d = LinearSVC(max_iter = 5000).fit(X_new, y)
    coef, intercept = linear_svm_3d.coef_.ravel(), linear_svm_3d.intercept_
    
    # 선형 결정 경계 그리기
    figure = plt.figure()
    if matplotlib.__version__ >= '3.4':
        # Axes3D가 자동으로 그램에 추가되는 방식은 matplotlib 3.4 버전에서
        # deprecated 되었습니다.
        # 이와 관련된 경고를 피하려면 auto_add_to_figure = False로 지정하고
        # figure.add_axes(ax)로 직접 추가하세요.
        
        ax = Axes3D(figure, elev = - 512, azim = -26, auto_add_to_figure = False)
        figure.add_axes(ax)
    else:
        ax = Axes3D(figure, elev = -152, azim = -26)
        
    xx = np.linspace(X_new[:, 0].min() - 2, X_new[:, 0].max() + 2, 50)
    yy = np.linspace(X_new[:, 1].min() - 2, X_new[:, 1].max() + 2, 50)
    
    XX, YY = np.meshgrid(xx, yy)
    ZZ = (coef[0] * XX + coef[1] * YY + intercept) / -coef[2]
    ax.plot_surface(XX, YY, ZZ, rstride = 8, cstride = 8, alpha = 0.3)
    
    ax.scatter(X_new[mask, 0], X_new[mask, 1], X_new[mask, 2], c='b',
               cmap = mglearn.cm2, s = 60, edgecolor = 'k')
    ax.scatter(X_new[~mask, 0], X_new[~mask, 1], X_new[~mask, 2], c='r', marker = '^',
               cmap = mglearn.cm2, s = 60, edgecolor = 'k')
    
    ax.set_xlabel("Feature 0")
    ax.set_ylabel("Feature 1")
    ax.set_zlabel("Feature 1 ** 2")

     

     

    ZZ = YY ** 2
    dec = linear_svm_3d.decision_function(np.c_[XX.ravel(), YY.ravel(), ZZ.ravel()])
    plt.contourf(XX, YY, dec.reshape(XX.shape), levels = [dec.min(), 0, dec.max()],
                camap = mglearn.cm2, alpha = 0.5)
    
    mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
    ax.set_xlabel("Feature 0")
    ax.set_ylabel("Feature 1")


    커널 기법

    • 데이터셋에 비선형 특성을 추가하여 강력한 선형 모델 생성 가능
    • 어떤 특성을 추가해야할지 파악하기 어려운 문제
    • 특성을 지나치게 추가할 경우 연산 비용 증가 문제.
    • 실제 데이터를 확장하지 않고 확장된 특성에 대한 데이터 포인트들의 거리 계산.

     

    from sklearn.svm import SVC
    X, y = mglearn.tools.make_handcrafted_dataset()
    svm = SVC(kernel = 'rbf', C = 10, gamma = 0.1).fit(X, y)
    mglearn.plots.plot_2d_separator(svm, X, eps=.5)
    
    # 데이터 포인터 그리기
    mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
    
    # 서포트 백터
    sv = svm.support_vectors_
    
    # dual_coef_의 부호에 의해 서포트 백터의 클래스 레이블이 결정됩니다.
    sv_labels = svm.dual_coef_.ravel() > 0
    mglearn.discrete_scatter(sv[:, 0], sv[:, 1], sv_labels, s = 15, markeredgewidth = 3)
    plt.xlabel("Feature 0")
    plt.ylabel("Feature 1")

     

     

     

    fig, axes = plt.subplots(3, 3, figsize = (15, 10))
    
    for ax, C in zip(axes, [-1, 0, 3]):
        for a, gamma in zip (ax, range(-1, 2)):
            mglearn.plots.plot_svm(log_C = C, log_gamma = gamma, ax = a)
            
    axes[0, 0].legend(['클래스 0', '클래스 1', '클래스 0 서포트 백터',
                      '클래스 1 서포트 백터'], ncol = 4, loc = (.9, 1.2))

     

     

     

    X_train, X_test, y_train, y_test = train_test_split(
    cancer.data, cancer.target, random_state = 0)
    
    svc = SVC()
    svc.fit(X_train, y_train)
    
    print("훈련 세트 정확도: {:.3f}".format(svc.score(Xc_train, yc_train)))
    print("테스트 세트 정확도: {:.3f}".format(svc.score(Xc_test, yc_test)))

     

     

    plt.boxplot(X_train, manage_ticks = False)
    plt.yscale('symlog')
    plt.xlabel("Feature list")
    plt.ylabel("Feature width")

     

     

    # 훈련 세트에서 특성별 최솟값 계산
    min_on_training = X_train.min(axis = 0)
    
    # 훈련 세트에서 특성별 (최댓값 - 최솟값) 범위 계산
    range_on_training = (X_train - min_on_training).max(axis = 0)
    
    # 훈련 데이터에 최솟값을 빼고 범위로 나누면
    # 각 특성에 대해 최솟값은 0 최댓값은 1이다.
    X_train_scaled = (X_train - min_on_training) / range_on_training
    print("특성별 최솟값\n", X_train_scaled.min(axis = 0))
    print("특성별 최댓값\n", X_train_scaled.max(axis = 0))

     

     

     

     

    # 테스트 세트에도 같은 작업을 적용하지만
    # 훈련 세트에서 계산한 최솟값고 범위를 사용합니다.
    X_test_scaled = (X_test - min_on_training) / range_on_training
    
    svc = SVC()
    svc.fit(X_train_scaled, y_train)
    
    print("훈련 세트 정확도: {:.3f}".format(svc.score(X_train_scaled, y_train)))
    print("테스트 세트 정확도: {:.3f}".format(svc.score(X_test_scaled, y_test)))

     

     

    svc = SVC(C = 20)
    svc.fit(X_train_scaled, y_train)
    
    print("훈련 세트 정확도: {:.3f}".format(svc.score(X_train_scaled, y_train)))
    print("테스트 세트 정확도: {:.3f}".format(svc.score(X_test_scaled, y_test)))

    'ABC 부트캠프 > 머신러닝' 카테고리의 다른 글

    19일차 - 지도학습 2  (1) 2023.04.12
    18일차 - 지도학습 1  (0) 2023.04.11
    17일차 - 머신러닝(ML)  (0) 2023.04.11

    댓글