[분류] 스팸메일 분류기 만들기

2020. 11. 28. 21:22노트/R : 통계

베이즈정리 

$P(Yes | Sunny, normal)

=$ $P(Yes)*P(Sunny, normal|Yes) \over {P(Yes)* P(Sunny,normal|Yes) + P(No) * P(Sunny,normal|No)}$

 

데이터 

sms_spam_ansi.txt
0.46MB

 

 

 

# stringAsFactors = True : Factor 형태로 스트링을 읽겠다.


sms_raw<-read.csv("C:/Users/LG/Downloads/dataset_for_ml/dataset_for_ml/sms_spam_ansi.txt", stringsAsFactors = FALSE, )

sms_raw$type <-factor(sms_raw$type)

str(sms_raw$type)

# ham과 spam의 갯수 
table(sms_raw$type)

# tm 패키지: 텍스트마이닝 패키지 
install.packages("tm")
library(tm)

# 코퍼스: 단어 집합 생성 -> VCorpus()
# 데이터 소스 객체 생성 -> VectorSource() 

sms_corpus <-VCorpus(VectorSource(sms_raw$text))
sms_corpus

as.character(sms_corpus[[1]])

# 1번부터 5번까지 문서 내용 출력(lapply 함수 이용)
lapply(sms_corpus[1:5], as.character)

sms_corpus_clean<- tm_map(sms_corpus,tolower)
sms_corpus_clean<-tm_map(sms_corpus , content_transformer(tolower))

#class(as.character(sms_corpus_clean[[1]])) # charactor 

# 매킨토시 운영체제의 경우 아래와 같은 옵션을 read.csv함수에 추가할 것 
#fileEncoding = "CP949", encoding = "UTF-8"

# 숫자 제거 
sms_corpus_clean <-tm_map(sms_corpus_clean, removeNumbers)

sms_corpus_clean<- tm_map(sms_corpus_clean, removePunctuation)

inspect(sms_corpus_clean[1:5])
# 구두점 제거
removePunctuation("hi....hello...bye ")

# 불용어(stop words) 제거 
# 불용어 : to, and, but, or .... 
stopwords()

sms_corpus_clean <- tm_map(sms_corpus_clean, removeWords, stopwords())
replacePunctuation <-function(x){
  gsub("[[:punct:]]+"," ",x)
}

# x에 전달된 문자열에 대해 punctuation은 제거(" ")
replacePunctuation("hi+.{hello<;}")

>>> [1] "hi hello "
gsub("한국","코리아",x)
>>> [1] "코리아 조선 우리나라 민국 코리아"
gsub("한국","코리아",x)
>>> [1] "대한민국 조선 우리나라 민국 대한민국"
gsub("우리나라","코리아",x)
>>> [1] "대한민국 조선 코리아 민국 대한민국"
gsub("조선","코리아",x)
>>> [1] "대한민국 코리아 우리나라 민국 대한민국"

 

# 형태소 분석 
install.packages("SnowballC")
library(SnowballC)

# 단어의 어근을 추출 
wordStem(c("learn","learned","learning","learns"))
>>> [1] "learn" "learn" "learn"
>>> [4] "learn"
# stemDocument함수 : ㅔㄱ스트 문서의 전체 코퍼스에 wordstem을 적용 
sms_corpus_clean <-tm_map(sms_corpus_clean, stemDocument)

# 추가 여백 제거
sms_corpus_clean<-tm_map(sms_corpus_clean,stripWhitespace)

lapply(sms_corpus[1:3], as.character)

 

# 토큰화(단어)
# DocumentTermMatrix() : sms 메세지 코퍼스 -> 토큰화 
# 행:sms 메시지, 열: 단어 
# DTM 행렬 , TDM 행렬 

sms_dtm <-DocumentTermMatrix(sms_corpus_clean)

sms_dtm2 <- DocumentTermMatrix(sms_corpus, control = list(tolower = TRUE,
                                                          removeNumbers= TRUE,
                                                          stopwords = TRUE,
                                                          removePunctuation = TRUE,
                                                          stemming = TRUE))

sms_dtm_train <-sms_dtm2[1:4169,]
sms_dtm_test<-sms_dtm2[4170:5559,]

sms_train_labels <-sms_raw[1:4169,]$type
sms_test_labels<-sms_raw[4170:5559,]$type
install.packages("wordcloud")
library(wordcloud)

wordcloud(sms_corpus_clean,
          scale = c(5,0.2),
          min.freq = 50,
          rot.per = 0.1,
          random.color = T,
          colors = brewer.pal(4,"Paired"),
          random.order = FALSE)

spam<-subset(sms_raw, type=="spam")
ham <- subset(sms_raw, type =="ham")
wordcloud(spam$text , max.words = 40, scale= c(3,0.5))

wordcloud(ham$text, max.words=40, scale=c(3,0.5))

# 최소 5번 이상 등장한 단어 
sms_freq_words<-findFreqTerms(sms_dtm_train,5)

str(sms_freq_words)
# 행렬의 열/행 단위로 전달(apply, MARGIN= 1(행), 2(열))
# apply(sms_dt)

sms_dtm_freq_train <-sms_dtm_train[,sms_freq_words]
sms_dtm_freq_test <-sms_dtm_test[,sms_freq_words]

convert_counts<-function(x){
  x<-ifelse(x>0, "YES","NO")
}

# 열 단위로 함수에데이터를 전달 
sms_train <-apply(sms_dtm_freq_train,MARGIN=2, convert_counts)

sms_test<-apply(sms_dtm_freq_test,MARGIN=2,convert_counts)
# 나이브 베이지안 필터기 생성(모델)
install.packages("e1071")
library(e1071)

sms_classifier<-naiveBayes(sms_train,sms_train_labels)

sms_test_pred<- predict(sms_classifier,sms_test)

sms_test_pred

library(gmodels)

CrossTable(sms_test_pred, sms_test_labels, prop.t=FALSE, prop.r=FALSE,dnn=c('predicted','actual'))