반응형

안녕하세요


오늘은 연관규칙 Apriori 알고리즘에 대해 알아보도록 하겠습니다!



Q1. Apriori 알고리즘 이란?


A1. 간단한 성능 측정치를 이용해 거대한 데이터베이스에서 데이터간의 연관성을 찾는 알고리즘



Q2. 그래서 어떤 패턴을 찾는데?


A2. 연관규칙은 장바구니 분석에 가장 많이 사용됩니다. 하지만 잠재적인 패턴을 찾을 때 또한 유용합니다.



예시: "기저귀를 살 때 맥주를 함께 산다"


그림출처: 사람과 디지털연구소


연관 규칙을 통해 맥주와 기저귀라는 별 상관없어 보이는 상품의 동시 구매 패턴을 발견하였습니다.



Q3. 굳이 왜 ML(머신러닝)으로 패턴을 찾아야해?


A3. k개의 아이템으로 2개씩 아이템을 묶어 연관패턴을 찾으려면 평가해야할 2^k개의 아이템 집합을 갖습니다.

만약 아이템이 100개면 2의 100승개의 아이템 집합이 생기므로 사람이 그 많은 데이터를 직접분석하기는 어렵습니다.




연관규칙에서 사용하는 두가지 통계척도


1. 지지도: 데이터에서 발생하는 빈도

count(x)

support(x) = ----------------------

N


2. 신뢰도: 예측능력이나 정확도의 측정치

support(x,y)

confidence(x -> y) = ------------------------------

support(x)




기저귀와 맥주의 예시 코드를 생성하여 연관규칙 알고리즘에 대해 알아봅시다!


# 1. 데이터 로드 x <- data.frame( beer=c(0,1,1,1,0), bread=c(1,1,0,1,1), cola=c(0,0,1,0,1), diapers=c(0,1,1,1,1), eggs=c(0,1,0,0,0), milk=c(1,0,1,1,1) ) # x 확인하기

x # 2. arules 패키지를 설치한다. (apriori함수를 이용하기위해 설치) # install.packages("arules") library(arules) trans <- as.matrix(x,"Transaction") trans # 3. apriori 함수를 이용해서 연관관계를 분석한다. rules <- apriori(trans, parameter=list(supp=0.2, conf=0.6, target = "rules")) rules # support: 지지도, confidence:신뢰도, lift: 향상도, count inspect(sort(rules))


결과




신뢰도가 클수록 연관관계가 높다는 의미입니다.


연관규칙을 평가하는 지수는 사실 위에서 언급한 2가지말고도 많은데

그 중 꽤 많이 쓰이는 것이 상관관계를 나타내는 lift입니다.



추가 : 연관관계 시각화하기

# install.packages("sna") # install.packages("rgl") library(sna) library(rgl) #visualization b2 <- t(as.matrix(trans)) %*% as.matrix(trans) b2.w <- b2 - diag(diag(b2)) #rownames(b2.w) #colnames(b2.w) gplot(b2.w , displaylabel=T , vertex.cex=sqrt(diag(b2)) ,

vertex.col = "Pink" , edge.col="grey" , boxed.labels=F ,

arrowhead.cex = .3 , label.pos = 3 , edge.lwd = b2.w*2)


결과



마지막으로, 연관규칙 학습을 위한 에이 프라이어리 알고리즘의 장단점을 알아보겠습니다.


장점1. 대규모 거래 데이터에서 작업할 수 있다.


장점2. 이해하기 쉬운 규칙을 생성한다.


장점3. '데이터 마이닝'과 데이터 베이스에서 예상치 못한 지식을 발굴하는 데 유용하다.


---------------------------------------------------------------------------------


단점1. 작은 데이터 셋에서는 유용하지 않을 수 있다.


단점2. 랜덤 패턴에서 비논리적 결론을 도출하기 쉽다.





오늘은 여기까지!!


다음은 k-means알고리즘으로 돌아오겠습니다!!

반응형
반응형



