LDA, QDA

LDA(선형판별분석법), QDA(이차판별분석법)

  • 선형판별 분석법(Linear discriminant analysis, LDA)과 이차판별 분석법(quadratic discriminant analysis, QDA)는 대표적인 확률론적 생성모형이다. 가능도 y의 클래스값에 따른 x의 분포에 대한 정보를 먼저 알아낸 후, 베이즈 정리를 사용하여 주어진 x에 대한 y의 확률분포를 찾아낸다.

생성모형

  • 생성모형에서는 베이즈 정리를 사용하여 조건부 확률 $p(y = k \mid x)$를 계산한다.
  • 분류 문제를 풀기 위해서는 각 클래스 $k$에 대한 확률을 비교하여 가장 큰 값을 선택한다. 따라서 모든 클래스에 대해 값이 같은 분모 $P(x)$은 굳이 계산하지 않아도 괜찮다.
  • 여기에서 사전확률 $P(y=k)$는 특별한 정보가 없는 경우, 다음처럼 계산한다.
  • 만약 다른 지식이나 정보로 알고있는 사전확률 값이 있다면 그 값을 사용하면 된다.

  • $y$에 대한 $x$의 조건부확률인 가능도는 다음과 같이 계산한다.

    • 1) $P(x \mid y = k)$가 특정한 확률분포 모형을 따른다고 가정한다. 즉, 확률밀도 함수의 형태를 가정한다.
    • 2) $k$번째 클래스에 속하는 학습 데이터 $\{x_1, \cdots, x_N\}$을 사용하여 이 모형의 모수값을 구한다.
    • 3) 모수값을 알고 있으므로 $P(x \mid y = k)$의 확률 밀도 함수를 구한 것이다. 즉, 새로운 독립변수 값 x이 어떤 값이 되더라도 $P(x \mid y = k)$의 값을 계산할 수 있다.

LDA(Linear Discriminant Analysis)

  • 3가지(1,2,3) 범주의 클래스를 가지고 있는 데이터가 아래와 같을 때, 그림을 보면 중심을 기점으로 마치 정규분포와 비슷하게 중심과의 거리가 멀어질수록 분포의 밀도가 떨어지는 듯해 보인다면 LDA로 문제를 풀 수 있을 것 같다는 생각이 들어야 한다.

  • LDA(Linear Discriminant Analysis)는 선형 판별 분석법으로 불리며, PCA와 매우 유사하다. LDA는 PCA와 유사하게 입력 데이터 세트를 저차원 공간에 projection하여 차원을 축소하는 기법이지만, 중요한 차이는 LDA는 지도학습의 분류(Classification)에서 사용하기 쉽도록 개별 클래스를 분별할 수 있는 기준을 최대한 유지하면서 차원을 축소한다. PCA는 입력 데이터의 변동성의 가장 큰 축을 찾았지만 LDA는 입력 데이터의 결정 값 클래스를 최대한 분리 할 수 축을 찾는다.

Linear Discriminant Analysis 배경

  • 먼저, LDA도 이전의 나이브 베이지안 모형과 같이 특정 가정이 존재한다.
    • 클래스 집단별로 동일한 공분산 구조를 지녔다는 가정
    • 클래스 집단별로 정규분포를 따른다는 가정
  • 아래 그림에서 가정을 적용한 후의 그림을 보면 3가지 영역으로 나누어져 있는데, 이러한 영역은 어떻게 나뉠수 있는지를 설명할 것이다.

LDA의 가정

  • 아래 그림과 같이 2차원(두가지 독립변수)의 두 가지 범주를 갖는 데이터를 분류하는 문제에서 LDA는 먼저 하나의 차원에 projection을 하여 차원을 축소시킨다. 그 후에 클래스별 분포의 분산 대비 평균의 차이가 크게 나는 지점(즉, 두 집단의 평균의 평균점)을 decision boundary로 설정한다.
  • 아래 두 그림 중 어떠한 decision boundary를 갖는 것이 더 분류를 잘 한다고 생각이드는가? 아무래도 오른쪽을 선택하는 분들이 많을 것이다. 이렇게 데이터가 동일하여도 projection되는 축에 따라 decision boundary가 달라진다.그러므로 projection되는 축을 정하는 것이 중요하다.

