본문 바로가기

R

[R] 머신러닝 - Naive Bayes로 학습 후 분류

머신러닝(machine learning)

: 인간의 학습 능력과 같은 기능을 컴퓨터가 하게 만드는 기술로

인공지능(AI) 연구분야의 하나이다.
*인공지능이란 인간이 원래 가지고 있는 지적 능력을 컴퓨터가 하게 만드는 기술
분류 : 주어진 데이터 분류
예측 : 과거의 수치를 기반으로 미래의 수치 예측
군집 : 데이터를 비슷한 집합으로 모으는 작업

 

지도학습(supervised learning)

: 레이블(정답)이 달려 있고 정해져 있는 데이터를 가지고 학습
예) 이미지학습

개/고양이, 스팸/햄, 긍정/부정, 시험성적예측, 로또예측, 주가예측
<분류, 예측>


비지도학습(unsupervised learning)

: 레이블(정답)이 없는 데이터를 학습을 통해 군집한다.
유사한 뉴스를 그룹으로 모으는 학습

<군집>

    문장                 레이블(정답)
오늘은 행복하다.        긍정
...


확률

: 어떤 사건이 발생할 기대값
일어날 가능성에 대해서 하는 말을 수치로 표현

0~1 사이 숫자로 표현한 값

Marginal Probability(한계확률,주변확률)

: 아무런 조건이 없는 상태에서 A라는 사건이 발생할 확률. P(A)
행과 열의 합을 빈도 전체합으로 나누면 한계확률을 구할 수 있다.
예) 

<<교차표>>

  만족 보통 불만족 행의 합 한계확률
여성 0 4 2 6 0.6
남성 2 1 1 4 0.4
열의 합 2 5 3 10  
한계확률 0.2 0.5 0.3    

P(여성) = 0.6
P(만족) = 0.2

 

결합확률(join probability)

: 두개 이상의 사건이 동시에 발생할 가능성을 나타내는 확률. P(A∩B)
사건 A와 사건 B가 동시에 발생할 확률

예) 위 교차표에서 10명중에서 남성이면서 만족할 확률은? 0.2(2/10)

 

조건부확률(conditional probability)

: 이미 하나의 사건이 발생한 상태에서 또 다른 사건이 발생할 가능성을 나타내는 확률. P(A|B)
예) 위 교차표에서 남성이라는 조건 하에서 만족일 확률? 

 P(만족|남성) =   P(남성∩만족)/P(남성) =  2/10 / 4/10  = 0.5
       


나이브베이즈(Naive Bayes)

: 데이터를 나이브(단순)하게 독립적인 사건으로 가정하고

이 독립사건들을 베이즈 이론에 대입시켜 가장 높은 확률의 레이블로 분류하는 알고리즘

 

사전에 알고 있는 정보(예측변수)를 바탕으로 어떤 사건(결과변수)이 발생할 확률을 계산
사건에 해당하는 결과변수는 범주형 변수이어야 하며 예측변수는 범주형 변수를 가정한다.

예) 복권이라는 단어가 있을 경우에 스팸일 확률? P(스팸|복권)  

P(스팸|복권) : 사후확률, 이벤트가 발생 후 확률
P(복권|스팸) : 우도(likelhood), 가능성(어떤 일이 있을 공산)
P(스팸) : 사전확률, 이벤트가 발생 전 확률
P(복권) : 주변우도(marginal likelhood), 확률변수가 아닌 상수로 고려

단어 복권 백만 수신취소
여부 YES NO YES NO YES NO  
스팸 3 19 11 11 13 9 22
2 76 15 63 21 57 78
5 95 26 74 34 66 100

스팸메일에서 복권=yes, 백만=no, 수신취소=yes 일 확률은?

ㄱ : 여집합

P(복권∩ㄱ백만∩수신취소)  =  P(복권∩ㄱ백만∩수신취소|스팸) * P(스팸) + P(복권∩ㄱ백만∩수신취소|햄) * P(햄)
P(복권∩ㄱ백만∩수신취소|스팸) =  P(복권|스팸) * P(ㄱ백만|스팸) * P(수신취소|스팸) 
P(복권∩ㄱ백만∩수신취소|햄 =  P(복권|햄) * P(ㄱ백만|햄) * P(수신취소|햄)

 

P(A|B) = P(B|A) * P(A) / P(B)

P(A|B) P(B|A) * P(A)

P(스팸|복권∩ㄱ백만∩수신취소) ∝ P(복권∩ㄱ백만∩수신취소|스팸) * P(스팸)

                                                                    P(복권|스팸) * P(ㄱ백만|스팸) * P(수신취소|스팸) * P(스팸)

                                                                          (3/22)       *         (11/22)      *          (13/22)         * (22/100) 

                                                                   = 0.008863636

 

P(햄|복권∩ㄱ백만∩수신취소) ∝ P(복권∩ㄱ백만∩수신취소|햄) * P(햄)
                                                                P(복권|햄) * P(ㄱ백만|햄) * P(수신취소|햄) * P(햄)
                                                                     (2/78)   *      (63/78)     *        (21/78)       * (78/100)

                                                                = 0.004349112

 

+) 라플라스 보정(Laplace estimator)

