문서 분류는 문서들을 2개 이상의 미리 정해진 그룹으로 분류하는 것입니다. 기계 학습으로 문서 분류를 할 경우 기본 원리 자체는 감성 분석과 동일합니다. 다만 감성분석은 긍/부정 2가지로만 분류되는 반면, 문서 분류는 여러 가지로 분류될 수 있다는 차이가 있습니다.
20 newsgroup 데이터로 문서 분류를 연습해보겠습니다. 이 데이터는 20개의 뉴스 그룹(일종의 주제별 커뮤니티 게시판)에서 모은 게시물로 이뤄져 있습니다.
scikit-learn에는 20 newsgroup 데이터를 바로 다운받을 수 있는 fetch_20newsgroups
함수가 있습니다.
from sklearn.datasets import fetch_20newsgroups
원래는 20개의 카테고리가 여기서는 3개 카테고리를 대상으로 문서 분류를 진행합니다. rec.motorcycles
, rec.sport.baseball
, rec.sport.hockey
3개 카테고리를 대상으로 하고, 이를 categories
변수로 저장합니다.
categories = [
'rec.motorcycles',
'rec.sport.baseball',
'rec.sport.hockey'
]
훈련용과 테스트용이 미리 분할되어 있으므로 다운만 받으면 됩니다.
subset
: 훈련(train)과 테스트(test)를 설정categories
: 분류하고자 하는 카테고리를 대입. 여기에서는 위에서 categories
로 정의한 변수를 대입합니다.newsgroups_train = fetch_20newsgroups(subset='train', categories=categories)
newsgroups_test = fetch_20newsgroups(subset='test', categories=categories)
데이터를 확인합니다. 훈련과 테스트셋에서 분류의 대상이 되는 데이터는 각각 newsgroups_train.data
, newsgroups_test.data
에 저장되어 있습니다.
newsgroups_train.data[1]
으로 훈련셋의 두번째 데이터를 확인할 수 있습니다.
print(newsgroups_train.data[1])
Organization: University of Notre Dame - Office of Univ. Computing From: <RVESTERM@vma.cc.nd.edu> Subject: Re: ugliest swing <1993Apr12.235334.25031@ptdcs2.intel.com> <34244@oasys.dt.navy.mil> Lines: 16 In article <34244@oasys.dt.navy.mil>, kiviat@oasys.dt.navy.mil (Brian Kiviat) says: > >What I think is hotdogish about his AB's is the way he leans out over >the plate to watch outside pitches etc. This not done to get a better >look at the pitch, but to make it seem,"this ball is so far out I need >to lean just to get near it so you better call it a ball". This is my >"unbiased" opinion of what I see. Your mileage will vary....... >Rickey is agreat player to watch if you forget who he is at the time. a lot of batters lean in when pitches come. rickey's crouch tends to exaggerate that, i think. "a great player to watch if you forget who he is" - "unbiased"... hmmm... bob vesterman.
3개의 카테고리 라벨은 0
, 1
, 2
3개입니다. 이 번호는 위에서 categories
에서 나타난 순서입니다.
훈련과 테스트셋에서 데이터의 카테고리는 각각 newsgroups_train.target
, newsgroups_test.target
에 저장되어 있습니다.
newsgroups_train.target[1]
으로 훈련셋의 두번째 데이터가 어떤 카테고리에 속하는지 확인할 수 있습니다.
print(newsgroups_train.target[1])
1
훈련셋의 두번째 데이터의 카테고리는 1
번이므로 rec.sport.baseball
에 속하는 것을 확인할 수 있습니다.
TF-IDF로 단어 문서 행렬을 만들어보겠습니다.
from sklearn.feature_extraction.text import TfidfVectorizer
stop_words
: 영어 불용어(관사 등) 제거max_features
: 분석에 포함될 단어의 수tfidf = TfidfVectorizer(stop_words='english', max_features=1000)
x_train.shape
으로 훈련셋의 크기를 확인할 수 있습니다.x_train = tfidf.fit_transform(newsgroups_train.data)
x_train.shape
(1795, 1000)
위 결과에서 (1795, 1000)
이란 문서의 수가 1,795개 이고, 단어가 1000종이라는 뜻입니다.
이어서 테스트용 데이터도 단어 문서 행렬로 만듭니다. 이때는 x_train
과 똑같은 방식으로 단어 문서 행렬을 만들어야 하므로 fit_transform
대신에 transform
을 사용합니다.
x_test = tfidf.transform(newsgroups_test.data)
y_test
와 y_train
은 다음과 같이 간단하게 만들 수 있습니다.
y_train = newsgroups_train.target
y_test = newsgroups_test.target
이후의 분석을 위해 데이터를 저장합니다.
import joblib
joblib.dump((x_train, x_test, y_train, y_test, tfidf), 'newsgroup.pkl')
['newsgroup.pkl']