본문 바로가기
Study

[NLP] 4. Document Classification

by Hwanin99 2024. 8. 20.

문서 분류

데이터 준비

  • 문서 분류에 필요한 데이터는 scikit-learn이 제공하는 20개의 주제를 가지는 뉴스그룹 데이터를 사용한다.
  • 텍스트는 CounterVectorizer를 거쳐 DTM으로 변환
    • DTM은 문서에 등장하는 단어들을 빈도수 별로 표현한 행렬
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split

news = fetch_20newsgroups()

x = news.data
y = news.target

cv = CountVectorizer()
x = cv.fit_transform(x)

x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.3)
print(x_train.shape,y_train.shape,x_test.shape,y_test.shape)
-----------------------------------------------------------------
(7919, 130107) (7919,) (3395, 130107) (3395,)

 

print(x_train[0])
-----------------
# (0번째 문서, index값) 몇 번 등장했는지

(0, 3220)	1 # 0번째 문서에 3220이라는 단어가 1번 등장했다.
(0, 3414)	1
(0, 5323)	1
(0, 5805)	1
(0, 6442)	1
(0, 6446)	1
(0, 6448)	1
(0, 6453)	1
(0, 11891)	1
(0, 12392)	2
(0, 13338)	1
(0, 14896)	1
(0, 15171)	2
(0, 17163)	1
(0, 17999)	1
(0, 18427)	2
(0, 19106)	1
(0, 20145)	1
(0, 20444)	1
(0, 20591)	3
(0, 20657)	2
(0, 20749)	2
(0, 21561)	1
(0, 25399)	3
(0, 25721)	1
:	:
(0, 123759)	2
(0, 123796)	1
(0, 123984)	2
(0, 124026)	3
(0, 124031)	1
(0, 124046)	1
(0, 124147)	1
(0, 124332)	5
(0, 124397)	1
(0, 124501)	4
(0, 124507)	5
(0, 124509)	1
(0, 124616)	5
(0, 124640)	1
(0, 125007)	1
(0, 125079)	1
(0, 125110)	4
(0, 125271)	1
(0, 125296)	1
(0, 128022)	6
(0, 128026)	2
(0, 128084)	1
(0, 128096)	3
(0, 128402)	10
(0, 128420)	1

1. Scikit-learn을 이용한 문서 분류

Logistic Regression

  • 로지스틱 회귀는 이름에 회귀라는 단어가 들어가지만, 가능한 클래스가 2개인 이진 분류를 위한 모델이다.
  • 로지스틱 회귀의 예측 함수는 다음과 같이 정의한다.

$$ \sigma (x) = \frac{1}{1+e^{-x}} $$

$$ \hat{y} = \sigma (w_0 + w_1 x_1 + ... + w_p x_p) $$

  • $\sigma$: 시그모이드 함수

 

  • 로지스틱 회귀의 학습 목표는 다음과 같은 목적 함수를 최소화하는 파라미터 $w$를 찾는 것이다.

$$ \text{BinaryCrossEntropy} = -\frac{1}{N} \sum\limits_{i=1}^N y_i log(\hat{y}_i) + (1-y_i) log(1-\hat{y}_i)$$

  • 로지스틱 회귀는 특성상 다중 분류에는 적합하지 않다.
from sklearn.metrics import accuracy_score
from  sklearn.linear_model import LogisticRegression

LR = LogisticRegression()
LR.fit(x_train,y_train) # LR을 fit하는 과정(학습을 시킴)
pred = LR.predict(x_test) # 학습된 것에 대해서 predict(x_test에 대해 predict한 값을 받아옴)
acc = accuracy_score(pred,y_test) # predict값과 y_test값을 비교해서 accuracy측정
print(acc)
-------------------------------------------------------------------------------------
0.8621502209131076

Support Vector Machine

  • 회귀, 분류, 이상치 탐지 등에 사용되는 지도학습 방법이다.
    • 클래스 사이의 경계에 위치한 데이터 포인트를 서포트 벡터라고 한다.
    • 각 서포트 벡터가 클래스 사이의 결정 경계를 구분하는데 얼마나 중요한지를 학습한다.
    • 각 서포트 벡터 사이의 마진이 가장 큰 방향으로 학습한다.
    • 서포트 벡터까지의 거리와 서포트 벡터들의 중요도를 기반으로 예측을 수행한다.
from sklearn import svm

SVM = svm.SVC(kernel='linear')
SVM.fit(x_train,y_train)
pred = SVM.predict(x_test)
acc = accuracy_score(pred,y_test)
print(acc)
---------------------------------
0.8220913107511045

Naive Bayes Classification

  • 베이즈 정리를 적용한 확률적 분류 알고리즘이다.
  • 모든 특성들이 독립임을 가정한다. (= naive 가정)
  • 입력 특성에 따라 다음과 같은 3개의 분류기가 존재한다.
    • 가우시안 나이브 베이즈 분류기
    • 베르누이 나이브 베이즈 분류기
    • 다항 나이브 베이즈 분류기

DTM을 이용한 나이브 베이즈

from sklearn.naive_bayes import MultinomialNB

NB = MultinomialNB()
NB.fit(x_train,y_train)
pred = NB.predict(x_test)
acc = accuracy_score(pred,y_test)
print(acc)
----------------------------------------------
0.8094256259204713

 

TF-IDF를 이용한 정확도 향상

