판별 분석 분류 알고리즘

Beginner

This tutorial is from open-source community. Access the source code

소개

이 실습에서는 선형 판별 분석 (LDA) 과 2 차 판별 분석 (QDA) 에 대해 배웁니다. LDA 와 QDA 는 각각 두 개 이상의 클래스 사이의 선형 및 2 차 결정 경계를 찾는 분류 알고리즘입니다. scikit-learn 라이브러리를 사용하여 이러한 알고리즘을 구현하고 결정 경계를 시각화할 것입니다.

VM 팁

VM 시작이 완료되면 왼쪽 상단 모서리를 클릭하여 Notebook 탭으로 전환하여 연습용 Jupyter Notebook에 접근합니다.

때때로 Jupyter Notebook 이 완전히 로드되기까지 몇 초 정도 기다려야 할 수 있습니다. Jupyter Notebook 의 제한으로 인해 작업 검증은 자동화될 수 없습니다.

학습 중 문제가 발생하면 Labby 에게 문의하십시오. 세션 후 피드백을 제공하면 문제를 신속하게 해결해 드리겠습니다.

라이브러리 가져오기 및 데이터셋 생성

먼저 필요한 라이브러리를 가져오고 두 개의 데이터셋을 생성합니다. 하나는 고정된 공분산을 가지고 다른 하나는 변하는 공분산을 가집니다.

import numpy as np
import matplotlib.pyplot as plt
from scipy import linalg
from matplotlib import colors
import matplotlib as mpl
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis, QuadraticDiscriminantAnalysis

## 고정된 공분산을 가진 데이터셋 생성
def dataset_fixed_cov():
    n, dim = 300, 2
    np.random.seed(0)
    C = np.array([[0.0, -0.23], [0.83, 0.23]])
    X = np.r_[np.dot(np.random.randn(n, dim), C), np.dot(np.random.randn(n, dim), C) + np.array([1, 1])]
    y = np.hstack((np.zeros(n), np.ones(n)))
    return X, y

## 변하는 공분산을 가진 데이터셋 생성
def dataset_cov():
    n, dim = 300, 2
    np.random.seed(0)
    C = np.array([[0.0, -1.0], [2.5, 0.7]]) * 2.0
    X = np.r_[np.dot(np.random.randn(n, dim), C), np.dot(np.random.randn(n, dim), C.T) + np.array([1, 4])]
    y = np.hstack((np.zeros(n), np.ones(n)))
    return X, y

색상맵 생성

시각화에 사용할 사용자 정의 색상맵을 생성합니다.

cmap = colors.LinearSegmentedColormap(
    "red_blue_classes",
    {
        "red": [(0, 1, 1), (1, 0.7, 0.7)],
        "green": [(0, 0.7, 0.7), (1, 0.7, 0.7)],
        "blue": [(0, 0.7, 0.7), (1, 1, 1)],
    },
)
plt.cm.register_cmap(cmap=cmap)

플롯 함수

데이터와 타원을 플롯하는 두 개의 함수를 정의합니다.