LDA decision boundary

  • 우선 분류를 하려면 각 클래스 집단의 평균의 차이가 큰 지점을 decision boundary로 찾는다면 쉽게 분류가 가능할 것이므로 아래 그림과 같이 두 평균 벡터의 차이에 평행한 축에 projection을 하여 두 클래스를 비교하게 된다. 그러나, 두 집단간의 분산은 크기 때문에(분산이 크다는 것은 변동성이 크다는 얘기이므로 데이터의 분포를 두 집단으로 나누기에 무리가 있다.) 아직까진 분류의 모형으로 부족해 보인다.

LDA decision boundary 결정 방법 - 01

  • 위에서와 같이 각 클래스 집단의 평균의 차이만을 고려하는 것이 아니라, 각 클래스 집단의 분산은 작게끔하는 방향으로 projection을 시켜야 할 것이다. 분산이 작다면 그만큼 데이터의 분포가 밀집되어있으므로 분류의 예측 성능 또한 높아질 가능성이 커지기 때문이다.

LDA decision boundary 결정 방법 - 02

LDA의 수학적 개념 이해 - 다변량 정규분포

  • 이변량 정규 분포는 두 변수간의 상관계수 $\rho$가 0이라면 두 변수는 독립이므로 결국 위의 정규분포의 식을 곱한 값이 될 것이다. 그러나, 상관계수 $\rho$가 0이 아닌 값으로 존재한다. 아래 수식과 같은 jointed probability distribution을 갖는다. 3D 이미지로 살펴본다면 $\rho$의 절대값이 높아질수록 더 강한 선형성을 갖으며 전체 feature 공간에 대해서는 비대칭적이게 되어진다. 즉, 각 축의 방향에서 보았을 경우 분포의 이미지가 달라지게 된다.

이변량 정규 분포

  • 다변량 정규 분포로 확장하기에 앞서서, 먼저 이변량 정규분포에 대해 정리한 후 그 개념을 확장시킬 것이다. 이변량 정규분포의 수식은 아래 그림과 같다. 만약 $\rho$가 0이 라면 위에서 언급했던 것과 같이 두 정규분포 수식을 단순한 곱한 것과 동일하다는 것을 확인 할 수 있다. 다변량 정규분포의 식에 $2X2$ 공분산행렬을 대입하여 계산한다면, 이변량 정규분포식이 나오게 된다.

다변량 정규 분포

  • 먼저 LDA는 확률적 생성모형이므로 확률값을 계산해본다면, 다음과 같이 k번째 범주 집단의 분포함수는 정의 될 수 있다.

로그 다변량 정규 분포 - 01

  • 그렇다면, 새롭게 들어오는 관측치에 대해 클래스를 분류할 경우 어떻게 확률값을 계산해야 할까? 다음과 같이 범주에서 2개를 한 쌍으로 뽑는 경우의 가지수$_{4}C_{2}$ 만큼의 계산을 통해 비교하여 최종적으로 확률값이 가장 높은 클래스로 분류를 할 것이다. 아래 수식에서 가장 마지막 수식은 이차식 처럼 모양이 나오게 되는데, 그 이유는 두 벡터의 내적이 되기 때문에 어떤 벡터를 먼저 곱하는지는 상관이 없기 때문이다. 즉, $x^{T} \sum^{-1} \mu_{k} = \mu_{k}^{T} \sum^{-1} x $이기 때문이다.

로그 다변량 정규 분포 - 02

  • Linear Discriminant Analysis로 불리는 이유는 아래와 같이 feature x에 대한 1차식의 형태(선형구조)이기 때문이다. 여기서 유추할 수 있는 점은 위의 식을 얻기 위해선 LDA의 중요한 가정 중 하나인 클래스 집단 별 동일한 공분산 구조를 갖고있는다는 가정 때문이었다. 만약, 클래스 집단 별 동일하지 않은 공분산 구조를 갖는다면 위의 식에서 공분산 행렬을 기준으로 곱해지는 2차형식(Quadratic form)이 없어지지 않을 것이다. 클래스 집단 별 다른 공분산 구조를 갖는다는 가정을 한다면 QDA가 된다.