from sklearn.feature_extraction.text import TfidfTransformer

tfidf = TfidfTransformer()
x_train_tf=tfidf.fit_transform(x_train)
x_test_tf=tfidf.fit_transform(x_test)

NB.fit(x_train_tf,y_train)
pred = NB.predict(x_test_tf)
acc = accuracy_score(pred,y_test)
print(acc)
-------------------------------------------------------------
0.795581737849779
  • 왜인지 오히려 정확도가 떨어졌다. 

Decision Tree

  • 결정 트리는 분류와 회귀에 사용되는 지도학습 방법이다.
    • 데이터 특성으로부터 추론된 결정 규칙을 통해 값을 예측한다.
    • if-then-else 결정 규칙을 통해 데이터를 학습한다.
    • 트리의 깊이가 깊을수록 복잡한 모델이다.
from sklearn.tree import DecisionTreeClassifier

DT = DecisionTreeClassifier()
DT.fit(x_train,y_train)
pred = DT.predict(x_test)
acc = accuracy_score(pred,y_test)
print(acc)
-----------------------------------------------
0.6156111929307806

XGBoost

  • 트리 기반의 앙상블 기법이다.
    • 분류에 있어서 다른 알고리즘보다 좋은 예측 성능을 보여준다.
    • XGBoost는 GBM 기반이지만, GBM의 단점인 느린 수행 시간과 과적합 규제 부재 등의 문제를 해결하였다.
    • 병렬 CPU 환경에서 빠르게 학습이 가능하다.
from xgboost import XGBClassifier

xgb = XGBClassifier(n_estimators=30,learning_rate=0.05,max_depth=3)
xgb.fit(x_train,y_train)
pred = xgb.predict(x_test)
acc = accuracy_score(pred,y_test)
print(acc)
-----------------------------------------------------------------
0.7054491899852725

교차 검증

  • 일반 검증은 학습 데이터가 테스트 데이터로 사용되지 않는다.
  • 교차 검증은 데이터를 n개의 집합으로 나누어 정확도를 계산해 학습 데이터로 사용된 데이터도 테스트 데이터로 사용한다.
  • 교차 검증을 사용하면 일반 검증보다 모델의 일반화가 잘 되어 있는지 평가가 가능하다.
    • 앞서 구성한 나이브 베이즈 모델을 교차 검증 하였다.
from sklearn.model_selection import cross_val_score

scores = cross_val_score(NB,x,y,cv=5)
print(scores,scores.mean())
---------------------------------------------------
[0.83870968 0.83826779 0.82368537 0.83031374 0.83642794] 0.833480903927519
  • 교차 검증을 통해 일반 검증보다 좀 더 일반화된 모델 생성이 가능하다.
  • 교차 검증은 일반 검증에 비해 n번 검증을 하여 비용이 더 많이 소요된다.

정밀도와 재현률

  • 정밀도(Precision)는 양성 클래스로 예측한 샘플이 양성 클래스일 확률을 의미한다.
    • 즉, 모델이 얼마나 양성 클래스를 잘 예측하는지를 나타낸다.
  • 재현률(Recall)은 양성 클래스인 샘플에서 모델이 양성 클래스로 예측한 샘플 비율을 의미하며, 모델이 얼마나 실제 상황을 재현하는지를 나타낸다.
  • 정밀도와 재현율의 가중 조화평균인 F1-Score라는 지표는 정확도에 비해 더 효과적인 모델 분석 지표이다.

 

  • 다중 클래스 분류 문제에서 정밀도와 재현률을 계산할 때는 클래스 간의 지표를 어떻게 합칠지 지정이 필요하다.
    • None: 클래스 간 지표를 합치지 말고 그대로 출력
    • micro: 정밀도와 재현률이 같다. 이로 인해 F1-Score도 정밀도, 재현률과 동일하다.
    • macro: 클래스 간 지표를 단순 평균한 값
    • weighted: 클래스 간 지표를 가중 평균한 값
from sklearn.metrics import precision_score,recall_score,f1_score

precision = precision_score(pred,y_test,average='micro')
recall = recall_score(pred,y_test,average='micro')
f1 = f1_score(pred,y_test,average='micro')

print(precision,recall,f1)
-----------------------------------------------------------------
0.7054491899852725 0.7054491899852725 0.7054491899852725

그리드 검색을 이용한 파라미터 최적화

  • 그리드 검색을 사용하면 분류기에 사용하는 파라미터 최적화가 가능하다.
    • estimator: 사용 모델 객체
    • param_gird: {사용 객체 : 지정 파라미터 리스트}
    • scoring: 최적화하고자 하는 성능 지표
    • cv: 교차 검증 분할 개수
from sklearn.model_selection import GridSearchCV

GS = GridSearchCV(estimator=NB,param_grid={'alpha':[0.001,0.01,0.1,1.]},scoring='accuracy',cv=10)
GS.fit(x,y)

print(GS.best_score_)
print(GS.best_params_)
--------------------------------------------------
0.8897820965842167
{'alpha': 0.001}

'Study' 카테고리의 다른 글

[NLP] 6. Topic Modeling  (0) 2024.08.21
[NLP] 5. Semantic Network Analysis  (0) 2024.08.20
[NLP] 3. Cluster Analysis  (0) 2024.08.19
[NLP] 2. Keyword Analysis  (1) 2024.08.19
[NLP] 1. National Language Processing  (0) 2024.08.19