감성 분석
감성 분석(Sentiment Analysis)
: 문서의 주관적인 감성/의견/감정/기분 등을 파악하기 위한 방법
- 감성분석은 문서 내 테스트가 나타내는 여러 가지 주관적인 단어와 문맥을 기반으로 감성(Sentiment)수치를 계산하는 방법 이용
- 감성 지수는 긍정 감성 지수와 부정 감성 지수로 구성되며 이들 지수를 합산해 긍정 감성 또는 부정 감성을 결정
- 감성 분석은 머신러닝 관점에서 지도학습과 비지도학습으로 나눌 수 있음
지도 학습 : 학습 데이터와 타깃 레이블 값을 기반으로 감성 분석 학습을 수행한 뒤 이를 기반으로 다른 데이터의 감서 분석을 예측하는 방법으로 일반적인 텍스트 기반의 분류와 거의 동일
비지도 학습 : 'Lexicon'이라는 일종의 감성 어휘 사전 이용, Lexicon은 감성 분석을 위한 용어와 문맥에 대한 다양한 정보를 가지고 있으며 이를 이용해 문서의 긍정적, 부정적 감성 여부를 판단
지도학습 기반 감성 분석 실습 - IMDB 영화평
영화평의 텍스트를 분석해 감성 분석 결과가 긍정 또는 부정인지를 예측하는 모델 만들기
import pandas as pd
review_df = pd.read_csv('')
review_df.head(3)
print(review_df['review'][0])
판다스의 DataFrame/Series는 문자열 연산을 지원하기 위해 str 속성을 이용
DataFrame/Series 객체에서 str을 적용하면 다양한 문자열 연산을 수행할 수 있음
import re
# <br> html 태그는 replace 함수로 공백으로 변환
review_df['review'] = review_df['review'].str.replace('<br />', ' ')
#파이썬의 정규 표현식 모듈인 re를 이용해 영어 문자열이 아닌 문자는 모두 공백으로 변환
review_df['review'] = review_df['review'].apply(lambda x : re.sub('[^a-zA-Z]', ' ', x))
from sklearn.model_selection import train_test_split
class_df = review_df['sentiment']
feature_df = review_df.drop(['id', 'sentiment'], axis=1, inplace=False)
X_train, X_test, y_train, y_test = train_test_split(feature_df, class_df, test_size=0.3, random_state=156)
X_train.shape, X_test.shape
예측 성능 평가는 이진 분류임을 고려해 테스트 데이터 세트의 정확도와 ROC-AUC를 모두 측정
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, roc_auc_score
#스톱 워드는 Enlglish, filtering, ngram은 (1,2)로 설정해 CountVectorization 수행
#LogisticRegression의 C는 10으로 설정
pipeline = Pipeline([('cnt_vect', CountVectorizer(stop_words='english', ngram_range=(1,2))),
('lr_clf', LogisticRegression(solver='liblinear', C=10))])
#Pipeline 객체를 이용해 fit(), predict()로 학습/예측 수행. predict_proba()는 roc_auc 때문에 수행
pipeline.fit(X_train['review'], y_train)
pred = pipeline.predict(X_test['review'])
pred_probs = pipeline.predict_proba(X_test['review'])[:,1]
print(accuracy_score(y_test, pred), roc_auc_score(y_test, pred_probs)
비지도학습 기반 감성 분석 소개
- Lexicon을 기반
많은 감성 분석용 데이터는 결정된 레이블 값을 가지고 있지 않음, 이러한 경우에 Lexicon이 유용하게 사용됨
한글을 지원하는 Lexicon은 없음
Lexicon은 감성 사전이며 긍정 감성 또는 부정 감성의 정도를 의미하는 수치를 가지고 있음 -> 감성 지수(polarity score)
감성 지수는 단어의 위치나 주변 단어, 문맥, POS(part of speech) 등을 참고해 결정됨
NLTK는 많은 서브 모듈을 가지고 있으며 그 중에 감성 사전인 Lexicon 모듈도 포함돼 있음
Wordent은 단순한 어휘 사전이 아닌 시맨틱 분석을 제공하는 어휘 사전
Wordnet은 다양한 상황에서 같은 어휘라도 다르게 사용되는 어휘의 시맨틱 정보를 제공하며, 이를 위해 각각의 품사로 구성된 개별 단어를 Synset(Sets of congitive synonyms)이라는 개념을 이용해 표현
Synset은 단순한 하나의 단어가 아니라 그 단어가 가지는 문맥, 시맨틱 정보를 제공하는 WordNet의 핵심 개념
NLTK의 감성 사전이 감성에 대한 훌륭한 사전 역할을 제공한 것은 맞지만, 아쉽게도 예측 성능이 그리 좋지 못함
따라서 NLTK 패키지가 아닌 다른 감성 사전을 적용하는 것이 일반적 : SentiWordNet, VADER, Pattern
SentiWordNet을 이용한 영화 감상평 감성 분석
1. 문서(Document)를 문장(Sentence) 단위로 분해
2. 다시 문장을 단어(Word) 단위로 토큰화하고 품사 태깅
3. 품사 태깅된 단어 기반으로 synset 객체와 senti_synset 객체 생성
4. Senti_synset에서 긍정 감성/부정 감성 지수를 구하고 이를 모두 합산해 특정 임계치 값 이상일 때 긍정 감성으로, 그렇지 않을 때는 부정 감성으로 결정
SentiWordNet을 이용하기 위해서 WordNet을 이용해 문서를 다시 단어로 토큰화한 뒤 어근 추출(Lemmatization)과 품사 태깅(POS Tagging)을 적용해야 함
VADER를 이용한 감성 분석
- 소셜 미디어의 감성 분석 용도로 만들어진 룰 기반의 Lexicon
VADER를 이용하면 매우 쉽게 감성 분석 수행 가능
from nltk.sentiment.vader import SentimentIntensityAnalyzer
senti_analyzer = SentimentIntensityAnalyzer()
senti_scores = senti_analzer.polarity_scores(train_df['review'][0])
print(senti_scores)
감성 사전을 이용한 감성 분석 예측 성능을 지도 학습 분류 기반의 예측 성능에 비해 아직은 낮은 수준이지만 결정 클래스 값이 없는 상황을 고려한다면 예측 성능에 일정 수준 만족할 수 있을 것