LDA 확률 계산

  • LDA(Linear Discriminant Analysis)에서는 각 $Y$ 클래스에 대한 독립변수 $X$의 조건부 확률 분포가 공통된 공분산 행렬을 가지는 다변수 정규분포(multivariate Gaussian normal distribution)이라고 가정한다.
  • 이 때는 조건부확률분포를 다음과 같이 정리할 수 있다.
  • 이 식에서 $C’(x)=exp C(x)$이다.
  • 이 식에서 $P(x)$는 $y$클래스값에 영향을 받지 않는다. 따라서
  • 모든 클래스 k에 대해 위와 같은 식이 성립하므로 클래스 $k_{l}$과 클래스 $k_{m}$의 경계선, 즉 두 클래스에 대한 확률값이 같아지는 $x$의 위치를 찾으면 다음과 같다.
  • 즉, 판별함수가 x에 대한 선형방정식이 되고 경계선의 모양이 직선이 된다.

정리 - LDA의 가정

정리 - LDA의 추정

정리 - LDA의 확률 추정

LDA와 eigen value와 eigen vector와의 연관성

  • 벡터 $a$를 다른 벡터 $b$에 직교하는 성분과 벡터 $b$에 평행한 성분으로 분해할 수 있는데, 평행한 성분을 벡터 $b$에 대한 투영성분(projection), 벡터 $b$에 대한 직교성분(rejection)이라고 하며 각각을 다음과 같이 표기한다.
  • 투영성분의 길이는 다음처럼 구할 수 있다.
  • 만약 벡터 $b$자체가 이미 단위벡터(Unit vector)이면 단위벡터에 대한 투영길이는 내적이 된다.
  • 투영성분 성분 벡터는 투영성분 길이와 벡터 $b$방향의 단위벡터의 곱이다.
  • 직교성분 벡터는 원래의 벡터에서 투영성분 성분 벡터를 뺀 나머지이다.

참고 : projection과 rejection
참고 : 제2 코사인법칙을 사용한 내적과의 연관성

Projection

  • 이러한 Projection이 LDA와의 관계를 설명하면 먼저, LDA의 목표인 클래스 집단 간의 평균은 크게하고 분산은 작게하는 decision boundary가 존재하는 Projection 공간을 말 할 수 있을 것이다.

LDA의 목표에 연관된 투영의 개념

  • 아래 그림에서 말하는 사영시킬 벡터 $a$라는 것은 decision boundary를 찾기위해 해당 데이터들을 투영시킨 벡터라는 의미이다. 위의 그림에서는 분포로 존재하는 공간의 축을 의미한다. 단 아래 그림의 수식들이 정확하기 위해선 먼저 각 데이터의 feature 벡터들이 Unit vector이고 사영된 벡터도 Unit vector인 경우에 한해서 아래의 수식이 정확하다고 할 수 있다.

LDA의 decision boundary를 찾기 위한 projection - 01

  • LDA의 목표에 맞게 클래스 집단의 평균의 차이는 크게하면서 분산은 최소화 시키는 사영을 찾는것이므로 아래와 같은 분수식을 사용할 수 있다. 각 평균과 분산은 projection된 성분을 가리킨다. 행렬표현으로 묶어서 다르게 표현한다면 맨 마직막의 수식들로 표현 가능하다.

LDA의 decision boundary를 찾기 위한 projection - 02

  • 행렬식에 대해 가장 큰 a값을 찾기 위해서는 미분을 해야 할 것이다. 미분을 통해 아래 그림과 같은 형태로 변형시킬 수 있다. 맨 마지막 수식을 살펴보면 eigen value와 eigen vector의 정의와 동일하게 볼 수 있음을 확인 할 수 있다.

LDA의 decision boundary를 찾기 위한 projection - 02

  • 위의 식을 다시한번 정리하면 eigen vector와 eigen value를 구할 수 있는데, 해당 데이터를 축소하는데 방향은 변하지 않고 길이만 변하는 벡터인 eigen vector를 찾으면 LDA의 decision boundary가 존재하는 공간인 벡터이다.

LDA의 decision boundary를 찾기 위한 projection - 03

LDA의 decision boundary에서 eigen vector의 역할

  • 이전에 decision boundary를 찾는 공식에서 살펴보면, 찾아낸 축이 기울기 역할을 하고 클래스 집단의 평균을 지나는 초평면이 decision boundary라는 사실을 확인할 수 있다.

