본문 바로가기

study

[Kaggle] IMDB 감정 분석 Part 1

오늘은 캐글 튜토리얼인 IMDB의 영화 리뷰 데이터의 감성분석을 진행해보고자 한다. 깃헙에 한글로 총 4파트로 나누어 친절하게 작성된 코드가 있어 참고고하여 정리해보았다. 아래 출처를 남겨두었다. 순서는 아래와 같다. 원문은 https://www.kaggle.com/c/word2vec-nlp-tutorial이다.

Tutorial Part 1 : Preprocessing & Bag Of Words modeling
Tutorial Part 2 : Word2Vec & Randomforest modeling
Tutorial Part 3 : Word2Vec & K-means algorithm
Tutorial Part 4 : TF-IDF & XGBoost algorithm
1. 데이터 수집
2. 데이터 정제
3. 모델링

 

1. 데이터 수집

캐글에서 "Bag of Words Meets Bags of Popcorn"이라는 제목의 대회를 들어가보면 데이터를 다운받을 수 있다. 추가로 ".tsv"라는 확장자명은 처음이라 당황했는데 Tab으로 구분한 파일이라는 뜻이다.

import pandas as pd

train = pd.read_csv('C:/Users/user/Github\Kaggle_IMDB movie review/labeledTrainData.tsv', header = 0, delimiter ='\t', quoting=3)
test = pd.read_csv('C:/Users/user/Github\Kaggle_IMDB movie review/testData.tsv', header = 0, delimiter ='\t', quoting=3)

train.head()
test.head()

우측부터 train, test dataset이고 각각 25,000 행을 가지고 있다.

 

1.1. 데이터 파악

데이터가 1이면 긍정적인 리뷰, 0이면 부정적인 리뷰이다. 또 자세히 보면 html 태그가 섞여 있는 것을 볼 수 있다. 전체 데이터를 보면 노이즈가 심하다.

 

1.2. 결측치 파악

train.isnull().sum()

 

2. 데이터 정제

기계가 텍스트를 이해할 수 있도록 텍스트를 정제해 준다. 신호와 소음을 구분한다. 아웃라이어데이터로 인한 오버피팅을 방지한다. 쉽게 말해 리뷰 데이터는 장문의 글인데, 그대로 기계에게 전달하면 알아먹지 못한다. 따라서 어떠한 기준에 따라 잘게 쪼개어 의미를 부여하여 전달해주어야한다. 그 전에 쓸모없거나 굳이 전달할 필요가 없는 데이터를 삭제하거나 수정 보완하는 것이다. 아래 나오는 모든 데이터 정제 과정은 train과 test data set 둘 다 적용한다.

1. BeautifulSoup을 통해 HTML 태그를 제거

2. 정규표현식으로 알파벳 이외의 문자를 공백으로 치환

3. NLTK 데이터를 사용해 Stopword를 제거

4. 문자열 처리

 

2.1. BeautifulSoup을 통해 HTML 태그를 제거

# HTML 태그 제거를 위한 모듈 설치
from bs4 import BeautifulSoup

# 예시로 첫번째 데이터만 실행
example1 = BeautifulSoup(train['review'][0], "html5lib")
example1.get_text()[:100] # 텍스트만 받아옴

전체 데이터를 보면 <br> 같은 태그가 제거되었음을 확인할 수 있다.

 

2.2. 정규표현식으로 알파벳 이외의 문자를 공백으로 치환

# 정규표현식을 사용하게 하는 모듈 설치
import re

# ^ : 시작을 의미, 알파벳 소대문자로 시작하는 문자만 추출
letters_only = re.sub('[^a-zA-z]',' ',example1.get_text())
letters_only[:100]

앞서 example1과 달리 '\'같은 특수문자가 공백으로 치환되었다.

 

영문의 대소문자 구분을 없애기 위해 모두 소문자로 변환

# 모두 소문자로 변환한다.
lower_case = letters_only.lower()

# 문자를 나눈다. => 토큰화
words = lower_case.split()
print(len(words))
words[:10]

 

2.3. NLTK 데이터를 사용해 Stopword를 제거

우선 NLTK란 "Natural Language Toolkit의 줄임말로 일반적으로 Python 프로그래밍 언어로 작성된 영어의 기호 및 통계 자연 언어 처리를위한 라이브러리 및 프로그램 모음입니다." 라고 한다. 위키참고

그리고 Stopword란, 우리말로 불용어라고 하는데 예측이나 분류하는데 크게 기여하지 않는 단어들을 말한다. 예를 들어 영어로 대화할때 "the, a,  to.." 등과 같은 단어들은 빈번하게 등장하지만 분석을 하는데에는 큰 기여를 하지 않는다. 따라서 이러한 단어들은 분석을 하기전에 미리 데이터에서 걸러내주어야 한다. 

import nltk
nltk.download('stopwords')

from nltk.corpus import stopwords
stopwords.words('english')[:10]

# 반복문을 이용하여 stopwords를 제거한 토큰들
words = [w for w in words if not w in stopwords.words('english')]

 

2.4. 사용자 정의함수로 문자열 처리