안녕하세요


오늘은 수치분석의 꽃 회귀분석에 대해 알아보도록 하겠습니다.(개인적인 생각임ㅎ)



회귀란?


유전학자 프린시스 골턴이 유전의 법칙을 연구하다가 나온 명칭으로


아버지의 키가 크다고 할지라도 아들의 키는 아들세대의 평균으로 접근하는 경향이 있다.


즉 평균으로의 회귀를 의미합니다.


회귀분석은 하나의 종속변수가 나머지 다른 독립변수들과의 어떠한 관계를 갖는가를 분석하는 방법입니다.



(기본적으로 ML에서 분류는 카테고리를 예측하는 것, 회귀는 수치 값을 예측하는 것입니다.)




회귀분석의 종류는 아래와 같이 다양합니다.






회귀 분석의 원리


회귀분석이란 회귀선을 도출하는 과정입니다.


y = ax + b (a, b: 회귀모수)


예를들어,

위의 그래프는

평수(독립변수)가 집값(종속변수)에 영향을 주는 정도를 나타낸 그래프입니다.



위의 직선의 경우


y = w1 * X + w2


여기서 잔차의 제곱의 합이 최소가 되도록 하는 최적의 선을 구하는 방법으로 최소 자승법을 이용합니다.





코드로 회귀분석에대해 더욱 자세히 알아보겠습니다.


이것은 제가 만든 미니 프로젝트 코드입니다.


주제: 첫 주의 누적관객 수가 그 영화의 흥망을 결정한다는 말이 있습니다.


이번에 그 첫 주 누적관객수에 영향을 미치는 요인을 영화 배급사가 결정할 수 있는 수치적인 요인으로 독립변수를 선택하였습니다.


종속변수: 첫 주 누적관객수

독립변수: 첫 주 누적 상영횟수, 첫 주 누적 스크린 수, 같은 날 개봉한 영화 수


data: 영화관입장권통합전산망 오픈API

################ 첫 주의 관객 수가 흥망을 결정한다. ################## ################ 첫 주 관객 수에 영향을 미치는 요인 ################## # db(mysql)에서 data 가져오기(2013-01-01 ~ 2018-06-15) library(RMySQL)


# dget() 함수는 이미 생성한 익명함수를 r로 로드하여 사용할 수 있습니다.

# 비밀번호와 주소를 감추기 위해 사용하였습니다. mysqldbConnect <- dget("mysqldbConnect.R") conn <- mysqldbConnect(dbname = "movieanalysis") c_sql <- "SELECT COUNT(*) FROM movie where openDt != ''" count <- dbGetQuery(conn, c_sql) count        # 19316

# r로 db에 있는 데이터 로드하기 r_sql <- c("SELECT * FROM movie where openDt != ''") document_r <- dbGetQuery(conn, r_sql) head(document_r)


######## 데이터 전처리 ############## # 한글이 깨지는 것을 복구하기위해 사용하였습니다. Encoding(document_r$movieNm) <-"UTF-8" head(document_r)

# 2013-01-01 이전 데이터 생략하기 document <- document_r[document_r$openDt > as.Date('2013-01-01'),] head(document) # 같은 날 개봉한 영화 수 (직접생성): sameDate document$sameDate <- '' for (i in 1:nrow(document)){ # print(j) document[i,"sameDate"] <- sum(document$openDt[i] == document$openDt) }


# normalization 등을 위해 data 전처리 str(document) document$salesAcc <- as.numeric(document$salesAcc) document$audiAcc <- as.numeric(document$audiAcc) document$audiChange <- as.numeric(document$audiChange) document$sameDate <- as.numeric(document$sameDate) document$showCnt <- as.numeric(document$showCnt) document$showRange <- substring(strptime(as.character(document$showRange), "%Y%m%d"), 1, 10) document$showRange <- as.Date(document$showRange) nrow(document) # table 정리 ncol = which(colnames(document) == "openDt") ncol1 = which(colnames(document) == "scrnCnt") ncol2 = which(colnames(document) == "sameDate") ncol3 = which(colnames(document) == "showRange")

