본문 바로가기
R-텍스트마이닝

맛집리뷰 감성분석

by 미스터탁 2018. 4. 4.


###############데이터 다운로드

sample.zip


############R로하는 감성분석

############네이버 맛집 리뷰 데이터로서 0~5점 사이 척도로 scoring 되어있습니다.



setwd("C:\\taling\\감성분석") ## Working Directory 설정 

load("comments.RData") ## 데이터를 load합니다.

load("score.RData")



head(comments) ## 데이터 확인, length확인

head(score)

length(comments)

length(score)



sam<-sample(1:length(comments),5000) ## 5000개만 sampling해서 합니다. 전체데이터는 너무 많아서.

co_sam<-comments[sam]

score_sam<-score[sam]




#########################

##Supervised Learning방법으로 감성분석 하기

##이 예에서는 Lasso와 Ridge를 사용하지만 같은 형태로 다른 알고리즘을 사용하실 수 있습니다.



ibrary(stringr)

## 편의상 형태소 분석을 하지 않고 공백으로 분리하여 진행합니다.

ta<-table(unlist(str_split(co_sam," "))) 

head(ta,30)



ta2<-ta[ta> 20] ## 단어 빈도 20개이상인것들만 추출



df<-data.frame(matrix(0,ncol=length(ta2),nrow=length(sam))) ## Document Term Matrix 생성, 학습에 사용될 input data

colnames(df)<-names(ta2) ## 칼럼 name은 앞서 추출한 word들

head(df)

i<-1

for(i in 1:length(sam)){

  uu<-  unlist(str_split(co_sam[i]," ")) ##  review를 불러들여 공백으로 분리 후,

  df[i,which(colnames(df)  %in% uu)]<-1 ## 칼럼 name과 일치하는 index에 1 부여

  cat("\n",i)

}



df2<-df[!apply(df,1,sum)==0,] ## 모든 칼럼이 0인 경우는 학습에 필요하지 않으므로 제거

score_sam2<-  score_sam[!apply(df,1,sum)==0] ## Y에서도 제거

nrow(df2);length(score_sam2)


save(df2,file="df2.RData")   ## 저장

save(score_sam2,file="score_sam2.RData")

load("df2.RData")

load("score_sam2.RData")



new_score<-ifelse(score_sam2 >2.5,1,0) ## 2.5이상이면 긍정(1), 아니면 부정(0)




library(glmnet)

### 학습에 사용할 알고리즘(Lasso, Ridge) library 호출


sam2<-sample(1:length(new_score),length(new_score)*0.7) ## Train / Validation으로 나누기 위한 작업

fit1<-glmnet(as.matrix(df2[sam2,]),new_score[sam2],family="binomial",lambda=0.001,alpha = 1) ##  모델fitting 


## alpha 가 1일때 lasso

### lambda 값에 따라 계수들을 0으로 만듦

## alpha 가 0일때 ridge

### lambda 값에 따라 계수들을 0으로 수렴시키지만 완전히 0으로 만들지는 않음

### 예측면에서는 ridge가 일반적으로 좋고, 변수를 선택한다고 한다면 lasso가 좀더 좋음


pr<-predict(fit1,as.matrix(df2[-sam2,])) ## validation data prediction

pr2<-ifelse(pr>0,1,0) ## y값이 0이상이면 긍정(1) 그게 아니면 부정으로 판단.

sum(pr2==new_score[-sam2])/length(pr2) ## accuracy ## 정확도



fit1$beta #######회귀 계수 출력





#########################

##Dictionary 기반 방법으로 감성분석 하기

##기본적인 Dictionary 기반 감성분석은 사전을 직접 제작하여야하나, 편의상 위 회귀모델에서 회귀계수를 출력하여 그 회귀 값들을 사전이라고 간주하고 감성분석을 진행하겠습니다.


beta<-fit1$beta[,1]

posi<-beta[beta > 0] ### 긍정 단어

nega<-beta[beta<0]  ### 부정 단어


sort(posi,decreasing = T)[1:10] ## top 10개

sort(nega,decreasing = F)[1:10]


dic<-c(posi,nega) ## concat

save(dic,file="dic.RData") ##저장



load("comments.RData")

load("score.RData")


### supervised learning에 쓰인 review들로 만들어진 사전이기 때문에, 검증을 위해서 다른 (확률상) review를 추출합니다.

test_sam<-sample(1:length(comments),5000)

test_co<-comments[test_sam]

test_score<-score[test_sam]

length(dic)

library(stringr)

j<-1

cal_score<-NULL

for(j in 1:length(test_score)){

  upc<-  unlist(str_split(test_co[j]," ")) ## 각 리뷰들을 공백으로 분리후

  ma<-match(upc,names(dic)) ## 사전과 match 시켜서, matching되는 사전들의 계수의 합을 감성 값으로 계산!!

  cal_score<-c(cal_score,sum(dic[ma[!is.na(ma)]]))

  cat("\n",j)

}



pred<-ifelse(cal_score > 0,1,0) ## 0이상이면 긍정, 아니면 부정으로 판단

test_score2<-ifelse(test_score>2.5,1,0)

sum(pred==test_score2)/length(pred) ## 정확도 계산




cal_emotion<-function(x){ ### 함수화 

  upc<-unlist(str_split(x," "))

  ma<-match(upc,names(dic))

  dic[ma[!is.na(ma)]]

  score<-round(sum(dic[ma[!is.na(ma)]]),1)

  score2<-ifelse(score>0,"긍정","부정")

  return(paste(c("감성점수 값은 ", score,"로서 ",score2,"입니다 "),collapse=""))

}


cal_emotion(("이 집은 엄청 맛없네요 비추 최악"))







인프런 강의 할인 쿠폰 코드입니다.

R로 하는 웹 크롤링 - 입문편(할인쿠폰코드) 236-69fc51d93a53 
https://www.inflearn.com/course/R-crawling# 

R로 하는 웹 크롤링 - 실전편 (할인쿠폰코드) 237-55c672aeb038 
https://www.inflearn.com/course/R-crawling-2# 

R로 하는 텍스트마이닝 (Top keyword부터 감성분석까지) (할인쿠폰코드) 238-c86096730061 
https://www.inflearn.com/course/R-text-mining#



R로 무작정 해보는 data science (할인쿠폰코드) 310-c6164f3d9be9 
https://www.inflearn.com/course/R-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%82%AC%EC%9D%B4%EC%96%B8%EC%8A%A4-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EC%BD%94%EB%94%A9#


반응형

댓글