%pylab
%load_ext watermark
%watermark -v -p sklearn,konlpy,pandas
Using matplotlib backend: Qt5Agg Populating the interactive namespace from numpy and matplotlib CPython 3.5.6 IPython 6.5.0 sklearn 0.20.0 konlpy 0.5.1 pandas 0.23.4
import konlpy
import pandas as pd
데이터 파일을 읽어 리뷰 텍스트와 점수를 text_train, y_train 변수에 저장합니다. 데이터 파일의 내용은 번호, 텍스트, 레이블이 탭으로 구분되어 한 라인에 한개의 데이터 샘플이 들어 있습니다.
df_train = pd.read_csv('data/ratings_train.txt', delimiter='\t', keep_default_na=False)
df_train.head()
id | document | label | |
---|---|---|---|
0 | 9976970 | 아 더빙.. 진짜 짜증나네요 목소리 | 0 |
1 | 3819312 | 흠...포스터보고 초딩영화줄....오버연기조차 가볍지 않구나 | 1 |
2 | 10265843 | 너무재밓었다그래서보는것을추천한다 | 0 |
3 | 9045019 | 교도소 이야기구먼 ..솔직히 재미는 없다..평점 조정 | 0 |
4 | 6483659 | 사이몬페그의 익살스런 연기가 돋보였던 영화!스파이더맨에서 늙어보이기만 했던 커스틴 ... | 1 |
text_train, y_train = df_train['document'].values, df_train['label'].values
같은 방식으로 테스트 데이터를 읽습니다.
df_test = pd.read_csv('data/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 0.4.5 버전부터 Twitter
클래스가 Okt
클래스로 바뀌었습니다. open-korean-text 프로젝트는 twitter-korean-text 프로젝트의 공식 포크입니다.
from konlpy.tag import Okt
okt_tag = Okt()
TfidfVectorizer
의 토큰 파서를 대체하기 위해 Okt
클래스를 사용하는 함수를 만듭니다.
def okt_tokenizer(text):
return okt_tag.morphs(text)
min_df
, ngram_range
, C
매개변수를 대상으로 그리드 서치를 수행합니다.
사이킷런 0.22 버전에서 LogisticRegression
클래스의 solver
매개변수 기본값이 liblinear
에서 lbfgs
로 변경될 예정입니다. 사이킷런 0.20 버전에서 solver
매개변수를 지정하지 않는 경우 이에 대한 경고 메세지가 출력됩니다. 경고 메세지를 피하기 위해 solver
매개변수 값을 liblinear
로 지정합니다.
사이킷런 0.22 버전에서 GridSearchCV
클래스의 cv
매개변수 기본값이 3에서 5로 바뀔 예정입니다. 0.20 버전에서 cv
매개변수를 지정하지 않는 경우 이에 관한 경고 메세지가 출력됩니다. 경고 메세지를 피하기 위해 cv
매개변수 값을 명시적으로 3으로 지정합니다.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import GridSearchCV
okt_param_grid = {'tfidfvectorizer__min_df': [3, 5 ,7],
'tfidfvectorizer__ngram_range': [(1, 1), (1, 2), (1, 3)],
'logisticregression__C': [0.1, 1, 10]}
okt_pipe = make_pipeline(TfidfVectorizer(tokenizer=okt_tokenizer), LogisticRegression(solver='liblinear'))
okt_grid = GridSearchCV(okt_pipe, okt_param_grid, cv=3)
# 그리드 서치를 수행합니다
okt_grid.fit(text_train[0:1000], y_train[0:1000])
print("최상의 크로스 밸리데이션 점수: {:.3f}".format(okt_grid.best_score_))
print("최적의 크로스 밸리데이션 파라미터: ", okt_grid.best_params_)
최상의 크로스 밸리데이션 점수: 0.704 최적의 크로스 밸리데이션 파라미터: {'tfidfvectorizer__min_df': 3, 'tfidfvectorizer__ngram_range': (1, 1), 'logisticregression__C': 1}
X_test_okt = okt_grid.best_estimator_.named_steps["tfidfvectorizer"].transform(text_test)
score = okt_grid.best_estimator_.named_steps["logisticregression"].score(X_test_okt, y_test)
print("테스트 세트 점수: {:.3f}".format(score))
테스트 세트 점수: 0.705
병렬 처리를 위해 Mecab
을 사용하여 전체 데이터로 학습시킵니다. Mecab
으로 토큰을 분할하는 함수를 만듭니다.
최신 macOS Mojave에서는 Mecab
에 필요한 jpype 라이브러리가 컴파일 오류가 발생합니다. 우분투에서 n_jobs=1
을 사용해 실행했습니다.
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, 100]}
mecab_pipe = make_pipeline(TfidfVectorizer(tokenizer=mecab_tokenizer), LogisticRegression(solver='liblinear'))
mecab_grid = GridSearchCV(mecab_pipe, mecab_param_grid, n_jobs=1, cv=3)
# 그리드 서치를 수행합니다
mecab_grid.fit(text_train, y_train)
print("최상의 크로스 밸리데이션 점수: {:.3f}".format(mecab_grid.best_score_))
print("최적의 크로스 밸리데이션 파라미터: ", mecab_grid.best_params_)
최상의 크로스 밸리데이션 점수: 0.870 최적의 크로스 밸리데이션 파라미터: {'tfidfvectorizer__min_df': 3, 'tfidfvectorizer__ngram_range': (1, 3), 'logisticregression__C': 10}
X_test_mecab = mecab_grid.best_estimator_.named_steps["tfidfvectorizer"].transform(text_test)
score = mecab_grid.best_estimator_.named_steps["logisticregression"].score(X_test_mecab, y_test)
print("테스트 세트 점수: {:.3f}".format(score))
테스트 세트 점수: 0.875