# 개봉한지 7일 뒤의 날짜를 추가한다.

table <- cbind.data.frame(document[,-c(ncol,ncol1,ncol2,ncol3)],

"scrnCnt" = document[,ncol1],"openDate" = document[,ncol],

"sameDate" = document[,ncol2], "showRange" = document[,ncol3],

"after_7days" = (as.Date(document$openDt)+7))

# 누적 데이터 구하기 library(data.table) table <- as.data.table(table) table <- table[,Cum.showCnt := cumsum(showCnt), by = movieCd] table <- table[,Cum.rank := cumsum(rank), by = movieCd] table$scrnCnt <- as.numeric(table$scrnCnt) table <- table[,Cum.scrnCnt := cumsum(scrnCnt), by = movieCd] head(table) # 첫 주 누적관객수 및 누적데이터만 추출하기 movieWeek <- NULL for (z in 1:nrow(table)){ if (table$after_7days[z] == table$showRange[z]){ movieWeek <- rbind(table[z,],movieWeek) } } head(movieWeek)

movieWeek$openDate <- as.Date(movieWeek$openDate) movieWeek[(movieWeek$movieNm == movieWeek$movieNm) & (movieWeek$openDate <= movieWeek$showRange),]

############## 다중 회귀 분석 ############ normalize <- function(x) { return ( (x-min(x)) / (max(x) - min(x)) ) } # 정규화: 종속변수에 대한 독립변수의 영향을 파악하기위해 # 독립변수: 그 주 개봉하는 영화수, 누적 스크린 수, 누적 상영횟수 (only 수치데이터) movie_n <- as.data.frame(lapply(movieWeek[,c("Cum.scrnCnt","sameDate","Cum.showCnt")],

normalize)) head(movie_n) head(movieWeek) movieWeek_n <- cbind(movieWeek[ , -c("sameDate","Cum.showCnt","Cum.rank","Cum.scrnCnt")],

movie_n) head(movieWeek_n) # train data set과 test data set 나누기 set.seed(18)    # 여러값 중 좋은 set.seed()값 찾기 nrow <- round(dim(movieWeek_n)[1]*0.7)


# data shuffle하기 train_indx <- sample(1:dim(movieWeek_n)[1], nrow, replace = F)

movie_train <- movieWeek_n[1:train_indx,] movie_test <- movieWeek_n[(train_indx+1): nrow(movieWeek_n),] nrow(movie_train) nrow(movie_test)

# 다중회귀모델 생성하기

set.seed(1)

# 선형 모델 함수 lm()이용 library(stats)

model <-lm(audiAcc ~ (sameDate + Cum.showCnt + Cum.scrnCnt), data= movie_train) summary(model)    # r-squared(결정계수) 값 등을 확인한다.

# Adjusted R-squared: 0.79


# test data set result result <- predict(model,movie_test[,c("sameDate", "Cum.showCnt", "Cum.scrnCnt")]) str(result) result<- as.vector(result) str(movie_test$audiAcc) str(result) # 테스트 데이터의 라벨과 예측결과와 상관관계가 어떻게 되는지 확인한다. cor(result, movie_test$audiAcc) # 0.914286 : 양의 상관관계가 매우 높다.



# 어떤 독립변수가 어떤 종속변수에 영향을 많이 미치는 가?

# 시각화. pairs.panels library(psych) pairs.panels(movieWeek_n[,c("audiAcc", "Cum.showCnt", "Cum.scrnCnt", "sameDate")],

main = "첫 주 관객 수에 영향을 미치는 요인") # audiAcc와 Cum.showCnt의 상관관계는 0.88정도이다.





 




추가) 상관관계란


상관분석은 두 변수가 서로 어떠한 관계인지 파악하는 분석으로 기울기에 따라 양의 상관관계, 음의 상관관계로 나눌 수 있습니다.