LDA의 수학적 개념 총 정리

  • Scikit-Learn은 선형판별분석법을 위한 LinearDiscriminantAnalysis 클래스를 제공한다.
    • 참고로 데이터는 아래 QDA와 동일한 데이터를 사용한다.
1
2
3
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

lda = LinearDiscriminantAnalysis(n_components=3, solver="svd", store_covariance=True).fit(X, y)
  • 선형판별 분석법에서는 기대값 벡터만 클래스에 따라 달라지고 공분산 행렬은 공통으로 추정한다.
1
lda.means_
결과
1
2
3
array([[-8.01254084e-04,  1.19457204e-01],
[ 1.16303727e+00, 1.03930605e+00],
[-8.64060404e-01, 1.02295794e+00]])
1
lda.covariance_
결과
1
2
array([[0.7718516 , 0.13942905],
[0.13942905, 0.7620019 ]])
  • 결과는 다음처럼 직선인 경계선을 가진다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
x1min, x1max = -5, 5
x2min, x2max = -4, 5
XX1, XX2 = np.meshgrid(np.arange(x1min, x1max, (x1max-x1min)/1000),
np.arange(x2min, x2max, (x2max-x2min)/1000))
YY = np.reshape(lda.predict(np.array([XX1.ravel(), XX2.ravel()]).T), XX1.shape)
cmap = mpl.colors.ListedColormap(sns.color_palette(["r", "g", "b"]).as_hex())
plt.contourf(XX1, XX2, YY, cmap=cmap, alpha=0.5)
plt.scatter(X1[:, 0], X1[:, 1], alpha=0.8, s=50, marker="o", color='r', label="클래스 1")
plt.scatter(X2[:, 0], X2[:, 1], alpha=0.8, s=50, marker="s", color='g', label="클래스 2")
plt.scatter(X3[:, 0], X3[:, 1], alpha=0.8, s=50, marker="x", color='b', label="클래스 3")
plt.xlim(x1min, x1max)
plt.ylim(x2min, x2max)
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
plt.legend()
plt.title("LDA 분석 결과")
plt.show()

LDA 분석의 결과

선형판별분석법을 사용하여 붓꽃 분류문제를 풀고 성능을 분류결과표와 분류보고서를 출력하라. 그리고 각 클래스에 대한 ROC 커브를 그려라.

1
2
from sklearn.datasets import load_iris
from sklearn.metrics import confusion_matrix, classification_report, roc_curve, roc_auc_score
  • 클래스별 고루 학습하기 위해 stratify하게 설정하였다.
1
2
3
4
iris = load_iris()
X = iris.data
y = iris.target
train_X, test_X, train_y, test_y = train_test_split(X, y, test_size=0.3, random_state=1234, stratify=y)
1
2
3
4
LDA = LinearDiscriminantAnalysis()
LDA.fit(train_X, train_y)
pred_LDA = LDA.predict(test_X)
confusion_matrix(pred_LDA, test_y)
결과
1
2
3
array([[15,  0,  0],
[ 0, 14, 0],
[ 0, 1, 15]])
1
print(classification_report(pred_LDA, test_y))
결과
1
2
3
4
5
6
7
8
9
              precision    recall  f1-score   support

0 1.00 1.00 1.00 15
1 0.93 1.00 0.97 14
2 1.00 0.94 0.97 16

accuracy 0.98 45
macro avg 0.98 0.98 0.98 45
weighted avg 0.98 0.98 0.98 45
1
roc_auc_score(label_binarize(test_y, classes=[0,1,2]), LDA.predict_proba(test_X))
1
2
3
4
5
6
7
8
9
10
11
12
13
label_test_y = label_binarize(test_y, [0, 1, 2])

fpr = [None] * 3
tpr = [None] * 3
thr = [None] * 3

for i in range(3):
fpr[i], tpr[i], thr[i] = roc_curve(label_test_y[:, i], LDA.predict_proba(test_X)[:, i])
plt.plot(fpr[i], tpr[i])

plt.xlabel('Fall-Out')
plt.ylabel('Recall')
plt.show()

iris 데이터에 대한 LDA 분석 결과의 ROC curve

