머신러닝 언어처리 – R로 WordCloud 만들어보기

머신러닝에서 가장 고난이도 작업이 언어 처리고 그 중에서도 더 고난이도 작업이 자연어 처리다. 언어처리를 제대로 하기 위해서 한국말 같이 조사가 많이 들어가는 언어는 조사와 명사, 동사를 구분해내야하고, 또 어떤 쓰임새로 쓰였는지도 모델 내에서 소화해야한다. 여기서 자연어 처리로 한 단계 더 넘어가면, 이 단어가 이 문장에서 단어 그대로의 의미로 쓰였는지, 아니면 비꼬는 표현인지도 알아내야하고, 결국 문맥이라는 걸 볼 수 밖에 없다. 쉽게 이야기하면, 인공지능의 성능이 매우 좋아야한다. 그리고 그런 퀄리티의 인공지능을 만나기가 쉽지 않다. 당장 구글 번역기에 비꼬는 표현 하나 넣고 실험해보라.

앞 문장은 번역을 잘 했는데, 뒷 문장에 숨겨진 의미, 즉 앞 문장의 질문을 부정적으로 보는 의미는 제대로 못 잡아내고 있다.

이걸 더 잘하게 하는 방법을 가르쳐달라면 필자도 도망갈 수 밖에 없고, 그냥 언어 처리에서 가장 쉬운 예제 하나를 소개하는 걸로 대신할까 한다.

 

1. WordCloud 만들기

간단하게 구글만 검색해도 Free가 붙은 WordCloud 만들어주는 웹사이트들이 많다. 그래서 이런 예제가 큰 도움이 될까 생각했는데, 지난번에 올린 페이스북 유저 데이터를 어떻게 분석에 활용하냐는 질문을 받고, 우선 가장 쉽게 해 볼 수 있는 Data Visualization으로 좋은 예제인 것 같아 골라봤다.

당연히 R에도 WordCloud에 관련된 패키지가 있고, 사용법도 쉽다. 우선 필요한 패키지들을 인스톨하자

 
install.packages("tm", "SnowballC", "wordcloud", "RcolorBrewer")
library(tm)
library(SnowballC)
library(wordcloud)
library(RColorBrewer)

tm은 텍스트 마이닝, SnowballC는 이 단어들을 뭉쳐줄 수 있는 패키지, 그리고 wordcloud는 당연히 불러온 단어들을 WordCloud로 만들어주는 패키지다.

단어들은 이전에 설명한 페이스북 유저 데이터를 직접 써도 되고, 저장된 CSV 파일이나 TXT 파일을 써도 된다.

데이터 링크

 
filePath <- 'http://datascienceplus.com/wp-content/uploads/2015/08/JEOPARDY_CSV.csv'
text <- readLines(filePath)
jeopQ <- read.csv(filePath, stringsAsFactors = FALSE)

 

제일 상단 코드는 CSV 파일을 불러오는 경우고, 파일명을 txt로 바꾼 경우는 두번째 라인으로, CSV 파일이면 세번째 라인으로 데이터를 불러오면 된다.

자 이제 데이터를 Corpus로 만들어 보자. Corpus는 뭐 대단한건 아니고, 단어들의 뭉텅이라고 생각하면 된다.

 
jeopCorpus <- Corpus(VectorSource(jeopQ$Question))
jeopCorpus <- tm_map(jeopCorpus, PlainTextDocument)

단어들을 뭉텅이로 만든다음, Text 문서로 변경했다. VectorSource라는 명령어는 단어들을 Vector로 바꿔주는거다. 이제 데이터가 잘 들어갔는지 확인하기 위해서

 
inspect(jeopCorpus)

그리고 단어가 아닌 내용들 (예, !,@,#,$ 같은 특수 문자들)을 제거하자.

 
toSpace <- content_transformer(function (x , pattern ) gsub(pattern, " ", x))
jeopCorpus <- tm_map(jeopCorpus, toSpace, "/")
jeopCorpus <- tm_map(jeopCorpus, toSpace, "@")
jeopCorpus <- tm_map(jeopCorpus, toSpace, "\\|")

toSpace라는 명령어를 만들어서, 지정하는 특수문자들을 제거하도록 했다.

이제 마침표나 i.e., etc. 같은 “단어” 추적에 별로 도움이 안 되는 단어를 정리해보자.

 
jeopCorpus <- tm_map(jeopCorpus, removePunctuation)
jeopCorpus <- tm_map(jeopCorpus, removeWords, stopwords('english'))
jeopCorpus <- tm_map(jeopCorpus, contents_transformer(tolower))
jeopCorpus <- tm_map(jeopCorpus, removeNumbers)

여기서 stopwords(‘english’)는 영어 문장에 들어가는 i.e., etc. 같은 표현들을 말한다. (심심해서 Korean 넣어봤는데 작동 안 하더라.) 아래 두 줄은 대문자를 소문자로 바꾸는 명령어와 번호를 제거하는 명령어다.

만약에 ‘the’나 ‘this’ 같은 표현을 없애고 싶으면 아까 stopwords(‘english’) 를 썼던 표현을 살짝 바꾸면 된다.

 
excludes <- c('the', 'this', stopwords('english'))
jeopCorpus <- tm_map(jeopCorpus, removeWords, excludes)

이제 영어 표현에서 과거형, 진행형 등을 만드는 ‘ed’, ‘ing’ 같은 표현들을 정리해야한다. 이걸 영어에서는 ‘stemming’이라고 표현하더라.

 
jeopCorpus <- tm_map(jeopCorpus, stemDocument)

어느정도 정리할만큼 다 정리한 것 같으니까 이제 단어들을 wordcloud로 만들어보자.

 
wordcloud(jeopCorpus, max.words = 100, min.freq = 5, random.order = FALSE, rot.per = 0.1, colors = brewer.pal(8, "Dark2")) 

max.words = 100은 최대 100개의 단어를 고르는 옵션이고, min.freq = 5는 최소한 5번 이상 나온 단어, random.order = FALSE 는 제일 많이 나온 단어가 먼저나오도록 지정하는 옵션이다. 많이 나오고 적게 나오고 이런게 안 중요하면 TRUE로 바꾸면 된다. rot.per는 단어들 중 세로로 나오는 단어의 비율이다. 마지막으로 colors는 지정 안 하면 검은색 글자만 나오는데, 여러가지 옵션을 지정해서 Frequency에 따라서 다른 색이 나오게 할 수 있다. 색상 옵션에 대해서 더 궁금하면 여기 를 참고 하시라.

 

2. 추가 옵션

이제 Term-Document 매트릭스를 하나 만들어보자.

 
dtm <- TermDocumentMatrix(jeopCorpus)
m <- as.matrix(dtm)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
head(d, 10)

상위 10개 단어와 그 단어가 몇 번이나 나왔는지 간단한 표가 R console에 나올 것이다.

비슷한 맥락으로, 최소 n번 나온 단어들 목록을 뽑고 싶으면,

 
findFreqTerms(dtm, lowfreq = n)

특정 단어와 얼마나 자주 함께 나왔는지를 따지고 싶으면, (corlimit은 상관관계의 최소값을 지정한다.)

 
findAssocs(dtm, terms = "특정단어", corlimit = 상관관계 최소값)

자주 나오는 단어들 목록을 뽑아서 그래프를 그려보면,

 
barplot(d[1:10,]$freq, las = 2, names.arg = d[1:10,]$word, col ="lightblue", main ="Most frequent words", ylab = "Word frequencies")

상위 10개 단어들이 몇 번이나 등장했는지 그래프가 나온다.

You may also like...

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다