Eggs Sunny Side Up
본문 바로가기
Computer Engineering/머신러닝

영화리뷰 분석

by guswn100059 2023. 6. 20.

데이터 다운로드 받는 사이트

http://ai.stanford.edu/~amaas/data/sentiment/


ROC곡선

- 임계값을 0 ~ 1까지 변화시켜 가면서

   x축 : 가짜 양성비율(FPR),

   y축 : 진짜 양성비율(TPR)을 표시해서 그린 곡선

- 임계값 변환에 따른 양성/음성 분류여부가 달라지고 ROC곡선도 달라짐

- ROC 곡선 아래 면적 --> AUC(Area Under the Curve)

- AUC 값이 1에 가까울수록 분류 모델의 성능이 좋다고 평가


### 문제정의
- 영화 리뷰데이터를 활용해서 긍정, 부정의 감성분석을 해보자
- 텍스트 데이터를 다루는 방법을 이해하자

### 데이터 수집
- 웹페이지에서 다운로드

# 파일을 읽어들이는 함수
from sklearn.datasets import load_files

# 데이터 폴더 경로를 기준으로 명시
train_data_url = './data/aclImdb/train/'
test_data_url = './data/aclImdb/test/'

review_train = load_files(train_data_url, shuffle=True) 
# shuffle=True : 데이터가 몰려있을 수 있으므로 석어서 가져오는 방법

review_test = load_files(test_data_url, shuffle=True)

review_train

review_train.keys()

# 부정 : 0, 긍정 : 1, 만약 2가 출력되면? unsup폴더를 삭제하지 않아서
review_train['target']

### 데이터 전처리

review_train['data'] # 실제 분석할 값들
len(review_train['data']) # 데이터 길이 확인
review_train['data'][0] # 첫번째 데이터 가져와서 확인하기

# 왜 데이터를 가져와서 확인해?
# 필요한 태그와 불필요한 태그를 구별하기 위해서
# 불필요한 <br/> 태그 제거

# 문장 처음의 'b' : 바이트 자료형을 명시한 것으로 삭제하면 X

#### 태그 제거
- br

review_train['data'][0].replace(b'<br />', b" ")
# 정규표현식 : 영어만 남기거나, 영어만 지우거나, 숫자만 지우거나
# 파이썬 ==> import re

##### 리스트 내포

# br 태그 없앤 걸 담아주기
text_train = [txt.replace(b'<br />', b" ") for txt in review_train['data']]
text_test = [txt.replace(b'<br />', b" ") for txt in review_test['data']]

# 내포를 사용하지 않을 경우의 코드
# txt_train = []
# for txt in review_train['data'] :
#     txt_train.append(txt.replace(b'<br />', b" "))

len(text_train)

# 텍스트 데이터의 특성상 전처리를 하면 데이터의 특성이 늘어나게 됨.
# ==> 데이터가 커진다는 의미
# 데이터의 범위(갯수)를 줄여서 사용 --> 1000개만
# 문제데이터 (전처리(br) 식제완료)
text_train = text_train[:1000] 
text_test = text_test[:1000]

# 정답 데이터
y_train = review_train['target'][:1000]
y_test = review_test['target'][:1000]

#### 토큰화 및 특징값 추출
- BOW(Bag of Words) --> 토큰화와 특징값 추출을 한번에 처리하는 함수
    - 단어 기준으로 토큰화
    - 어떤 단어가 긍정/부정에 영향을 많이 끼치는지 확인

from sklearn.feature_extraction.text import CountVectorizer

# BOW 함수 받아오기
testCV = CountVectorizer()

test_words = ['hello world', 'JONNA noisy.', 'loooose', 'angry앵구리!!!']

# 어떤 것을 토큰으로 만들어야 하는지 결정
# 토큰들을 사전화
testCV.fit(test_words)

# 띄어쓰기를 기준으로 만들어진 토큰 사전 확인
testCV.vocabulary_

# 수치화
testCV.transform(test_words).toarray()

test_words

##### 실제 데이터에 적용하기

movie_bow = CountVectorizer(max_df=3000, min_df=10, ngram_range=(1, 3))

# 토큰사전 구축 - 학습
movie_bow.fit(text_train)

len(movie_bow.vocabulary_)

X_train = movie_bow.transform(text_train)
X_test = movie_bow.transform(text_test)

X_train

#### 토큰화 + 모델학습 --> 한 번에 진행하기
- 3 ~ 6단계 한 번에 진행(4단계는 생략)
- Pipeline : 기능들을 연결
- BOW(CountVectorizer) + SVM(LinearSVC)

from sklearn.pipeline import make_pipeline
from sklearn.svm import LinearSVC

pipe_model = make_pipeline(CountVectorizer(), LinearSVC())

# 학습
pipe_model.fit(text_train, y_train)

##### Pipeline 예측

pipe_model.predict(text_test)

##### GridSearch

from sklearn.model_selection import GridSearchCV

grid_params = {
    'countvectorizer__min_df' : [10,20,30],
    'countvectorizer__max_df' : [3000,5000,7000],
    'countvectorizer__ngram_range' : [(1,1),(1,2),(1,3)],
    'linearsvc__C' : [0.01,0.1,1,10,100]
}

grid_model = GridSearchCV(pipe_model, grid_params, cv=3)

grid_model.fit(text_train, y_train)

grid_model.best_params_

grid_model.predict(text_test)

### 탐색적 데이터 분석
- 문장에 단어가 몇 번 나왔는지 별 의미가 없는 분석단계로 생략.

### 모델 선택 및 하이퍼 파라미터 튜닝

from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import LinearSVC

tree_model = DecisionTreeClassifier()
svm_model = LinearSVC()

#### 교차검증
- 잘 나오는 모델을 사용하기 위해서

from sklearn.model_selection import cross_val_score

cross_val_score(tree_model, X_train, y_train, cv=5).mean()

cross_val_score(svm_model, X_train, y_train, cv=5).mean()

### 학습

svm_model.fit(X_train, y_train)

### 평가

svm_model.score(X_train, y_train)

svm_model.score(X_test, y_test)

#### 예측

# 예측할 데이터 만들기
reviews = ['This movie is so good', 'Fantastic movie', 'bad']

# 토큰화, 수치화
review_trans = movie_bow.transform(reviews)

# 학습 데이터에서 진행한 전처리를 동일하게 진행해줘야 함

svm_model.predict(review_trans)

### 어떤 단어가 긍정/부정에 영향을 줬는지 알아보자

# 필요한 것
# 1. 단어(특성)에 대한 가중치 - svm 모델이 가지고 있음
svm_model.coef_
word_weights = svm_model.coef_[0]
word_weights

# 2. 단어의 순서(토큰 사전)
voca = movie_bow.vocabulary_
voca

# DataFrame으로 구성
import pandas as pd

df = pd.DataFrame([voca.keys(), voca.values()])

# 번호를 인덱스로 사용하기 위해 전치, 행과 열을 뒤집겠다.
df = df.T

# 1번 컬럼을 기준으로 정렬
df = df.sort_values(by=1)

# 가중치(coef) 컬럼 추가
df['coef'] = word_weights

df = df.sort_values(by='coef', ascending=False)
df

# 긍정에 가장 많은 영향을 끼친 단어들
df.head(10)

# 부정에 가장 많은 영향을 끼친 단어들
df.tail(10)

 

 

 

 

 

 

 

 

 

 

 

 

 

댓글