plot_confusion_matrix
์ ์๋ช
์ ํ์ฌ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
sklearn.metrics.plot_confusion_matrix(estimator, X, y_true, labels=None, sample_weight=None, normalize=None, display_labels=None, include_values=True, xticks_rotation='horizontal', values_format=None, cmap='viridis', ax=None)
์ด ํจ์๋ ์ถ์ ๊ธฐ์ ์์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ฉฐ ์ด๋ฏธ ์์ธก๋ ๋ ์ด๋ธ๊ณผ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ ๋ช ๊ฐ์ง ๋จ์ ์ด ์์ต๋๋ค.
์ ์: estimator
๋ฐ X
๋์ ์ฌ์ฉ๋ ์์ธก ๋ ์ด๋ธ y_pred
์ plot_confusion_matrix
์ ๋ฌํ๋๋ก ํ์ฉํฉ๋๋ค. ๋ด ์๊ฐ์ ๊ฐ์ฅ ๊นจ๋ํ ์๋ฃจ์
์ ํจ์์์ ์์ธก ๋จ๊ณ๋ฅผ ์ ๊ฑฐํ๊ณ accuracy_score
์ ์ ์ฌํ ์๋ช
์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค(์: (y_true, y_pred, labels=None, sample_weight=None, ...)
. ๊ทธ๋ฌ๋ ํ์ ํธํ์ฑ์ ์ ์งํ๊ธฐ ์ํด y_pred
๋ฅผ ์ ํ์ ํค์๋ ์ธ์๋ก ์ถ๊ฐํ ์ ์์ต๋๋ค.
์ฐ๋ฆฌ๋ ํ์คํ ํ์ ํธํ์ฑ์ ์ ์งํด์ผ ํ์ง๋ง y_pred
ํค์๋ arg๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ผ๋ก ๋ค๋ฆฝ๋๋ค. y_pred๊ฐ ์ ๋ฌ๋์์ง๋ง X ๋๋ estimator๋ ์ ๋ฌ๋๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํด์ผ ํฉ๋๋ค.
@jhennrich PR์ ์ ์ถํ์๊ฒ ์ต๋๊น?
PR์ ์ ์ถํ๋๋ฐ ํ์ฌ CI์ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ ๊ฐ์์ ์์ง ํต๊ณผ๋์ง ์์์ต๋๋ค.
์ฌ๋ฌ ๋ฒ ์์ธก์ ๊ณ์ฐํ์ง ์๋๋ก plot_XXX(y_true, y_pred)
๋ฅผ ์ง์ํด์ผ ํ๋ค๋ ๋ฐ ๋์ํฉ๋๋ค.
plot_roc_curve ๋ฐ plot_precision_recall_curve์์๋ ์ ์ฌํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
y_pred๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๊ด์ฐฎ์ ๊ฒ ๊ฐ์ง๋ง ์์งํ ์ข์ ํด๊ฒฐ์ฑ
์ ์๋๋ผ๊ณ ์๊ฐํฉ๋๋ค.
**kwargs๋ฅผ ํ์ฉํ๋ ํจ์(์: plot_precision_recall_curve)์ ๊ฒฝ์ฐ ์ด์ ๋ฒ์ ๊ณผ์ ํธํ์ฑ์ ์ ์งํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ ๊ฒ ๊ฐ์ต๋๊น?
์ด์ ๋ฒ์ ๊ณผ์ ํธํ์ฑ์ ์ ์งํ ์ ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? #15883์ ์ ์์ด ๊ด์ฐฎ์ ๊ฒ ๊ฐ์ต๋๋ค.
์ด์ ๋ฒ์ ๊ณผ์ ํธํ์ฑ์ ์ ์งํ ์ ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? #15883์ ์ ์์ด ๊ด์ฐฎ์ ๊ฒ ๊ฐ์ต๋๋ค.
์ฐ๋ฆฌ๋ plot_confusion_matrix์์ **kwargs๋ฅผ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค. @NicolasHug
์ฝฐ๋ฅด๊ทธ๊ฐ ์ ๋ฌธ์ ์ธ๊ฐ?
ํ , ๊ทธ๋์ ๋ ๋ค๋ฅธ ์ฑ๊ฐ์ ๊ฒ์ด ์์ต๋๋ค. ์ฐ๋ฆฌ๋ plot_roc_curve ๋ฐ plot_precision_recall_curve(๋ฐ plot_partial_dependence)์์ **kwargs๋ฅผ ์ง์ํ์ง๋ง plot_confusion_matrix์์๋ ์ง์ํ์ง ์์ต๋๋ค.
์ฝฐ๋ฅด๊ทธ๊ฐ ์ ๋ฌธ์ ์ธ๊ฐ?
**kwargs ์์ ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ถ๊ฐํ๋ฉด ์ด์ ๋ฒ์ ๊ณผ์ ํธํ์ฑ์ ์ ์งํ ์ ์์ต๋๋ค. ๊ทธ๋ ์ฃ ?
๋ด PR์ ๋ณ๊ฒฝ ์ฌํญ์ ์ด์ ๋ฒ์ ๊ณผ ํธํ๋๋ฉฐ **kwargs๋ฅผ ๊ณ์ ์ถ๊ฐํ ์ ์์ต๋๋ค. ํ์ง๋ง @qinhanmin2014 ์ ๋์ํฉ๋๋ค. ํจ์ฌ ๊นจ๋ํ ์๋ฃจ์
์ estimator
๋ฐ X
๋ฒ๋ฆฌ๊ณ ๋๋ถ๋ถ์ ๋ด์ฉ๊ณผ ์ผ์นํ๋ ์์น ์ธ์(y_true, y_pred, ...)๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ๋ค๋ฅธ sklearn ๋ฌผ๊ฑด.
**kwargs ์์ ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ถ๊ฐํ๋ฉด ์ด์ ๋ฒ์ ๊ณผ์ ํธํ์ฑ์ ์ ์งํ ์ ์์ต๋๋ค. ๊ทธ๋ ์ฃ ?
์
ํจ์ฌ ๋ ๊นจ๋ํ ์๋ฃจ์ ....
๋ถํํ๋ ๊ทธ๊ฒ์ ์ฌ์ฉ ์ค๋จ ์ฃผ๊ธฐ๊ฐ ํ์ํฉ๋๋ค(๋ฒ๊ทธ ์์ ๋ฆด๋ฆฌ์ค์์ ๋งค์ฐ ๋น ๋ฅด๊ฒ ๋ง๋ค์ง ์๋ ํ ํ์ง๋ง ์์ฌ์ค๋ฝ์ต๋๋ค...)
@thomasjpfan , ์์ธก ๋์ ์ ์ถ์ ๊ธฐ๋ฅผ ์ ๋ ฅ์ผ๋ก ์ ๋ฌํด์ผ ํ๋ ์ด์ ๊ฐ ์์ต๋๊น?
๊ฐ์ฌํฉ๋๋ค. ๋จผ์ y_pred๋ฅผ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค. **kwags๋ ๋ ๋ค๋ฅธ ๋ฌธ์ ์ ๋๋ค.
๋ถํํ๋ ๊ทธ๊ฒ์ ์ฌ์ฉ ์ค๋จ ์ฃผ๊ธฐ๊ฐ ํ์ํฉ๋๋ค(๋ฒ๊ทธ ์์ ๋ฆด๋ฆฌ์ค์์ ๋งค์ฐ ๋น ๋ฅด๊ฒ ๋ง๋ค์ง ์๋ ํ ํ์ง๋ง ์์ฌ์ค๋ฝ์ต๋๋ค...)
๋ถ๊ฐ๋ฅํ ๊ฒ ๊ฐ์ ํ์จ
@thomasjpfan , ์์ธก ๋์ ์ ์ถ์ ๊ธฐ๋ฅผ ์ ๋ ฅ์ผ๋ก ์ ๋ฌํด์ผ ํ๋ ์ด์ ๊ฐ ์์ต๋๊น?
API ์ค๊ณ๋ฅผ ์ฌ๊ณ ํด์ผ ํ๋ค๋ ๋ฐ ๋์ํฉ๋๋ค. @amueller ๋ ping์ ์๋
์ฌ์ฉ์๊ฐ ์์ ๋ง์ ํ๋กํ ๋ถ๋ถ์ ์ ๊ณตํ๊ณ ์์ ๋ง์ ํผ๋ ํ๋ ฌ์ ์ ๊ณตํ๋ ค๋ ๊ฒฝ์ฐ:
from sklearn.metrics import ConfusionMatrixDisplay
confusion_matrix = confusion_matrix(...)
display_labels = [...]
disp = ConfusionMatrixDisplay(confusion_matrix=confusion_matrix,
display_labels=display_labels)
disp.plot(...)
์ด๊ฒ์ ๋ค๋ฅธ ๋ฉํธ๋ฆญ ํ๋กํ ๊ธฐ๋ฅ์ ๋ํด์๋ ์ ์ฌํ๊ฒ ์ํํ ์ ์์ต๋๋ค.
plot_confusion_matrix
๋ ์ถ์ ๊ธฐ์ ์ถ๋ ฅ์ ํ๋ฅญํ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ ์ค์ฝ์ด๋ฌ์ฒ๋ผ ์ค๊ณ๋์์ต๋๋ค. ์ฆ, ConfusionMatrixDisplay
๋ฐ estimator์ ์ํธ์์ฉํ๊ธฐ ์ํ ํธ๋ฆฌํ wrapper์
๋๋ค.
์ถ์ ๊ธฐ๋ฅผ ๋จผ์ ์๋ฝํ๋ฉด ํ๋กํ
๊ธฐ๋ฅ์ ๋ํ ๊ท ์ผํ ์ธํฐํ์ด์ค๊ฐ ์๊น๋๋ค. ์๋ฅผ ๋ค์ด, plot_partial_dependence
๋ ๋ถ๋ถ ์ข
์ ํ๋กฏ์ ์์ฑํ๋ ๋ฐ ํ์ํ ๋ชจ๋ ๊ณ์ฐ์ ์ํํ๊ณ ์ด๋ฅผ PartialDependenceDisplay
ํฉ๋๋ค. ์ฌ์ฉ์๋ ์ฌ์ ํ PartialDependenceDisplay
์ง์ ์์ฑํ ์ ์์ง๋ง ์ด ๊ฒฝ์ฐ ๋ ๋ง์ด ๊ด์ฌํ๊ฒ ๋ฉ๋๋ค.
๋น๋ก y_pred
๊ฐ confusion_matrix
์ง์ ์ ๋ฌ๋๊ณ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ฒ๋ฆฌํ๋๋ก ํ๋ ํ๋กํ
๊ธฐ๋ฅ๊ณผ ๊ด๋ จ๋ ๋ฉํธ๋ฆญ์ผ๋ก ์ ๋ฌ๋ ์ ์๋๋ก "๋น ๋ฅธ ๊ฒฝ๋ก"๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค.
PDP๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ํ์ํ ์์ธก ๊ณ์ฐ์ ์๋นํ ๋ณต์กํฉ๋๋ค. ๋ํ ์ด๋ฌํ ์์ธก์ ์ผ๋ฐ์ ์ผ๋ก ์๋ฅผ ๋ค์ด ์ค์ฝ์ด๋ฌ ๋๋ ๋ฉํธ๋ฆญ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. PDP๋ฅผ ํ๋กํ ํ ๋๋ง ์ ์ฉํฉ๋๋ค. ๋ฐ๋ผ์ ์ด ๊ฒฝ์ฐ์๋ plot_partial_dependence์ ์ถ์ ๊ธฐ๋ง ํ์ฉํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ ๋๋ค.
ํผ๋ ํ๋ ฌ์ OTOH์์ ์์ธก์ ์ค์ ๋ก est.predict(X)
์
๋๋ค.
๋๋ ์ฐ๋ฆฌ๊ฐ ์ฌ๊ธฐ์์ ๊ท ์ผํ ์ธํฐํ์ด์ค๋ฅผ ์ํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด๊ฒ์ 2๊ฐ์ง ๋งค์ฐ ๋ค๋ฅธ ์ ๋ ฅ ์ฌ์ฉ ์ฌ๋ก์ ๋๋ค.
ํธ์ง: ๋ํ, ํธ๋ฆฌ ๊ธฐ๋ฐ PDP๋ ์์ธก์ด ์ ํ ํ์ํ์ง ์์ต๋๋ค.
์ถ์ ๊ธฐ ์์ด ๋ง์ฃผํ๊ฒ ๋ ๋ค๋ฅธ ๊ฒ๋ค์ด ์์ต๋๋ค. ์๋ฅผ ๋ค์ด plot_precision_recall_curve
๊ฐ y_pred
๋ฅผ ์๋ฝํ๋ ๊ฒฝ์ฐ ๋ ์ด์ ์ ์ถํ ์ ์๊ธฐ ๋๋ฌธ์ pos_label
๊ฐ ํ์ํฉ๋๋ค. ์ด ๊ฒฝ์ฐ PrecisionRecallDisplay
์ง์ ์ฌ์ฉํ๊ณ ์ฌ์ฉ์๊ฐ ํ๋กฏ์ ์ฌ๊ตฌ์ฑํ๋ ๋ฐ ํ์ํ ๋งค๊ฐ๋ณ์๋ฅผ ๊ณ์ฐํ๋๋ก ํ๊ณ ์ถ์ต๋๋ค.
์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ์ด API๋ก ์ด๋ค ์ข ๋ฅ์ ์ง๋ฌธ์ ๋๋ตํ๋์ง์ ๋ฌ๋ ค ์์ต๋๋ค. ํ์ฌ ์ธํฐํ์ด์ค๋ ์ถ์ ๊ธฐ๋ฅผ ํ๊ฐํ๋ ๊ฒ์ ์ค์ฌ์ผ๋ก ํ์ ํ๋ฏ๋ก ์ถ์ ๊ธฐ๋ฅผ ์ธ์๋ก ์ฌ์ฉํฉ๋๋ค. "์ด ํ๋ จ๋ ๋ชจ๋ธ์ด ์ด ์ ๋ ฅ ๋ฐ์ดํฐ๋ก ์ด๋ป๊ฒ ์๋ํฉ๋๊น?"
y_pred, y_true
์๋ฝํ๋ฉด ์ด์ "์ด ๋ฉํธ๋ฆญ์ด ์ด ๋ฐ์ดํฐ๋ก ์ด๋ป๊ฒ ์๋ํฉ๋๊น?"๋ผ๋ ์ง๋ฌธ์ด ์๊น๋๋ค. ์ด ๋ฐ์ดํฐ๋ ๋ชจ๋ธ์ ์ํด ์์ฑ๋๊ฑฐ๋ ์์ฑ๋์ง ์์ ์ ์์ต๋๋ค.
์ด ํน์ ๊ฒฝ์ฐ @jhennrich ์์ ConfusionMatrixDisplay๋ฅผ ์ง์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ด ์ฌ์ค์ ๋๋ค.
ํ ๊ฐ์ง ๋จ์ ์ ๊ธฐ๋ณธ๊ฐ์ด ์๊ธฐ ๋๋ฌธ์ display_labels
๋ฅผ ์ง์ ํด์ผ ํ๋ค๋ ๊ฒ์
๋๋ค.
@thomasjpfan ์ผ๋ฐ์ ์ผ๋ก Display ๊ฐ์ฒด์ ํฉ๋ฆฌ์ ์ธ ๊ธฐ๋ณธ๊ฐ์ ์ ๊ณตํ์ฌ Display ๊ฐ์ฒด๋ฅผ ์ง์ ์ฌ์ฉํ ์ ์๋ค๊ณ ์๊ฐํ์ญ๋๊น?
display_labels
์ ๊ฐ์ ์ผ๋ถ ๋งค๊ฐ๋ณ์์ ๊ฒฝ์ฐ ํฉ๋ฆฌ์ ์ธ ๊ธฐ๋ณธ๊ฐ์ด ์์ต๋๋ค. ๋ค๋ฅธ Display
๊ฐ์ฒด ๋งค๊ฐ๋ณ์๋ ์ ์ ํ ๊ธฐ๋ณธ๊ฐ์ ๊ฐ์ง ์ ์์ต๋๋ค. ์ผ๋ถ ๋งค๊ฐ๋ณ์๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, confusion_matrix
์ ๊ณตํด์ผ ConfusionMatrixDisplay
๋๋ precision
๋ฐ recall
์ ๋ํด PrecisionRecallDisplay
.
์ด๋ฐ ์ข ๋ฅ์ ๊ณ ์ ์ ์ธ ํจํด ์ค ํ๋๋ ๋ค์์ ์ ์ํ๋ ๊ฒ์ ๋๋ค.
ConfusionMatrixDisplay.from_estimator(...)
ConfusionMatrixDisplay.from_predictions(...)
๊ทธ๋ฌ๋ ์ด๊ฒ์ scikit-learn์ ๋งค์ฐ ๊ด์ฉ์ ์ด์ง ์์ต๋๋ค.
ํท๊ฐ๋ฆฌ๊ธฐ ์์ํฉ๋๋ค. ํ์ฌ API์ ๋ชฉํ๋ ์ฌ์ฉ์๊ฐ ์ฌ๋ฌ ๋ฒ ํ๋กฏํ๋ ค๋ ๊ฒฝ์ฐ ์ฌ๋ฌ ๋ฒ ๊ณ์ฐํ๋ ๊ฒ์ ํผํ๋ ๊ฒ์ด์ง๋ง y_true ๋ฐ y_pred๋ฅผ ํ์ฉํ๋ฉด ์ฌ์ฉ์๊ฐ ์ฌ๋ฌ ๋ฒ ๊ณ์ฐํ ํ์๊ฐ ์์ต๋๊น? (PDP์์๋ ์ํฉ์ด ๋ค๋ฅด๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค)
@jnothman ๊ทธ API๋ ๊ฝค ๋ฉ์ ธ ๋ณด์ ๋๋ค!
@qinhanmin2014 estimator, X, y
๋๋ y_true, y_pred
ํ๋ฉด "์ฌ๋ฌ ๋ฒ ๊ณ์ฐํ์ง ์์" API๋ฅผ ์ถฉ์กฑํ๋ ๋ฐ ์๋ํฉ๋๋ค. ๋ ๊ฒฝ์ฐ ๋ชจ๋ ํผ๋ ํ๋ ฌ์ด ๊ณ์ฐ๋์ด Display
๊ฐ์ฒด์ ์ ์ฅ๋ฉ๋๋ค.
๊ทธ๋ค ์ฌ์ด์ ์ฐจ์ด์ ์ ํผ๋ ํ๋ ฌ์ ๊ณ์ฐ์ด ์์๋๋ ์์น์
๋๋ค. y_pred
์ ๋ฌ์ ์ถ์ ๊ธฐ์ "๋ฏธ๋ฆฌ ๊ณ์ฐ๋" ๊ฐ์ผ๋ก ์๊ฐํ ์ ์์ต๋๋ค.
๊ทธ๋์ y_true, y_pred
๊ฐ estimator, X, y
(๋ฌผ๋ก PDP๋ ์๋)๋ณด๋ค ๋ซ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์๋ํ๋ฉด ๋๋๋ก(์ข
์ข
?) ์ฌ์ฉ์๋ ์์ธก์ ํ๋กํ
ํ ๋ฟ๋ง ์๋๋ผ ์์ธก๋ ๋ถ์ํ๊ธฐ๋ฅผ ์ํ๊ธฐ ๋๋ฌธ์
๋๋ค. ํ์ฌ API๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ ๋ฒ ์์ธก์ ๊ณ์ฐํด์ผ ํฉ๋๋ค.
๋ฉํธ๋ฆญ์ ๊ฒฝ์ฐ y_true, y_pred
๋ณด๋ค estimator, X, y
y_true, y_pred
์ฌ์ฉ์ ๋ํ ์ ํธ๋๋ฅผ ํ์ธํ ์ ์์ต๋๋ค. ๋ฉํธ๋ฆญ์ ๋ํ ํ๋กํ
์ด y_true, y_pred
๋ง ์ง์ํ๋ค๊ณ ์์ํด ๋ณด์ธ์.
est = # fit estimator
plot_partial_dependence(est, X, ...)
# if plot_confusion_matrix accepts `y_true, y_pred`
y_pred = est.predict(X)
plot_confusion_matrix(y_true, y_pred, ...)
# if plot_roc_curve supports `y_true, y_score`
y_score = est.predict_proba(X)[: , 1]
plot_roc_curve(y_true, y_score, ...)
plot_precision_recall_curve(y_true, y_score, ...)
ํ์ฌ API๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
est = # fit estimator
plot_partial_dependence(est, X, ...)
plot_confusion_matrix(est, X, y, ...)
plot_roc_curve(est, X, y, ...)
# this will call `predict_proba` again
plot_precision_recall_curve(est, X, y, ...)
๋ ๊ฐ์ง ์ต์ ์ ๋ชจ๋ ์ง์ํ๋ API๋ฅผ ๊ฐ๊ณ ์ถ์ต๋๋ค(์ด์จ๋ ).
๋ฉํธ๋ฆญ์ ๊ฒฝ์ฐ estimator, X, y๋ณด๋ค y_true, y_pred ์ฌ์ฉ์ ๋ํ ์ ํธ๋๋ฅผ ๋ณผ ์ ์์ต๋๋ค. ๋ฉํธ๋ฆญ์ ๋ํ ํ๋กํ ์ด y_true, y_pred๋ง ์ง์ํ๋ค๊ณ ์์ํด ๋ณด์ธ์.
์, ์ด๊ฒ์ด ์ ๊ฐ ๋งํ๊ณ ์ ํ๋ ๋ฐ์ ๋๋ค.
๋ ๊ฐ์ง ์ต์ ์ ๋ชจ๋ ์ง์ํ๋ API๋ฅผ ๊ฐ๊ณ ์ถ์ต๋๋ค(์ด์จ๋ ).
์ด๊ฒ์ด ์ค์ฉ์ ์ธ ํด๊ฒฐ์ฑ ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ฑ๊ฐ์ ์ผ์ ๋์ y_pred๋ง ์ถ๊ฐํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค(์ฆ, plot_confusion_matrix(estimator, X, y_true, ..., y_pred)).
๋ค, ๋ง์ง๋ง์ ์์ ๊ฒ์ด๊ณ API๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ ๋๋ค:
plot_confusion_matrix(y_true=y_true, y_pred=y_pred, ...)
๋ด๊ฐ ๊ด์ฐฎ๋ค๊ณ ์๊ฐํ๋ ๊ฒ. ์ด๊ฒ์ ๋ณธ์ง์ ์ผ๋ก PR์ ๋๋ค. https://github.com/scikit-learn/scikit-learn/pull/15883
๋ค, ๋์ ์์ ๊ฒ์ด๊ณ API๋ ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ผ ๊ฒ์ ๋๋ค. plot_confusion_matrix(y_true=y_true, y_pred=y_pred, ...)
y_true๋ฅผ ์ถ๊ฐํ๊ณ est & X๋ฅผ ์ ๊ฑฐํด์ผ ํ๋ค๋ ๋ง์์ด์ ๊ฐ์? ๋ถ๊ฐ๋ฅํ ๊ฒ ๊ฐ์๋ฐ์? (๋ง์ง๋ง์ y_pred๋ง ์ถ๊ฐํ ์ ์๊ธฐ ๋๋ฌธ์)
0.22.1์์ ์ด๊ฒ์ ํด๊ฒฐํ๊ณ ์ถ์ต๋๊น? @NicolasHug @thomasjfox ์ด๊ฒ์ 0.22.1์ ๋ฃ๋ ๊ฒ์ด ์ข๋ค๊ณ ์๊ฐํ์ง๋ง ๋์์ ์ด๊ฒ์ด ์๋ก์ด ๊ธฐ๋ฅ์ธ ๊ฒ ๊ฐ์ต๋๋ค.
์๋์, 0.22.1์ ๋ฃ์ง ๋ง์ญ์์ค. ๋ช ๋ฐฑํ semver ์๋ฐ์ ๋๋ค.
@qinhanmin2014 ๋ง์ง๋ง์ y_pred
๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ est, X
์ ๊ฑฐํ๋ ๊ฒ์ ๋ค์ ๋ฆด๋ฆฌ์ค์ ์ํ๋ ์๋ก์ด ๊ธฐ๋ฅ์ฒ๋ผ ๋ณด์
๋๋ค.
y_true๋ฅผ ์ถ๊ฐํ๊ณ est & X๋ฅผ ์ ๊ฑฐํด์ผ ํ๋ค๋ ๋ง์์ด์ ๊ฐ์? ๋ถ๊ฐ๋ฅํ ๊ฒ ๊ฐ์๋ฐ์?
๊ฒฐ๊ตญ ๋๋ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์ฝ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ ์ธํฐํ์ด์ค๋ฅผ ๋ชจ๋ ์ง์ํ๋ ๊ฒ์ ์ ํธํฉ๋๋ค.
est, X
๋ ์๋ต ํจ์ ์ ํ, ๊ฒฐ๊ณผ ๋ถํ ๋ฐ ๋ฉํธ๋ฆญ์ ์ ๋ฌ์ ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋น ๋ฅธ ๋ถ์์ ์ํํ๋ ๊ฒ์ด ๋ ์ฝ์ต๋๋ค.y_true, y_pred
๋ ๊ธฐ๋ณธ ๋ฉํธ๋ฆญ์ผ๋ก ์์
ํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ๊ณ ์์ธก์ ์ด๋ฏธ ์ ์ฅํ ์ฌ์ฉ์๋ฅผ ์ํ ๊ฒ์
๋๋ค.https://github.com/scikit-learn/scikit-learn/issues/15880#issuecomment -565489619๋ฅผ ์ํํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์์ต๋๊น?
์ด ์ ์ฒด ์ค๋ ๋๋ฅผ ์ฝ์ง๋ ์์์ง๋ง ์ฌ๊ธฐ์์ ์ธํฐํ์ด์ค๋ฅผ ํ์ฉํ๋ฉด plot_roc_curve
๋ํด์๋ ์ํํด์ผ ํฉ๋๋ค. ์ฌ๊ธฐ์ ์ธํฐํ์ด์ค๋ ์์ธก์ ์ ๊ณตํ๋ ๊ฒ๊ณผ ์ถ์ ๊ธฐ๋ฅผ ์ ๊ณตํ๋ ๊ฒ ์ฌ์ด์์ ์๋นํ ๋ค๋ฆ
๋๋ค(ํ๋๋ pos_label์ด ํ์ํ๊ณ ๋ค๋ฅธ ํ๋๋ ๊ทธ๋ ์ง ์์ต๋๋ค) 'NS).
๋ฐ๋ผ์ ๋์ผํ ์ธํฐํ์ด์ค์์ ๋ ๋ค ํ์ฉํ๋ ๊ฒ์ ๋์ ์๊ฐ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค(๋๊ตฐ๊ฐ ์ถ์ ๊ธฐ๋ฅผ ์ ๋ฌํ ๋ pos_label์ ์ ๋ฌํ๊ณ ์์ํ์ง ๋ชปํ ๊ฒฐ๊ณผ๋ฅผ ์ป์).
ConfusionMatrixDisplay.from_estimator(...)
ConfusionMatrixDisplay.from_predictions(...)
์๋ํ ์ ์์ง๋ง ๊ธฐ๋ณธ์ ์ผ๋ก plot_confusion_matrix
์ค๋ณต๋๋ฏ๋ก ํจ์๋ฅผ ๋ค์ ์ ๊ฑฐํ๊ณ ํด๋์ค์ ํจ์ ๊ฐ์ ์ฑ
์์ ๋ณ๊ฒฝํฉ๋๋ค(ํด๋์ค๊ฐ ๊ณ์ฐ์ ์ํํ์ง ์๋๋ค๊ณ ๋งํ์ต๋๋ค).
from_predictions
๋ฅผ plot_roc_curve
ํ๋ ค๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก roc_curve
์ธํฐํ์ด์ค๋ฅผ ์๋ฒฝํ๊ฒ ๋ฏธ๋ฌ๋งํด์ผ ํฉ๋๋ค. ๋ฐ๋ผ์ ์ฌ์ฉ์๊ฐ roc_curve
ํจ์๋ฅผ ์ง์ ํธ์ถํ ๋ค์ ๊ฒฐ๊ณผ๋ฅผ Display ๊ฐ์ฒด์ ์ ๋ฌํ๋๋ก ํ๋ ๊ฒ๋ ๋์์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํ์ ๊ฐ์ฒด ๋์์ธ์ ์ ์ฒด ๋ชฉ์ ์ @jhennrich๊ฐ ์ธ๊ธํ ์ฌ์ฉ
@amueller ๊ธฐ์ ์ ์ผ๋ก ๋น์ ์ด ๋ง์ต๋๋ค. ๋ด ๋ฌธ์ ์ ๋ํ ํ์ฌ ์๋ฃจ์
์ ConfusionMatrixDisplay
์
๋๋ค. ๊ทธ๋ฌ๋ ๋ค์์ ์ฌ์ฉํ๋ ๊ฒ์ ์ ๋ง ์ํฌ๋ฆ
๋๋ค.
plot
๋ฉ์๋๋ฅผ ํธ์ถํด์ผ ํฉ๋๋ค.๋ด๊ฐ ์๊ฐํ ์์๋ ๋ชจ๋ ์์ฉ ํ๋ก๊ทธ๋จ์ ๊ฒฝ์ฐ plot_confusion_matrix
์ ์๋ช
(y_true, y_pred, ...)
์ฐ๋ฆฌ๊ฐ ํ์ฌ ๊ฐ์ง๊ณ ์๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ ํธ๋ฆฌ ํ ๊ฒ์
๋๋ค. ๋ด ์๊ฐ์๋ ์์ธก์ ๋ช
์์ ์ผ๋ก ๊ณ์ฐํ๋ ค๋ ํจ์ฌ ๋ ๋ง์ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์์ต๋๋ค(๋ด ๊ฒฌํด๊ฐ ํธํฅ๋์ด ์๋ค๊ณ ํ์ ํ์ง๋ง).
plot_confusion_matrix(y_true, y_pred)
์๋ช
์ด ์๊ณ ์ค์ ๋ก estimator
, x
, y
๋ฐ์ดํฐ์ ์ฌ์ฉํ๋ ค๋ ๊ฒฝ์ฐ ์์ฑํ ์ถ๊ฐ ์ฝ๋๊ฐ ๊ฑฐ์ ์์ต๋๋ค. : plot_confusion_matrix(y, estimator.predict(x))
.
์ด์ ๋นํด ํ์ฌ ์๋ช
์ด ์๊ณ y_true
๋ฐ y_pred
์์ ํ๋กฏํ๋ ค๋ฉด ๋ ๋ง์ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค.
์ ์๊ฐ์๋ plot_confusion_matrix(y_true, y_pred)
์๋ช
์ด ๊ธฐ๋ณธ๊ฐ์ด์ด์ผ ํ๊ณ estimator
, x
, y
ํ๋ ๋ค๋ฅธ ํจ์๊ฐ ๋งจ ์์ ๋น๋๋์ด์ผ ํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก ConfusionMatrixDisplay
ํด๋์ค์ ์ด๋ฉด์ ์๋ ์์ด๋์ด๋ฅผ ์์งํ ์ดํดํ์ง ๋ชปํฉ๋๋ค. ์ด ํจ์์๋ ๋จ์ผ ์์ฑ์์ ์ ํํ ํ๋์ ๋ฉ์๋๋ง ์์ผ๋ฏ๋ก ์ฌ์ฉํ ๋๋ง๋ค ๊ฒฐ๊ตญ ์ธ์คํด์ค๋ฅผ ๋ง๋ค๊ณ plot
ํจ์๋ฅผ ํธ์ถํ๊ฒ ๋ฉ๋๋ค. ์ ์ด๊ฒ์ด ๋จ์ง ํจ์๊ฐ ์๋๋ผ ํด๋์ค์ฌ์ผ ํ๋์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๋ํ ๋ค๋ฅธ *Display
ํด๋์ค(PrecisionRecall, ROC, ...)๊ฐ ์์ง๋ง ์์ฑ์์ plot()
์๋ช
์ด ์์ ํ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์ด์จ๋ ๊ต์ฒดํ ์ ์์ต๋๋ค.
์๋ง๋ ์ด๊ฒ์ ์ด ๋ฌธ์ ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ฉ๋๋ค.
@jhennrich
plot_confusion_matrix(y_true, y_pred) ์๋ช ์ด ์๊ณ ์ค์ ๋ก ์ด๋ฅผ ์ถ์ ๊ธฐ, x, y ๋ฐ์ดํฐ์ ์ฌ์ฉํ๋ ค๋ ๊ฒฝ์ฐ ์์ฑํด์ผ ํ ์ถ๊ฐ ์ฝ๋๋ ๊ฑฐ์ ์์ต๋๋ค: plot_confusion_matrix(y, estimator.predict(x)).
ํผ๋ ํ๋ ฌ์ ๊ฒฝ์ฐ y_true, y_pred
์ธํฐํ์ด์ค๊ฐ ์๋ ๊ฒฝ์ฐ estimator.predict
๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ ๊ฐ๋จํฉ๋๋ค. ๋ฐ๋ฉด์ plot_roc_auc
์ ๊ฒฝ์ฐ ์ฌ์ฉ์๋ ์ฌ๋ผ์ด์ฑ์ ์ํํด์ผ ํฉ๋๋ค.
y_pred = est.predict_proba(X)
plot_roc_curve(y_true, y_pred[:, 1])
# or
y_pred = est.decision_function(X)
plot_roc_curve(y_true, y_pred[:, 1])
๋ง์ง๋ง์ผ๋ก ConfusionMatrixDisplay ํด๋์ค์ ์ด๋ฉด์ ์๋ ์์ด๋์ด๋ฅผ ์์งํ ์ดํดํ์ง ๋ชปํฉ๋๋ค. ํจ์์๋ ๋จ์ผ ์์ฑ์์ ์ ํํ ํ๋์ ๋ฉ์๋๋ง ์์ผ๋ฏ๋ก ์ฌ์ฉํ ๋๋ง๋ค ๊ฒฐ๊ตญ ์ธ์คํด์ค๋ฅผ ๋ง๋ค๊ณ ํ๋กฏ ํจ์๋ฅผ ํธ์ถํ๊ฒ ๋ฉ๋๋ค. ์ ์ด๊ฒ์ด ๋จ์ง ํจ์๊ฐ ์๋๋ผ ํด๋์ค์ฌ์ผ ํ๋์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
Display
๊ฐ์ฒด์ ๋ชฉ์ ์ ์ฌ์ฉ์๊ฐ ๋ค์ ๊ณ์ฐํ์ง ์๊ณ plot
์ฌ๋ฌ ๋ฒ ํธ์ถํ ์ ์๋๋ก ๊ณ์ฐ๋ ๊ฐ์ ์ ์ฅํ๋ ๊ฒ์
๋๋ค. ์ด๊ฒ์ plot_partial_dependence
๋ฅผ ์ฌ์ฉํ์ฌ ๋ณผ ์ ์์ต๋๋ค.
# Does expensive computation
disp = plot_partial_dependence(est, ...)
# change line color without needing to recompute partial dependence
disp.plot(line_kw={"c": "red"})
์์งํ, ๋๋ ์ด ๋ฌธ์ ์ ๋ํด ๊ฒฝ๊ณํ๊ณ ์๋ค. est, X, y
์ธํฐํ์ด์ค๋ฅผ ํ๋กํ
ํ๊ณ ์ ๊ฑฐํ๊ธฐ ์ํด ๋ฉํธ๋ฆญ ์ธํฐํ์ด์ค๋ฅผ ๋ณต์ฌํ๋ ๋ฐฉํฅ์ผ๋ก ์ด๋ํ๋ ๋ฐ +0.1์
๋๋ค. :/
ํผ๋ ํ๋ ฌ์ ๊ฒฝ์ฐ y_true, y_pred ์ธํฐํ์ด์ค๊ฐ ์๋ ๊ฒฝ์ฐ estimator.predict๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ด ๊ฐ๋จํฉ๋๋ค. ๋ฐ๋ฉด์ plot_roc_auc์ ๊ฒฝ์ฐ ์ฌ์ฉ์๋ ์ฌ๋ผ์ด์ฑ์ ์ํํด์ผ ํฉ๋๋ค.
์, ํ์ง๋ง ๊ทธ๋ ๊ฒ ํจ์ผ๋ก์จ ์์ธก์ ์ฌ๋ฌ ๋ฒ ๊ณ์ฐํ๋ ๊ฒ์ ํผํ ์ ์์ต๋๋ค(์์ธก์ ์ข ์ข ๊ทธ๋ ๊ฒ ๋น์ธ์ง ์์ง๋ง)
์๋ง๋ 0.23์ plot_XXX(ํด๋น๋๋ ๊ฒฝ์ฐ)์์ y_true, y_pred
๋ฅผ ์ง์ํ๋ ์ค์ฉ์ ์ธ ์๋ฃจ์
์ผ ๊ฒ์
๋๋ค.
@jhennrich ๋ ์ด๋ธ์ ๋ช
์์ ์ผ๋ก ์ ๋ฌํ์ง ์๊ณ ์ด๋ป๊ฒ ํ์๊ฒ ์ต๋๊น? ์ฃผ์ด์ง confusion_matrix
์์ ๋ ์ด๋ธ์ ์ ์ถํ ์ ์๋ค๋ฉด ๊ทธ๋ ๊ฒ ํ ๊ฒ์
๋๋ค.
๊ทธ๋ฌ๋ ์ค์ ๋ก ๋น์ ์ด ์ณ์ต๋๋ค. ํ ์ค์ด ์๋๋ผ ์ธ ์ค์ ๋๋ค.
Confusion_matrix ์ ๊ฒฝ์ฐ ๋ ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ๊ฐ y_true
๋ฐ y_pred
์ ๋ฌํ ์ ์๋ค๋ ๋ฐ ๋์ํ๋ ๊ฒฝํฅ์ด ์์ต๋๋ค.
์ธํฐํ์ด์ค๊ฐ ํ์ฌ ๊ทธ๋๋ก์ธ ์ด์ ๋ ๋ค๋ฅธ ๋ฉํธ๋ฆญ ํ๋กํ
๊ธฐ๋ฅ๊ณผ ์ผ๊ด์ฑ์ ์ ์งํ๊ธฐ ์ํจ์
๋๋ค. @thomasjpfan์ด ๋งํ๋ฏ์ด roc ๊ณก์ ์ ํ๋กฏํ๊ธฐ์ ๋ ๋ช
ํํฉ๋๋ค.
ํ์ฌ ํผ๋ ํ๋ ฌ์ ๊ทธ๋ฆฌ๋ ์ฝ๋์ roc ๊ณก์ ์ ๊ทธ๋ฆฌ๋ ์ฝ๋๋ ๋์ผํฉ๋๋ค. ์ ์ํ ๋ณ๊ฒฝ ์ฌํญ์ผ๋ก ์ธํด ๋ ์ด์ ๋์ผํ์ง ์์ผ๋ฉฐ ๋์ผํ๊ฒ ๋ง๋๋ ์ฌ์ด ๋ฐฉ๋ฒ๋ ์์ ๊ฒ์ ๋๋ค.
๋ฌธ์ ๋ ์ด ๊ฒฝ์ฐ ์ผ๊ด๋ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ๋ ๊ฒ์ด ๋ ๋์์ง ์๋๋ฉด ๋จ์ํ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ๋ ๊ฒ์ด ๋ ๋์๊ฐ์
๋๋ค.
@jhennrich ๋์๊ฒ ์ง์ง ์ง๋ฌธ์ plot_roc_curve
๋ํ ์ฌ๋ฐ๋ฅธ ์ธํฐํ์ด์ค๊ฐ ๋ฌด์์ธ์ง์
๋๋ค. ๊ทธ๊ฒ์ ๋ํ ์๊ฐ์ด ์์ต๋๊น?
@thomasjpfan roc auc๋ ํ๋กํ
ํ๋ ๋ฐ y_store
๋ฅผ ์ฌ์ฉํ๋ ์ชฝ์ผ๋ก ๊ธฐ์ธ๊ณ ์์ต๋๊น?
๋ฉํธ๋ฆญ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ ๋์ ์ค์ฝ์ด๋ฌ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ ๋ฐ์๋ ํ์คํ ์ฅ๋จ์ ์ด ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ ๋ณต์กํ ๊ฒฝ์ฐ์๋ ์ค์ฝ์ด๋ฌ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ํจ์ฌ ์์ ํฉ๋๋ค.
@qinhanmin2014
y_pred
๋ฅผ plot_confusion_matrix
์ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค. ๋ฌธ์ ๋ y_score
๋ฅผ plot_roc_curve
๋ฐ plot_precision_recall_curve
์ ์ถ๊ฐํ ์ง ์ฌ๋ถ์
๋๋ค. ๊ทธ๋ ๊ฒ ํ๋ฉด ์์์ ๋งํ๋ฏ์ด pos_label
๋ ์ถ๊ฐํด์ผ ํ๋ฉฐ ์ํฉ์ด ๋ ๋ณต์กํด์ง๋๋ค.
๋๋ ์ด๊ฒ์์ ์ธ ๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ด
๋๋ค.
a) y_pred
plot_confusion_matrix
์ ์ถ๊ฐํ๊ณ y_score
๋ฅผ plot_roc_curve
๋ฑ์ ์ถ๊ฐํ์ง ๋ง์ญ์์ค. ๋จ์ : predict_proba
ํธ์ถ ๋ฌธ์ ์ฌ๋ฌ ๋ฒ ์ด๋ฌํ ์ธก์ ํญ๋ชฉ์ ๋ํด ๊ธฐ์กด ์ํ๋ฅผ ์ ์งํฉ๋๋ค.
b) Display
๊ฐ์ฒด๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๊ฒ์ ๋ ์ฝ๊ฒ ๋ง๋์ญ์์ค(์ฌ์ค ๋ฐฉ๋ฒ์ ๋ชจ๋ฅด์ง๋ง).
c) ๋ฉํธ๋ฆญ ์ธํฐํ์ด์ค๋ฅผ ๋ฏธ๋ฌ๋งํ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด๋ ๊ธฐ๋ฅ์ ์ถ๊ฐํฉ๋๋ค. ๋จ์ : ๋ ํฐ API ํ๋ฉด.
plot_X
๊ธฐ๋ฅ์ด ์ค์ฝ์ด๋ฌ์ ๋ฉํธ๋ฆญ ์ธํฐํ์ด์ค๋ฅผ ๋์์ ๋ฏธ๋ฌ๋งํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ์ข์ ์๊ฐ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
@adrinjalali ์ด๋ค ์์ผ๋ก๋ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฒ์ด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค. ๋ค์ ํ์์์ ๋ ผ์ํ์๊ฒ ์ต๋๊น?
๋๋ ๋๋๋ก ์ด ๋ฌธ์ ์ ๋ํด ์ ๋ชฝ์ ๊พผ๋ค. ๋ฉํธ๋ฆญ์ ์ถ๋ ฅ์ ์ง์ ๊ฐ์ ธ์ค๋ ์ ์ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
result = confusion_matrix(...)
ConfusionMatrixDisplay.from_metric(result).plot()
roc ๊ณก์ ์ ๊ฒฝ์ฐ:
result = roc_curve(...)
RocCurveDisplay.from_metric(*result).plot()
์ฐธ๊ณ ๋ก, ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๋ณด๋ฉด ์ ์ ์ธํฐํ์ด์ค๋ณด๋ค ๋ฉํธ๋ฆญ ์ธํฐํ์ด์ค์ ์ต์ํ ์ฌ์ฉ์๊ฐ ๋ ๋ง๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋๋ ๋๋๋ก ์ด ๋ฌธ์ ์ ๋ํด ์ ๋ชฝ์ ๊พผ๋ค.
์ ๋ผ :(
์ฐธ๊ณ ๋ก, ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๋ณด๋ฉด ์ ์ ์ธํฐํ์ด์ค๋ณด๋ค ๋ฉํธ๋ฆญ ์ธํฐํ์ด์ค์ ์ต์ํ ์ฌ์ฉ์๊ฐ ๋ ๋ง๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋๋ ์ด๊ฒ์ด ํ์คํ ์ฌ์ค์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ๋ํ ์ฌ๋๋ค์ด ์ฌ์ฉํ๋ ๊ฒ์ด ๋งค์ฐ ํ์ y_pred
๊ฐ ์ฌ์ฉ๋์ด์ผ ํ ๋ y_score
ํ๊ณ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ฉด ๋ญ๊ฐ ๋ค๋ฅด๊ณ ์๋ -์ ํ ํ์๊ฐ ์์์ ๋งํด์ฃผ์ง ์๊ธฐ ๋๋ฌธ์ ์๋ชป๋ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ณ ์๋ค ํ ๋ฒ์ ๋ฌธ์๋ฅผ ์ฝ์ต๋๋ค.
๋น์ ์ด ์ ์ํ ์ ์ ๋ฐฉ๋ฒ์ด ์์ฑ์์ ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ง๋ง ๋ญ๊ฐ ๊ฐ๊ณผํ๊ณ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์๋
ํ์ธ์, ๋ฐฉ๊ธ ๋ฌธ์ ์ ์ฐฌ์ฑํ๋ฅผ ๋์ก์ต๋๋ค. ์ค๋ sklearn ์ฌ์ฉ์๋ก์ plot_confusion_matrix
๋ํ ํ์ฌ API๊ฐ ๋งค์ฐ... ํผ๋์ค๋ฝ์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ ์ถ๊ฐ(๋ณต์ฌ-๋ถ์ฌ๋ฃ๊ธฐ๊ฐ ์ ์)๋ฅผ ์ ๋ง ์ข์ํ์ง๋ง, ๋ฉํธ๋ฆญ ํจ์๋ ํญ์ (y_true, y_pred) ์ฒด๊ณ๋ฅผ ์ฌ์ฉํ๋๋ฐ, ์ด๋ ๋ ์ ์ฐํ๊ณ ์ด๋ฏธ ์ต์ํด์ ธ ์์ต๋๋ค.
์ ๊ฒฝ์ฐ์๋ ๋ชจ๋ธ์ด ๋งค์ฐ ๋๋ฆฌ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ถ์ํ ๋๋ง๋ค ๋ค์ ์คํํ๋ ๊ฒ๋ณด๋ค ํ์ผ์์ ์์ธก์ ๋ก๋ํ๋ ๊ฒ์ด ์ข๊ธฐ ๋๋ฌธ์ ์ถ์ ๊ธฐ๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ ์๋ฏธ๊ฐ ์์ต๋๋ค. ์ด ์ค๋ ๋์์ *Display ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์๋ค๋ ๊ฒ์ ์๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ฒ์ ๊ฐ๋ฅ์ฑ์ ๊ทธ๋ฆฌ ์ข์ง ์์ต๋๋ค. ์ต์ํ plot_confusion_matrix
๋ฌธ์๋ ํผ๋ ํ๋ ฌ ์ฌ์ฉ์ ๊ฐ์ด๋์ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ?
์ ๊ฒฝ์ฐ์๋ ๋ชจ๋ธ์ด ๋งค์ฐ ๋๋ฆฌ๊ณ ์์ธก์ ๋ก๋ํ๋ ๊ฒ์ด ์ข๊ธฐ ๋๋ฌธ์ ์ถ์ ๊ธฐ๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ ์๋ฏธ๊ฐ ์์ต๋๋ค.
์ ๋ ฅํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ํ์ฌ API๊ฐ ํผ๋์ค๋ฝ๋ค๋ฉด ์ธํฐํ์ด์ค์ ๊ฐ์ ๋ ๋ฉํธ๋ฆญ API๋ก ์ด๋ํ๊ณ ๊ณ ํต์ค๋ฌ์ด ์ฌ์ฉ ์ค๋จ ์ฃผ๊ธฐ๋ฅผ ๊ฑฐ์น๋ ๊ฒ์ด ๋ ํฉ๋ฆฌ์ ์ผ ๊ฒ์ ๋๋ค.
๋ฉํธ๋ฆญ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ ๋ ๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๊ทธ๋ฌ๋ ๋๋ ๋ํ ์ฌ๋๋ค์ด y_score๋ฅผ ์ฌ์ฉํด์ผ ํ ๋ y_pred๋ฅผ ์ฌ์ฉํ๊ณ ์๋ชป๋ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ณ ์๋ค๊ณ ํ์ ํฉ๋๋ค. ์ธํฐํ์ด์ค๊ฐ ๋ค๋ฅธ ๊ฒ์ ํด์ผ ํ๋ค๊ณ ๋งํ์ง ์๊ณ ์๋ฌด๋ ๋ฌธ์๋ฅผ ์ฝ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
@pzelasko ์ด ๋ฌธ์ ์ ๋ํด ์ด๋ป๊ฒ ์๊ฐํ์ญ๋๊น?
@thomasjpfan ๋ฌธ์ ๋ฅผ ์ดํดํฉ๋๋ค. ์ด๋ ค์ด ๋ฌธ์ ์
๋๋ค. ์๋ง๋ ํฉ๋ฆฌ์ ์ธ ํํ์ ์ด ํจ์์ ๋ํด ํค์๋ ์ธ์๋ง ํ์ฉํ๋ ๊ฒ์
๋๋ค(์ด์ Python 2๋ฅผ ๋ ์ด์ ์ง์ํ ํ์๊ฐ ์์ต๋๋ค)? ์ข์์: def plot_confusion_matrix(*, y_true, y_pred, ...)
. ์ฌ์ ํ ๋๋จธ์ง ๋ฉํธ๋ฆญ๊ณผ ๋ค๋ฅด์ง๋ง 1) ๊ทธ๋ด๋งํ ์ด์ ๊ฐ ์์ต๋๋ค. 2) ์ต์ํ ๋ค๋ฅธ ๊ธฐ๋ฅ๊ณผ ๋์ผํ ์ ํ์ ์
๋ ฅ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
์ด์จ๋ , ๋๋ ๋น์ ์ด API ๋ณ๊ฒฝ์ ์ฃผ์ ํ๋ ์ด์ ๋ฅผ ์๊ณ ์์ต๋๋ค. ๊ทธ๋์ ์ต์ํ ๋ฌธ์์์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ธ๊ธํ ๊ฒ์ ์ ์ํ์ต๋๋ค. (์ค์ ๋ก ์ฌ๋ฌ ๋ฒ ์ฝ์๊ณ ์ ๋ง ๊ฐ์ฌํฉ๋๋ค!)
y_true
๋ฐ y_pred
๋ฅผ ์ฌ์ฉํ๋ ํ์ฌ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. https://scikit-learn.org/stable/auto_examples/miscellaneous/plot_display_object_visualization.html#create -confusionmatrixdisplay
์ฌ๊ธฐ์์ ์คํธ๋ ์นญ์ ํ๊ณ ์๋ค๋ ๊ฒ์ ์๊ณ ์์ง๋ง ์ด๊ฒ์ ์ด๋ป์ต๋๊น?
plot_confusion_matrix(estimator='precomputed', y_true, y_pred, ...)
์ฌ๊ธฐ์ ๋ ๋ฒ์งธ ์์น๋ y_true
๊ฒฝ์ฐ ์์ธก์ผ๋ก estimator='precomputed
ํฉ๋๋ค.
๋ ๋๋ฆฌ๊ณ ์ถ๋ค๋ฉด plot_confusion_matrix((estimator, X, y), ...)
๋๋ plot_confusion_matrix((y_true, y_pred), ...)
์ ํธํ์ง๋ง ๋ฉํธ๋ฆญ๊ณผ ๊ฐ์ API์ ๊ด๋ จํ์ฌ @amueller๊ฐ ์ ๊ธฐํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋์ง ํ์ ํ ์ ์์ต๋๋ค.
metric
API๋ฅผ ํ์ฉํ๋ ๊ฒ์ด ์ค์ ๋ก ์๋ฏธ๊ฐ ์๋ ๋ช ๊ฐ์ง ์๋ก์ด ํ๋กํ
์ ํธ๋ฆฌํฐ๊ฐ ์์ต๋๋ค.
plot_prediction_error
plot_calibration_curve
(CC @lucyleeow )@amueller ๊ฐ pos_label
๋ฑ์ ์ ๋ฌํด์ผ ํ๋ค๊ณ ์ธ๊ธํ ๋ฌธ์ ๋ฅผ ์ดํดํ์ง๋ง ์์ ์ธ๊ธํ ๊ธฐ๋ฅ์๋ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค.
์ด ๋ ๊ฐ์ง์ ๋ํด ์ค์ฝ์ด๋ฌ์ ๋ฉํธ๋ฆญ API๋ฅผ ๋ชจ๋ ์ง์ํด๋ ๋ฉ๋๊น? ์ฐ๋ฆฌ๋ ๊ฑฐ๊ธฐ์์ ์ด์ ๋ฒ์ ๊ณผ์ ํธํ์ฑ์ ๋ํด ๊ฑฑ์ ํ ํ์๊ฐ ์์ต๋๋ค.
๋๋ ์ฌ์ ํ ์ฐ๋ฆฌ๊ฐ ์ถ์ ๊ธฐ์์ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ precomputed
์ฌ์ฉ์ ๋ํ ์ ์ ์์ ์ง์งํฉ๋๋ค. ์ด ๊ฒฝ์ฐ ์๋ช
์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
plot_confusion_matrix(estimator='precomputed', y_true, y_pred, ..., metric_kwargs=None)
๋๋ ์ด๊ฒ์ด ์ด๋ป๊ฒ ์๊ฒผ๋์ง ๋ณด๊ธฐ ์ํด PR์ ํ ๊ฒ์ด๋ค.
์์ง API์ ๋ํด ์ค์ ๋ก ๋ ผ์ํ๋ ๊ฒ์ด ์๋๋ผ ์ PR์ ๋ํด ๋ ๊ฐ์ง ์ต์ ์ ๋ชจ๋ ์ง์ํด๋ ๋๋์ง ๋ฌป๋ ๊ฒ๋ฟ์ ๋๋ค.
(ํ์ง๋ง API์ ๊ดํด์๋ '๋ฏธ๋ฆฌ ๊ณ์ฐ๋'์ด ๋ณ๋ก ๋์์ด ๋์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. X
๋ฌด์์ ํฉ๋๊น? ์ ์ ํ ์ค๋ฅ๋ฅผ ํตํด (y_pred)์ (estimator, X)๋ฅผ ์ํธ ๋ฐฐํ์ ์ผ๋ก ์ ์งํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ํ estimator๊ฐ ๋ฏธ๋ฆฌ ๊ณ์ฐ๋๋ค๋ ๊ฒ์ ๋ฌด์์ ์๋ฏธํฉ๋๊น?)
๋๋ estimator='none'
, estimator='predictions'
, estimator='precomputed_predictions'
, X
๋ y_pred
๋๋ y_score
๋ฉ๋๋ค. ์ถ์ ๊ธฐ์์ X
๋ก ๋ฏธ๋ฆฌ ๊ณ์ฐ๋ ๊ฑฐ๋ฆฌ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ๊ณผ ๊ฑฐ์ ๊ฐ์ต๋๋ค.
์ด ๋ ๊ฐ์ง์ ๋ํด ์ค์ฝ์ด๋ฌ์ ๋ฉํธ๋ฆญ API๋ฅผ ๋ชจ๋ ์ง์ํด๋ ๋ฉ๋๊น?
๋ ๊ฐ์ง ์ต์ ์ ๋ชจ๋ ์ง์ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํฉ๋๊น? ๋ ๊ฐ์ง ๊ธฐ๋ฅ์ผ๋ก?
๋๋ ๋ํ ์ข์ํ์ ๊ฒ์ ๋๋ค :
CalibrationDisplay.from_estimator(...)
CalibrationDisplay.from_predictions(...)
๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ๋ ๊ฒ์ ๋๋ค.
ํํ https://github.com/scikit-learn/scikit-learn/issues/15880#issuecomment -670590882 ์ฌ์ฉ์ ๋ํ Guillaume์ ์ ์์ ํ๋์ ์ต์ ์ ๋๋ค. ์ฒ์๋ถํฐ ๊ฑฐ๊ธฐ์๋ถํฐ ์์ํ๋ค๋ฉด ์ต๊ณ ์ ์ ํ์ด ๋์์ ๊ฑฐ๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ํํ์ ์ฌ์ฉํ๋ฉด ๊ธฐ์กด ์ ํธ๋ฆฌํฐ์์ ์ผ๊ด์ฑ์ด ๊นจ์ง๊น ๊ฑฑ์ ๋ฉ๋๋ค.
์ํธ ๋ฐฐ์ ๋ฅผ ํฌํจํ๋ plot_XYZ(estimator=None, X=None, y=None, y_pred=None)
๋ ๋ ๋ค๋ฅธ ์ต์
์ด๋ฉฐ ํ์ฌ๋ก์๋ ์ด๊ฒ์ด ์ ๊ฐ ์นํธํ๋ ์ต์
์
๋๋ค.
๋๋ CalibrationDisplay.from_estimator(...)
๋ฅผ ์ข์ํ์ง๋ง Andy๊ฐ ์ธ๊ธํ๋ฏ์ด plot_XYZ
ํจ์๋ฅผ ์ ๊ฑฐํด์ผ ํฉ๋๋ค. ๊ณ ๋ คํด ๋ณผ ๊ฐ์น๊ฐ ์์ต๋๋ค.
๋๋ ์ฐ๋ฆฌ๊ฐ ํํ๋ก ์ด๋ํ๊ณ ํ์ฌ ๋์์ ๋ ์ด์ ์ฌ์ฉํ์ง ์์ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. (ํํ ์ฌ์ฉ์ ๋์ํ๋ ํ)
์ด๊ฒ์ ๋ค์์คํ์ด์ค๋ฅผ ๋
ผ์ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์
๋๋ค. ๋ง์ต๋๊น?
ํ๋์ ํจ์์ ํ๋์ ์์ฑ์๊ฐ ์๋ , ๋ ๊ฐ์ ํด๋์ค ๋ฉ์๋๊ฐ ์๋ , ๋ ๊ฐ์ ํจ์๊ฐ ์๋ ๊ทธ๊ฒ์ ์ ํํ ๋์ผํ ๊ธฐ๋ฅ๊ณผ ๊ธฐ๋ณธ์ ์ผ๋ก ๋์ผํ ์ฝ๋์
๋๋ค.
@pzelasko @jhennrich ๋ ๊ฐ์ ํด๋์ค ๋ฉ์๋ ๋๋ ๋ ๊ฐ์ ๊ธฐ๋ฅ์ ๊ฐ๋ ๊ฒ์ ๋ํด ์ด๋ป๊ฒ ์๊ฐํ์ญ๋๊น? ์๋๋ฉด ํ์ด์ฌ์์ ์ฝ๊ฐ ์ง์ ๋ถํ ๋จ์ผ ํจ์๋ฅผ ์ ํธํ์๊ฒ ์ต๋๊น?
๊ทธ๋ฆฌ๊ณ ๋ ๊ฐ์ ํจ์ ๋๋ ๋ ๊ฐ์ ํด๋์ค ๋ฉ์๋๋ฅผ ์ ํธํ๋ค๋ฉด ๊ฒ์ ๊ฐ๋ฅ์ฑ์๋ ๋ถ๊ตฌํ๊ณ ์ด๋ค ์ด์ ์ด ์์ต๋๊น? ๋ฐ๊ฒฌ ๊ฐ๋ฅ์ฑ์ classmethods๋ฅผ ์ํํ๋ ์ถฉ๋ถํ ์ด์ ๊ฐ ๋ ์ ์์ง๋ง ๋ ๊ฐ์ง ๊ธฐ๋ฅ์ ๊ฐ๋ ๊ฒ์ ๋ํ ๊ฐ๋ ฅํ ์ฃผ์ฅ์ ๋ณด์ด์ง ์์ต๋๋ค.
์ฌ๊ธฐ์ ์ฐจ๋จ ๋ผ๋ฒจ์ ์ถ๊ฐํ ์ ์์ต๋๊น? #18020, #17443 (cc @cmarmo) ์งํ์ ๋ง๊ณ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ฐจ๋จ์ ๋ผ๋ฒจ์ PR ์ฐจ๋จ์ ๊ฐ ์๋ ๋ฆด๋ฆฌ์ค ์ฐจ๋จ์ (์ถ์ ์ ์ ๋ฐ๋์ ๊ณ ์ณ์ผ ํ ์ฌํญ)๋ฅผ ์ํ ๊ฒ์ ๋๋ค.
์์ ๋คํ์ด๋ค.
@pzelasko @jhennrich ๋ ๊ฐ์ ํด๋์ค ๋ฉ์๋ ๋๋ ๋ ๊ฐ์ ๊ธฐ๋ฅ์ ๊ฐ๋ ๊ฒ์ ๋ํด ์ด๋ป๊ฒ ์๊ฐํ์ญ๋๊น? ์๋๋ฉด ํ์ด์ฌ์์ ์ฝ๊ฐ ์ง์ ๋ถํ ๋จ์ผ ํจ์๋ฅผ ์ ํธํ์๊ฒ ์ต๋๊น?
๊ทธ๋ฆฌ๊ณ ๋ ๊ฐ์ ํจ์ ๋๋ ๋ ๊ฐ์ ํด๋์ค ๋ฉ์๋๋ฅผ ์ ํธํ๋ค๋ฉด ๊ฒ์ ๊ฐ๋ฅ์ฑ์๋ ๋ถ๊ตฌํ๊ณ ์ด๋ค ์ด์ ์ด ์์ต๋๊น? ๋ฐ๊ฒฌ ๊ฐ๋ฅ์ฑ์ classmethods๋ฅผ ์ํํ๋ ์ถฉ๋ถํ ์ด์ ๊ฐ ๋ ์ ์์ง๋ง ๋ ๊ฐ์ง ๊ธฐ๋ฅ์ ๊ฐ๋ ๊ฒ์ ๋ํ ๊ฐ๋ ฅํ ์ฃผ์ฅ์ ๋ณด์ด์ง ์์ต๋๋ค.
๋๋ two-classmethods ์ ๊ทผ ๋ฐฉ์์ ๊ฐ์ฅ ์ข์ํฉ๋๋ค. ํนํ from_xxx
ํจํด - @thomasjpfan์ด ์ ์ํ ๊ฒ๊ณผ ๊ฐ์ sth:
CalibrationDisplay.from_estimator(...) CalibrationDisplay.from_predictions(...)
2๊ฐ์ ํด๋์ค ๋ฐฉ์์ ์ฌ์ฉํ๋ ๊ฒ์ ๋ํด ๊ฐํ ๋ฐ๋๊ฐ ์์ ๊ฒ ๊ฐ์ผ๋ ๊ทธ๋ ๊ฒ ํด๋ณด์. ๋ค์์ ์ํํด์ผ ํฉ๋๋ค.
ํ์ฌ ์กด์ฌํ๋ ํ๋กฏ์ ๋ํ ํด๋์ค ๋ฉ์๋๋ฅผ ์๊ฐํฉ๋๋ค.
ConfusionMatrixDisplay
PrecisionRecallDisplay
RocCurveDisplay
DetCurveDisplay
PartialDependenceDisplay
. ์ด ๊ฒฝ์ฐ from_predictions
classmethod๋ฅผ ๋์
ํ๊ณ ์ถ์ง ์์ต๋๋ค. ์๋ฏธ๊ฐ ์๊ธฐ ๋๋ฌธ์ from_estimator
๋ง ์ํฉ๋๋ค.์์ ๋์ด๋ ๋ชจ๋ ๋์คํ๋ ์ด์ ๋ํด ํด๋น plot_...
๊ธฐ๋ฅ์ ๋ ์ด์ ์ฌ์ฉํ์ง ์์ต๋๋ค. plot_det_curve
๋ ์์ง ์ถ์๋์ง ์์๊ธฐ ๋๋ฌธ์ ๋ ์ด์ ์ฌ์ฉํ์ง ์์๋ ๋ฉ๋๋ค. ์ ๊ฑฐํ๋ฉด ๋ฉ๋๋ค.
#17443 ๋ฐ #18020๊ณผ ๊ฐ์ ์๋ก์ด PR์ ๊ฒฝ์ฐ plot
ํจ์๋ฅผ ๋์
ํ๋ ๋์ ํด๋์ค ๋ฉ์๋๋ฅผ ์ฆ์ ๊ตฌํํ ์ ์์ต๋๋ค.
์ด๊ฒ์ ์ฝ๊ฐ์ ์์ ์ด์ง๋ง #17443 ๋ฐ #18020์ด ์ด๋ฏธ ์์ผ๋ก ๋์๊ฐ ์ ์๋๋ก 0.24 ์ด์ ์ ์๋ฃํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
@thomasjpfan @jnothman @amueller @glemaitre์ ์ด์๊ฐ ์์ต๋๊น?
@jhennrich @pzelasko , Display ๊ฐ์ฒด ์ค ํ๋์ ํด๋์ค ๋ฉ์๋๋ฅผ ๋์ ํ๊ธฐ ์ํด PR์ ์ ์ถํ๋ ๋ฐ ๊ด์ฌ์ด ์์ผ์ญ๋๊น?
๊ฒฐ์ ํด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค @NicolasHug! #17443์ผ๋ก ์ด๋ํฉ๋๋ค(์ด์ ์ ๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฐ ํ)
๋๋ ์ด์๊ฐ ์์ต๋๋ค.
์ด์๋ ์์ต๋๋ค.
๊ทธ ๋ค์์๋ ๋ค๋ฅธ ์์
์ ์ฒ๋ฆฌํ๊ณ ์ง์ฐ๋ PR์ ์งํํฉ๋๋ค.
@lucyleeow ๋ด๊ฐ ๊ทธ ๋ชจ๋ ์์
์ ์ํํ์ง ์์๊ณ ์ผ๋ถ PR์ ์ฐพ๊ณ ์๋ ๊ฒฝ์ฐ๋ฅผ ๋ณด๋ด ์ฃผ์ธ์. :)
๊ธฐ์ฌํ๊ณ ์ถ์ง๋ง ํ์ฌ ๋๋ฌด ๋ง์ ํ๋ก์ ํธ์ ์ฐธ์ฌํ๊ณ ์์ต๋๋ค. ์ ์์ ๋ค์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค!
์ข์ ์๋ฆฌ :)