[Python] 머신러닝 완벽가이드 - 08. 텍스트 분석[한글 텍스트 처리]
Updated:
파이썬 머신러닝 완벽가이드 교재를 토대로 공부한 내용입니다.
실습과정에서 필요에 따라 내용의 누락 및 추가, 수정사항이 있습니다.
기본 세팅
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
mpl.rc('font', family='NanumGothic') # 폰트 설정
mpl.rc('axes', unicode_minus=False) # 유니코드에서 음수 부호 설정
# 차트 스타일 설정
sns.set(font="NanumGothic", rc={"axes.unicode_minus":False}, style='darkgrid')
plt.rc("figure", figsize=(10,8))
warnings.filterwarnings("ignore")
7. 한글 텍스트 처리
7.1 네이버 영화 평점 데이터
데이터는 https://github.com/e9t/nsmc에서 받을 수 있다.
이 데이터를 이용해서 감성 분석을 진행해보자.
train_df = pd.read_csv('nsmc-master/ratings_train.txt', sep='\t')
train_df.head(3)
id | document | label | |
---|---|---|---|
0 | 9976970 | 아 더빙.. 진짜 짜증나네요 목소리 | 0 |
1 | 3819312 | 흠...포스터보고 초딩영화줄....오버연기조차 가볍지 않구나 | 1 |
2 | 10265843 | 너무재밓었다그래서보는것을추천한다 | 0 |
train_df['label'].value_counts( )
0 75173
1 74827
Name: label, dtype: int64
-
0은 부정 감성, 1은 긍정 감성을 의미한다.
-
target의 분포는 거의 균등하게 나타났다.
train_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150000 entries, 0 to 149999
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 150000 non-null int64
1 document 149995 non-null object
2 label 150000 non-null int64
dtypes: int64(2), object(1)
memory usage: 3.4+ MB
-
데이터는 150,000 x 3으로 이루어져 있다.
-
document 컬럼은 일부 결측이 존재하여 이를 공백으로 변환하겠다.
7.1.1 텍스트 전처리
import re
# document 결측 공백으로 변환
train_df = train_df.fillna(" ")
# 정규 표현식으로 숫자를 공백으로 변경 (정규 표현식에서 \d는 숫자를 의미)
train_df["document"] = train_df["document"].apply(lambda x: re.sub(r"\d+", " ", x))
# test set 동일 작업
test_df = pd.read_csv('nsmc-master/ratings_test.txt', sep='\t')
test_df = test_df.fillna(" ")
test_df["document"] = test_df["document"].apply(lambda x: re.sub(r"\d+", " ", x))
# id 컬럼 제거
train_df.drop("id", axis=1, inplace=True)
test_df.drop("id", axis=1, inplace=True)
- document 결측값과 숫자를 공백으로 변환하였고 id 컬럼은 제거하였다.
7.1.2 감성 분석
tokenizer 함수
from konlpy.tag import Twitter
twitter = Twitter()
def tw_tokenizer(text):
# 텍스트를 형태소 단어로 토큰화 후 리스트로 반환
tokens_ko = twitter.morphs(text)
return tokens_ko
-
피처 벡터화에 사용할 tokenizer 함수를 생성하였다.
-
twitter.morphs()
는 문장을 형태소 단어 형태로 토큰화 한다. -
Twitter
는 현재Okt
(Open Korea Text)로 변경되었고, 여기선 그냥Twitter
로 썼다.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV
# TF-IDF 피처 벡터화, 로지스틱
pipeline = Pipeline([
("tfidf_vect", TfidfVectorizer(tokenizer=tw_tokenizer, ngram_range=(1,2), min_df=3, max_df=0.9)),
("lr_clf", LogisticRegression())
])
# GridSearchCV
params = {
"lr_clf__C": [1, 3.5, 10]
}
grid_cv = GridSearchCV(pipeline, param_grid=params, scoring="accuracy", verbose=1)
grid_cv.fit(train_df['document'], train_df['label'])
print(grid_cv.best_params_, round(grid_cv.best_score_,4))
Fitting 5 folds for each of 3 candidates, totalling 15 fits
[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done 15 out of 15 | elapsed: 85.8min finished
{'lr_clf__C': 3.5} 0.8616
-
파이프라인을 이용해 TF-IDF 피처 벡터화, 로지스틱 회귀 객체를 생성하였다.
-
수행 시간을 고려해서 하이퍼 파라미터는 3개 중 최적을 찾았다.
-
최적 하이퍼 파라미터 C는 3.5일 때 최고 0.8616의 정확도로 나타났다.
from sklearn.metrics import accuracy_score
# 예측/평가 (best_estimator로 안해도 이미 최적으로 학습되어 있음)
best_estimator = grid_cv.best_estimator_
pred = best_estimator.predict(test_df["document"])
acc = accuracy_score(test_df["label"], pred)
print(f"Logistic Regression 정확도: {acc:.4f}")
Logistic Regression 정확도: 0.8618
-
test에 대한 정확도는 0.8618로 나타났다.
-
피처 벡터화시 반드시 train으로 학습한 벡터화 객체로 test를 벡터화 하여야한다.
-
여기선 파이프라인을 사용했기에 예측시 원래 객체로 입력하였다.
Leave a comment