def review_to_words(raw_review):
    # 1. HTML 제거
    review_text = BeautifulSoup(raw_review, 'html.parser').get_text()
    # 2. 영문자가 아닌 문자는 공백으로 변환
    letters_only = re.sub('[^a-zA-Z]', ' ', review_text)
    # 3. 소문자 변환
    words = letters_only.lower().split()
    # 4. Stopwords를 세트로 변환
    # 파이썬에서는 리스트보다 세트로 찾는게 훨씬 빠르다.
    stops = set(stopwords.words('english'))
    # 5. Stopwords 제거
    meaningful_words = [w for w in words if not w in stops]
    # 6. 어간추출
    stemming_words = [stemmer.stem(w) for w in meaningful_words]
    # 7. 공백으로 구분된 문자열로 결합하여 결과를 반환
    return(' '.join(stemming_words))
    
# 예시로 첫 리뷰만 적용
clean_review = review_to_words(train['review'][0])
clean_review

 

이제 모든 리뷰 데이터에 적용하도록 반복문을 짜보았다.

# 5000개 단위로 상태를 찍도록 개선, test data set도 동일하게 적용
clean_train_reviews = []
for i in range(0,num_reviews) :
    if (i+1) % 5000 == 0:
        print('Review {} of {}'.format(i+1, num_reviews))
    clean_train_reviews.append(review_to_words(train['review'][i]))

 

좀 더 간결한 코드로, 사용자 정의 함수를 적용하고 기존 데이터 셋에 새 칼럼을 추가하여 넣어주었다. 

우측부터 train, test data set

 

3. 모델링

3.1. Scikit-Learn의 CountVectorizer

Scikit-Learn의 CountVectorizer를 통해 feature 생성한다. CountVectorizer는 다음과 같은 인수를 가질 수 있다. (CountVectorizer란 단어들의 출현 빈도로 여러 문서들을 벡터화)

stop_words : 문자열 {‘english’}, 리스트 또는 None (디폴트) (stop words 목록.‘english’이면 영어용 스탑 워드 사용)
analyzer : 문자열 {‘word’, ‘char’, ‘char_wb’} 또는 함수(단어 n-그램, 문자 n-그램, 단어 내의 문자 n-그램)
token_pattern : string(토큰 정의용 정규 표현식)
tokenizer : 함수 또는 None (디폴트) (토큰 생성 함수)
ngram_range : (min_n, max_n) 튜플(n-그램 범위)
max_df : 정수 또는 [0.0, 1.0] 사이의 실수. 디폴트 1(단어장에 포함되기 위한 최대 빈도)
min_df : 정수 또는 [0.0, 1.0] 사이의 실수. 디폴트 1(단어장에 포함되기 위한 최소 빈도)
출처 : https://datascienceschool.net
# 리뷰의 토큰을 피쳐로 변환
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.pipeline import Pipeline

# 튜토리얼과 다르게 파라미터 값을 수정
vectorizer = CountVectorizer(analyzer = 'word', 
                             tokenizer = None,
                             preprocessor = None, 
                             stop_words = None, 
                             min_df = 2, # 토큰이 나타날 최소 문서 개수
                             ngram_range=(1, 3),
                             max_features = 20000)

# 속도 개선을 위해 파이프라인을 사용하도록 개선
pipeline = Pipeline([('vect', vectorizer),])

# 벡터화
train_data_features = pipeline.fit_transform(clean_train_reviews)
train_data_features

 

 

벡터화한 피쳐를 데이터 프레임화하여 확인해보았다.

 

3.2. 랜덤포레스트

3.2.1. 모델 학습

from sklearn.ensemble import RandomForestClassifier

# 랜덤포레스트 분류기를 사용
forest = RandomForestClassifier(n_estimators = 100, n_jobs = -1, random_state=2018)
forest = forest.fit(train_data_features, train['sentiment'])

 

3.2.2. K-Fold 교차검증

모델을 적용하기전 train data set을 통해 교차 검증을 실시한다. K번 실시 후 그 평균을 보고 모델의 신뢰도를 판단한다. 해당 모델은 약 0.92가 나왔다.

model : 회귀 분석 모형
X : 독립 변수 데이터
y : 종속 변수 데이터
scoring : 성능 검증에 사용할 함수 이름
cv : 교차검증 생성기 객체 또는 숫자.
출처 : https://datascienceschool.net

 

from sklearn.model_selection import cross_val_score
score = np.mean(cross_val_score(forest,train_data_features,train['sentiment'], cv=10, scoring='roc_auc'))

 

3.2.3. 모델 적용

# test 데이터를 벡터화 함
test_data_features = pipeline.transform(clean_test_reviews)
test_data_features = test_data_features.toarray()

# 벡터화한 test 데이터를 넣고 예측한다.
result = forest.predict(test_data_features)

 

마치며..

BOW(Bag of words)의 한계

문서의 양이 많다면 필요한 벡터 수가 많아 비효율적이다. sparse vector는 계산량으로나 공간적으로 단점이다. 단순히 빈도 측정으로 글의 맥락과 관계없는 분석이라는 점이 한계이다. 또한 오탈자와 같은 단어를 엄밀히 정제해야 한다. 따라서 그렇지 못한 데이터는 사실상 분석하기 어렵다.

 

출처 : https://github.com/yunah0515

 

yunah0515 - Overview

yunah0515 has 16 repositories available. Follow their code on GitHub.

github.com

'study' 카테고리의 다른 글

Colab 시작하기  (0) 2020.03.26
러닛 - 자연어 처리 기초  (0) 2020.03.25
[Kaggle] IMDB 감정 분석 Part 1  (0) 2020.03.21
아파트 분양가격 동향  (0) 2020.03.19
스타벅스 이디야 매장 수 비교  (0) 2020.03.19
러닛 - 우주 최초 플립러닝 플랫폼  (0) 2020.03.16