QDA(Quadratic Discriminant Analysis)

  • 나이브 베이즈 모형은 조건부독립이라는 가정이 있었기 때문에 사실상 각 설명변수들간의 공분산 구조를 반영하진 않는다. 그에 반해, LDA는 설명변수간 비슷한 수준의 공분산 구조를 갖는다는 가정하에 모형을 실행하는데, 공분산 구조의 차이가 심하게 난다면, LDA 가정을 실행할 수 없다. 이런 경우에 사용하는 것이 바로 QDA이다. LDA는 가장 작은 그룹의 샘플 수가 독립(설명)변수의 개수보다 많아야 하는데 나이브 베이즈 모형은 조건부 독립을 가정하기에 훨씬 더 적은 샘플이더라도 추정이 가능하다.

LDA 가정 총 정리

  • 이차판별분석법(QDA)에서는 독립변수 x가 실수이고 확률분포가 다변량 정규분포라고 가정한다. 단 x분포의 위치와 형태는 클래스에 따라 달라질 수 있다.즉, 클래스별로 다른 공분산 구조를 갖는다는 의미이다. 공분산 구조가 동일하지 않아 이차형식(Quadratic form)이 남게 된다.

QDA의 개념

  • 이 분포들을 알고 있으면 독립변수 $x$에 대한 $y$ 클래스의 조건부확률분포는 다음과 같이 베이즈 정리와 전체 확률의 법칙으로 구할 수 있다.
  • LDA는 Decision boundary가 선형으로 되기 때문에 아래 그림에서 보는 것과 같은 데이터 분포이면 구분하는데 어렵다. 허나 변수의 제곱을한 추가적인 변수들을 통해 이를 보완할 수 있다. 그렇지 않고 현재 존재하는 변수들만 사용해 문제를 풀기 위해선 QDA를 사용하는 것이 좋다. 중간에 있는 그림은 클래스 별 같은 공분산 구조를 가진다고 가정을 하고 변수를 추가해 주어 계산되는 반면에 오른쪽 그림은 처음 데이터 변수들만 사용하게 된다. 허나, QDA는 클래스별 서로 다른 공분산 구조를 가진다는 가정이 있기 때문에 모수를 추정하는 횟수가 그 만큼 더 많이 늘어나는 문제도 있다.

LDA와 QDA의 비교 - 01

LDA와 QDA의 비교 - 02

  • 예를 들어 $y$가 1,2,3 이라는 3개의 클래스를 가지고 각 클래스에서의 $x$의 확률분포가 다음과 같은 기대값 및 공분산 행렬을 가진다고 가정하자.
  • $y$의 사전 확률은 다음과 같이 동일하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
N = 100
rv1 = sp.stats.multivariate_normal([ 0, 0], [[0.7, 0.0], [0.0, 0.7]])
rv2 = sp.stats.multivariate_normal([ 1, 1], [[0.8, 0.2], [0.2, 0.8]])
rv3 = sp.stats.multivariate_normal([-1, 1], [[0.8, 0.2], [0.2, 0.8]])
np.random.seed(0)
X1 = rv1.rvs(N)
X2 = rv2.rvs(N)
X3 = rv3.rvs(N)
y1 = np.zeros(N)
y2 = np.ones(N)
y3 = 2 * np.ones(N)
X = np.vstack([X1, X2, X3])
y = np.hstack([y1, y2, y3])

plt.scatter(X1[:, 0], X1[:, 1], alpha=0.8, s=50, marker="o", color='r', label="class 1")
plt.scatter(X2[:, 0], X2[:, 1], alpha=0.8, s=50, marker="s", color='g', label="class 2")
plt.scatter(X3[:, 0], X3[:, 1], alpha=0.8, s=50, marker="x", color='b', label="class 3")
plt.xlim(-5, 5)
plt.ylim(-4, 5)
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
plt.legend()
plt.show()

클래스별 서로 다른 모수를 갖는 정규분포

  • Scikit-Learn은 이차판별 분석법을 위한 QuadraticDiscriminantAnalysis클래스를 제공한다.
1
2
3
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis

qda = QuadraticDiscriminantAnalysis(store_covariance=True).fit(X, y)
  • 학습용 데이터에서 가능도를 추정한 후에는 다음과 같은 속성을 가지게 된다.
    • priors_ : 각 클래스 $k$의 사전확률
    • means_ : 각 클래스 $k$에서 $x$의 기대값 벡터 $\mu_{k}$의 추정치 벡터
    • covariance_ : 각 클래스 $k$에서 $x$의 공분산 행렬 $\sum_{k}$의 추정치 행렬.(생성자 인수 store_covariance=True인 경우에만 제공)