: 확률값이 0이 나오지 않도록 작은 값으로 보정한다. (1로 보정)
전체에 대한 값은 보정 X 


[문제217] 비아그라=YES,돈=NO,식료품=NO,주소삭제=YES일때 스팸일 확률을 구하세요.

단어 비아그라 식료품 주소삭제
여부 YES NO YES NO YES NO YES NO  
스팸 4 16 10 10 0 20 12 8 20
1 79 14 66 8 72 23 57 80
5 95 24 76 8 92 35 65 100
비아그라=YES,돈=NO,식료품=NO,주소삭제=YES일때 스팸일 확률 = P(스팸|비아그라∩ㄱ돈∩ㄱ식료품∩주소삭제)   

P(스팸|비아그라∩ㄱ돈∩ㄱ식료품∩주소삭제) 
= P(비아그라|스팸) * P(ㄱ돈|스팸) * P(ㄱ식료품|스팸) * P(주소삭제|스팸) * P(스팸) 
= (4/20) * (10/20) * (20/20) * (12/20) * (20/100) = 0.012

P(햄|비아그라∩ㄱ돈∩ㄱ식료품∩주소삭제)
= P(비아그라|햄) * P(ㄱ돈|햄) * P(ㄱ식료품|햄) * P(주소삭제|햄) * P(햄)
= (1/80) * (66/80) * (72/80) * (23/80) * (80/100) = 0.002134688 

P(스팸|비아그라∩ㄱ돈∩ㄱ식료품∩주소삭제) = 0.012 / (0.002134688 + 0.012) = 0.8489752

naiveBayes 모델

mail <- read.csv("c:/data/mail.csv",header = T)
head(mail)
str(mail)

#naiveBayes 모델
install.packages("e1071")
library(e1071)
nb <- naiveBayes(mail[1:4],mail$분류)

test <- data.frame('YES','NO','NO','YES')
names(test) <- names(mail[,1:4])
predict(nb,test)

[문제218] 비아그라=YES, 돈=NO, 식료품=YES, 주소삭제=YES 일때 스팸일 확률을 구하세요.

비아그라=YES, 돈=NO, 식료품=YES, 주소삭제=YES 일때 스팸일 확률 = P(스팸|비아그라∩ㄱ돈∩식료품∩주소삭제) 

P(스팸|비아그라∩ㄱ돈∩식료품∩주소삭제) 
= P(비아그라|스팸) * P(ㄱ돈|스팸) * P(식료품|스팸) * P(주소삭제|스팸) * P(스팸) 
= (5/24) * (11/24) * (1/24) * (13/24) * (20/100) = 0.0004310137 → 라플라스 보정

P(햄|비아그라∩ㄱ돈∩식료품∩주소삭제)
= P(비아그라|햄) * P(ㄱ돈|햄) * P(식료품|햄) * P(주소삭제|햄) * P(햄)
= (2/84) * (67/84) * (9/84) * (24/84) * (80/100) = 0.000465084

P(스팸|비아그라∩ㄱ돈∩식료품∩주소삭제) = 0.0004310137/ (0.0004310137+0.000465084) = 0.4809896
P(햄|비아그라∩ㄱ돈∩식료품∩주소삭제) = 0.000465084 / (0.0004310137+0.000465084) = 0.5190104

naiveBayes 모델

mail <- read.csv("c:/data/mail.csv",header = T)
head(mail)
str(mail)

#naiveBayes 모델
install.packages("e1071")
library(e1071)
nb <- naiveBayes(mail[1:4],mail$분류)

test <- data.frame('NO','NO','NO','YES')
names(test) <- names(mail[,1:4])
predict(nb,test)

[문제219] 메일안에 복권이라는 단어가 있을 경우에 스팸일 확률은?

P(스팸) = 0.22 , P(복권|스팸) = 0.136 , P(복권|햄) = 0.025

P(복권) = P(복권|스팸) * P(스팸) + P(복권|햄) * P(햄)
        = (0.136*0.22)+(0.025*(1-0.22)) = 0.04942
P(스팸|복권) = (0.136*0.22)/ 0.04942 = 0.6054229

[문제220] 영화 장르를 분류해주세요.

movie <- read.csv("c:/data/movie.csv",header = T)
head(movie)

#학습데이터(80%), 테스트데이터(20%) 무작위 분리
idx <- sample(2,nrow(movie),replace = T,prob = c(0.8,0.2)) #replace = T 복원 추출
idx
length(idx)
table(idx)

#학습데이터(80%=1)
movie_train <- movie[idx==1,1:5]
nrow(movie_train)

#테스트데이터(20%=2) 
movie_test <- movie[idx==2,1:5]
nrow(movie_test)

#학습데이터 정답
movie_train_labels <- movie[idx==1,6]
length(movie_train_labels)