점들의 흩어진 모습을 보고 두 변수의 관계를 파악하는데 밀도의 차이에 따라서 상관계수를 나타냅니다.


상관계수는 -1에서 1사이의 값을 가지며

상관계수의 수치가 0에 가까울수록 상관관계가 약하다는 뜻이고

+1에 가까우면 양의 상관관계가, -1에 가까우면 음의 상관관계가 강하다는 것을 의미합니다.



위의 코드에서 꼭 알아야하는 것!!


1. library(stats)를 이용하였다.


2. library(stats) 중 lm()함수를 이용하여 회귀분석을 하였다.


# 선형 모델 함수 lm()이용 model <-lm(audiAcc ~ (sameDate + Cum.showCnt + Cum.scrnCnt), data= movie_train) summary(model)    # r-squared(결정계수) 값 등을 확인한다.

# Adjusted R-squared: 0.79 # 독립변수가 많으면 저절로 높아질 수 있는 Multiple R-squared대신 사용

# test data set result result <- predict(model,movie_test[,c("sameDate", "Cum.showCnt", "Cum.scrnCnt")])


lm()함수를 이용하여 하나의 독립변수를 이용하면 단순회귀분석이 가능합니다!!





오늘은 여기까지!!


더 궁금하신 점은 댓글 남겨주세요~


다음은 연관규칙 알고리즘으로 돌아오겠습니다

반응형
반응형

 


안녕하세요


오늘은 R로 하는 머신러닝 지도학습 분류 3번째,


결정 트리에 대해 알아보도록 하겠습니다.




우선

1. 의사결정 트리란?


의사결정 rule을 계층적 나무구조로 도표화하여 분류 및 예측할 수 있는 분석 방법



분류율에 대한 정확도만 따지면 신경망 또는 회귀분석등의 분류 방법들보다 낮게 평가되기도 하지만


" 결과를 쉽게 이해하고 설명할 수 있으며 의사결정을 하는데 직접적으로 사용할 수 있다 "

는 장점이 있습니다!




2. 의사결정 트리의 알고리즘의 다양한 종류


각각의 이름과 알고리즘의 기준 속성은 다음과 같습니다.


ID3 : 엔트로피

C4.5, C5.0 : 정보획득량

CART : 카이제곱

CHAID : 카이제곱




3. 의사결정 트리 알고리즘에서 고려해야할 문제



1) 훈련 데이터를 어떤 속성으로 분할해야하는가?


위의 다양한 기준이 있는 이유 또한 이 질문에 대한 각각의 답을 낸 결과 아닐까요?



2) 트리 성장(분할과정)은 언제, 어떻게 정지해야하는가?


의사결정 트리를 시각화하여 순도가 높게 분류되는지 확인하기



3) 과적합 문제는 어떻게 해결해야할까?


가지치기(tree pruning)를 이용하여 불필요한 질문 제거하기




4. C5.0 알고리즘 이용하기

정보획득량을 기준으로 결정 트리를 시각화 하도록 하겠습니다.



정보획득량이란 무엇일까요?


정보획득량 = 분할전 엔트로피 - 분할 후 엔트로피



그렇다면 엔트로피의 공식을 알아봅시다.

위의 식을 이해하려면 log확률을 알아야합니다.


모르는 분들을 위해 제 블로그에 각각 간단하게 포스팅하였습니다~




5. 코드로 알아보기




 1. 의사결정 패키지 C50 을 설치한다.


2. 데이터를 로드한다.


3. 데이터를 suffle한다.


4. train 데이터와 test 데이터로 나눈다.


5. train 데이터로 분류 모델을 생성한다.


6. 분류모델과 test 데이터로 분류 결과를 예측한다.


7. Tree를 시각화한다.