1
qda.priors_
결과
1
array([0.33333333, 0.33333333, 0.33333333])
1
qda.means_
결과
1
2
3
array([[-8.01254084e-04,  1.19457204e-01],
[ 1.16303727e+00, 1.03930605e+00],
[-8.64060404e-01, 1.02295794e+00]])
1
qda.covariance_[0]
결과
1
2
array([[ 0.73846319, -0.01762041],
[-0.01762041, 0.72961278]])
1
qda.covariance_[1]
결과
1
2
array([[0.66534246, 0.21132313],
[0.21132313, 0.78806006]])
1
qda.covariance_[2]
결과
1
2
array([[0.9351386 , 0.22880955],
[0.22880955, 0.79142383]])
  • 이 확률분포를 사용하여 분류를 한 결과는 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
x1min, x1max = -5, 5
x2min, x2max = -4, 5
XX1, XX2 = np.meshgrid(np.arange(x1min, x1max, (x1max-x1min)/1000),
np.arange(x2min, x2max, (x2max-x2min)/1000))
YY = np.reshape(qda.predict(np.array([XX1.ravel(), XX2.ravel()]).T), XX1.shape)
cmap = mpl.colors.ListedColormap(sns.color_palette(["r", "g", "b"]).as_hex())
plt.contourf(XX1, XX2, YY, cmap=cmap, alpha=0.5)
plt.scatter(X1[:, 0], X1[:, 1], alpha=0.8, s=50, marker="o", color='r', label="클래스 1")
plt.scatter(X2[:, 0], X2[:, 1], alpha=0.8, s=50, marker="s", color='g', label="클래스 2")
plt.scatter(X3[:, 0], X3[:, 1], alpha=0.8, s=50, marker="x", color='b', label="클래스 3")
plt.xlim(x1min, x1max)
plt.ylim(x2min, x2max)
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
plt.title("이차판별분석법 결과")
plt.legend()
plt.show()

QDA의 결과

QDA를 사용하여 iris classification문제를 풀고 성능을 confusion_matrix와 classification_report를 출력하라. 그리고 각 클래스에 대한 ROC 커브를 그려라.

1
2
from sklearn.datasets import load_iris
from sklearn.metrics import confusion_matrix, classification_report
  • 각 클래스를 동일하게(stratify) 학습시키기 위해서 train과 test를 나눌때 설정해주었다.
1
2
3
4
iris = load_iris()
X = iris.data
y = iris.target
train_X, test_X, train_y, test_y = train_test_split(X, y, test_size=0.3, random_state=1234, stratify=y)
1
2
3
4
QDA = QuadraticDiscriminantAnalysis()
QDA.fit(train_X, train_y)
pred_QDA = QDA.predict(test_X)
confusion_matrix(pred_QDA, test_y)
결과
1
2
3
array([[15,  0,  0],
[ 0, 14, 0],
[ 0, 1, 15]])
1
print(classification_report(pred_QDA, test_y))
결과
1
2
3
4
5
6
7
8
9
              precision    recall  f1-score   support

0 1.00 1.00 1.00 15
1 0.93 1.00 0.97 14
2 1.00 0.94 0.97 16

accuracy 0.98 45
macro avg 0.98 0.98 0.98 45
weighted avg 0.98 0.98 0.98 45
1
roc_auc_score(label_binarize(test_y, classes=[0,1,2]), QDA.decision_function(test_X))
1
roc_auc_score(label_binarize(test_y, classes=[0,1,2]), QDA.predict_proba(test_X))
1
2
3
4
5
6
7
8
9
10
11
12
13
label_test_y = label_binarize(test_y, [0, 1, 2])

fpr = [None] * 3
tpr = [None] * 3
thr = [None] * 3

for i in range(3):
fpr[i], tpr[i], thr[i] = roc_curve(label_test_y[:, i], QDA.predict_proba(test_X)[:, i])
plt.plot(fpr[i], tpr[i])

plt.xlabel('위양성률(Fall-Out)')
plt.ylabel('재현률(Recall)')
plt.show()

iris test data에 대한 QDA ROC curve