#테스트데이터 정답
movie_test_labels <- movie[idx==2,6]
length(movie_test_labels)

#naiveBayes
nb <- naiveBayes(movie_train,movie_train_labels,laplace = 1) #laplace : 라플라스 보정 옵션

test_predict <- predict(nb,movie_test)
sum(test_predict==movie_test_labels)/length(movie_test_labels)

install.packages("gmodels")
library(gmodels) #x=정답, y=예측
gmodels::CrossTable(x=movie_test_labels,y=test_predict,prop.chisq = T, #prop.chisq : 카이제곱검정
                    dnn=c('실제','예측')) #dnn : dimnames names을 부여할 때 사용

+) sample(뽑고자 하는 후보군, 뽑을 갯수, 추출 방법, 확률 정보) : 무작위 추출 함수
replace = F 비복원 추출(뽑은건 다시 넣지 않음)
replace = T 복원 추출(뽑은걸 다시 모집단에 넣음)

 

++) gmodels::CrossTable(x = 정답, y = 예측, prop.chisq = 카이제곱검정, dnn = names)

 

[문제221] spam메일과 ham메일을 분류 해주세요.

library(stringr)
library(tm)
sms <- read.csv("c:/data/sms_spam.csv",header = T)
head(sms)
str(sms)

#sms$text 확인
str_detect(sms$text,'www')
length(grep('www',sms$text))
as.vector(na.omit(str_extract(sms$text,'www\\S+')))
as.vector(na.omit(str_extract(sms$text,'(http|https)\\S+')))

#말뭉치 생성
sms_corpus <- VCorpus(VectorSource(sms$text))
lapply(sms_corpus[1:2],content)

#전처리시 사용할 함수 정의
convert <- content_transformer(function(x,pattern){
  return(gsub(pattern,' ',x))
})

#전처리
sms_corpus_clean <- tm_map(sms_corpus,content_transformer(tolower))
lapply(sms_corpus_clean[1:2],content)

sms_corpus_clean <- tm_map(sms_corpus_clean,convert,'(http|https)\\S+')
sms_corpus_clean <- tm_map(sms_corpus_clean,convert,'www\\S+')
sms_corpus_clean <- tm_map(sms_corpus_clean,convert,'/|:|;|\\.|"|<|>|\\?|!')
sms_corpus_clean <- tm_map(sms_corpus_clean,convert,"'|%|&|\\^|\\$|%")
sms_corpus_clean <- tm_map(sms_corpus_clean,convert,'\\(|\\)')
sms_corpus_clean <- tm_map(sms_corpus_clean,removeWords,tm::stopwords())
sms_corpus_clean <- tm_map(sms_corpus_clean,removeNumbers)
sms_corpus_clean <- tm_map(sms_corpus_clean,stripWhitespace)
lapply(sms_corpus_clean[1:10],content)

#DTM 생성
sms_dtm <- DocumentTermMatrix(sms_corpus_clean,control = list(wordLengths=c(2,Inf)))
inspect(sms_dtm)
as.matrix(sms_dtm)

 

#학습데이터(80) 테스트데이터(20) 분리
idx <- sample(2,nrow(sms_dtm),replace=T,prob=c(0.8,0.2))
sms_dtm[1,]

#학습데이터
sms_dtm_train <- sms_dtm[idx==1,]
inspect(sms_dtm_train)

#테스트데이터
sms_dtm_test <- sms_dtm[idx==2,]
inspect(sms_dtm_test)

#학습데이터 정답
sms_dtm_train_labels <- sms[idx==1,1]
length(sms_dtm_train_labels)

#테스트데이터 정답
sms_dtm_test_labels <- sms[idx==2,1]
length(sms_dtm_test_labels)

#빈도수를 범주형 자료로 수정 0 : NO, 1 이상의 값 : YES
convert_count <- function(x){
  x <- ifelse(x>0,'YES','NO')
}

sms_train <- apply(sms_dtm_train,MARGIN = 2,convert_count) #margin = 2 :열방향으로 함수 적용
sms_train[1,]
sms_test <- apply(sms_dtm_test,MARGIN = 2,convert_count)
sms_test[1,]

sms_nb <- naiveBayes(sms_train,sms_dtm_train_labels)

test_predict <- predict(sms_nb,sms_test)
CrossTable(x=sms_dtm_test_labels, y=test_predict)

해석)

ham이나 spam으로 오분류 된 메일 : 9개

spam이나 ham으로 오분류 된 메일 : 10개

정확도 : (923+144)/1086 = 0.9825046

'R' 카테고리의 다른 글

[R] ngram, 토근화  (0) 2022.02.18
[R] 감성분석 예제 - 취임사 분석(군산대 감성분석사전)  (0) 2022.02.18
[R] 자연어 처리 - NLP  (0) 2022.02.16
[R] 감성분석  (0) 2022.02.16
[R] text mining  (0) 2022.02.15
Recent Posts
Popular Posts
Recent Comments