์ ๋ฒ ์๊ฐ์ ์์๋ณธ ๋์ด๋ธ ๋ฒ ์ด์ฆ ๋ถ๋ฅ ๋ชจ๋ธ์ ์ง์ ์ค์ตํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค~
*์ถ์ฒ*
https://m.blog.naver.com/baek2sm/221786426960
ํ์ด์ฌ ๋์ด๋ธ ๋ฒ ์ด์ฆ ๋ถ๋ฅ ๋จธ์ ๋ฌ๋ ์๊ณ ๋ฆฌ์ฆ ์์
๋จธ์ ๋ฌ๋&๋ฅ๋ฌ๋ ์ฟก๋ถ(MLCook) ์ฌ์ดํท๋ฐ ๋์ด๋ธ ๋ฒ ์ด์ฆ ๋ถ๋ฅ ์์ ์๋ ํ์ธ์. ๋๋ค์ฝ๋์ ๋๋ค. ์ด...
blog.naver.com
(์ด ๋ถ์ ๊ธ์ ์ฐธ๊ณ ํ์ฌ ๊ฑฐ์ ๋๊ฐ์ด ์ค์ตํ๊ธฐ์ ์ถ์ฒ๋ฅผ ๋จผ์ ๋ฐํ๋๋ค)
1. ๋์ด๋ธ ๋ฒ ์ด์ฆ ๋ถ๋ฅ ๋ชจ๋ธ ๊ฐ์
- ๋จธ์ ๋ฌ๋ ๊ธฐ๋ฒ ์ค ํ๋์ด๋ฉฐ ์ ํต์ ์ผ๋ก ํ ์คํธ ๋ถ๋ฅ๋ฅผ ์ํด ์ฌ์ฉ๋์๋ ์๊ณ ๋ฆฌ์ฆ
- ์ง๋ํ์ต ์๊ณ ๋ฆฌ์ฆ
- ๊ธฐ๋ณธ ์๋ฆฌ๋ ๋ฒ ์ด์ฆ ์ ๋ฆฌ(Baye’s theorem)๋ฅผ ์ ์ฉํ ์๋ฆฌ
- ํํ ์คํธ ๋ฉ์ผ ๋ถ๋ฅ๋ก ์ค๋ช ๋จ
์คํธ ๋ฉ์ผ ๋ถ๋ฅ
ํ ์คํธ์ ๋ฑ์ฅํ๋ ๋จ์ด๋ค์ ๋น๋๋ฅผ ํ ๋๋ก ์ ์ ๋ฉ์ผ์ ์ํ ํ๋ฅ ๊ณผ ์คํธ ๋ฉ์ผ์ ์ํ ํ๋ฅ ์ ๊ฐ๊ฐ ๊ณ์ฐํ๊ณ ํ๋ฅ ์ด ๋ ๋์ ์ชฝ์ ๊ฒฐ๊ณผ๋ก ์ถ๋ ฅํจ
์์์ผ๋ก ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์
P(์ ์ ๋ฉ์ผ | ํ ์คํธ) = P(๋จ์ด1 | ์ ์ ๋ฉ์ผ) * P(๋จ์ด2 | ์ ์ ๋ฉ์ผ) * P(์ ์ ๋ฉ์ผ)
P(์คํธ ๋ฉ์ผ | ํ ์คํธ) = P(๋จ์ด1 | ์คํธ ๋ฉ์ผ) * P(๋จ์ด2 | ์คํธ ๋ฉ์ผ) * P(์คํธ ๋ฉ์ผ)
์ฌ๊ธฐ์ P( ๋จ์ด1 | ์ ์ ๋ฉ์ผ)์ ํ๋ฅ ์ ์ ์ ๋ฉ์ผ์ธ ํ์ต ๋ฐ์ดํฐ ์ธํธ์์ ๋จ์ด1์ด ์ถํํ ๋น๋๋ก ๊ณ์ฐ๋จ
์ฆ, ๋์ด๋ธ ๋ฒ ์ด์ฆ ์๊ณ ๋ฆฌ์ฆ์ ํ ์คํธ์ ์์ ์๊ด์์ด ํ ์คํธ์ ์ถํํ ๋น๋๋ฅผ ํ ๋๋ก ๋ถ๋ฅํจ
2. ๋์ด๋ธ ๋ฒ ์ด์ฆ ๋ถ๋ฅ ๋ชจ๋ธ ์ค์ต
๋ฐ์ดํฐ ์ธํธ ์ค๋ช
- ์ฌ์ดํท๋ฐ์์ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ ๋ด์ค ๋ถ๋ฅ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์ด์ฉ
- ๋์ ๋๋ฆฌ ํํ๋ก ์ ์ฅ๋์ด ์์
- ์๋ฌธ 20๊ฐ topic data๋ก, target 0 ~ 19 ์ด 20๊ฐ topic์ผ๋ก ๋ ์ ๋ต์ง๊ฐ ์์
- 18846 ์ data(๋ฌธ๋จ) ์ด ์์ผ๋ฉฐ, ๊ฐ ๋ฌธ๋จ๋ณ ๊ธธ์ด๋ ๋ชจ๋ ๋ค๋ฆ
- ์ด ๋ฐ์ดํฐ ์ธํธ๋ ์ด 20๊ฐ์ ๋ด์ค ์นดํ
๊ณ ๋ฆฌ๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก ๋ฌด์์๋ก ๋ถ๋ฅํ์ ๋ ๊ธฐ๋๋๋ ์ ํ๋๋ 5%...
(์ฐพ์๋ด๋ ์ ์ ํ๋๊ฐ 5%์ธ์ง ๋ชจ๋ฅด๊ฒ ์)
์ฌ์ฉํ ๋ชจ๋ธ๊ณผ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
# -*- coding:utf-8 -*-
from sklearn.datasets import fetch_20newsgroups #๋ด์ฅ๋ ๋ฐ์ดํฐ์
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
import numpy as np
# ๋ถ๋ฅ์ฉ ์ํ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
news = fetch_20newsgroups()
X, y, labels = news.data, news.target, news.target_names
# ํ์ต/ํ
์คํธ ๋ฐ์ดํฐ์
๋ถํ
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1, stratify=y)
๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
# ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ(๋ฒกํฐํ)
vectorizer = CountVectorizer()
tfid = TfidfTransformer()
X_train_vec = vectorizer.fit_transform(X_train)
X_test_vec = vectorizer.transform(X_test)
X_train_tfid = tfid.fit_transform(X_train_vec)
X_test_tfid = tfid.transform(X_test_vec)
ํ ์คํธ ๋ฐ์ดํฐ์ด๊ธฐ์ ๊ทธ๋๋ก ํ์ต์ ์ฌ์ฉํ ์ ์๊ณ ์ฝ๊ฐ์ ์ ์ฒ๋ฆฌ ํ์ํจ
์ฌ์ดํท๋ฐ์์๋ ํ ์คํธ ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ๋ฅผ ์ํ ๊ธฐ๋ฅ๋ค๋ ์ ๊ณตํจ
์ฌ๊ธฐ์ ์ค์ํ ์ ์ CounterVectorizer์ธ๋ฐ ์ด๋ ํ ์คํธ๋ฅผ ๋จ์ด ํ๋ ฌ๋ก ๋ณํ์์ผ์ค
- ์์(์ถ์ฒ : ์ฌ์ดํท๋ฐ ๊ณต์ ๋ฌธ์)
์๋์ ํ ์คํธ ๋ฆฌ์คํธ๋ฅผ ๋ณํํ ๊ฒฐ๊ณผ๋ฅผ ๋ด๋ณด์
์ ํ ์คํธ๋ฅผ countervectorizer๋ก ๋ณํํ๋ฉด ์๋๊ฐ์ ๋ฐ์ดํฐ๊ฐ ์ถ๋ ฅ๋จ
๋ค์์ผ๋ก TfidfTransformer๋ฅผ ์ฌ์ฉํ์ฌ ํน์ ์ํ(ํ ์คํธ)์ ํฌํจ๋ ๋จ์ด ๋น๋์์ ํน์ ๋จ์ด๊ฐ ํฌํจ๋ ์ํ์ ์๊น์ง ๊ณ ๋ คํ์ฌ ๊ฐ์ค์น๋ฅผ ๋ถ์ฌํ ํ๋ ฌ๋ก ๋ณํ
์ด๋ ๊ฒ ํ๋ฉด ํ์ต์ ์ํ ์ ์ฒ๋ฆฌ ๊ณผ์ ์ด ๋ง๋ฌด๋ฆฌ๋จ
์์ด ๋ฌธ์ฅ์ ์ด๋ ๊ฒ ๊ฐ๋จํ๊ฒ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ์ง๋ง ํ๊ตญ์ด๋ ์กฐ๊ธ ๋ ๋ณต์กํจ
๋ชจ๋ธ ํ์ต ๋ฐ ํ์ดํผ ํ๋ผ๋ฏธํฐ ์ค์
# ๋ค์ค๋ถ๋ฅ ๋์ด๋ธ ๋ฒ ์ด๋ธ + ๊ทธ๋ฆฌ๋์์น๋ก ๋ชจ๋ธ ํ์ต
nb = MultinomialNB()
param_grid = [{'alpha': np.linspace(0.01, 1, 100)}]
gs = GridSearchCV(estimator=nb, param_grid=param_grid, scoring='accuracy', cv=5, n_jobs=-1)
gs.fit(X_train_tfid, y_train)
๊ทธ๋ฆฌ๋์์น๋?
๊ทธ๋ฆฌ๋์์น๋ ๋ชจ๋ธ ํ์ดํผ ํ๋ผ๋ฏธํฐ์ ๋ฃ์ ์ ์๋ ๊ฐ๋ค์ ์์ฐจ์ ์ผ๋ก ์ ๋ ฅํ๋ค์ ๊ฐ์ฅ ๋์ ์ฑ๋ฅ์ ๋ณด์ด๋
ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ค์ ์ฐพ๋ ํ์ ๋ฐฉ๋ฒ์ด๋ค.
๋์ด๋ธ ๋ฒ ์ด์ฆ ๋ชจ๋ธ์์ ์ค์ํ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ alpha๊ฐ์
๊ทธ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ๋ค
์์ ์ธ๊ธํ๋ ์์
P(์ ์ ๋ฉ์ผ | ํ ์คํธ) = P(๋จ์ด1 | ์ ์ ๋ฉ์ผ) * P(๋จ์ด2 | ์ ์ ๋ฉ์ผ) * P(์ ์ ๋ฉ์ผ)
๋ ์ฝ๊ฐ์ ๋ฌธ์ ๊ฐ ์์
์ฌ๋ฌ ๋จ์ด์ ์ถํ ํ๋ฅ ์ค ํ๋๋ผ๋ 0์ด ๋๋ฉด ์ ์ฒด ํ๋ฅ ์ด 0์ด ๋์ด๋ฒ๋ฆฌ๋ ๋ฌธ์ ๊ฐ ๋ฐ์
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ผํ๋ผ์ค ์ค๋ฌด๋ฉ์ด๋ผ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํจ
๋ผํ๋ผ์ค ์ค๋ฌด๋ฉ
๊ฐ๊ฐ์ ๋ชจ๋ ํ๋ฅ ์ ํน์ ๊ฐ์ ๋ํด์ฃผ๋ฉด ๊ฐ์ด 0์ด ๋์ด๋ฒ๋ฆฌ๋ ๋ฌธ์ ๋ฅผ ๋ฐฉ์ง
์ด๋ alpha ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ฅผ ํตํด ๊ฐ์ ์ง์ ํ ์ ์์
# ๊ทธ๋ฆฌ๋์์น ํ์ต ๊ฒฐ๊ณผ ์ถ๋ ฅ
print('๋ฒ ์คํธ ํ์ดํผ ํ๋ผ๋ฏธํฐ: {0}'.format(gs.best_params_))
print('๋ฒ ์คํธ ํ์ดํผ ํ๋ผ๋ฏธํฐ ์ผ ๋ ์ ํ๋: {0:.2f}'.format(gs.best_score_))
๊ทธ๋ฆฌ๋ ์์น๋ฅผ ํตํด ํ์ตํ์ ๋ ๊ฐ์ฅ ๋ฒ ์คํธ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ก alpha๋ 0.01์ ๊ฐ์ผ ๋ ์๊ณ
์ด๋ ์ ํ๋๋ 89%์์
์ค์ ๋ก ์์ธกํด๋ณด๊ธฐ
# ์ต์ ํ ๋ชจ๋ธ ์ถ์ถ
model = gs.best_estimator_
# ํ
์คํธ์ธํธ ์ ํ๋ ์ถ๋ ฅ
score = model.score(X_test_tfid, y_test)
print('ํ
์คํธ์ธํธ์์์ ์ ํ๋: {0:.2f}'.format(score))
ํ ์คํธ์ธํธ์์์ ๋ถ๋ฅ ์ ํ๋๋ 90%๋ก ๋์ด๋ธ ๋ฒ ์ด์ฆ ์๊ณ ๋ฆฌ์ฆ์ ๋จ์ํ ๋น๋๋ฅผ ํตํด ๋ถ๋ฅํ์ง๋ง ์ ๋ฒ ์ข์ ์ฑ๋ฅ์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ ํ์ธํ ์ ์์
# ํ
์คํธ์ธํธ ์์ธก ๊ฒฐ๊ณผ ์ํ ์ถ๋ ฅ
predicted_y = model.predict(X_test_tfid)
for i in range(10):
print('์ค์ ๊ฐ: {0}, ์์ธก ๊ฐ: {1}'.format(labels[y_test[i]], labels[predicted_y[i]]))
ํ์ต๋ ๋ชจ๋ธ๋ก ๋ถ๋ฅ ์คํํ ๊ฒฐ๊ณผ์ด๋ค
3. ๋ชจ๋ธ ํ๊ฐ ๋ฐฉ๋ฒ
log loss
๊ฐ์
- ๋ชจ๋ธ ์ฑ๋ฅ ํ๊ฐ ์ ์ฌ์ฉ๊ฐ๋ฅํ ์งํ๋ก, ๋ถ๋ฅ ๋ชจ๋ธ ํ๊ฐํ ๋ ์ฌ์ฉ๋๋ค
๊ฐ๋
- ๋ชจ๋ธ์ด ์์ธกํ ํ๋ฅ ๊ฐ์ ์ง์ ์ ์ผ๋ก ๋ฐ์ํ์ฌ ํ๊ฐ
- ํ๋ฅ ๊ฐ์ ์์ logํจ์์ ๋ฃ์ด์ ๋ณํ์ ์ํจ ๊ฐ์ผ๋ก ํ๊ฐํจ -> ์๋ชป ์์ธกํ ์๋ก, ํจ๋ํฐ ๋ถ์ฌํ๊ธฐ ์ํจ(*์ง๊ด์ ํด์)
-log(x)(์์ ๋ก๊ทธํจ์, ํ๋์ ๊ทธ๋ํ)๋ฅผ ์ฌ์ฉํจ
ํ๋ฅ ์ 0.2๋ก ์ผ์ ํ๊ฒ ์ค์ด๋ค์ง๋ง, ์์ ๋ก๊ทธ๊ฐ์ ์ ์ ๋ ํฌ๊ฒ ์ฆ๊ฐํ๋ ๊ฒ์ ์ ์ ์์ ( => ๊ทธ๋ํ์์์๋ ํ๋ฅ ์ด ๋ฎ์์ง์๋ก ์ข์ธก์ผ๋ก ํฅํจ)
์ผ๋ฐ ์ง์ ๊ทธ๋ํ(์ฃผํฉ์)์ด์๋ค๋ฉด ํ๋ฅ ์ฒ๋ผ ์ผ์ ํ๊ฒ ๊ฐ์ค์น๊ฐ ์ฆ๊ฐํ์ ๊ฒ
์ฆ, log loss ๊ฐ์ ๋ฎ์์๋ก ์ข์ ์งํ์ด๋ค
+) ๋ง์ผ ๊ด์ธก์น(row)๊ฐ ์ฌ๋ฌ ๊ฐ์ผ ๊ฒฝ์ฐ, ์ค์ ํด๋์ค์ ํด๋นํ๋ ํ๋ฅ ๊ฐ์ ์์ ๋ก๊ทธ๋ฅผ ์ทจํ๊ณ ํ๊ท ์ ๋ด์ด ์ฐ์ถํ๋ค
ํผ๋ ๋งคํธ๋ฆญ์ค((Confusion Matrix)
์ค์ ๊ฐ๊ณผ ๋ถ๋ฅ ๋ชจ๋ธ๋ก ๋ถ๋ฅํ ์์ธก๊ฐ์ ํ๊ฐํ์ฌ ๊ฐ์ฒด์ ์๋ฅผ ์ผ๋ค
์๋ฏธ
- positice -> 1/ 'Success'/ 'Pass'/ 'Live
- negative -> 0'/ 'Fail'/ 'Non Pass'/ 'Dead'
- TP (True Positive)
- FP (False Positive)
- FN (False Negative)
- TN (True Negative)
(P์ N์ ์์ธก์น๋ฅผ ์๋ฏธํ๋ฉฐ, ์ด๊ฑธ ์ค์ ๊ฐ๊ณผ ๋น๊ตํ์ ๋ ๋งํ์ผ๋ฉด True, ํ๋ ธ์ผ๋ฉด False ๋ก ํ๊ธฐํ ๊ฒ์)
์ถ๊ฐ๋ก
FP: ์์ธก์ ์ฐธ์ด๋ ์ค์ ๋ ๊ฑฐ์ง, ์ 1์ข
์ค๋ฅ
FN: ์ค์ ๋ ์ฐธ์ด๋ ์์ธก์ ๊ฑฐ์ง, ์ 2์ข
์ค๋ฅ
์ด๋ผ๊ณ ๋ ํ๋ค
ํผ๋ ๋งคํธ๋ฆญ์ค ๊ธฐ๋ฐ ๋ถ๋ฅ ๋ชจ๋ธ ์ฑ๋ฅ ํ๊ฐ ์งํ
๋ชจ๋ ๊ด์ธก์น์ ๊ฐ์๋ฅผ N (= TP + TN + FP + FN) ์ด๋ผ๊ณ ํ๋ฉด,
- ์ ํ๋ (Accuracy) = (TP + TN) / N
- ์ฌํ์จ (recall rate), ๋ฏผ๊ฐ๋ (Sensitivity) = TP / (TP + FN)
- ํน์ด๋ (Specificity) = TN / (FP + TN)
- ์ ๋ฐ๋ (Precision) = TP / (TP + FP)
์ ์์์ ํตํด ์ํ ์ ์๋ค
์ ํ๋์ ๋ํด ๋ ์์ธํ ์์๋ณด์๋ฉด
์ฐ์ ์๋ฏธ๋ ์ ์ฒด ๋ฐ์ดํฐ ์ค์์ ์์ธกํ ๊ฐ์ด ์ค์ ๊ฐ๊ณผ ๋ถํฉํ๋ ๋น์จ์ด๋ผ๊ณ ๋ ํ ์ ์๊ณ
์ด๋ฌํ ์์์ผ๋ก ๊ตฌํ ์ ์๋ค
์ ๋ฐ๋, ์ฌํ์จ, ํน์ด๋ ๊ฐ์ ๊ฒฝ์ฐ
์ ๋ฐ๋(precision): ์์ธก์ด ์ฐธ์ธ ๊ฐ ์ค ์ค์ ์ฐธ์ธ ๊ฐ
์ฌํ์จ(recall,Sensitivity,TPR): ์ค์ ์ฐธ์ธ ๊ฐ ์ค ์์ธก๋ ์ฐธ์ธ ๊ฐ
ํน์ด๋(specificity): ์์ธก์ด ๊ฑฐ์ง์ธ ๊ฐ ์ค ์ค์ ๊ฑฐ์ง์ธ ๊ฐ
๋ผ๊ณ ์ ์ํ ์ ์์ผ๋ฉฐ
์์ ๊ฐ์ ์์์ผ๋ก ๊ตฌํ ์ ์๋ค
๊ทธ๋ฆฌ๊ณ ์ ๋ฐ๋์์๋ FP(๊ฑฐ์ง์ผ๋ก ์์ธกํ์ผ๋, ์ค์ ๋ก ์ฐธ์ธ ๊ฒฝ์ฐ)๋ฅผ ์ค์ด๋ ๊ฒ, ์ฌํ์จ์์๋ FN(๊ฑฐ์ง์ผ๋ก ์์ธกํ๊ณ , ์ค์ ๋ก๋ ๊ฑฐ์ง์ธ ๊ฒฝ์ฐ)์ ์ค์ด๋ ๊ฒ์ด ์ค์ํ๋ค.
์ฆ FP, FN์ด ์ปค์ง๋ฉด ์ ๋ฐ๋, ์ฌํ์จ ๊ฐ๊ฐ ์์์ง๋ค
์ถ์ฒ
- https://github.com/baek2sm/MLCook/blob/master/sklearn-cook/classification/NaiveBayes_c.py
- https://velog.io/@hhhs101/confusionmatrix
- https://rfriend.tistory.com/771
- https://youtu.be/i5U2inxzXx4