decision_tree_fun <- function(){

# 1. 필요한 패키지 설치

# install.packages("C50")

# C50 라이브러리

library(C50) # 이원교차표 라이브러리

library(gmodels)

# tree 시각화를 위한 패키지 library(rpart) library(rattle)

# 2. 데이터 로드하기 print("분석할 csv파일을 입력하세요 ")

data <- file.choose()

na.string <- NA


table1 <- read.csv(data, header = T, na.string = na.string) d_col <- menu(c(colnames(table1),'none'), title="삭제할 컬럼을 선택하시오 ")

table1 <- table1[,-d_col]


l_col <- menu(colnames(table1), title="label이 될 컬럼을 선택하시오 ")

# 연속형데이터는 factor로 변환하지 않는다.

# 팩터 라벨 한글 제거 fctr_ls <- which( sapply(table1, class) == "factor" ) if( length(fctr_ls) !=0 ) { cat('***주의***\nFactor에 한글이 포함되어 있으면 에러가 발생할 수 있습니다.

\nFactor 라벨을 영문 혹은 숫자로 변경하십시오.\n\n') while( TRUE ) { chg_num <- menu(c('SKIP', colnames(table1)[fctr_ls]) , title = "라벨을 변환할 팩터컬럼을 선택하세요\n

-> 더이상 변환할 컬럼이 없다면 SKIP을 선택합니다.") if( chg_num == 1 ) break chng_lv <- NULL lv <- levels( table1[,fctr_ls[chg_num-1]] ) for( i in 1:length(lv) ) { chng_lv <- c(chng_lv, readline( paste('기존 :', lv[i], '-> 변경 : ')) ) } levels( table1[,fctr_ls[chg_num-1]] ) <- chg_lv } }


trials <- readline(prompt = "trials 값을 입력하세요 ")

# 3. 데이터 shuffle 하기 # 조절할 것1_set.seed() set.seed(11) table_shuffle <- table1[sample(nrow(table1)),]


# 4. train 데이터와 test 데이터 나누기 train_num <- round(0.7*nrow(table_shuffle),0) table_train <- table_shuffle[1:train_num, ] table_test <- table_shuffle[(train_num +1): nrow(table_shuffle), ] l_col <- colnames(table1)[l_col] ncol1 <- which(colnames(table1) == l_col)

# 5. 분류모델을 생성한다. # 조절할 것2_trials: 시도할 횟수 정함 model <- C5.0(table_train[ ,-ncol1], table_train[ ,ncol1], trials = as.numeric(trials)) result <- predict(model, table_test[ ,-ncol1])

# 6. 테스트 데이터로 예측한 결과(정확도) 확인

CrossTable(x = table_test[,ncol1], y= result)


# 7. Tree 시각화하기 # as.formula와 paste로 ~.을 붙여야한다.

tree <- rpart(label~. , data=data.frame(table1[,-ncol1], label = table1[,l_col]), control=rpart.control(minsplit=2))

# color 지정하기 fancyRpartPlot(tree,palettes = c("Greys","RdPu")) }


결과






오늘은 여기까지!!


다음은 회귀분석으로 돌아오겠습니다~


또 봐요~

반응형
반응형


안녕하세요~


오늘은 머신러닝 지도학습 알고리즘 중


나이브 베이즈 분류 알고리즘을 알아봅시다!!



나이브 베이지 분류란?

베이지안 기법 기반의 분류기는 훈련 데이터를 활용해 특정 값이 제공하는 증거기반으로 결과가 관측될 확률을 계산하는 방법


(사전확률을 이용해 사후확률을 알 수 있습니다.)



그렇다면,


나이브 베이즈 알고리즘은

언제 사용할까?



결과에 대한 전체 확률을 추정하기 위해 동시에 여러 속성 정보를 고려해야만 하는 문제에 가장 적합합니다.


모든 사건이 독립이라면 다른 사건을 관측해 어떤 사건을 예측하는 것은 불가능합니다. 


다시말해, 종속사건이 예측모델링에 기반이 됩니다.



<배경 지식>


조건부 확률





R 을 통해 본 나이브베이즈 분류 알고리즘


data : 영화 관람객

data설명: data frame형태의 데이터

column: 나이, 성별, 직업, 결혼여부, 이성친구, 장르(label)



[실습 순서]



1. 데이터 로드


2. 필요없는 데이터를 정제한다.


3. label(정답)이 될 컬럼을 factor로 변환한다.


4. train 데이터와 test 데이터로 나눈다.


5. library(e1071)을 이용하여

train 데이터로 naivebayes모델을 훈련시킨다.


6. 모델의 정확도를 확인한다.


7. 이원 교차표를 그려서 결과를 확인한다.


8. 튜닝한다.





직접 사용자 정의 function()으로 만들어 코드를 재사용 하고자 하였습니다.


naive_bayes_fun <- function() {

# 1. 데이터를 로드한다. # 내 컴퓨터에서 파일을 선택할 수 있는 창이 켜진다. data <- file.choose() na.string <- NA table1 <- read.csv(data, stringsAsFactors = F, na.string = na.string) # menu()를 사용하면 관련된 것의 숫자(순서)를 return한다. col <- menu(colnames(table1), title = "라벨이 될 컬럼 이름을 입력하세요 ") # readline()함수를 이용하면 사용자가 입력한 값을 읽어들일 수 있다. lap <- readline(prompt = "laplace값을 입력하세요 ")

# 2. data 정제: 매번 다르기때문에 여기서는 생략함 # 3. label을 factor로 변환한다.

# CrossTable Error 때문에 여기서는 전부 factor로 변환하였습니다.

for(i in 1:dim(table1)[2]){ table1[,i] <- factor(table1[,i]) } # 4. 훈련데이터와 테스트 데이터로 나눈다. set.seed(12) # 행의 건수 확인 train_cnt <- round(0.7 * dim(table1)[1]) # shuffle 하는 방법 중 하나 train_indx <- sample(1:dim(table1)[1], train_cnt, replace = F) table_train <- table1[train_indx,] table_test <- table1[-train_indx,]

# 5. 나이브 베이즈 함수를 이용해서 장르(label)를 분류하는 모델을 생성한다. library(e1071) # V1~: label(기준으로 사용), laplace: positive double controlling Laplace smoothing. # laplace로 공격적으로 필터링하는 정도를 조절할 수 있음 model1 <- naiveBayes(table_train[,col]~. , data = table_train, laplace = as.numeric(lap))

# 6. 모델로 테스트 데이터로 정확도 측성한다. # 예측하기 result1 <- predict(model1, table_test[, -col]) # 7. 이원 교차표로 분류의 최종 결과를 확인한다. library(gmodels) # 실제 예측 CrossTable(x = table_test[,col], y = result1)


# 정확도 확인하기

prop.table(table(ifelse(table_test[,col]==result1,"o","x" )))

}


# 8. 튜닝한다.


더 알맞은 shuffled data을 위해 set.seed()값으로 변경하고

laplace 값을 조절하여

필터링하는 정도를 조절하여 더 나은 값을 얻을 수 있습니다. (여기서는 0.1로 주어 결과를 내보았음)




[결과]




# 참고: 보시면 알 수 있듯이 여기 movie data는 굉장이 적은 데이터이기 때문에

training data 와 test data로 나눌 때 굉장히 불편했습니다.

큰데이터로 각각의 data의 비율을 변경해보세요~



[정확도]


prop.table(table(ifelse(table_test[,col]==result,"o","x" )))


 o            x 


0.75            0.25 





나이브 베이즈 알고리즘의

한계점


나이브 베이즈 알고리즘은 데이터에 대한 약간 naive(순진한)을 가정하고 있습니다.

특히 데이터 셋의 모든 특징을 동등하게 중요하고 독립적이라고 가정합니다.



이 한계점을 극복하기위한 다양한 분류 알고리즘에 대해 앞으로 알아보도록 하겠습니다!


우선 의사결정 트리부터~

반응형

+ Recent posts