프로그래밍/R

R을 이용한 텍스트 감성분석 | 영화리뷰 감성분석 해보기

bonong 2019. 2. 13. 21:45
반응형

 

 

 

영화 리뷰를 가지고 하나하나 리뷰를 명사로 추출하고 추출한 명사로 워드 클라우드를 만들었습니다

이번에는 영화 리뷰를 가지고 좀 더 리뷰를 쓸모 있게(?) 하기 위해

하나하나 리뷰를 감성사전으로 감성을 분석해 보겠습니다

 

데이터 준비

먼저 감성 분석을 하기 위해서는 데이터가 필요합니다

데이터는 이전에 영화리뷰를 크롤링한 데이터로 하겠습니다

 

R 기본으로 크롤러 만들기

 

데이터가 준비되면 데이터와 비교할 사전이 필요합니다

깃허브에 있는 군산대 감성사전을 쓰겠습니다

 

https://github.com/park1200656/KnuSentiLex

군산대 감성사전 다운로드

 

 

들어가게 되면 이런 화면이 뜨는데 저는 neg_pol_word.txt 와 pos_pol_word.txt 파일을 사용합니다

다운로드 받고 보기 좋게 neg_pol_word.txt 는 negative.txt 로 pos_pol_word.txt 는 positive.txt로 바꿉니다

그리고 파일을 열어서 출처와 단어수, 극성이 적혀있는것을 다 지워주고 저장합니다

 

위에 처럼 확인할 수 있습니다

군산대 감성사전에서는 미리 점수가 매겨져있는 사전도 있는데 그사전을 사용하려고 했지만

R에서 계속 오류가 나서 긍부정어를 다 1점으로 하고

각 문장에 대하여 긍정에서 부정을 빼는 방식으로 정했습니다

 

예를 들어

재미있지만 마지막 결말이 별로네요

이런 문장에서 재미있다는 긍정어 하나와 별로라는 부정어 하나가 있는데

1(재미) - 1(별로) = 0이 나와 중립이 되는 방식입니다

 

 

패키지 준비

감성분석에 필요한 패키지는

 

1
2
library(plyr)
library(stringr)
cs

 

두개가 있습니다

 

시작하기 전에는 항상 파일을 저장하고 가져올 폴더를 지정합니다

 

1
setwd("C://Temp")
cs

 

긍부정어 단어 파일을 setwd로 지정한 폴더에 넣어준다

 

 

감성분석

 

1
txt<-readLines("movie_review_Ext_J.txt")
cs

 

제일 먼저 데이터를 txt로 가져옵니다

 

 

1
2
3
4
5
positive <- readLines("positive.txt", encoding = "UTF-8")
positive=positive[-1]
 
negative <- readLines("negative.txt", encoding = "UTF-8")
negative=negative[-1]
cs

 

다음으로 감성사전에서 가져온 positive.txt 와 negative.txt 를 변수에 불러옵니다

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
sentimental = function(sentences, positive, negative){
  
  scores = laply(sentences, function(sentence, positive, negative) {
    
    sentence = gsub('[[:punct:]]', '', sentence) # 문장부호 제거
    sentence = gsub('[[:cntrl:]]', '', sentence) # 특수문자 제거
    sentence = gsub('\\d+', '', sentence)        # 숫자 제거
    
    word.list = str_split(sentence, '\\s+')      # 공백 기준으로 단어 생성 -> \\s+ : 공백 정규식, +(1개 이상)
    words = unlist(word.list)                    # unlist() : list를 vector 객체로 구조변경
    
    pos.matches = match(words, positive)           # words의 단어를 positive에서 matching
    neg.matches = match(words, negative)
    
    pos.matches = !is.na(pos.matches)            # NA 제거, 위치(숫자)만 추출
    neg.matches = !is.na(neg.matches)
    
    score = sum(pos.matches) - sum(neg.matches)  # 긍정 - 부정   
    return(score)
  }, positive, negative)
  
  scores.df = data.frame(score=scores, text=sentences)
  return(scores.df)
}
 
cs

 

어디서 가져온지 모르겠지만 구글링하다가 찾게 되었습니다

긍,부정어를 비교하는 함수인데 만든 사람 리스펙...

 

 

1
2
3
4
5
result=sentimental(txt, positive, negative)
 
result$color[result$score >=1] = "blue"
result$color[result$score ==0] = "green"
result$color[result$score < 0] = "red"
cs

 

저 함수를 이용해서 result 변수에 함수에 의해 분석한 결과가 들어갑니다

 

긍정은 1점이상 0점은 중립 부정은 0점 아래로 설정하기 위해

color에 긍정을 blue 중립은 green 부정은 red로 설정

> table(result$color)

 blue green   red 
  547  1693   161

 

1
2
3
result$remark[result$score >=1] = "긍정"
result$remark[result$score ==0] = "중립"
result$remark[result$score < 0] = "부정"
cs

 

이어서 1점이상은 긍정으로 0점은 중립으로 0점 아래는 부정이라고 설정합니다 

 

1
2
3
4
sentiment_result= table(result$remark)
 
pie(sentiment_result, main="감성분석 결과",
    col=c("blue","red","green"), radius=0.8)
cs

 pie(sentiment_result, main="감성분석 결과",

    col=c("blue","red","green"), radius=0.8)



> sentiment_result

긍정 부정 중립 
 547  161 1693

 

 

 

이렇게 결과가 나온다 하지만 이런 식으로 할 경우

5개의 영화리뷰를 감성분석한 결과 중립이 대다수를 차지합니다

아무래도 긍, 부정어에서 점수가 다 1점이라서 중립이 많이 생기는것 같습니다

 

중립을 빼고 볼때 영화 평점이 높을수록 긍정이 많이 있다.

하지만 예외도 있다 평점이 좋은 영화지만 슬픈분위기의 영화는 긍정과 부정이 거의 동일하게 나온다

 

 

 

 

 

 

 

 

반응형