WIDA/DACON 분류-회귀

[DACON/김규리] 분류 모델 뜯어보기, 분류 모델 평가방식

kyuree 2023. 3. 31. 00:41

저번 시간에 알아본 나이브 베이즈 분류 모델을 직접 실습해보도록 하겠습니다~

 

*출처* 

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