불균형 분류를 위한 정밀도 - 재현율 지표

Beginner

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

소개

이 튜토리얼은 분류기 출력 품질을 평가하기 위해 정밀도 - 재현율 지표를 사용하는 단계별 가이드를 제공합니다. 정밀도 - 재현율 곡선은 클래스가 매우 불균형적인 경우 예측 성공도를 측정하는 데 유용한 지표입니다. 정보 검색에서 정밀도는 결과의 관련성을 측정하는 지표이고, 재현율은 실제로 관련성이 있는 결과가 몇 개 반환되었는지를 측정하는 지표입니다.

VM 팁

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

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

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

데이터셋 및 모델

붓꽃 (iris) 데이터셋과 선형 SVC 분류기를 사용하여 두 종류의 붓꽃을 구분하는 방법을 보여줍니다. 먼저 필요한 라이브러리를 가져오고 데이터셋을 로드합니다.

import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC

X, y = load_iris(return_X_y=True)

다음으로, 데이터셋에 노이즈 특징을 추가하고 학습 및 테스트 세트로 분할합니다.

random_state = np.random.RandomState(0)
n_samples, n_features = X.shape
X = np.concatenate([X, random_state.randn(n_samples, 200 * n_features)], axis=1)

X_train, X_test, y_train, y_test = train_test_split(
    X[y < 2], y[y < 2], test_size=0.5, random_state=random_state
)

마지막으로, StandardScaler를 사용하여 데이터를 스케일링하고 선형 SVC 분류기를 학습 데이터에 맞춥니다.

classifier = make_pipeline(
    StandardScaler(), LinearSVC(random_state=random_state, dual="auto")
)
classifier.fit(X_train, y_train)

정밀도 - 재현율 곡선 플롯

정밀도 - 재현율 곡선을 플롯하려면 sklearn.metrics 라이브러리의 PrecisionRecallDisplay 클래스를 사용합니다. 곡선을 계산하기 위해 from_estimator 또는 from_predictions 메서드를 사용할 수 있습니다. from_estimator 메서드는 곡선을 플롯하기 전에 예측을 계산하는 반면, from_predictions 메서드는 예측 점수를 직접 제공해야 합니다.

from sklearn.metrics import PrecisionRecallDisplay

## from_estimator 메서드 사용
display = PrecisionRecallDisplay.from_estimator(
    classifier, X_test, y_test, name="LinearSVC", plot_chance_level=True
)
_ = display.ax_.set_title("2-class 정밀도 - 재현율 곡선")

## from_predictions 메서드 사용
y_score = classifier.decision_function(X_test)

display = PrecisionRecallDisplay.from_predictions(
    y_test, y_score, name="LinearSVC", plot_chance_level=True
)
_ = display.ax_.set_title("2-class 정밀도 - 재현율 곡선")

다중 레이블 분류를 위한 정밀도 - 재현율 곡선 플롯

정밀도 - 재현율 곡선은 다중 레이블 설정을 지원하지 않습니다. 그러나 이 경우를 처리하는 방법을 결정할 수 있습니다. 다중 레이블 데이터셋을 생성하고, OneVsRestClassifier 를 사용하여 학습 및 예측한 후 정밀도 - 재현율 곡선을 플롯합니다.

from sklearn.preprocessing import label_binarize
from sklearn.multiclass import OneVsRestClassifier
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import average_precision_score

## 다중 레이블 데이터 생성
Y = label_binarize(y, classes=[0, 1, 2])
n_classes = Y.shape[1]
X_train, X_test, Y_train, Y_test = train_test_split(
    X, Y, test_size=0.5, random_state=random_state
)

## OneVsRestClassifier 를 사용하여 학습 및 예측
classifier = OneVsRestClassifier(
    make_pipeline(StandardScaler(), LinearSVC(random_state=random_state, dual="auto"))
)
classifier.fit(X_train, Y_train)
y_score = classifier.decision_function(X_test)

## 각 클래스에 대한 정밀도와 재현율 계산
precision = dict()
recall = dict()
average_precision = dict()
for i in range(n_classes):
    precision[i], recall[i], _ = precision_recall_curve(Y_test[:, i], y_score[:, i])
    average_precision[i] = average_precision_score(Y_test[:, i], y_score[:, i])

## 마이크로 평균 정밀도와 재현율 계산
precision["micro"], recall["micro"], _ = precision_recall_curve(Y_test.ravel(), y_score.ravel())
average_precision["micro"] = average_precision_score(Y_test, y_score, average="micro")

## 마이크로 평균 정밀도 - 재현율 곡선 플롯
display = PrecisionRecallDisplay(
    recall=recall["micro"],
    precision=precision["micro"],
    average_precision=average_precision["micro"],
    prevalence_pos_label=Counter(Y_test.ravel())[1] / Y_test.size,
)
display.plot(plot_chance_level=True)
_ = display.ax_.set_title("모든 클래스에 대한 마이크로 평균")

## 각 클래스의 정밀도 - 재현율 곡선 및 등-F1 곡선 플롯
colors = cycle(["navy", "turquoise", "darkorange", "cornflowerblue", "teal"])
_, ax = plt.subplots(figsize=(7, 8))
f_scores = np.linspace(0.2, 0.8, num=4)
lines, labels = [], []
for f_score in f_scores:
    x = np.linspace(0.01, 1)
    y = f_score * x / (2 * x - f_score)
    (l,) = plt.plot(x[y >= 0], y[y >= 0], color="gray", alpha=0.2)
    plt.annotate("f1={0:0.1f}".format(f_score), xy=(0.9, y[45] + 0.02))

display = PrecisionRecallDisplay(
    recall=recall["micro"],
    precision=precision["micro"],
    average_precision=average_precision["micro"],
)
display.plot(ax=ax, name="마이크로 평균 정밀도 - 재현율", color="gold")

for i, color in zip(range(n_classes), colors):
    display = PrecisionRecallDisplay(
        recall=recall[i],
        precision=precision[i],
        average_precision=average_precision[i],
    )
    display.plot(ax=ax, name=f"클래스 {i}의 정밀도 - 재현율", color=color)

handles, labels = display.ax_.get_legend_handles_labels()
handles.extend([l])
labels.extend(["등-F1 곡선"])
ax.set_xlim([0.0, 1.0])
ax.set_ylim([0.0, 1.05])
ax.legend(handles=handles, labels=labels, loc="best")
ax.set_title("다중 클래스로 확장된 정밀도 - 재현율 곡선")
plt.show()

요약

이 튜토리얼에서는 분류기 출력 품질을 평가하기 위해 정밀도 - 재현율 지표를 사용하는 단계별 가이드를 제공했습니다. sklearn.metrics 라이브러리의 PrecisionRecallDisplay 클래스를 사용하여 이진 분류의 정밀도 - 재현율 곡선을 플롯하는 방법을 배웠습니다. 또한, OneVsRestClassifier를 사용하여 다중 레이블 분류의 정밀도 - 재현율 곡선을 플롯하고 각 클래스의 정밀도와 재현율을 계산하는 방법을 학습했습니다.