Text Analyis Basic using Scikit-Learn and KoNLPy (python 텍스트 분석 03)
이 분석은 개인적인 local 사정상, Docker 환경에서 실습했음을 알린다.
Docker 환경을 만든 이유는 local OS : Window 10 Home edition 이기 때문이다.
- docker toolbox 로 진행했는데, 꽤나 힘들었다. KoNLPy 순서로 진행한다.
이 외에도, KoNLPy (형태소 분석기 = 한국어 전용 어간분석기) 를 사용할 수 있고, 실제로도 이를 많이 사용한다.
그러나, 현재 실습 환경이 Window 인 관계로, 생략한다. 이는 추후 Collab 에서 활용하도록 한다
“KoNLPy의 Mecab() 클래스는 윈도우에서 지원되지 않습니다.” (http://konlpy.org/ko/latest/install/)
## 라이브러리 로드
import pandas as pd
import numpy as np
import re
import matplotlib.pyplot as plt
%matplotlib inline
# 시각화 결과가 선명하게 표시되도록
%config InlineBackend.figure_format = 'retina'
시각화를 위한 한글폰트 설정
# Window 한글폰트 설정
# plt.rc("font", family="Malgun Gothic")
# Mac 한글폰트 설정
plt.rc("font", family="AppleGothic")
plt.rc('axes', unicode_minus=False)
Naver Movie Review 가져오기
이미 github 에 txt 파일로 정제된것을 활용했다.
df_train = pd.read_csv('/home/cypision/Alchemy/dataset/naver_movie_sample/ratings_train.txt',delimiter='\t',keep_default_na=False)
df_train.head(2)
id | document | label | |
---|---|---|---|
0 | 9976970 | 아 더빙.. 진짜 짜증나네요 목소리 | 0 |
1 | 3819312 | 흠...포스터보고 초딩영화줄....오버연기조차 가볍지 않구나 | 1 |
lable 이 0 이면 부정적인 리뷰. 1이면 긍정적인 리뷰다
numpy 배열로 바꿔보면
text_train = df_train.document.values
y_train = df_train.label.values
print(text_train.shape,y_train.shape)
(150000,) (150000,)
print(type(text_train),text_train.ndim)
<class 'numpy.ndarray'> 1
## text data 불러와서 가공하기
df_test = pd.read_csv('/home/cypision/Alchemy/dataset/naver_movie_sample/ratings_test.txt',delimiter='\t',keep_default_na=False)
text_test = df_test['document'].values
y_test = df_test.label.values
데이터 탐색하기
len(text_train), np.bincount(y_train)
(150000, array([75173, 74827]))
len(text_test), np.bincount(y_test)
(50000, array([24827, 25173]))
KoNLPy 를 tokenizer 로 활용하기
KoNLPy 는 앞선 post 에서 언급했던, 형태소 분석기이고 기본적으로 5개 정도가 있다.
여기서는 2개 정도만 실습해보기로 한다.
Okt 이른바 Twitter 형태소 분석기 활용
from konlpy.tag import Okt ## Twitter --> Okt 로 버전업하면서 명칭이 바뀌었다.
twitter_tag = Okt()
def twitter_tokenizer(text):
return twitter_tag.morphs(text)
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import GridSearchCV
twit_param_grid = {'tfidfvectorizer__min_df':[3,5,7],
'tfidfvectorizer__ngram_range':[(1,1),(1,2),(1,3)],
'logisticregression__C':[0.1,1,10]}
## 여기가 핵심이다.
## 기본 TfidfVectorizer() 는 정규식을 활용하자만, 여기서는 KoNLPy 에 해당하는 어간(형태소) tokenizer 를 사용한다.
t_pipe = make_pipeline(TfidfVectorizer(tokenizer=twitter_tokenizer),LogisticRegression())
t_grid = GridSearchCV(t_pipe,twit_param_grid)
t_grid.fit(text_train[0:1000],y_train[0:1000])
print(t_grid.best_score_)
print(t_grid.best_params_)
0.718
{'logisticregression__C': 1, 'tfidfvectorizer__min_df': 3, 'tfidfvectorizer__ngram_range': (1, 3)}
이제 최적의 조합을 찾았으니, text set를 변환시키고 (KoNLPy tokenzier 를 사용하고) 실제 test 결과를 구해본다
t_grid.best_estimator_
Pipeline(memory=None,
steps=[('tfidfvectorizer',
TfidfVectorizer(analyzer='word', binary=False,
decode_error='strict',
dtype=<class 'numpy.float64'>,
encoding='utf-8', input='content',
lowercase=True, max_df=1.0, max_features=None,
min_df=3, ngram_range=(1, 3), norm='l2',
preprocessor=None, smooth_idf=True,
stop_words=None, strip_accents=None,
sublinear_tf=False,
token...
tokenizer=<function twitter_tokenizer at 0x7f0b5545f268>,
use_idf=True, vocabulary=None)),
('logisticregression',
LogisticRegression(C=1, class_weight=None, dual=False,
fit_intercept=True, intercept_scaling=1,
l1_ratio=None, max_iter=100,
multi_class='auto', n_jobs=None,
penalty='l2', random_state=None,
solver='lbfgs', tol=0.0001, verbose=0,
warm_start=False))],
verbose=False)
x_test_konlypy = t_grid.best_estimator_.named_steps['tfidfvectorizer'].transform(text_test)
score = t_grid.best_estimator_.named_steps['logisticregression'].score(x_test_konlypy,y_test)
print(score)
0.70698
딱히 비교할 건 없지만, 꽤나 잘 맞는다
Mecab 형태소 분석기 활용
from konlpy.tag import Mecab
mecab = Mecab()
def mecab_tokenizer(text):
return mecab.morphs(text)
mecab_param_grid = {'tfidfvectorizer__min_df':[3,5,7],
'tfidfvectorizer__ngram_range':[(1,1),(1,2),(1,3)],
'logisticregression__C':[0.1,1,10]}
## 여기가 핵심이다.
## 기본 TfidfVectorizer() 는 정규식을 활용하자만, 여기서는 KoNLPy 에 해당하는 어간(형태소) tokenizer 를 사용한다.
m_pipe = make_pipeline(TfidfVectorizer(tokenizer=mecab_tokenizer),LogisticRegression())
m_grid = GridSearchCV(m_pipe,mecab_param_grid)
m_grid.fit(text_train[0:1000],y_train[0:1000])
GridSearchCV(cv=None, error_score=nan,
estimator=Pipeline(memory=None,
steps=[('tfidfvectorizer',
TfidfVectorizer(analyzer='word',
binary=False,
decode_error='strict',
dtype=<class 'numpy.float64'>,
encoding='utf-8',
input='content',
lowercase=True,
max_df=1.0,
max_features=None,
min_df=1,
ngram_range=(1, 1),
norm='l2',
preprocessor=None,
smooth_idf=True,
stop_words=N...
n_jobs=None,
penalty='l2',
random_state=None,
solver='lbfgs',
tol=0.0001,
verbose=0,
warm_start=False))],
verbose=False),
iid='deprecated', n_jobs=None,
param_grid={'logisticregression__C': [0.1, 1, 10],
'tfidfvectorizer__min_df': [3, 5, 7],
'tfidfvectorizer__ngram_range': [(1, 1), (1, 2),
(1, 3)]},
pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
scoring=None, verbose=0)
print(m_grid.best_score_)
print(m_grid.best_params_)
0.7529999999999999
{'logisticregression__C': 1, 'tfidfvectorizer__min_df': 3, 'tfidfvectorizer__ngram_range': (1, 2)}
m_grid.best_estimator_
Pipeline(memory=None,
steps=[('tfidfvectorizer',
TfidfVectorizer(analyzer='word', binary=False,
decode_error='strict',
dtype=<class 'numpy.float64'>,
encoding='utf-8', input='content',
lowercase=True, max_df=1.0, max_features=None,
min_df=3, ngram_range=(1, 2), norm='l2',
preprocessor=None, smooth_idf=True,
stop_words=None, strip_accents=None,
sublinear_tf=False,
token...
tokenizer=<function mecab_tokenizer at 0x7f0b2f7a3378>,
use_idf=True, vocabulary=None)),
('logisticregression',
LogisticRegression(C=1, class_weight=None, dual=False,
fit_intercept=True, intercept_scaling=1,
l1_ratio=None, max_iter=100,
multi_class='auto', n_jobs=None,
penalty='l2', random_state=None,
solver='lbfgs', tol=0.0001, verbose=0,
warm_start=False))],
verbose=False)
x_test_konlypy = m_grid.best_estimator_.named_steps['tfidfvectorizer'].transform(text_test)
score = m_grid.best_estimator_.named_steps['logisticregression'].score(x_test_konlypy,y_test)
print(score)
0.74632
그렇다…이렇다 할 특별한 부분은 없지만…결과는 훨씬 좋은 듯. ㅋㅋ
Comments