사이킷런에서 제공하는 fetch_20newsgroups() API를 이용한 20 뉴스그룹 분류 실습
- 텍스트 분류는 학습 데이터를 통해 특정 문서 분류 모델을 생성한 뒤 다른 문서의 분류를 예측하는 것
- 텍스트를 먼저 정규화 한 뒤 피처 벡터화를 적용하고 로지스틱 회귀 알고리즘을 적용해 분류를 학습/예측/평가
- 사이킷런의 Pipeline 객체를 통해 피처 벡터화 파라미터와 GridSearchCV기반의 하이퍼 파라미터 튜닝을 한꺼번에 수행
1. 텍스트 정규화
- 데이터 로딩 후, 데이터 세트의 key 값 확인
from sklearn.datasets import fetch_20newsgroups
news_data = fetch_20newsgroups(subset='all', random_state=156)
print(news_data.keys())
[output]
dict_keys(['data', 'filenames', 'target_names', 'target', 'DESCR'])
- Target 칼럼의 구성 확인
- Target 값은 20개로 구성 됨
# target 값 확인
import pandas as pd
print('target 클래스의 값과 분포도\n', pd.Series(news_data.target).value_counts().sort_index())
print('target 클래스의 이름들\n', news_data.target_names)
[output]
target 클래스의 값과 분포도
0 799
1 973
2 985
3 982
4 963
5 988
6 975
7 990
8 996
9 994
10 999
11 991
12 984
13 990
14 987
15 997
16 910
17 940
18 775
19 628
dtype: int64
target 클래스의 이름들
['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']
- 하나의 개별 데이터 값 확인
- 헤더와 푸터 정보를 포함하는 것은 텍스트 분석의 의도를 벗어나기 때문에 제거
#개별 데이터 한 개만 출력
print(news_data.data[0])
[output]
From: egreen@east.sun.com (Ed Green - Pixel Cruncher)
Subject: Re: Observation re: helmets
Organization: Sun Microsystems, RTP, NC
Lines: 21
Distribution: world
Reply-To: egreen@east.sun.com
NNTP-Posting-Host: laser.east.sun.com
In article 211353@mavenry.altcit.eskimo.com, maven@mavenry.altcit.eskimo.com (Norman Hamer) writes:
>
> The question for the day is re: passenger helmets, if you don't know for
>certain who's gonna ride with you (like say you meet them at a .... church
>meeting, yeah, that's the ticket)... What are some guidelines? Should I just
>pick up another shoei in my size to have a backup helmet (XL), or should I
>maybe get an inexpensive one of a smaller size to accomodate my likely
>passenger?
If your primary concern is protecting the passenger in the event of a
crash, have him or her fitted for a helmet that is their size. If your
primary concern is complying with stupid helmet laws, carry a real big
spare (you can put a big or small head in a big helmet, but not in a
small one).
---
Ed Green, former Ninjaite |I was drinking last night with a biker,
Ed.Green@East.Sun.COM |and I showed him a picture of you. I said,
DoD #0111 (919)460-8302 |"Go on, get to know her, you'll like her!"
(The Grateful Dead) --> |It seemed like the least I could do...
- remove 파라미터로 header, footer, quotes 정보 제거, subset 파라미터로 학습, 테스트 데이터 분리
#subset = 'train' 으로 학습용 데이터만 추출, remove = ('headers', 'footers', 'quoters')로 내용만 추출
train_news = fetch_20newsgroups(subset = 'train', remove = ('headers', 'footers', 'quotes'),
random_state=156)
X_train = train_news.data
y_train = train_news.target
#subset = 'test'로 테스트용 데이터만 추출, remove = ('headers', 'footers', 'quoters')로 내용만 추출
test_news = fetch_20newsgroups(subset = 'test', remove = ('headers', 'footers', 'quotes'),
random_state=156)
X_test = test_news.data
y_test = test_news.target
print('학습 데이터 크기 : {0}, 테스트 데이터 크기 : {1}'.format(len(train_news.data),
len(test_news.data)))
[output]
학습 데이터 크기 : 11314, 테스트 데이터 크기 : 7532
2. 피처 벡터화 변환과 모델 학습/예측/평가
2.1 CountVectorizer 를 이용한 피처 벡터화
- 테스트 데이터에서 countvectorizer를 적용할 때는 학습 데이터를 이용해 fit된 객체를 이용해 transform을 해야 학습 데이터와 테스트 데이터의 변환 시 피처 개수가 같아짐
- 학습 데이터를 피처 벡터화 한 결과 11314개의 문서에서 피처(단어)가 101631개로 만들어짐
# CountVectorizer 를 이용한 피처 벡터화
from sklearn.feature_extraction.text import CountVectorizer
cnt_vect = CountVectorizer()
cnt_vect.fit(X_train)
X_train_cnt_vect = cnt_vect.transform(X_train)
# 학습데이터로 fit()된 CountVectorizer 를 통해 테스트 데이터 피처 벡터화 변환 수행
X_test_cnt_vect = cnt_vect.transform(X_test)
print('학습 데이터 텍스트의 CountVectorizer Shape:', X_train_cnt_vect.shape)
[output]
학습 데이터 텍스트의 CountVectorizer Shape: (11314, 101631)
- 로지스틱 회귀 모델을 적용해 뉴스그룹에 대한 분류 예측, 정확도 평가
#LogisticRegression 을 이용하여 학습/예측/평가 수행
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
import warnings
warnings.filterwarnings('ignore')
lr_clf = LogisticRegression(solver = 'liblinear')
lr_clf.fit(X_train_cnt_vect, y_train)
pred = lr_clf.predict(X_test_cnt_vect)
print('CounterVectorizered Logistic Regression 의 예측 정확도는 {0:.3f}'.format(accuracy_score(y_test, pred)))
[output]
CounterVectorizered Logistic Regression 의 예측 정확도는 0.617
2.2 TF-IDF 를 이용한 피처 벡터화
- 단순 카운트 기반보다 훨씬 높은 예측 정확도 제공
# TF-IDF 벡터화를 적용해 학습 데이터 세트와 테스트 데이터 세트 변환
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf_vect = TfidfVectorizer()
tfidf_vect.fit(X_train)
X_train_tfidf_vect = tfidf_vect.transform(X_train)
X_test_tfidf_vect = tfidf_vect.transform(X_test)
#LogisticRegression 을 이용하여 학습/예측/평가 수행
lr_clf = LogisticRegression(solver = 'liblinear')
lr_clf.fit(X_train_tfidf_vect, y_train)
pred = lr_clf.predict(X_test_tfidf_vect)
print('TF-IDF Logistic Regression 의 예측 정확도는 {0:.3f}'.format(accuracy_score(y_test, pred)))
[output]
TF-IDF Logistic Regression 의 예측 정확도는 0.678
- TF-IDF 벡터화에 다양한 파라미터를 제공, GridSerachCV를 통해 모델 예측 성능 향상
#stop words 필터링을 추가하고 ngram 을 기본(1,1) -> (1,2) 변경해 피처 벡터화 적용
tfidf_vect = TfidfVectorizer(stop_words = 'english', ngram_range=(1,2), max_df =300)
tfidf_vect.fit(X_train)
X_train_tfidf_vect = tfidf_vect.transform(X_train)
X_test_tfidf_vect = tfidf_vect.transform(X_test)
#GridSearchCV 를 통한 하이퍼 파라미터 최적화
from sklearn.model_selection import GridSearchCV
#최적 C 값 도출 튜닝 수행. CV 는 3폴드
lr_clf = LogisticRegression(solver = 'liblinear')
params = {'C':[0.01, 0.1, 1, 5, 10]}
grid_cv_lr = GridSearchCV(lr_clf, param_grid=params, cv = 3, scoring='accuracy', verbose=1)
grid_cv_lr.fit(X_train_tfidf_vect, y_train)
print('Logistic Regression best C parmeter:', grid_cv_lr.best_params_)
#최적 C 값으로 학습된 grid_cv로 예측 및 정확도 평가
pred = grid_cv_lr.predict(X_test_tfidf_vect)
print('TF-IDF Vectorized Logistic Regression의 예측 정확도는 {0:.3f}'.format(accuracy_score(y_test, pred)))
[output]
Fitting 3 folds for each of 5 candidates, totalling 15 fits
Logistic Regression best C parmeter: {'C': 10}
TF-IDF Vectorized Logistic Regression의 예측 정확도는 0.704
3. 사이킷런 Pipeline 사용 및 GridSearchCV와의 결합
3.1 Pipeline을 사용한 피처벡터화, 모델 학습/예측
- pipeline 클래스를 이용하면 피처벡터화의 ML 알고리즘 학습/예측을 위한 코드 작성을 한 번에 진행할 수 있음
- 머신러닝 코드를 직관적이고 쉽게 작성할 수 있음
- 수행 시간의 절약
#사이킷런의 Pipeline 클래스 이용
from sklearn.pipeline import Pipeline
#TFidfVectorizer 객체를 tfidf_vect로, LogisticRegression 객체를 lr_clf 로 생성하는 Pipeline 생성
pipeline = Pipeline([('tfidf_vect', TfidfVectorizer(stop_words='english', ngram_range=(1,2), max_df=300)),
('lr_clf', LogisticRegression(solver = 'liblinear', C=10))
])
#별도의 TfidfVectorizer 객체의 fit(), transform()과 LogisticRegression 의 fit(), predict()가 필요없음
#pipeline()의 fit()과 predict()만으로도 한꺼번에 피처 벡터화와 ML 학습/예측 가능
pipeline.fit(X_train, y_train)
pred = pipeline.predict(X_test)
print('Pipeline을 통한 Logistic Regression의 예측 정확도는 : {0:.3f}'.format(accuracy_score(y_test,pred)))
[output]
Pipeline을 통한 Logistic Regression의 예측 정확도는 : 0.704
3.2 Pipeline과 GridSerachCV와의 결합
- GridSearchCV 의 클래스 생성 파라미터에 Pipeline을 입룍해 피처벡터화를 위한 파라미터와 ML 하이퍼 파라미터를 모두 한번에 최적화 할 수 있음
- 모든 파라미터를 최적화하려면 너무 많은 튜닝 시간이 소모됨
#GridSearchCV + Pipeline
pipeline = Pipeline([
('tfidf_vect', TfidfVectorizer(stop_words='english')),
('lr_clf', LogisticRegression())
])
#pipeline 에 기술된 각각의 객체 변수에 언더바 2개(__)를 붙여 GridSearchCV 생성
#파라미터/하이퍼파라미터 이름과 값을 설정
params = { 'tfidf_vect__ngram_range': [(1,1), (1,2), (1,3)],
'tfidf_vect__max_df': [100, 300, 700],
'lr_clf__C': [1,5,10]
}
#GridSearchCV의 생성자에 Estimator 가 아닌 Pipeline 객체 입력
grid_cv_pipe = GridSearchCV(pipeline, param_grid=params, cv=3, scoring='accuracy', verbose=1)
grid_cv_pipe.fit(X_train, y_train)
print(grid_cv_pipe.best_params_, grid_cv_pipe.best_score_)
pred = pipeline.predict(X_test)
print('Pipeline을 통한 Logistic Regression 예측 정확도는 {0:.3f}'.format(accuracy_score(y_test,pred)))
'데이터 > 머신러닝' 카테고리의 다른 글
[NLP] Chapter 8 | 텍스트 분석 (비지도학습 기반 감성 분석) (0) | 2023.02.05 |
---|---|
[NLP] Chapter 8 | 텍스트 분석 (지도학습 기반 감성 분석) (0) | 2023.02.04 |
[NLP] Chapter 8 | 텍스트 분석 (소개 및 기반지식) (1) | 2023.02.02 |
[RecSys] Chapter 9 | 추천시스템 (0) | 2023.02.01 |
[Clustering] Chapter 7 | 군집화 실습 - 고객 세그멘테이션 (1) | 2023.01.28 |