def plot_data(lda, X, y, y_pred, fig_index):
    splot = plt.subplot(2, 2, fig_index)
    if fig_index == 1:
        plt.title("선형 판별 분석")
        plt.ylabel("고정된 공분산을 가진 데이터")
    elif fig_index == 2:
        plt.title("사차 판별 분석")
    elif fig_index == 3:
        plt.ylabel("변하는 공분산을 가진 데이터")

    tp = y == y_pred  ## 참 양성
    tp0, tp1 = tp[y == 0], tp[y == 1]
    X0, X1 = X[y == 0], X[y == 1]
    X0_tp, X0_fp = X0[tp0], X0[~tp0]
    X1_tp, X1_fp = X1[tp1], X1[~tp1]

    ## 클래스 0: 점
    plt.scatter(X0_tp[:, 0], X0_tp[:, 1], marker=".", color="red")
    plt.scatter(X0_fp[:, 0], X0_fp[:, 1], marker="x", s=20, color="#990000")  ## 진한 빨강

    ## 클래스 1: 점
    plt.scatter(X1_tp[:, 0], X1_tp[:, 1], marker=".", color="blue")
    plt.scatter(X1_fp[:, 0], X1_fp[:, 1], marker="x", s=20, color="#000099")  ## 진한 파랑

    ## 클래스 0 과 1: 영역
    nx, ny = 200, 100
    x_min, x_max = plt.xlim()
    y_min, y_max = plt.ylim()
    xx, yy = np.meshgrid(np.linspace(x_min, x_max, nx), np.linspace(y_min, y_max, ny))
    Z = lda.predict_proba(np.c_[xx.ravel(), yy.ravel()])
    Z = Z[:, 1].reshape(xx.shape)
    plt.pcolormesh(xx, yy, Z, cmap="red_blue_classes", norm=colors.Normalize(0.0, 1.0), zorder=0)
    plt.contour(xx, yy, Z, [0.5], linewidths=2.0, colors="white")

    ## 평균
    plt.plot(lda.means_[0][0], lda.means_[0][1], "*", color="yellow", markersize=15, markeredgecolor="grey")
    plt.plot(lda.means_[1][0], lda.means_[1][1], "*", color="yellow", markersize=15, markeredgecolor="grey")

    return splot


def plot_ellipse(splot, mean, cov, color):
    v, w = linalg.eigh(cov)
    u = w[0] / linalg.norm(w[0])
    angle = np.arctan(u[1] / u[0])
    angle = 180 * angle / np.pi  ## 각도를 도로 변환
    ## 2 표준 편차의 채워진 가우시안
    ell = mpl.patches.Ellipse(mean, 2 * v[0] ** 0.5, 2 * v[1] ** 0.5, angle=180 + angle, facecolor=color, edgecolor="black", linewidth=2)
    ell.set_clip_box(splot.bbox)
    ell.set_alpha(0.2)
    splot.add_artist(ell)
    splot.set_xticks(())
    splot.set_yticks(())

LDA 공분산 타원 플롯

LDA 의 공분산 타원체를 플롯합니다.

def plot_lda_cov(lda, splot):
    plot_ellipse(splot, lda.means_[0], lda.covariance_, "red")
    plot_ellipse(splot, lda.means_[1], lda.covariance_, "blue")

QDA 공분산 타원 플롯

QDA 의 공분산 타원체를 플롯합니다.

def plot_qda_cov(qda, splot):
    plot_ellipse(splot, qda.means_[0], qda.covariance_[0], "red")
    plot_ellipse(splot, qda.means_[1], qda.covariance_[1], "blue")

결정 경계 시각화

1 단계에서 생성된 데이터셋을 사용하여 LDA 와 QDA 의 결정 경계를 시각화합니다.

plt.figure(figsize=(10, 8), facecolor="white")
plt.suptitle("선형 판별 분석 (LDA) 대 사차 판별 분석 (QDA)", y=0.98, fontsize=15)

for i, (X, y) in enumerate([dataset_fixed_cov(), dataset_cov()]):
    ## 선형 판별 분석
    lda = LinearDiscriminantAnalysis(solver="svd", store_covariance=True)
    y_pred = lda.fit(X, y).predict(X)
    splot = plot_data(lda, X, y, y_pred, fig_index=2 * i + 1)
    plot_lda_cov(lda, splot)
    plt.axis("tight")

    ## 사차 판별 분석
    qda = QuadraticDiscriminantAnalysis(store_covariance=True)
    y_pred = qda.fit(X, y).predict(X)
    splot = plot_data(qda, X, y, y_pred, fig_index=2 * i + 2)
    plot_qda_cov(qda, splot)
    plt.axis("tight")

plt.tight_layout()
plt.subplots_adjust(top=0.92)
plt.show()

요약

이 실습에서는 선형 판별 분석 (LDA) 과 사차 판별 분석 (QDA) 에 대해 배웠습니다. 두 개의 데이터셋을 생성하고, 각각 LDA 와 QDA 를 사용하여 선형 및 사차 결정 경계를 찾았습니다. 각 알고리즘의 결정 경계와 공분산 타원체를 시각화했습니다.