갈루아의 반서재

텍스트 분류를 위한 나이브 베이즈 (1) - 데이터 전처리


나이브 베이즈를 통한 텍스트 분류


범주를 가진 텍스트 문서가 있고, 보지 못한 새로운 인스턴스의 범주를 예측하도록 나이브 베이즈 알고리즘을 훈련시킨다.사이킷런에서 구할 수 있는 데이터셋을 사용하여 20개의 다른 주제로 19,000개 뉴스 그룹 메시지를 분류한다.


1) 데이터셋 가져오기

학습에 필요한 데이터를 가져온다.

1
2
3
4
5
6
7
8
9
10
>>> %pylab inline
>>> 
>>> import logging
>>> logging.basicConfig()
>>> ​
>>> from sklearn.datasets import fetch_20newsgroups
>>> 
>>> news = fetch_20newsgroups(subset='all')
>>> 
Populating the interactive namespace from numpy and matplotlib
cs


실행시 다음과 같은 에러가 발생하는 경우, ln[3], [4] 의 코드를 추가한다.

1
No handlers could be found for logger "sklearn.datasets.twenty_newsgroups"
cs


2) 데이터셋 속성 확인

데이터셋의 여러 가지 속성을 확인해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> print news.keys()
 
['description''DESCR''filenames''target_names''data''target']
 
>>> print news.description
 
the 20 newsgroups by date dataset
 
>>> print type(news.data), type(news.target), type(news.target_names)
 
<type 'list'> <type 'numpy.ndarray'> <type 'list'>
 
>>> print news.target_names
 
['alt.atheism''comp.graphics''comp.os.ms-windows.misc''comp.sys.ibm.pc.hardware''comp.sys.mac.hardware''comp.windows.x''misc.forsale''rec.autos''rec.motorcycles''rec.sport.baseball''rec.sport.hockey''sci.crypt''sci.electronics''sci.med''sci.space''soc.religion.christian''talk.politics.guns''talk.politics.mideast''talk.politics.misc''talk.religion.misc']
cs


총 인스턴스의 갯수는 18,846개이다.

1
2
3
4
>>> print len(news.data)
18846
>>> print len(news.target)
18846
cs


첫 번째 인스턴스의 내용을 살펴보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> print news.data[0], news.target[0], news.target_names[news.target[0]]
 
From: Mamatha Devineni Ratnam <mr47+@andrew.cmu.edu>
Subject: Pens fans reactions
Organization: Post Office, Carnegie Mellon, Pittsburgh, PA
Lines: 12
NNTP-Posting-Host: po4.andrew.cmu.edu
I am sure some bashers of Pens fans are pretty confused about the lack
of any kind of posts about the recent Pens massacre of the Devils. Actually,
I am  bit puzzled too and a bit relieved. However, I am going to put an end
to non-PIttsburghers' relief with a bit of praise for the Pens. Man, they
are killing those Devils worse than I thought. Jagr just showed you why
he is much better than his regular season stats. He is also a lot
fo fun to watch in the playoffs. Bowman should let JAgr have a lot of
fun in the next couple of games since the Pens are going to beat the pulp out of Jersey anyway. I was very disappointed not to see the Islanders lose the final
regular season game.          PENS RULE!!!
10 rec.sport.hockey
cs



데이터 전처리

텍스트 기반 데이터셋을 수치 기반 데이터셋으로 변환해야 한다. 하나의 속성인 메시지의 텍스트를 의미 있는 수치 속성의 집합으로 변환하는 함수가 필요하다. 직관적으로 단어들을 보고 단어의 빈도 분포와 각 속성을 특징지을 수 있다. sklearn.feature_extraction.text 모듈은 텍스트 문서를 수치 속성 벡터로 만들 수 있는 유용한 함수를 가지고 있다.


먼저 훈련 데이터(75%)와 테스트 데이터(25%)로 구분한다.

1
2
3
4
5
6
SPLIT_PERC = 0.75
split_size = int(len(news.data)*SPLIT_PERC)
X_train = news.data[:split_size]
X_test = news.data[split_size:]
y_train = news.target[:split_size]
y_test = news.target[split_size:]
cs


sklearn.feature_extraction.text 의 메서드

http://scikit-learn.org/stable/modules/classes.html#module-sklearn.feature_extraction.text

CountVectorizer : 텍스트 말뭉치로부터 단어 딕셔너리 생성. 각 인스턴스는 문서에서 특정 단어가 나타나는 횟수가 원소인 수치 속성 벡터로 변환

HashingVectorizer : 토큰을 속성 색인으로 연결하는 해싱함수를 구현하고 CountVectorizer와 같이 카운트 계산

TfidVectorizer : CountVectorizer와 같이 작동하지만 단어 빈도와 역문서 빈도TF-IDF(Term Frequency - Inverse Document Frequency) 계산 사용 문서나 말뭉치에서 단어의 중요성 측정. 문서의 전체 말뭉치에서 단어 빈도와 비교해 현재 문서에서 빈도가 높은 단어 찾음. 이러한 방법으로 결과를 정규화하고 너무 빈도가 높은 단어를 피함. 인스턴스 특정에 유용하지 않을 수 있음