지난번 포스팅에서는 거래 데이터 (transaction data)를 가지고 R을 사용하여 연관규칙 분석을 하였습니다.

 

이번 포스팅에서는 범주형 데이터와 연속형 데이터를 가지고 연관규칙을 생성(association rule mining on categorical data and continuous data)하는 방법을 소개하겠습니다. 

 

보통 연관규칙 분석을 배운다고 하면 거래 데이터(transaction data)만 가능한걸로 알고 끝내기 쉬운데요, 범주형 또는 연속형 데이터에 대해서도 연관규칙을 생성할 수 있다는 것을 알고 나면 연관규칙을 적용할 수 있는 범위가 늘어납니다.

 

가령 범주형 데이터를 가지고 연관규칙을 찾는 다면 아래와 같은 예가 있을 수 있습니다. 연속형 데이터를 범주형 데이터로 변환 (이산형화, discretization)하면 위의 예와 같은 연관규칙을 도출할 수 있습니다. 아래 예에서는 '연령'을 '연령대'로 구간을 나누었습니다.

 

 

 

[범주형 데이터 연관규칙 예]

 

{선형대수 수강 = Pass, 통계/확률 수강 = Pass}  →  {Machine Learning 수강 = Pass}

 

{성별 = 여성, 거주지역 = 분당, 연령대 = 30세~39세, 아동용품 구매경험 여부 = Yes}  →  {모바일쇼핑재구매 = Yes} 

 

 

범주형 데이터 또는 연속형 데이터를 가지고 연관규칙 분석을 하는 기본 원리는 "이항 데이터(binary data)로 변환하여 연관규칙 분석 방법을 수행"하는 것입니다.

 

아래의 가상의 데이터셋을 가지고 예를 들어보겠습니다.

성별(Gender), 아동상품구매여부(Child_Prd_YN), 모바일앱이용여부(Mobile_App_Use), 재구매여부(Re_Order) 등의 변수는 범주형 데이터(categorical data)이며, 연령(Age)은 연속형 데이터(continuous data)에 속합니다.  이를 '1', '0' 의 두개의 값만 가지는 변수로 변환하는 이항변수화(Binarization)을 하면 아래와 같습니다.

 

 

[ 범주형/연속형 데이터의 이항변수화 (Binarization) ]

 

 

 

이항변수화를 할 때 구간을 몇 개로 나눌 것인지가 중요한데요, 너무 잘게 쪼개서 구간을 많이 만들게 되면 연관규칙이 잘 안나올 수 있습니다. 왜냐하면 구간을 잘게 쪼개면 각 구간별 freqnency 가 작아져서 지지도(support) 값이 낮아지고, inqrequent item set은 pruning 되기 때문입니다.  따라서 적당한(?) 구간으로 (너무 잘게 쪼개지 않게) 나누는 것이 필요합니다.  위의 예에서는 연령(age)의 경우 20대, 30대, 40대의 3개 구간으로만 나누어보았습니다.

 

 

R을 가지고 위의 가상의 간략한 예제 데이터를 가지고 연관규칙을 생성해보겠습니다.

 

R의 as(dataset, "transactions") 함수를 이용하면 연관규칙분석을 위한 이항변수화(binirization) 작업을 별도로 안해줘도 되므로 편리합니다. 단, 연속형 변수를 범주형 변수로 만드는 이산형화(discretization)하는 작업은 아래 예처럼 코딩을 해줘야 합니다.

 

 

(1) 범주형 dataset 확보, 연속형 변수의 이산형화(discretization)

 

> ##--------------------------------------------------------------
> ## categorical data -> binarization -> association rule analysis
> ##--------------------------------------------------------------
> 
> # vector -> cbind -> data.frame
> cust_id <- c(1, 2, 3, 4, 5, 6)
> gender <- c("FEMALE", "MALE", "FEMALE", "FEMALE", "MALE", "FEMALE")
> age <- c(23, 28, 42, 34, 45, 36)
> child_prd_yn <- c("NO", "NO", "NO", "YES", "NO", "YES")
> mobile_app_use <- c("YES", "YES", "NO", "YES", "NO", "YES")
> re_order <- c("YES", "NO", "NO", "YES", "NO", "YES")
> 
> cust_mart <- cbind(cust_id, gender, age, child_prd_yn, mobile_app_use, re_order)
> cust_mart <- as.data.frame(cust_mart)
> sapply(cust_mart, class)
       cust_id         gender            age   child_prd_yn mobile_app_use       re_order 
      "factor"       "factor"       "factor"       "factor"       "factor"       "factor" 
> 
> 
> # cust_id : factor -> character
> # age : factor -> numeric
> cust_mart <- transform(cust_mart, 
+                        cust_id = as.character(cust_id),
+                        age = as.numeric(age))
> 
> sapply(cust_mart, class)
       cust_id         gender            age   child_prd_yn mobile_app_use       re_order 
   "character"       "factor"      "numeric"       "factor"       "factor"       "factor" 
> 
> 
> # age : custinuous data -> discretization
> cust_mart <- within(cust_mart, {
+   age_cd = character(0)
+   age_cd[ age <= 29 ] = "age_20"
+   age_cd[ age > 29 & age <= 39 ] = "age_30"
+   age_cd[ age > 39 ] = "age_40"
+   age_cd = factor(age_cd, level = c("age_20", "age_30", "age_40"))
+ })
> 
> 
> # dataset for assocition rule : (1) deleting 'cust_id', 'age'
> cust_mart_ar <- subset(cust_mart, select = -c(cust_id, age))
> str(cust_mart_ar)
'data.frame':	6 obs. of  5 variables:
 $ gender        : Factor w/ 2 levels "FEMALE","MALE": 1 2 1 1 2 1
 $ child_prd_yn  : Factor w/ 2 levels "NO","YES": 1 1 1 2 1 2
 $ mobile_app_use: Factor w/ 2 levels "NO","YES": 2 2 1 2 1 2
 $ re_order      : Factor w/ 2 levels "NO","YES": 2 1 1 2 1 2
 $ age_cd        : Factor w/ 3 levels "age_20","age_30",..: 1 1 1 1 1 1
> 

 

 

 

(2) 거래데이터 형식으로 데이터 변환하기 : as(dataset, "transactions")

 

> # dataset for assocition rule : (2) transaction data format
> install.packages("arules")
Installing package into ‘C:/Users/Owner/Documents/R/win-library/3.2’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/3.2/arules_1.4-1.zip'
Content type 'application/zip' length 1885277 bytes (1.8 MB)
downloaded 1.8 MB

package ‘arules’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
	C:\Users\Owner\AppData\Local\Temp\Rtmp0ybsUO\downloaded_packages
> library(arules)
필요한 패키지를 로딩중입니다: Matrix

다음의 패키지를 부착합니다: ‘arules’

The following objects are masked from ‘package:base’:

    abbreviate, write

Warning message:
패키지 ‘arules’는 R 버전 3.2.5에서 작성되었습니다 
> 
> cust_mart_ar_tr <- as(cust_mart_ar, "transactions")
> str(cust_mart_ar_tr)
Formal class 'transactions' [package "arules"] with 3 slots
  ..@ data       :Formal class 'ngCMatrix' [package "Matrix"] with 5 slots
  .. .. ..@ i       : int [1:30] 0 2 5 7 8 1 2 5 6 8 ...
  .. .. ..@ p       : int [1:7] 0 5 10 15 20 25 30
  .. .. ..@ Dim     : int [1:2] 11 6
  .. .. ..@ Dimnames:List of 2
  .. .. .. ..$ : NULL
  .. .. .. ..$ : NULL
  .. .. ..@ factors : list()
  ..@ itemInfo   :'data.frame':	11 obs. of  3 variables:
  .. ..$ labels   : chr [1:11] "gender=FEMALE" "gender=MALE" "child_prd_yn=NO" "child_prd_yn=YES" ...
  .. ..$ variables: Factor w/ 5 levels "age_cd","child_prd_yn",..: 3 3 2 2 4 4 5 5 1 1 ...
  .. ..$ levels   : Factor w/ 7 levels "age_20","age_30",..: 4 5 6 7 6 7 6 7 1 2 ...
  ..@ itemsetInfo:'data.frame':	6 obs. of  1 variable:
  .. ..$ transactionID: chr [1:6] "1" "2" "3" "4" ...
> 

 

 

 

 

(3) 연관규칙 생성 (association rule generation) : arules package, apriori algorithm

 

 

> # association rule generation
> cust_mart_ar_tr_rule <- apriori(cust_mart_ar_tr, 
+                              parameter = list(support = 0.3, confidence = 0.5))
Apriori

Parameter specification:
 confidence minval smax arem  aval originalSupport support minlen maxlen target   ext
        0.5    0.1    1 none FALSE            TRUE     0.3      1     10  rules FALSE

Algorithmic control:
 filter tree heap memopt load sort verbose
    0.1 TRUE TRUE  FALSE TRUE    2    TRUE

Absolute minimum support count: 1 

Warning in apriori(cust_mart_ar_tr, parameter = list(support = 0.3, confidence = 0.5)) :
  You chose a very low absolute support count of 1. You might run out of memory! Increase minimum support.

set item appearances ...[0 item(s)] done [0.00s].
set transactions ...[9 item(s), 6 transaction(s)] done [0.00s].
sorting and recoding items ... [9 item(s)] done [0.00s].
creating transaction tree ... done [0.00s].
checking subsets of size 1 2 3 4 5 done [0.00s].
writing ... [135 rule(s)] done [0.00s].
creating S4 object  ... done [0.00s].

 

 

(4) 연관규칙 탐색 (inspection of association rule) : inspect(association rule)

 

 

> # association rule inspection > inspect(head(cust_mart_ar_tr_rule, 20)) # head 20 rules lhs rhs support confidence lift 1 {} => {re_order=YES} 0.5000000 0.5000000 1.0 2 {} => {re_order=NO} 0.5000000 0.5000000 1.0 3 {} => {child_prd_yn=NO} 0.6666667 0.6666667 1.0 4 {} => {mobile_app_use=YES} 0.6666667 0.6666667 1.0 5 {} => {gender=FEMALE} 0.6666667 0.6666667 1.0 6 {} => {age_cd=age_20} 1.0000000 1.0000000 1.0 7 {gender=MALE} => {re_order=NO} 0.3333333 1.0000000 2.0 8 {re_order=NO} => {gender=MALE} 0.3333333 0.6666667 2.0 9 {gender=MALE} => {child_prd_yn=NO} 0.3333333 1.0000000 1.5 10 {child_prd_yn=NO} => {gender=MALE} 0.3333333 0.5000000 1.5 11 {gender=MALE} => {age_cd=age_20} 0.3333333 1.0000000 1.0 12 {mobile_app_use=NO} => {re_order=NO} 0.3333333 1.0000000 2.0 13 {re_order=NO} => {mobile_app_use=NO} 0.3333333 0.6666667 2.0 14 {mobile_app_use=NO} => {child_prd_yn=NO} 0.3333333 1.0000000 1.5 15 {child_prd_yn=NO} => {mobile_app_use=NO} 0.3333333 0.5000000 1.5 16 {mobile_app_use=NO} => {age_cd=age_20} 0.3333333 1.0000000 1.0 17 {child_prd_yn=YES} => {re_order=YES} 0.3333333 1.0000000 2.0 18 {re_order=YES} => {child_prd_yn=YES} 0.3333333 0.6666667 2.0 19 {child_prd_yn=YES} => {mobile_app_use=YES} 0.3333333 1.0000000 1.5 20 {mobile_app_use=YES} => {child_prd_yn=YES} 0.3333333 0.5000000 1.5

 

 

 

(5) 특정 관심있는 연관규칙만 선별해서 보기 : subset()

 

  예) 연관규칙의 right-hand side 에 "재구매여부=예"를 포함하고 "lift >=2" 인 rule만 선별(subset)

 

> # subset : right-hand sied in "re_order = YES" & lift >= 2 > cust_mart_ar_tr_rule_reorder <- subset(cust_mart_ar_tr_rule, + subset = rhs %in% "re_order=YES" & lift >= 2) > > inspect(cust_mart_ar_tr_rule_reorder) lhs rhs support confidence lift 1 {child_prd_yn=YES} => {re_order=YES} 0.3333333 1 2 2 {child_prd_yn=YES, mobile_app_use=YES} => {re_order=YES} 0.3333333 1 2 3 {gender=FEMALE, child_prd_yn=YES} => {re_order=YES} 0.3333333 1 2 4 {child_prd_yn=YES, age_cd=age_20} => {re_order=YES} 0.3333333 1 2 5 {gender=FEMALE, mobile_app_use=YES} => {re_order=YES} 0.5000000 1 2 6 {gender=FEMALE, child_prd_yn=YES, mobile_app_use=YES} => {re_order=YES} 0.3333333 1 2 7 {child_prd_yn=YES, mobile_app_use=YES, age_cd=age_20} => {re_order=YES} 0.3333333 1 2 8 {gender=FEMALE, child_prd_yn=YES, age_cd=age_20} => {re_order=YES} 0.3333333 1 2 9 {gender=FEMALE, mobile_app_use=YES, age_cd=age_20} => {re_order=YES} 0.5000000 1 2 10 {gender=FEMALE, child_prd_yn=YES, mobile_app_use=YES, age_cd=age_20} => {re_order=YES} 0.3333333 1 2

 

 

 

제일 마지막 결과까지 보고 나면 '어, 저거 rule-base 규칙인데...어디서 많이 본건데...' 싶지 않으신가요?  Decision Tree랑 뭔가 모르게 비슷하다는 생각이 좀 들지요?  혹시 명확한 target을 가진 (설명력이 좋은) 분류 규칙 찾는 목적이라면 Decision Tree 를 쓰는게 더 효과적일 수 있습니다.  (가령, 재구매고객의 특성이 뭐지? 처럼요)

 

그런데 뭔지는 지금은 모르겠지만 '기존에는 잘 몰랐으면서 & insight가 담겨있고 & 설명가능하고 & 실행가능한' 연관규칙을 한번 찾아봐 줘, 그러면 내가 그 rule들을 평가해보고 쓸만한거 추려서 이용해볼게...하는 상황이면 연관규칙 분석을 사용하시면 됩니다. 

 

Decision Tree는 하햐식 방식(Top to bottom)으로 분류규칙을 만들어나가는데 반해 (즉, child node는 parent node에 종속적), 연관규칙, 순차패턴은 규칙이 서로 독립적이라는게 다릅니다.

 

이상으로 범주형, 연속형 데이터의 연관규칙 분석에 대해서 알아보았습니다.

 

다음번 포스팅에서는 순차분석(sequence analysis)에 대해서 알아보겠습니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡'를 꾸욱~ 눌러주세요.

 

728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 대용량 데이터로 부터 효율적으로 연관규칙(association rules)을 도출할 수 있는 apriori algorithm 에 대하여 알아보았습니다.

 

이번 포스팅에서는 R의 arules package를 가지고 분석하는 방법을 예를 들어서 설명하도록 하겠습니다. 

(그동안 선형대수랑 기계학습 이론 내용만 포스팅하다보니 R 사용법 포스팅한지가 너무 오래된거 같아요. ^^;)

 

arules package는 Apriori algorithm으로 구현되었 있습니다.

 

 

 

1. arules package 설치 및 library(arules)로 로딩

 

aruels package는 base package가 아니므로 별도 설치 필요합니다.

 

 

 > install.packages("arules")
Installing package into ‘C:/Users/Owner/Documents/R/win-library/3.2’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/3.2/arules_1.4-1.zip'
Content type 'application/zip' length 1885514 bytes (1.8 MB)
downloaded 1.8 MB

package ‘arules’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
C:\Users\Owner\AppData\Local\Temp\Rtmp4sJVWg\downloaded_packages
> library(arules)
필요한 패키지를 로딩중입니다: Matrix

다음의 패키지를 부착합니다: ‘arules’

The following objects are masked from ‘package:base’:

    abbreviate, write

Warning message:
패키지 ‘arules’는 R 버전 3.2.5에서 작성되었습니다

 

 

2. 데이터 확보 및 탐색

 

분석에 사용할 데이터는 Epub 거래 데이터셋 입니다.  Help에 'Epub' 을 검색해보면 아래와 같은 설명이 나옵니다. Vienna University of Economics and Business Administration에서의 2003~2008년까지 기간 동안 전자책 다운로드 이력/거래 데이터입니다.

 

> help(Epub)

 

 

Epub {arules}

R Documentation

Epub Data Set

Description

The Epub data set contains the download history of documents from the electronic publication platform of the Vienna University of Economics and Business Administration. The data was recorded between Jan 2003 and Dec 2008.

Usage

data(Epub)

Format

Object of class transactions with 15729 transactions and 936 items. Item labels are document IDs of the from "doc\_11d". Session IDs and time stamps for transactions are also provided.

Author(s)

Michael Hahsler

Source

Provided by Michael Hahsler from ePub-WU at http://epub.wu-wien.ac.at.

 

 

 

data(Epub)로 로딩하고 summary(Epub)로 데이터셋 요약정보를 살펴보겠습니다. 

- sparse format 형식으로 저장된 itemMatrix의 거래(transactions) 데이터셋이며,

- 15,729개의 행(즉, 거래)과 936개의 열(items)으로 구성되어 있습니다.

- 밀도(density)가 0.1758755% 라고 되어 있는데요, 전체 15729*936개의 cell 중에서 0.1758% 의 cell에 거래가 발생해서 숫자가 차 있다는 뜻입니다. (일부 책벌레 애독자가 한꺼번에 다수의 책을 사고, 대부분의 독자는 item 1개나 2개 단품 위주로 샀기 때문에 이렇게 밀도가 낮겠지요?)

- 'most frequent items' 는 거래 빈도가 가장 많은 top 5의 품목명과 거래빈도를 제시해주고 있습니다.

  (doc_11d 가 356회 거래 빈도 발생으로 1위) 

- 'element (itemset/transaction) length distribution' 은 하나의 거래 장바구니(즉, row 1개별로)에 품목(item)의 개수별로 몇 번의 거래가 있었는지를 나타냅니다.

(장바구니에 item 1개 짜리 단품만 거래한 경우가 11,615건으로서 가장 많고, item 2개 거래는 2,189건이군요)

- 마지막에 item 정보의 label 형식과 transaction ID, TimeStamp 정보의 format 예시가 나옵니다.

 

> data(Epub)
> summary(Epub)
transactions as itemMatrix in sparse format with
 15729 rows (elements/itemsets/transactions) and
 936 columns (items) and a density of 0.001758755 

most frequent items:
doc_11d doc_813 doc_4c6 doc_955 doc_698 (Other) 
    356     329     288     282     245   24393 

element (itemset/transaction) length distribution:
sizes
    1     2     3     4     5     6     7     8     9    10    11    12    13    14 
11615  2189   854   409   198   121    93    50    42    34    26    12    10    10 
   15    16    17    18    19    20    21    22    23    24    25    26    27    28 
    6     8     6     5     8     2     2     3     2     3     4     5     1     1 
   30    34    36    38    41    43    52    58 
    1     2     1     2     1     1     1     1 

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   1.000   1.000   1.646   2.000  58.000 

includes extended item information - examples:
   labels
1 doc_11d
2 doc_13d
3 doc_14c

includes extended transaction information - examples:
    transactionID           TimeStamp
10792  session_4795 2003-01-02 10:59:00
10793  session_4797 2003-01-02 21:46:01
10794  session_479a 2003-01-03 00:50:38 

 

 

참고로, R을 분석에 많이 사용해본 분이라면 dataframe 형식의 데이터셋을 많이 사용해보셨을 텐데요, 연관규칙분석에서 사용할 itemMatrix in sparse format 형식의 데이터셋과 비교해보면 아래와 같이 차이가 있습니다.  위에서 Epub 데이터셋의 density가 0.1758%로서 item별 matrix cell의 거의 대부분이 숭숭 비어있다고 했는데요, 비어있는 cell까지 모두 저장하려면 메모리 비효율이 발생하므로 cell의 차있는 부분(즉, 거래발생 항목, nonzero elements)에 대해서만 효율적으로 데이터를 저장해놓는 방식이 itemMatrix in sparse format 형식입니다. 저장 효율이 좋아지는 대신 반대급부로 access하는 것이나 저장구조는 좀 복잡해집니다.   

(행렬의 대부분의 cell이 '0'이면 sparse matrix 라고 하며, 그 반대는 dense matrix 라고 합니다.)

 

csv 파일을 dataframe 으로 업로드할 때 read.csv() 함수를 사용하는 것처럼, transaction 데이터를 연관규칙분석을 위해 sparse format의 itemMatrix로 업로드하기 위해서는 read.transactions("dataset.csv") 함수를 사용합니다.

 

 

 

 

 

 

이번에는 inspect() 함수를 사용해서 거래 데이터 10개만 뽑아서 살펴보겠습니다.

 

 > ## check itemsets in sparse matrix

> inspect(Epub[1:10])
      items                    transactionID TimeStamp          
10792 {doc_154}                session_4795  2003-01-02 10:59:00
10793 {doc_3d6}                session_4797  2003-01-02 21:46:01
10794 {doc_16f}                session_479a  2003-01-03 00:50:38
10795 {doc_11d,doc_1a7,doc_f4} session_47b7  2003-01-03 08:55:50
10796 {doc_83}                 session_47bb  2003-01-03 11:27:44
10797 {doc_11d}                session_47c2  2003-01-04 00:18:04
10798 {doc_368}                session_47cb  2003-01-04 04:40:57
10799 {doc_11d,doc_192}        session_47d8  2003-01-04 09:00:01
10800 {doc_364}                session_47e2  2003-01-05 02:48:36
10801 {doc_ec}                 session_47e7  2003-01-05 05:58:48

 

 

 

다음으로 itemFrequency() 함수를 이용해서 거래품목(item)별로 거래에서 차지하는 비율(support)를 살펴보겠습니다. Epub[ , 1:10] 으로 앞에 10개만 indexing 해왔습니다.

 

> ## support per item: itemFrequency()
> itemFrequency(Epub[ , 1:10])
     doc_11d      doc_13d      doc_14c      doc_14e      doc_150      doc_151 
0.0226333524 0.0009536525 0.0024794965 0.0017801513 0.0015894208 0.0007629220 
     doc_153      doc_154      doc_155      doc_156 
0.0006357683 0.0013351135 0.0010808062 0.0031152648

 

 

 

itemFrequencyPlot(dataset, support = xx) 함수를 이용해서 지지도 1% 이상의 item에 대해 막대그래프를 그려보겠습니다.

 

> ## item frequency plot : itemFrequentPlot()
> itemFrequencyPlot(Epub, support = 0.01, main = "item frequency plot above support 1%")

 

 

 

이번에는 itemFrequencyPlot(dataset, topN = xx) 함수를 사용해서 support 상위 30개의 막대그래프를 그려보겠습니다. support 1등 item이 'doc_11d'이고 2~2.5% 사이로군요. 30등 tiem은 'doc_3ec'이고 support가 약 1% 이네요.

 

> ## item frequency plot top 30 : itemFrequencyPlot(,topN)
> itemFrequencyPlot(Epub, topN = 30, main = "support top 30 items")

 

 

 

 

아래는 image()함수sample()함수를 이용해서 500개의 무작위 샘플을 가지고 matrix diagram을 그려본 것입니다.  그림의 점들은 거래가 발생한 item을 의미합니다. 이 그림만 봐서는 어떤 패턴이 있는지 알기가 어렵지요? ^^' 

 

> # matrix diagram : image()
> image(sample(Epub, 500, replace = FALSE), main = "matrix diagram")

 

 

 

 

 

3. 연관규칙 분석 (association rule analysis)

 

arules 패키지의 apriori() 함수를 이용해서 연관규칙을 분석해보겠습니다.

 

parameter 에 list로 minimum support, minimum confidence, minimum length 를 지정해주면 이를 충족시키지 못하는 superset에 대해서는 pruning 을 해서 빠르게 연관규칙을 찾아줍니다.

 

그런데, 아래 예시에서는 minumum support = 0.01 로 했더니 기준이 너무 높았던지 연관규칙이 '0'개 나왔네요.

 

 

> ## association rule analysis : apriori()
> Epub_rule <- apriori(data = Epub, 
+                      parameter = list(support = 0.01, 
+                                       confidence = 0.20, 
+                                       minlen = 2))
Apriori

Parameter specification:
 confidence minval smax arem  aval originalSupport support minlen maxlen target   ext
        0.2    0.1    1 none FALSE            TRUE    0.01      2     10  rules FALSE

Algorithmic control:
 filter tree heap memopt load sort verbose
    0.1 TRUE TRUE  FALSE TRUE    2    TRUE

Absolute minimum support count: 157 

set item appearances ...[0 item(s)] done [0.00s].
set transactions ...[936 item(s), 15729 transaction(s)] done [0.00s].
sorting and recoding items ... [19 item(s)] done [0.00s].
creating transaction tree ... done [0.00s].
checking subsets of size 1 2 done [0.00s].
writing ... [0 rule(s)] done [0.00s].
creating S4 object  ... done [0.00s]

 

 

minumum support 기준을 0.001 로 낮추어서 다시 한번 분석을 해보겠습니다. 

아래처럼 결과가 나왔습니다.  연관규칙 분석은 기본 개념과 결과를 해석할 줄 알면 분석툴로 분석하는 것은 이처럼 매우 쉽습니다. (컴퓨터는 연산해야할 일이 엄청 많지만요...)

 

> # re-setting minimum support from 0.01 to 0.001
> Epub_rule_2 <- apriori(data = Epub, 
+                      parameter = list(support = 0.001, 
+                                       confidence = 0.20, 
+                                       minlen = 2))
Apriori

Parameter specification:
 confidence minval smax arem  aval originalSupport support minlen maxlen target   ext
        0.2    0.1    1 none FALSE            TRUE   0.001      2     10  rules FALSE

Algorithmic control:
 filter tree heap memopt load sort verbose
    0.1 TRUE TRUE  FALSE TRUE    2    TRUE

Absolute minimum support count: 15 

set item appearances ...[0 item(s)] done [0.00s].
set transactions ...[936 item(s), 15729 transaction(s)] done [0.00s].
sorting and recoding items ... [481 item(s)] done [0.00s].
creating transaction tree ... done [0.02s].
checking subsets of size 1 2 3 done [0.00s].
writing ... [65 rule(s)] done [0.00s].
creating S4 object  ... done [0.00s]

 

> Epub_rule_2
set of 65 rules

 

 

 

4. 연관규칙 조회 및 평가

 

연관규칙을 Epub_rule 이라는 객체에 저장을 해두었으므로, summary() 함수를 써서 연관규칙에 대해 개략적으로 파악을 해보면 아래와 같습니다. 

 

62개 rule이 2개 item으로 이루어져 있고, 3개 rule은 3개 item으로 구성되있군요. 지지도(support), 신뢰도(confidence), 향상도(lift)에 대한 기초통계량도 같이 제시가 되었는데요, 향상도 최소값이 11.19로서 전반적으로 꽤 높군요.

 

> summary(Epub_rule_2)
set of 65 rules

rule length distribution (lhs + rhs):sizes
 2  3 
62  3 

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.000   2.000   2.000   2.046   2.000   3.000 

summary of quality measures:
    support           confidence          lift       
 Min.   :0.001017   Min.   :0.2048   Min.   : 11.19  
 1st Qu.:0.001081   1st Qu.:0.2388   1st Qu.: 34.02  
 Median :0.001208   Median :0.2874   Median : 59.47  
 Mean   :0.001435   Mean   :0.3571   Mean   :105.16  
 3rd Qu.:0.001526   3rd Qu.:0.3696   3rd Qu.:100.71  
 Max.   :0.004069   Max.   :0.8947   Max.   :454.75  

mining info:
 data ntransactions support confidence
 Epub         15729   0.001        0.2

 

 

 

연관규칙을 평가하기 위해 개별 규칙(rule)을 inspect()함수를 사용해서 살펴보겠습니다.  아래 결과에 1~20개의 rule을 제시했는데요, lhs : Left-hand side, rhs : Right-hand side 를 의미합니다.

 

> # inspection of 1~20 association rules : inspect() > inspect(Epub_rule_2[1:20]) lhs rhs support confidence lift 1 {doc_506} => {doc_507} 0.001207960 0.6551724 303.09432 2 {doc_507} => {doc_506} 0.001207960 0.5588235 303.09432 3 {doc_470} => {doc_4c6} 0.001080806 0.2048193 11.18612 4 {doc_714} => {doc_574} 0.001080806 0.3695652 113.97826 5 {doc_574} => {doc_714} 0.001080806 0.3333333 113.97826 6 {doc_4bf} => {doc_4ac} 0.001080806 0.5000000 77.10294 7 {doc_6e9} => {doc_6e8} 0.001207960 0.6785714 333.53906 8 {doc_6e8} => {doc_6e9} 0.001207960 0.5937500 333.53906 9 {doc_6e9} => {doc_6e7} 0.001271537 0.7142857 321.00000 10 {doc_6e7} => {doc_6e9} 0.001271537 0.5714286 321.00000 11 {doc_749} => {doc_74a} 0.001017229 0.3555556 86.03897 12 {doc_74a} => {doc_749} 0.001017229 0.2461538 86.03897 13 {doc_6e8} => {doc_6e7} 0.001335113 0.6562500 294.91875 14 {doc_6e7} => {doc_6e8} 0.001335113 0.6000000 294.91875 15 {doc_3d6} => {doc_3c4} 0.001144383 0.2465753 79.15068 16 {doc_3c4} => {doc_3d6} 0.001144383 0.3673469 79.15068 17 {doc_3d6} => {doc_4b4} 0.001017229 0.2191781 51.45451 18 {doc_4b4} => {doc_3d6} 0.001017229 0.2388060 51.45451 19 {doc_3c4} => {doc_574} 0.001017229 0.3265306 100.70588 20 {doc_574} => {doc_3c4} 0.001017229 0.3137255 100.70588

 

 

 

위처럼 주욱 나열을 해놓으면 rule이 수백, 수천개가 되면 일일이 눈으로 보고 평가하기가 쉽지가 않습니다.  봐야할 rule이 많을 때는 sort() 함수를 써서 분석가가 보고자하는 기준에 맞게 by 매개변수로 정렬을 하여 우선순위를 뒤서 보면 유용합니다.  아래 예는 lift 를 기준으로 상위 20개 연관규칙을 정렬해보았습니다.  매우 유용하지요?!!

 

 

> # sorting association rules by lift : sort( , by = "lift") > inspect(sort(Epub_rule_2, by = "lift")[1:20]) lhs rhs support confidence lift 65 {doc_6e7,doc_6e8} => {doc_6e9} 0.001080806 0.8095238 454.75000 64 {doc_6e7,doc_6e9} => {doc_6e8} 0.001080806 0.8500000 417.80156 63 {doc_6e8,doc_6e9} => {doc_6e7} 0.001080806 0.8947368 402.09474 7 {doc_6e9} => {doc_6e8} 0.001207960 0.6785714 333.53906 8 {doc_6e8} => {doc_6e9} 0.001207960 0.5937500 333.53906 9 {doc_6e9} => {doc_6e7} 0.001271537 0.7142857 321.00000 10 {doc_6e7} => {doc_6e9} 0.001271537 0.5714286 321.00000 1 {doc_506} => {doc_507} 0.001207960 0.6551724 303.09432 2 {doc_507} => {doc_506} 0.001207960 0.5588235 303.09432 13 {doc_6e8} => {doc_6e7} 0.001335113 0.6562500 294.91875 14 {doc_6e7} => {doc_6e8} 0.001335113 0.6000000 294.91875 39 {doc_87c} => {doc_882} 0.001335113 0.6000000 171.58909 40 {doc_882} => {doc_87c} 0.001335113 0.3818182 171.58909 4 {doc_714} => {doc_574} 0.001080806 0.3695652 113.97826 5 {doc_574} => {doc_714} 0.001080806 0.3333333 113.97826 20 {doc_574} => {doc_3c4} 0.001017229 0.3137255 100.70588 19 {doc_3c4} => {doc_574} 0.001017229 0.3265306 100.70588 22 {doc_4b4} => {doc_3c4} 0.001207960 0.2835821 91.02985 21 {doc_3c4} => {doc_4b4} 0.001207960 0.3877551 91.02985 11 {doc_749} => {doc_74a} 0.001017229 0.3555556 86.03897

 

 

 

아래는 정렬 기준을 '지지도(support)'로 해서 top 20 연관규칙을 뽑아본 것입니다.  편하고 좋지요?!

 

> # sorting association rules by support : sort(, by = "support")
> inspect(sort(Epub_rule_2, by = "support")[1:20])
   lhs          rhs       support     confidence lift     
50 {doc_72f} => {doc_813} 0.004068917 0.3516484   16.81178
45 {doc_4ac} => {doc_16e} 0.002797381 0.4313725   53.42566
46 {doc_16e} => {doc_4ac} 0.002797381 0.3464567   53.42566
62 {doc_364} => {doc_71}  0.002733804 0.2336957   15.91255
60 {doc_60e} => {doc_6bf} 0.002670227 0.2745098   21.06227
61 {doc_6bf} => {doc_60e} 0.002670227 0.2048780   21.06227
49 {doc_972} => {doc_8f9} 0.002161612 0.2281879   18.69358
58 {doc_1a2} => {doc_4c7} 0.002098035 0.2391304   17.99657
56 {doc_424} => {doc_359} 0.001843728 0.3020833   44.40625
57 {doc_359} => {doc_424} 0.001843728 0.2710280   44.40625
47 {doc_4da} => {doc_84b} 0.001780151 0.2314050   34.01653
48 {doc_84b} => {doc_4da} 0.001780151 0.2616822   34.01653
52 {doc_8a8} => {doc_8af} 0.001716574 0.2903226   47.07715
53 {doc_8af} => {doc_8a8} 0.001716574 0.2783505   47.07715
27 {doc_803} => {doc_3fc} 0.001589421 0.3289474   59.47142
28 {doc_3fc} => {doc_803} 0.001589421 0.2873563   59.47142
55 {doc_466} => {doc_19f} 0.001525844 0.2264151   25.80640
59 {doc_359} => {doc_4c7} 0.001398690 0.2056075   15.47368
13 {doc_6e8} => {doc_6e7} 0.001335113 0.6562500  294.91875
14 {doc_6e7} => {doc_6e8} 0.001335113 0.6000000  294.91875

 

 

 

 

또 하나 유용한 tip이 있다면 subset() 함수를 써서 관심이 있는 item이 포함된 연관규칙만 선별해서 보는 방법입니다.  subset()함수를 이용해 연관규칙에서 "doc_72f"나 "doc_4ac"를 포함하는 규칙을 선별하는 방법은 아래와 같습니다.

 

 

> # subset of association rules : subset()
> rule_interest <- subset(Epub_rule_2, items %in% c("doc_72f", "doc_4ac"))
> inspect(rule_interest)
   lhs          rhs       support     confidence lift    
6  {doc_4bf} => {doc_4ac} 0.001080806 0.5000000  77.10294
45 {doc_4ac} => {doc_16e} 0.002797381 0.4313725  53.42566
46 {doc_16e} => {doc_4ac} 0.002797381 0.3464567  53.42566
50 {doc_72f} => {doc_813} 0.004068917 0.3516484  16.81178

 

 

 

연관규칙을 찾을 때 왼쪽(lhs : Left-hand side)이나 오른쪽(rhs: Right-hand side)을 기준으로 원하는 항목(item)이 포함된 규칙만 찾고 싶을 때는 아래와 같이 lhs 나 rhs 조건을 주면 됩니다.

 

> # subset with left-hand side item : subset(lhs %in% "item")
> rule_interest_lhs <- subset(Epub_rule_2, lhs %in% c("doc_72f", "doc_4ac"))
> inspect(rule_interest_lhs)
   lhs          rhs       support     confidence lift    
45 {doc_4ac} => {doc_16e} 0.002797381 0.4313725  53.42566
50 {doc_72f} => {doc_813} 0.004068917 0.3516484  16.81178 

 

 

 

위에서는 사용한 %in% (select itemsets matching any given item) 조건은 적어도 하나의 제품이라도 존재하면 연관규칙을 indexing해온다는 뜻입니다.  이에 반해 %pin% (partial matching) 는 부분 일치만 하더라도, %ain% (select only itemsets matching all given item) 는 완전한 일치를 할 때만 indexing을 하게 됩니다. 

 

아래에 item 이름에 부분적으로라도 "60e"라는 철자가 들어가 있는 item이 들어가 있는 연관규칙을 부분집합으로 indexing해오는 예를 들어보겠습니다.  이 기능도 꽤 유용하겠지요?

 

> # partial subset : %pin%
> rule_interest_pin <- subset(Epub_rule_2, items %pin% c("60e"))
> inspect(rule_interest_pin)
   lhs          rhs       support     confidence lift    
60 {doc_60e} => {doc_6bf} 0.002670227 0.2745098  21.06227
61 {doc_6bf} => {doc_60e} 0.002670227 0.2048780  21.06227

 

 

 

 

Rule의 왼쪽에 "doc_6e8"과 "doc_6e9" item을 동시에 정확히 가지고 있는 rule을 "ain" 을 사용해서 선별해보면 아래와 같습니다.

 

> rule_interest_lhs_ain <- subset(Epub_rule_2, lhs %ain% c("doc_6e8", "doc_6e9"))
> inspect(rule_interest_lhs_ain)
    lhs                  rhs       support     confidence lift    
[1] {doc_6e8,doc_6e9} => {doc_6e7} 0.001080806 0.8947368  402.094

 

 

 

 

support, confidence, lift 조건을 추가해서 부분집합(subset)을 취할 수도 있습니다.  아래 예는 신뢰도(confidence) 0.25 초과하는 rule 을 선별하라는 조건을 추가하였습니다.  참 편하지요?!

 

> # partial subset with confidence condition : %pin%, confidence
> rule_interest_pin_conf <- subset(Epub_rule_2, items %pin% c("60e") & confidence > 0.25)
> inspect(rule_interest_pin_conf)
   lhs          rhs       support     confidence lift    
60 {doc_60e} => {doc_6bf} 0.002670227 0.2745098  21.06227 

 

 

 

 

5. 연관규칙의 시각화 : arulesViz package

 

arulesViz package를 사용해서 연관규칙을 시각화해보겠습니다.

 

 

  • Scatter plot for association rules 

> install.packages("arulesViz")
> library(arulesViz)

>

> # scatter plot of association rules
> plot(Epub_rule_2)

 

 

 

 

  • Grouped matrix for assocation rules

> # grouped matrix for association rules
> plot(sort(Epub_rule_2, by = "support")[1:20], method = "grouped")

 

* 65개 rule을 모두 그리니깐 너무 작게 나와서 support 기준 상위 20개만 선별해서 그렸음

 

 

  • Network Graph for assocation rules

참고로 아래 그래프의 원은 item element가 아니라 {item} → {item} 연관규칙의 지지도(support)를 나타냅니다. 지지도에 따라 원의 크기가 비례합니다. 색깔은 향상도(Lift)를 나타냅니다. 색깔이 진할수록 향상도가 높습니다. 그런데 화살표(from lhs to rhs)가 그려지다 말아서 그래프가 영... 어색합니다. -_-???

 

 

> # Graph for association rules
> plot(Epub_rule_2, method = "graph", control = list(type="items"))

 

 

 


위의 65개 연관규칙 그래프의 라벨 글자 크기(label font size, default = 1)를 줄이고, 화살표 크기(arrow size, default = 1)도 조금 잘게 해보겠습니다.   네트워크 그래프 그릴 때 사용하는 igraph 패키지의 파라미터 설정 방법 사용하면 됩니다. 위의 그래프보다는 아주 조금 더 나은거 같기는 한데요, 많이 좋아보인다는 느낌은 안드네요. ^^;; (그래프 그릴 때마다 위치가 조금씩 달라지므로 제가 화면 캡쳐해놓은 거랑은 아마 다르게 그려질 거예요)



> # changing font size(vertex.label.cex), arrow 

> plot(Epub_rule_2, method = "graph", 

+      control = list(type="items"), 

+      vertex.label.cex = 0.7, 

+      edge.arrow.size = 0.3,

+      edge.arrow.width = 2)

 


Edge : 선 관련 파라미터

 Vertex : 점 관련 파라미터

- edge.color : 지정 (default = "darkgrey")

- edge.width :

- edge.arrow.size : 화살 크기

- edge.arrow.width : 화살

- edge.arrow.mode : 화살 머리 유형 (0 : 없음,  1 : 역방향,  2 : 순방향,   3 : 양방향)

(무방향 네트워크의 경우 default = 0)

 

- edge.lty : 유형 ("solid", "dashed", "dotted", "dotdash", "longdash", "twodash")

- edge.label : 레이블

- edge.label.family : 레이블 종류 ("serif", "sans", "mono" )

- edge.label.font : 레이블 글자형 (1 : plain text, 2 : bold, 3 : italic, 4 : bold italic)

- edge.label.cex : 레이블 크기 (default = 1)

- edge.label.color : 레이블 (default = "navy") 

 - vertex.size : 크기, vector 가능 (default = 15)

- vertex.color : (default = "SkyBlue2")

- vertex.frame.color : 윤곡의 (default = "black")

- vertex.shape : 형태 ("circle", "square", "rectangle", "none", default = "circle")

 

- vertex.label : 레이블 (vector)

- vertex.label.family : 레이블 종류 ("serif", "sans", "mono" )

- vertex.label.font : 레이블 글자형 (1 : plain text, 2 : bold, 3 : italic, 4 : bold italic)

- vertex.label.cex : 레이블 크기 (default = 1)

- vertex.label.dist : 중심과 레이블 거리 (default = 0)

- vertex.label.degree : 레이블 방향(radian) ( : 0, : pi, : -pi/2, : pi/2)

- vertex.label.color : 레이블 (default = "navy")

* igraph 참고 : http://rfriend.tistory.com/221





Network graph for association rules 그래프 해석을 좀더 쉽게 할 수 있도록 아래 그래프의 몇 개의 item 간 연관규칙 그래프 옆에다가 association rule(left-hand => right-hand rule, support, confidence, lift) 분석 결과를 매핑해서 표시를 해보았습니다.  item 과 item 의 연관규칙 관계를 화살표로 나타내구요, 원의 크기는 지지도, 원의 색깔은 향상도를 나타냅니다. 


  • 화살표 (arrow) : left-hand => right-hand rule 의 방향(direction from left to right)을 나타냄
  • 원의 크기 (circle size) : 지지도(support)에 비례해서 커짐
  • 원의 색깔 (circle color) : 향상도(lift)에 비례해서 색이 진해짐





연관규칙 그래프 시각화를 좀더 이쁘게 하려면 연관규칙 개수를 20개 이내로 줄여주면 됩니다. 아래는 연관규칙 55~65번째 (11개 규칙) 만 선별해서 type = "items" 로 그려본 것인데요, label 글자 크기나 화살표 등이 전혀 거슬리지 않고 자연스럽지요?


[ 그림 1]  Graph-based visualization with item and rules as vertices



> plot(Epub_rule_2[55:65], method = "graph", control = list(type="items"))



 




type = "itemsets" 으로 설정을 해주면 아래의 그래프 처럼 "item-set" (가령, {doc_6e8, doc_6e9}, {doc_6e7, doc_6e9} 처럼 여러개 item 들이 들어 있는 바구니) 끼리의 연관규칙 관계를 시각화해줍니다. 

  • 화살표 두께(width) : item-set 간 연관규칙 지지도(support)에 비례하여 커짐
  • 화살표 색깔(color) : item-set 간 연관규칙 향상도(lift)에 비례하여 진해짐

type = "items" (위의 [그림1]) 일 때와 type = "itemsets" (아래의 [그림 2]) 일때의 동그라미로 표시해 둔 부분을 유심히 비교해서 살펴보시면 서로 연관규칙을 어떻게 표현하는 것인지 이해할 수 있을 것입니다. 서로 장단점이 있지요? 



[ 그림 2]  Graph-based visualization with item-sets as vertices



> plot(Epub_rule_2[55:65], method="graph", control=list(type="itemsets"))

 






 

6. 연관규칙을 CSV 파일로 저장

 

마지막으로 write() 함수를 사용해서 분석한 연관규칙을 CSV 파일로 저장해보겠습니다.  나중에 엑셀로 불러다가 후속 분석/작업하는데 필요할 수도 있겠지요?  file = "경로" 지정할 때 경로구분표시가 '\'가 아니라 '/' 로 해주어야 하는 것에 주의하시기 바랍니다. Windows 탐색기의 경로 그대로 복사해다가 붙이면 경로구분표시가 '\' 되어 있어서 오류납니다.

 

> # saving in CSV format : write() > write(Epub_rule_2, + file = "C:/Users/Owner/Documents/R/Epub_rule.csv", + sep = ",", + quote = TRUE, + row.names = FALSE)

 

 

 

마지막으로 as() 함수를 이용하여 연관규칙을 데이터프레임(dataframe) 구조로 변환해서 저장해보겠습니다.  연관규칙이 데이터프레임으로 되어있으면 다른 분석할 때 가져다 쓰기에 편하겠지요?

 

> # transforming into dataframe
> Epub_rule_df <- as(Epub_rule_2, "data.frame")

 

 

> str(Epub_rule_df)
'data.frame':	65 obs. of  4 variables:
 $ rules     : Factor w/ 65 levels "{doc_16e} => {doc_4ac}",..: 22 23 14 44 26 20 43 41 42 38 ...
 $ support   : num  0.00121 0.00121 0.00108 0.00108 0.00108 ...
 $ confidence: num  0.655 0.559 0.205 0.37 0.333 ...
 $ lift      : num  303.1 303.1 11.2 114 114 ...

 

 

 

데이터프레임으로 만들었으니 이전 포스팅에서 배웠던 IS(Interest-Support) Measure 와 교차지지도(cross support) 흥미측도를 생성할 수 있습니다.  R arules 패키지에서 자동으로 생성해주는 것은 지지도(support), 신뢰도(confidence), 향상도(lift) 3개뿐이다 보니 IS측도나 교차지지도는 직접 코딩해서 계산해줘야 합니다. 

 

아래 예시는 IS 기준으로 내림차순한 다음에 IS측도 상위 10개만 indexing한 것입니다.  (교차지지도는 최소지지도, 최대지지도 구해서 나눠줘야 하는 복잡함이 있으므로 패쓰... ^^; )

 

> # IS(Interest-Support) measure = sqrt(lift(A,B)*support(A,B))
> Epub_rule_df <- transform(Epub_rule_df, IS = sqrt(lift*support))
> Epub_rule_df[order(-Epub_rule_df$IS), ][1:10, ]
                            rules     support confidence     lift        IS
65 {doc_6e7,doc_6e8} => {doc_6e9} 0.001080806  0.8095238 454.7500 0.7010682
64 {doc_6e7,doc_6e9} => {doc_6e8} 0.001080806  0.8500000 417.8016 0.6719840
63 {doc_6e8,doc_6e9} => {doc_6e7} 0.001080806  0.8947368 402.0947 0.6592317
9          {doc_6e9} => {doc_6e7} 0.001271537  0.7142857 321.0000 0.6388766
10         {doc_6e7} => {doc_6e9} 0.001271537  0.5714286 321.0000 0.6388766
7          {doc_6e9} => {doc_6e8} 0.001207960  0.6785714 333.5391 0.6347454
8          {doc_6e8} => {doc_6e9} 0.001207960  0.5937500 333.5391 0.6347454
13         {doc_6e8} => {doc_6e7} 0.001335113  0.6562500 294.9187 0.6274950
14         {doc_6e7} => {doc_6e8} 0.001335113  0.6000000 294.9187 0.6274950
1          {doc_506} => {doc_507} 0.001207960  0.6551724 303.0943 0.6050833

 

 

 

이상으로 R arules 패키지를 사용해서 연관규칙 분석하는 방법을 마치도록 하겠습니다.

 

다음번 포스팅에서는 범주형 데이터의 연관분석에 대하여 알아보도록 하겠습니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡'를 꾸욱 눌러주세요.

 


 

 

연관규칙 분석을 위해 transactions format으로 데이터를 변환하는 방법에 대한 질문이 자주 있어서 아래와 같이 데이터 유형별로 예를 들어 정리하였습니다. 참고하세요.

 

 

##==== [참고] List를 transactons format 으로 변환하기 ====

 

 

> ##------------------------------------------
> ## List -> transactions 자료로 변환
> ##------------------------------------------
> # transaction list
> tr_list <- list(c("a", "b"), 
+                 c("a", "c"), 
+                 c("b", "c", "d"), 
+                 c("a", "e"), 
+                 c("c", "d", "e"))
> # set transaction names
> names(tr_list) <- paste("tr", c(1:5), sep = "_")
> tr_list
$tr_1
[1] "a" "b"

$tr_2
[1] "a" "c"

$tr_3
[1] "b" "c" "d"

$tr_4
[1] "a" "e"

$tr_5
[1] "c" "d" "e"

> tr <- as(tr_list, "transactions")
> tr
transactions in sparse format with
 5 transactions (rows) and
 5 items (columns)
> summary(tr)
transactions as itemMatrix in sparse format with
 5 rows (elements/itemsets/transactions) and
 5 columns (items) and a density of 0.48 

most frequent items:
      a       c       b       d       e (Other) 
      3       3       2       2       2       0 

element (itemset/transaction) length distribution:
sizes
2 3 
3 2 

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    2.0     2.0     2.0     2.4     3.0     3.0 

includes extended item information - examples:
  labels
1      a
2      b
3      c

includes extended transaction information - examples:
  transactionID
1          tr_1
2          tr_2
3          tr_3

 

 

 

 

##==== [참고] Matrix를 transactions format 으로 변환하기 ====

 

 

> ##-------------------------------------------
> ## Matrix -> transactions 자료로 변환
> ##-------------------------------------------
> tr_matrix <- matrix(c(1, 1, 0, 0, 0, 
+                       1, 0, 1, 0, 0, 
+                       0, 1 , 1, 1, 0, 
+                       1, 0, 0, 0, 1, 
+                       0, 0, 1, 1, 1), 
+                     ncol = 5)
> # set dim names
> dimnames(tr_matrix) <- list(c("a", "b", "c", "d", "e"),
+ paste("tr", c(1:5), sep = "_"))
> tr_matrix
  tr_1 tr_2 tr_3 tr_4 tr_5
a    1    1    0    1    0
b    1    0    1    0    0
c    0    1    1    0    1
d    0    0    1    0    1
e    0    0    0    1    1
> # coerce into transactions
> tr2 <- as(tr_matrix, "transactions")
> tr2
transactions in sparse format with
 5 transactions (rows) and
 5 items (columns)
> summary(tr2)
transactions as itemMatrix in sparse format with
 5 rows (elements/itemsets/transactions) and
 5 columns (items) and a density of 0.48 

most frequent items:
   tr_3    tr_5    tr_1    tr_2    tr_4 (Other) 
      3       3       2       2       2       0 

element (itemset/transaction) length distribution:
sizes
2 3 
3 2 

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    2.0     2.0     2.0     2.4     3.0     3.0 

includes extended item information - examples:
  labels
1   tr_1
2   tr_2
3   tr_3

includes extended transaction information - examples:
  transactionID
1             a
2             b
3             c

 

 

 

 

##==== [참고] DataFrame을 transactions format 으로 변환하기 ( 1 ) ====

 

 

> ##------------------------------------------------
> ## data.frame -> transactions 자료로 변환
> ##------------------------------------------------
> tr_dataframe <- data.frame(
+   age = as.factor(c("30대", "20대", "30대", "40대", "10대")), 
+   grade = as.factor(c("A", "B", "A", "A", "C")))
> 
> # coerce into transactions
> tr3 <- as(tr_dataframe, "transactions")
> 
> tr3
transactions in sparse format with
 5 transactions (rows) and
 7 items (columns)
> summary(tr3)
transactions as itemMatrix in sparse format with
 5 rows (elements/itemsets/transactions) and
 7 columns (items) and a density of 0.2857143 

most frequent items:
 grade=A age=30대 age=10대 age=20대 age=40대  (Other) 
       3        2        1        1        1        2 

element (itemset/transaction) length distribution:
sizes
2 
5 

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
      2       2       2       2       2       2 

includes extended item information - examples:
    labels variables levels
1 age=10대       age   10대
2 age=20대       age   20대
3 age=30대       age   30대

includes extended transaction information - examples:
  transactionID
1             1
2             2
3             3 

 

 

 

##==== [참고] DataFrame을 transactions format 으로 변환하기 ( 2 ) =====

 

 

> ## as(split([dadaframe[,"itemID"], dataframe[,"transactionID"]), "transactions") 함수
> ##-- making data.frame
> transactionID <- c(rep("tr1", 3), rep("tr2", 4))
> itemID <- c("item1", "item2", "item3", "item1", "item2", "item4", "item5")
> tr_df <- data.frame(transactionID, itemID)
> str(tr_df)
'data.frame': 7 obs. of  2 variables:
$ transactionID: Factor w/ 2 levels "tr1","tr2": 1 1 1 2 2 2 2
$ itemID       : Factor w/ 5 levels "item1","item2",..: 1 2 3 1 2 4 5
>
> ## converting data.frame to transactions format
> tr <- as(split(tr_df[,"itemID"], tr_df[,"transactionID"]), "transactions")
> inspect(tr)
    items                     transactionID
[1] {item1,item2,item3}       tr1         
[2] {item1,item2,item4,item5} tr2 

 


## ==== [참고] TimeStamp 가 있는 거래 데이터 text 파일을 읽어와서 Sequence analysis를 할 수 있는 transactions format 으로 변환하기 

* 예제 거래 데이터 text 파일: 

tr.txt


* 순차규칙분석(Sequence analysis)는 https://rfriend.tistory.com/195 를 참고하시기 바랍니다. 


아래와 같은 거래 데이터 text 파일이 있다고 하겠습니다. 변수 이름은 순서대로 "X", "sequenceID", "eventID", "SIZE", "item" 입니다. 



0 GSFS1480140045034589400 2019-02-13 1 "TV"

1 GSFS1480140045034589400 2019-03-19 1 "AC"

2 GSFS1480140045034589400 2019-08-01 1 "CA"

3 GSFS1480140045034589400 2019-11-13 1 "RF"

4 GSFS1480151310065913100 2019-04-18 1 "AC"

5 GSFS1480151310065913100 2019-06-15 1 "AC, TV"

 



위의 거래 데이터 text 파일을 나중에 순차분석(Sequence analysis)을 할 수 있는 transactions format 으로 불러오려면 "arulesSequences" 패키지의 read_baskets() 함수를 사용하면 되는데요, 이때 구분자(seperator)를 지정해주고 (이 예에서는 1 space " "), 라벨 정보(label information) 을 지정해주어야 합니다. (제일 마지막의 "item" 이름은 생략). 만약 read_baskets() 함수 안에서 info = c() 를 지정해주지 않으면 칼럼 하나에 전체 데이터가 모두 들어가게 되어 이후의 순차분석을 진행할 수 없습니다. 


eventID 가 요인형(factor)으로 불어와졌으므로 시간 순서를 부여하기 위해 as.Date() 함수를 사용하여 날짜형 변수로 변환해주었습니다. 


transactions format으로 준비가 되었으면 cspade() 함수를 사용하여 순차분석을 실시해 순차 규칙을 도출하고, summary() 와 as(seq_rule, "data.frame") 으로 순차 규칙을 보기 좋게 출력해보았습니다.  



# install and load arulesSequences package

install.packages("arulesSequences")

library("arulesSequences")


# read text file with label information

> tr <- read_baskets(con = "/Users/ihongdon/Downloads/tr.txt", 

+                    sep = " ", 

+                    info = c("X", "sequenceID", "eventID", "SIZE"))

Warning message:

In read_baskets(con = "/Users/ihongdon/Downloads/tr.txt", sep = " ",  :

  'eventID' is a factor

> str(tr)

Formal class 'transactions' [package "arules"] with 3 slots

  ..@ data       :Formal class 'ngCMatrix' [package "Matrix"] with 5 slots

  .. .. ..@ i       : int [1:7] 4 0 2 3 0 1 5

  .. .. ..@ p       : int [1:7] 0 1 2 3 4 5 7

  .. .. ..@ Dim     : int [1:2] 6 6

  .. .. ..@ Dimnames:List of 2

  .. .. .. ..$ : NULL

  .. .. .. ..$ : NULL

  .. .. ..@ factors : list()

  ..@ itemInfo   :'data.frame': 6 obs. of  1 variable:

  .. ..$ labels: chr [1:6] "\"AC\"" "\"AC," "\"CA\"" "\"RF\"" ...

  ..@ itemsetInfo:'data.frame': 6 obs. of  4 variables:

  .. ..$ X         : int [1:6] 0 1 2 3 4 5

  .. ..$ sequenceID: Factor w/ 2 levels "GSFS1480140045034589400",..: 1 1 1 1 2 2

  .. ..$ eventID   : Factor w/ 6 levels "2019-02-13","2019-03-19",..: 1 2 5 6 3 4

  .. ..$ SIZE      : int [1:6] 1 1 1 1 1 1

> as(tr, "data.frame")

       items X              sequenceID    eventID SIZE

1     {"TV"} 0 GSFS1480140045034589400 2019-02-13    1

2     {"AC"} 1 GSFS1480140045034589400 2019-03-19    1

3     {"CA"} 2 GSFS1480140045034589400 2019-08-01    1

4     {"RF"} 3 GSFS1480140045034589400 2019-11-13    1

5     {"AC"} 4 GSFS1480151310065913100 2019-04-18    1

6 {"AC,,TV"} 5 GSFS1480151310065913100 2019-06-15    1

> # transforming eventID from factor to Date type for sequence analysis

> transactionInfo(tr)$eventID <- as.Date(transactionInfo(tr)$eventID, origin="2015-04-01")

> str(tr)

Formal class 'transactions' [package "arules"] with 3 slots

  ..@ data       :Formal class 'ngCMatrix' [package "Matrix"] with 5 slots

  .. .. ..@ i       : int [1:7] 4 0 2 3 0 1 5

  .. .. ..@ p       : int [1:7] 0 1 2 3 4 5 7

  .. .. ..@ Dim     : int [1:2] 6 6

  .. .. ..@ Dimnames:List of 2

  .. .. .. ..$ : NULL

  .. .. .. ..$ : NULL

  .. .. ..@ factors : list()

  ..@ itemInfo   :'data.frame': 6 obs. of  1 variable:

  .. ..$ labels: chr [1:6] "\"AC\"" "\"AC," "\"CA\"" "\"RF\"" ...

  ..@ itemsetInfo:'data.frame': 6 obs. of  4 variables:

  .. ..$ X         : int [1:6] 0 1 2 3 4 5

  .. ..$ sequenceID: Factor w/ 2 levels "GSFS1480140045034589400",..: 1 1 1 1 2 2

  .. ..$ eventID   : Date[1:6], format: "2019-02-13" "2019-03-19" "2019-08-01" ...

  .. ..$ SIZE      : int [1:6] 1 1 1 1 1 1

>

>

> transactionInfo(tr)

  X              sequenceID    eventID SIZE

1 0 GSFS1480140045034589400 2019-02-13    1

2 1 GSFS1480140045034589400 2019-03-19    1

3 2 GSFS1480140045034589400 2019-08-01    1

4 3 GSFS1480140045034589400 2019-11-13    1

5 4 GSFS1480151310065913100 2019-04-18    1

6 5 GSFS1480151310065913100 2019-06-15    1

> # Sequence Rule analysis

> seq_rule <- cspade(tr, 

+                    parameter = list(support = 0.1, maxsize = 5, maxlen = 4), 

+                    control = list(verbose = TRUE))


parameter specification:

support : 0.1

maxsize :   5

maxlen  :   4


algorithmic control:

bfstype  : FALSE

verbose  :  TRUE

summary  : FALSE

tidLists : FALSE


preprocessing ... 1 partition(s), 0 MB [0.023s]

mining transactions ... 0 MB [0.013s]

reading sequences ... [0.011s]


total elapsed time: 0.047s

Warning message:

In makebin(data, file) : 'eventID' is a factor

> summary(seq_rule)

set of 21 sequences with


most frequent items:

   "AC"    "CA"    "RF"    "TV"    "AC, (Other) 

     11       8       8       8       4       4 


most frequent elements:

 {"AC"}  {"CA"}  {"RF"}  {"TV"}  {"AC,} (Other) 

     11       8       8       8       2       4 


element (sequence) size distribution:

sizes

1 2 3 4 

7 9 4 1 


sequence length distribution:

lengths

1 2 3 4 

6 9 5 1 


summary of quality measures:

    support      

 Min.   :0.5000  

 1st Qu.:0.5000  

 Median :0.5000  

 Mean   :0.5238  

 3rd Qu.:0.5000  

 Max.   :1.0000  


includes transaction ID lists: FALSE 


mining info:

 data ntransactions nsequences support

   tr             6          2     0.1

>

> # sequence rule as a DataFrame format

> as(seq_rule, "data.frame")

                        sequence support

1                       <{"AC"}>     1.0

2                       <{"AC,}>     0.5

3                       <{"CA"}>     0.5

4                       <{"RF"}>     0.5

5                       <{"TV"}>     0.5

6                        <{TV"}>     0.5

7                 <{"AC"},{TV"}>     0.5

8                   <{"AC,,TV"}>     0.5

9            <{"AC"},{"AC,,TV"}>     0.5

10               <{"AC"},{"RF"}>     0.5

11               <{"CA"},{"RF"}>     0.5

12               <{"TV"},{"RF"}>     0.5

13        <{"TV"},{"CA"},{"RF"}>     0.5

14        <{"TV"},{"AC"},{"RF"}>     0.5

15        <{"AC"},{"CA"},{"RF"}>     0.5

16 <{"TV"},{"AC"},{"CA"},{"RF"}>     0.5

17               <{"AC"},{"CA"}>     0.5

18               <{"TV"},{"CA"}>     0.5

19        <{"TV"},{"AC"},{"CA"}>     0.5

20               <{"AC"},{"AC,}>     0.5

21               <{"TV"},{"AC"}>     0.5

 



많은 도움 되었기를 바랍니다.

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. :-)

 

728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 연관규칙(association rule)의 평가척도로서 지지도(support), 신뢰도(confidence), 향상도(lift), IS측도(Interest-Support), 교차지지도(cross support) 에 대하여 알아보았습니다.

 

이번 포스팅에서는 연관규칙 (1세대) 알고리즘으로서 Apriori algorithm 에 대해 소개하도록 하겠습니다.  알고리즘을 이해하면 컴퓨터 내부에서 무슨 일이 일어나고 있는지, 컴퓨터가 어떻게 그 많은 연산을 효율적으로 수행하는지 원리를 알 수 있습니다.

 

 

 

1) 왜 효율적인 연관규칙 탐색 알고리즘이 필요한가?

 

거래에서 나타나는 모든 항목들의 집합(item set)을 이라고 할 때, 모든 가능한 부분집합의 개수는 공집합을 제외하고 개 입니다.

 

그리고 모든 가능한 연관규칙의 개수입니다.

 

이를 그래프로 나타내면 아래와 같은데요, 가능한 부분집합의 개수나 연관규칙의 개수가 item 이 증가할 때 마다 지수적으로 증가함을 알 수 있습니다.

 

item이 5개이면 subset 개수가 31개, rule 개수가 180개가 되며, => item이 10개만 되어도 subset 개수가 1023개, rule 개수가 57002 개가 됩니다.  이렇게 지수적으로 증가하는 subset과 rule들을 연필과 종이를 가지고 일일이 계산한다는 것은 미친짓입니다.  그리고 컴퓨터로 계산한다고 해도 계산복잡도와 필요 연산량이 어마무시하게 많아져서 시간이 굉~장히 오래 걸립니다.(심하면 하루를 꼬박 넘기고, 이틀, 사흘....)  이러므로 "빠르고 효율적인 연관규칙 계산 알고리즘"과 "연관규칙 평가 측도(기준)"이 필요한 것입니다.  

 

 

 

 

 

5개의 원소 항목을 가지는 I={A, B, C, D, E} 에 대하여 가능한 모든 항목집합을 예시로 풀어보면 아래와 같습니다. 

 

 

 

 

 

2) 연관규칙 생성 전략 및 Algorithm에는 무엇이 있나?

 

부분집합의 개수가 2^k - 1 개로서 지수적으로 증가하기 때문에 모든 경우의 수에 대해 지지도를 계산하는 것이 연산량이 엄청납니다. 그래서 연산량을 줄이기 위해 아래의 3가지 전략 중의 하나를 사용합니다.

 

1) 모든 가능한 항목집합의 개수(M)를 줄이는 전략 ▶ Apriori algorithm

2) Transaction 개수(N)을 줄이는 전략 ▶ DHP algorithm

3) 비교하는 수(W)를 줄이는 전략 ▶ FP-growth algorithm

 

 

 

3) 빈발항목집합을 추출하는 Apriori algorithm 의 원리, 원칙은 무엇인가?

 

위의 3개의 알고리즘 중에서 1세대 Apriori algorithm에 대해서만 예를 들어서 설명해보겠습니다.

 

최소지지도 이상을 갖는 항목집합을 빈발항목집합(frequent item set)이라고 합니다.  모든 항목집합에 대한 지지도를 계산하는 대신에 최소 지지도 이상의 빈발항목집합만을 찾아내서 연관규칙을 계산하는 것이 Apriori algorithm의 주요 내용입니다. 

 

빈발항목집합 추출의 Apriori Principle

 

1) 한 항목집합이 빈발(frequent)하다면 이 항목집합의 모든 부분집합은 역시 빈발항목집합이다.
(frequent item sets -> next step) 

 

2) 한 항목집합이 비비발(infrequent)하다면 이 항목집합을 포함하는 모든 집합은 비빈발항목집합이다. (superset -> pruning)

 

 

Apriori Pruning Principle


If there is any itemset which is infrequent, its superset should not be generated/tested
(Agrawal & Srikant @VLDB’94, Mannila, et al. @ KDD’ 94)

 

위의 Apriori Pruning Principal 을 도식화한 예시는 아래와 같습니다.  아래 예시 그림처럼 {A, B} item set이 비빈발항목(infrequent item set)이면 그 및에 {A, B}를 포함해서 줄줄이 딸린 {A, B, C}, {A, B, D}, {A, B, E}, {A, B, C, D}, {A, B, C, E}, {A, B, D, E}, {A, B, C, D, E}도 역시 비빈발항목인, 영양가 없는 superset 일 것이므로 볼 필요도 없으니 (안봐도 비디오...), 아예 처음부터 가지치기(pruning)를 하라는 것입니다. 

 

 

 

{A, B, C, D, E}의 5개 원소 항목을 가지는 4건의 transaction에서 minimum support 2건 (=2건/총4건=0.5) 기준으로 pruning 하는 예를 들어보겠습니다.

 

 

 

위의 예시를 tree 형식으로 색깔로 infrequent item set과 그의 하위 superset을 나타내보면 아래와 같습니다.  색깔 칠해진 superset 들은 가지치기(pruning) 당해서 지지도 계산을 하지 않게 됩니다.

 

 

[그림 1]

 

 

 

위에서 예와 그림으로 소개한 빈발항목집합 추출 Pseudo Aprior algorithm 은 아래와 같습니다.

 

Pseudo Apriori algorithm

 

[Reference] "Fast Algorithms for Mining Association Rules", Rakesh Agrawal, Ramakrishman Srikant, 1994

 

(위의 (3)번 apriori-gen(Lk-1) 에서 (k-1)-항목 빈발항목집합후보를 생성하고, (9)번에서 minimum support  count 보다 큰 빈발항목집합만 추출, 즉 최소지지도 미만은 pruning)

 

 

4) 빈발항목집합의 후보를 생성하고 연관규칙을 도출하는 Apriori algorithm의 원리는?

 

이후에 빈발항목집합의 후보(candidates list)를 생성하고, 연관규칙을 생성한 후에, 최소신뢰도 기준 (minimun confidence criteria)를 적용해서 최소 신뢰도에 미달하는 연관규칙은 제거(pruning)하게 됩니다. 

 

빈발항목집합 후보를 생성하기 위해, (k-1)-항목 빈발항목집합에서 처음 (k-2) 항목이 같은 항목들만 혼합하여 k-항목 빈발항목집합 후보를 생성합니다. 

아래에 2-항목 빈발항목집합 을 가지고 3항목 빈발항목후보 를 생성하는 예를 들어보겠습니다.  2-항목 빈발항목집합에서 (k-1)-항목, 즉 1-항목이 같은 항목은 노란색을 칠한 {B}항목입니다. 따라서 {B}항목이 포함된 {B, C}와 {B, E}를 혼합해서 k-항목 빈발항목집합, 즉 3-항목 빈발항목집합 후보를 만들면 {B, C, E} 가 됩니다. 나머지 {A, B}, {C, E}는 무시하게 됩니다.  실제로 위의 [그림1]에서 살아남은 3-항목 빈발항목집합이 {B, C, E} 입니다 (3-항목 빈발항목의 나머지 항목집합은 superset으로서 pruned 됨).

 

 

[그림2]

 

[Reference] "R, SAS, MS-SQL을 활용한 데이터마이닝", 이정진, 자유아카데미, 2011

 

 

빈발항목집합을 도출했으므로 이제 연관규칙을 생성해보겠습니다.  빈발항목집합 L의 항목들을 공집합이 아닌 두 개의 서로 다른 부분집합 X와 Y로 나누어 하나의 연관규칙 X → Y를 만들었다고 합시다. k-항목 빈발항목집합 L은 최대 개(공집합과 전체집합 제외)의 연관규칙을 만들수가 있으며, 이중에서 최소신뢰도(minimum confidence) 조건을 만족하는 연관규칙을 찾으면 됩니다.

 

연관규칙 생성의 Apriori principle


빈발항목집합 L에 대하여 연관규칙 X → Y 가 최소신뢰도 기준을 만족하지 않으면 X의 어떠한 부분집합 X'에 대한 연관규칙 X' → L - X' 도 최소신뢰도 기준을 만족할 수 없다

 

 

3-항목 빈발항목집합 C3 {B, C, E}를 가지고 6개 (=2^k - 2 = 2^3 -2 = 8 - 2 =6개) 의 연관규칙을 만들어보면 아래 그림과 같습니다.  이때 가령 아래 검정색으로 테두리를 친 {C, E} → {B} 연관규칙이 최소신뢰도 기준에 미달했다고 할 경우, 그 밑에 딸린 {C} → {B, E}, {E} → {B, C} 연관규칙은 제거(pruning)하게 됩니다.

 

[그림3]

 

 

[그림1]에서 처럼 비빈발항목(infrequent)에 대해서 최소지지도(minimum support) 기준 미달 항목을 가지치기(pruning)하고 -> [그림2]에서 처럼 빈발항목후보를 생성한 후에 -> [그림3]에서 처럼 최소신뢰도(minimum confidence) 기준 미달하는 연관규칙을 제거해나가는 반복(iteration) 작업을 새로운 연관규칙이 없을 때까지 하게 됩니다.

 

 

다음번 포스팅에서는 R을 가지고 연관규칙 분석하는 예를 들어보겠습니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ♡'를 꾸욱~ 눌러주세요.

 

728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 연관규칙분석, 장바구니분석, 순차분석의 개략적인 정의와 활용에 대해서 알아보았습니다.

 

이번 포스팅에서는 연관규칙(association rule)의 흥미를 평가할 수 있는 척도(interestingness measure) 들로서 지지도, 신뢰도, 향상도, IS측도, 교차지지도에 대해서 알아보겠습니다.

 

(참고. 연관규칙은 비지도학습으로서, Y값에 대한 label이 없는 상태에서 데이터에 숨겨진 패턴을 찾는 분석기법임.  Y값에 대한 label을 가지고 하는 지도학습인 예측이나 분류에서 하는 모델 성과평가와 Y값 label 없이 숨겨진 패턴을 찾는 연관규칙의 흥미척도는 성격이 다름)

 

이들 연관규칙 평가 척도가 중요한 이유는 연관규칙 분석을 하게 되면 수십, 수백, 수천개의 association rule 들이 쏟아지기 때문에 육안으로 일일이 보고 평가하기가 너무 힘들기 때문입니다.  (1) 모래사장에서 보석반지를 눈으로 찾는 방법과, (2) 모래를 거를 수 있는 체(screening filter)에 다가 삽으로 모래를 퍼다가 부어서 체에 걸러진 물건들 속에서 보석반지가 있나 확인하는 방법 중에서 어떤 것이 더 효율적이고 효과적일지 생각해보시면 됩니다.  (2)번  체를 사용하는 후자 방법에서 사용하는 체가 오늘 포스팅의 주제가 되겠습니다.

 

 

X와 Y를 서로 공통원소가 없는 항목들의 집합이라고 하고, X->Y 를 if X then B라는 연관규칙이라고 하며, N은 전체 거래 건수, n(X), n(Y)는 항목집합 X와 Y의 거래 건수(즉, row 개수)라고 했을 때, 지지도(Support), 신뢰도(Confidence), 향상도(Lift)의 정의는 아래와 같습니다.

 

  • 지지도 (Support)

    :
    두 항목 XY의 지지도는 전체 거래 건수 중에서 항목집합 XY를 모두 포함하는 거래 건수의 비율을 말합니다.   지지도는 좋은 규칙(빈도가 많은, 구성비가 높은)을 찾거나, 불필요한 연산을 줄일 때(pruning, 가지치기)의 기준으로 사용합니다.

지지도(support) s(X→Y) 

= X와 Y를 모두 포함하는 거래 수 / 전체 거래 수 = n(X∪Y) / N 


 

  • 신뢰도 (Confidence)

    : 항목집합 X를 포함하는 거래 중에서 항목집합 Y포함하는 거래 비율 (조건부 확률) 을 말합니다.  신뢰도가 높을 수록 유용한 규칙일 가능성 높다고 할 수 있습니다.

신뢰도(Confidence) c(X→Y) 

= X와 Y를 모두 포함하는 거래 수 / X가 포함된 거래 수 = n(X∪Y) / n(X) 

 

 

  • 향상도 (Lift)

    항목집합 X가 주어지지 않았을 때의 항목집합 Y의 확률 대비 항목집합 X가 주어졌을 대 항목집합 Y의 확률 증가 비율을 말합니다. 다른말로 표현하자면, 향상도가 1보다 크거나(+관계) 작다면(-관계) 우연적 기회(random chance)보다 우수함을 의미합니다. (X와 Y가 서로 독립이면 Lift = 1)

향상도(Lift)

= 연관규칙의 신뢰도/지지도 = c(X→Y) / s(Y)

 

 

 

연관규칙 평가 척도 : 지지도(Support), 신뢰도(Confidence), 향상도(Lift)

 

 

아래에 어떤 슈퍼마켓에서 5명의 고객에 의해서 발생한 5건의 거래(transaction N=5)을 가지고 예를 들어보았습니다.

 

 

참고로, 신뢰도(confidence)는 rule의 순서에 따라서 값이 달라집니다. 즉 신뢰도 c(X→Y)와 c(Y→X)의 값이 다르며, 이를 비대칭적 척도(asymmetric measure)라고 합니다.

 

반면에, 향상도(lift)는 Lift(X→Y) 값과 Lift(Y→X)의 값이 서로 같으며, 이런 특성을 가지는 척도를 대칭적 척도(symmetric measure)라고 합니다.  위의 예제를 가지고 한번 직접 계산해서 확인해보시기 바랍니다.

 

 

위의 3개의 rule 평가 척도를 소개하였는데요, 각각의 평가 관점이 다르기 때문에 어느 하나만을 가지고 rule을 평가하는 것이 아니라 보통은 3개의 척도를 모두 사용합니다.

 

보통 (1) 특정 지지도(Support) 와 신뢰도(Confidence) 이하의 rule 은 screening out 시키게끔 해놓고,

(minimun support, minimum confidence)

 

(2) 향상도(Lift) 내림차순(양의 관계를 찾을 때)으로 sorting을 해서 rule을 평가하는 식으로 이용하곤 합니다. 

 

그리고 관심이 있는 상품이나 item이 있으면 목적에 맞게 해당 item이 left-hand side 나 right-hand side 에 있는 rule만을 subset으로 선별해서 보기도 하구요.

 

 

분석에 oriented 된 통계전문가, 기계학습 전문가의 경우 신뢰도(confidence)와 향상도(lift)가 높은 rule을 눈에 불을 켜고 찾고, 선호하는 경향이 있습니다.  그런데 매출과 이익을 책임져야 하는 사업부 현업의 경우는 연관규칙을 보는 view가 조금 다를 수 있습니다.  "그 rule을 적용하면 기대할 수 있는 매출 증가분이 얼마나 되는데요?"라는 질문이 사업부 현업이 던지는 질문인데요, 이 질문에 만족할 만한 답을 주려면 '지지도(Support)'가 높아서 전체 거래 건수 중에서 해당 rule이 포함된 거래건수가 많아야지만이 해당 rule을 가지고 마케팅전략을 수립해서 실전에 적용했을 때 높은 매출 증가를 기대할 수 있게 됩니다.  즉, 아무리 신뢰도(confidence)와 향상도(lift)가 높아도 지지도(support)가 빈약해서 전체 거래 중에 가뭄에 콩나듯이 나오는 거래유형의 rule이라면 사업부 현업은 아마 무시할 겁니다.  현업을 빼고 분석가만 참여한 연관규칙 분석이 위험하거나 아니면 실효성이 떨어질 수 있는 이유입니다.  그리고 지지도(support)가 매우 낮으면 몇 개 소수이 관측치의 치우침만으로도 신뢰도나 향상도가 크게 영향을 받게 되어 '우연'에 의한 규칙이 잘못 선별될 위험도 있습니다.

 

 

위와 같이 지지도(support), 신뢰도(confidence), 향상도(lift)의 한계를 보완하기 위한 다양한 평가척도가 더 있는데요, 그 중에서도 IS(Interest-Support) 측도, 교차지지도(cross support) 에 대해서 간략하게 소개하겠습니다. 

 

연관규칙 A → B 에 대하여

  •  IS(Interest-Support) 측도 : 향상도(lift)와 지지도(support)의 곱에 제곱근을 취한 값

    ☞ 향상도(lift)와 지지도(support)가 모두 높을 수록 IS 측도값도 커짐. 둘 중에 하나라도 작으면 IS측도는 작아지며, 지지도는 낮고 향상도만 높은 rule이나 향상도는 낮고 지지도만 높은 rule을 screening out 시키고 둘다 높은 rule만 선별할 수 있음.

  • 교차지지도(cross support) : 최대지지도에 대한 최소지지도의 비율


    ☞ 항목집합 에 대하여 의미 없는 연관규칙의 생성을 방지하기 위하여 교차지지도 r(X)를 이용함.  분자에 지지도 중에서 최소값을, 분모에는 지지도 중에서 최대값을 가져다가 계산을 하므로 지지도의 최소값과 최대값의 차이가 클 수록 교차지지도는 낮아지게 되며, 이 비율이 매우 작으면 항목집합 X에서 생성되는 연관규칙이 의미가 없을 가능성이 높음.

 

지지도(support), 신뢰도(confidence), 향상도(lift), 이에 더해 IS측도나 교차지지도 등의 척도만을 가지고 기계적으로 연관규칙을 찾았다고 해서 끝나는 것은 아닙니다.  반드시 업 전문가(business domain expert)의 해석, 평가, 판단, 개입이 있어야지 연관규칙분석이 끝이 납니다.

 

 

연관규칙을 (1) 설명이 가능한가? (Explainable), (2) 활용이 가능한가? (Actionable) 라는 두 개의 기준을 가지고 평가를 해봐서 '설명이 가능하고 & 활용이 가능한 연관규칙 (Explainable & Actionable association rule)' 만이 최종적으로 살아남아 현장에 적용이 되고 그 효과를 검증받게 됩니다.

 

아래에 Useful rule, Trivial rule, Inexplicable rule의 예를 보면 금방 이해하실 수 있을 것입니다.  실제 연관규칙 분석을 해보면 rule이 엄청 많이 쏟아지는데 반해, 똘똘한 rule의 최종 판단/선별에 업 전문가의 개입이 필요하다는 점이 현장에서 많이 쓰이지 못하고 있는 장애 요인이 되고 있는게 아닌가 싶습니다.

 

 

 

다음번 포스팅에서는 Apriori algorithm 에 대해서 알아보도록 하겠습니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ♡'를 꾸욱~ 눌러주세요.

 

728x90
반응형
Posted by Rfriend
,

지난 포스팅에서 기계학습의 정의, 학습 및 과적합(overfitting)에 대한 큰 그림, 개략적이고 이론적인 내용을 다루었습니다.

 

이번 포스팅부터는 기계학습 분석 기법의 각론으로 들어가보겠습니다.

 

먼저, Y값(종속변수, 목표변수)이 없는 상태에서 데이터 속에 숨겨져 있는 패턴, 규칙을 찾아내는 비지도학습(unsupervised learning)의 하나인 '연관규칙분석(Association Rule Analysis)', 혹은 유통업계에서 사용하는 용어로 '장바구니분석(Market Basket Analysis)'에 대해서 알아보겠습니다.

 

보통 기계학습, 데이터마이닝 교육을 받는다고 하면 단골메뉴로 나오는 분석 기법이기도 하며, "맥주와 기저귀" 사례(이거 가짜 사례임... -_-')와 함께 많이 회자되곤 합니다.  그러다 보니 '회귀분석' 만큼이나 분석 강의 좀 들어봤다 하는 사람이면 열에 아홉은 연관규칙분석을 들어는 봤고, 그러다보니 만만하게(?) 보는 것도 좀 있는 것 같고요, rule이 엄청 많이 나오는데 그중에서 쓸모있는 것은 별로 찾지 못해서 재미를 잘 못보고 평가절하받는 기법인것도 같습니다.  

 

 

B2C 업종에 종사하는 분이라면 약방의 감초처럼 빼놓을 수 없는게 상품추천(recommendation) 일텐데요, 추천을 위해 많이 사용하는 분석 기법이 연관규칙분석, 순차분석입니다.

 

 

 

상품 추천에 사용하는 분석기법들을 아주 간략히 소개하자면,

  • 연관규칙분석, 장바구니분석 (Association Rule Analysis, Market Basket Analysis) : 고객의 대규모 거래데이터로부터 함께 구매가 발생하는 규칙(: A à 동시에 B)을 도출하여, 고객이 특정 상품 구매 시 이와 연관성 높은 상품을 추천
  • 순차분석 (Sequence Analysis)고객의 시간의 흐름에 따른 구매 패턴(A à 일정 시간 후 B)을 도출하여, 고객이 특정 상품 구매 시 일정 시간 후 적시에 상품 추천
  • Collaborative Filtering모든 고객의 상품 구매 이력을 수치화하고, 추천 대상이 되는 고객A와 다른 고객B에 대해 상관계수를 비교해서, 서로 높은 상관이 인정되는 경우 고객B가 구입 완료한 상품 중에 고객A가 미구입한 상품을 고객A에게 추천
  • Contents-based recommendation고객이 과거에 구매했던 상품들의 속성과 유사한 다른 상품 아이템 중 미구매 상품을 추천 (Collaborative Filtering유사 고객을 찾는 것과 비교됨)
  • Who-Which modeling특정 상품()을 추천하는 모형을 개발 (: 신형 G5 핸드폰 추천 스코어모형)하여 구매 가능성 높은(: 스코어 High) 고객() 대상 상품 추천

등이 있습니다. 

 

 

상품 추천은 이미 몇 십년 전부터 실전에 적용이 되어 왔고, 그 선진 업체들의 경우 효과를 톡톡히 보고 있습니다.

추천은 그 자체로 환전성이 있기 때문에 가치가 있다. 넷플릭스의 경우 대여되는 영화의 2/3가 추천을 통해 발생했으며, 구글 뉴스(Google News)의 경우 38% 이상이 추천을 통해서 조회가 발생하는 것으로 알려져 있다. 또한 아마존의 경우에도 추천을 통해 판매가 전체 매출액의 35%를 넘는다. ...

 

* 출처 : 넷플릭스의 빅데이터, 인문학적 상상력과의 접점, 조영신, KISDI 동향 Focus 

 

물론 연관규칙이나 순차분석만 가지고 상품추천하는 것은 아닙니다만, 연관규칙분석, 순차분석은 상품추천에 활용할 수 있는 가장 기본적인 분석기법임에는 틀림없습니다.  아래에 넥플릭스에서 상품추천에 이용하는 알고리즘 소개글을 보면 사용할 수 있는 데이터를 모조리 모아서, 분석기법을 여러개 조합해서 상품추천을 하고 있는것으로 보입니다.

 

넥플릭스는 이용자들이 동영상에 매긴 별점과 위치정보, 기기정보, 플레이버튼 클릭 수, 평일과 주말에 따른 선호 프로그램, 소셜 미디어 내에서 언급된 횟수 등을 분석해 알고리즘을 개발했다. 

* 출처 : 넷플릭스의 빅데이터, 인문학적 상상력과의 접점, 조영신, KISDI 동향 Focus 

 

 

암튼, 서두가 길었습니다.  연관규칙 본론으로 들어가겠습니다.

 

규칙(rule)이란 "if condition then result"  (if A --> B) 의 형식으로 표현을 합니다.

 

연관규칙(association rule)은 특정 사건이 발생하였을 때 함께 (빈번하게) 발생하는 또 다른 사건의 규칙을 말합니다. 

 

연관규칙에서 사용하는 기본 용어에 대해서 짚고 넘어가자면,

  • 항목 집합 (Item set) : 전체 Item (I) 중에서 가능한 부분 집합,
  • 항목 집합의 집합 (The set of item sets) : Item의 부분집합들로 구성된 집합,

 

연관규칙을 다시 좀 어려운 위의 용어를 사용해서 써보자면, 연관규칙이란 특정 항목 집합이 발생하였을 때 또 다른 항목 집합이 발생하는 규칙을 말합니다.

 

 

가령,

 

{맥주} --> {기저귀} 

  : 맥주를 사는 고객은 기저귀도 같이 산다

 

{남성, 금요일, 맥주} --> {기저귀}

  : 금요일에 맥주를 사는 남성 고객은
    기저귀도 같이 산다

 

같은 규칙이 연관규칙의 예가 되겠습니다.

 

 

 

 

연관규칙분석, 장바구니분석, 순차분석... 용어가 좀 헷갈릴 수 도 있는데요, 개념 이해를 위해 비교를 해보자면요,

 

연관규칙(association rule)은 "What goes WITH what?" 즉, 동시 구매품목에 관심을 가지는데 비해서, 순차분석(sequeuce analysis)은 "What goes AFTER what?" 처럼 시간의 순서에 따른 규칙에 관심을 가집니다.  연관분석할 때는 주문번호, 고객ID, 구매상품코드만 있으면 되는데요, 순차분석을 하려면 "Time-stamp" 변수가 추가로 꼭 필요합니다.

 

장바구니분석(Market basket analysis)는 연관규칙을 유통업에서 부르는 용어입니다. 도식화하자면 장바구니분석은 연관규칙의 부분집합(?)이라고도 할 수 있겠네요.

 

 

 

유통업에서 장바구니분석(연관분석)을 통해 상품 추천뿐만이 아니라 상품 진열이라든지 상품 패키징, 번들링, (홈쇼핑의 경우) 방송순서나 카달로그 배치 등 다방면에 적용을 할 수 있습니다.

 

연관규칙은 유통업말고도 여러 업종에서 사용되는데요, 의료계에서는 암 데이터 분석에서 단백질 서열과 자주 발견되는 DNA 패턴을 찾는다던지, 증상과 질병 간 연관관계 등을 찾는데 연관규칙을 사용합니다.

 

순차분석은 의료비 허위 청구 순서 패턴을 찾는다던지, 휴대폰서비스 이용 부당행위 사전 조합 식별, 불량 유발 공정/장비 패턴 탐지, 웹사이트나 모바일앱의 메뉴별 클릭 스트림 분석 등을 하는데 사용할 수 있습니다.

 

다음번 포스팅에서는 연관규칙의 평가 척도 (지지도, 신뢰도, 향상도)에 대해서 알아보도록 하겠습니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡'를 꼬옥 눌러주세요. ^^

 

728x90
반응형
Posted by Rfriend
,

지난 포스팅에서는 지도학습(Supervised Learning)에 있어서

  - 과적합(Over-fitting)이란 무엇인가?

  - 과적합을 파악하고 피하기 위한 방법은? (How to avoid over-fitting?)


에 대하여 알아보았습니다.

 

이번 포스팅에서는 과적합 이야기 세번째로, Bias-Variance Trade-off, 다른 말로는 Bias-Variance Delimma 에 대해서 소개하도록 하겠습니다.  지난번 소개한 과적합에 나왔던 내용과 핵심은 똑같은데요, Bias와 Variance 용어와 수식을 사용해서 과적합(Over-fitting), 과소적합(Under-fitting)을 다른 view로 풀어보겠습니다.  학습(Training)과 과적합(Over-fitting)에 대해서 정확히 이해하는 것이 매우 매우 중요하므로 이번에 한번 더 복습하는 셈 치면 좋겠습니다.


 

먼저, Wikipedia에서 정의하고 있는 Bias와 Variance의 뜻부터 살펴보겠습니다.

 

  • Bias : Bias는 학습 알고리즘에서 잘못된 가정으로 부터 나오는 에러이다.  높은 bias는 학습 알고리즘이 설명변수(독립변수)와 목표변수(종속변수) 간의 연관성있는 관계를 놓치게 한다.
    ("The bias is error from erroneous assumptions in the learning algorithm. High bias can cause an algorithm to miss the relevant relations between features and target outputs (underfitting).")
  • Variance : Variance는 훈련 데이터 내의 작은 변동에 대한 민감성으로부터 나오는 에러이다. 높은 variance는 의도한(일반화) 학습결과를 내기보다는 훈련 데이터 내의 무작위 소음을 모델링함에 따라 과적합을 야기한다.
    ("The variance is error from sensitivity to small fluctuations in the training set. High variance can cause overfitting: modeling the random noise in the training data, rather than the intended outputs.")

    - From : Wikipedia

 

 

Wikipedia 설명 내용이 좀 어려울 수도 있는데요, 아래 그림을 참고하시면 이해하는데 도움이 될 것 같습니다.

 

Bias는 쉽게 말하면 Truth 값으로 부터 평균이 얼마나 떨어져 있느냐는 척도입니다.  아래 예시 그림에서, Truth 평균으로 부터 Observed 평균이 가까운 (1)번과 (3)번은 Bias가 작고, 평균의 거리가 먼 (2)번과 (4)번은 Bias가 큽니다.

 

Variance는 통계학에서 말하는 '분산', 그 분산입니다.  편차 제곱의 합을 자유도로 나누어준 값이요. (= 표준편차(standard deviation)을 제곱한 값).  아래 그림 예시에서, 퍼진 정도가 좁은 (1)번과 (2)번은 variance가 작고, 퍼진 정도(산포)가 큰 (3)번과 (4)번은 variance가 큽니다.  

 

 

 

군대 다녀오신 분들은 신병교육대랑 자대 배치 후 첫 사격에서 '영점 사격'을 했을 텐데요, '영점 사격' 할 때는 Bias보다 Variance가 중요합니다.  Variance가 작아야지 가늠쇠를 조절해서 Bias를 줄일 수 있거든요.  Bias가 작아도 Variance가 크다면 그건 스나이퍼 기질이 없다는 거고(영점조정을 할 수 없으므로 대책이 없음 -_-;), PRI(피터지고, 알통배고, 이갈리는....) 얼차레 꾀나 받았을 거라고 필자는 감히 예상해봅니다.  (여담으로, 필자는 군대 시절 '스나이퍼' 소리 들었음 ^^v)

 

 

통계학 시간에 정규분포(Normal Distribution)에 대해서 배우셨을 텐데요, 위의 그림에서 소개한 (1) Bias : Low,  Variance : Low,  (2) Bias : High,  Variance : Low,  (3) Bias : Low,  Variance : High, (4) Bias : High,  Variance : High 의 4개 유형을 정규분포 확률밀도함수 그래프로 그려보면 아래와 같습니다.

 

 

 

 

Bias, Variance에 대해서 이제 이해하셨으리라 믿고요, Bias-Variance Trade-off 로 넘어가보겠습니다.

Bias-Variance Trade-off 란

 - Bias를 작게 하려면 Variance가 높아지고 (아래 그림의 오른쪽 Over-fitting 상황),

 - Variance를 작게 하려면 Bias가 커지는 (아래 그림의 왼쪽 Under-fitting 상황)

Delimma 를 말합니다. 

 

즉, Bias와 Variance를 동시에 작게 하기가 불가능하다는 뜻입니다. 

 

Bias 를 작게(Bias : Low) 한다고 계속 Training을 시키면 데이터 셋에 있는 Noise까지 통째로 암기를 해버리는 과적합(over-fitting)에 빠져서, 즉 온갖 x변수를 죄다 가져다 써서 유연성을 높이는 대신에 모델 복잡도를 확 높여버려서, 새로운 데이터에 모델을 적용시키면 제대로 예측이나 분류를 못하고 틀리게(variance : high) 됩니다.

 

 

 

이런 딜레마 상황에서 우리는 Bias를 작게 하는 데 몰빵을 한다거나 (Over-fitting), 혹은 Variance를 작게 하는데 몰빵(Under-fitting)할 수는 없는 법이고, 결국은 Bias와 Variance의 적절한 균형점(위 그림의 optimum model complexity, ie, sweet zone)을 찾게 됩니다. 

 

어떻게 찾느냐구요?  지난번 포스팅에서 소개한 Cross-validation 기법을 사용합니다.  데이터 셋을 Training set, Validation set, Test set으로 나누어서 -> Training set으로 훈련시켜 모형을 만들고 (iteration....) --> Validation set을 사용해서 over-fitting 시작하는 지점을 탐지해서 적정 시점에 훈련을 중지시킨 후에 (Over-fitting 방지) --> Test set으로 최종 모델의 성능을 평가합니다.

 

 

위의 그림, 그래프로 직관적으로 이해할 수 있도록 설명하였다면, 좀 어렵더라도 통계 수식으로 풀어보면 아래와 같습니다.  'Variance of the fit'과 (Bias of the fit)^2 은 trade-off 관계에 있으므로, 둘 모두를 동시에 작게 할 수는 없습니다.

 

 

 

[Reference]  “The Bias-Variance Tradeoff ,Cross-Validation and Over-fitting in Prediction”, 
               Professor. George S. Easton

 

 

과적합을 피하는데 샘플을 많이 확보한다거나, 독립변수의 수를 줄이는 것 또한 도움이 됩니다.  나중에 (회귀분석 포스팅 후반부에) 변수 선택기법으로 LASSO (The Least Absolute Shrinkage and Selection Operator) 소개하면서 Bias, Variance 개념 사용하니 잘 알아두시면 좋겠습니다.

 

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ♡~' 단추를 꾸욱~ 눌러주세요. ^^

 

728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 과적합(Over-fitting)이란 무엇인지, 그리고 과적합이 왜 문제인지에, 과적합이 아니라 데이터에 내재한 구조, 관계, 규칙을 일반화(generalization)하여 적정적합을 시킬 수 있도록 학습하는 것이 왜 중요한지에 대하여 알아보았습니다.

 

그렇다면 이번 포스팅에서는 어떻게 과적합을 파악하고 피할 수 있는지(How to detect and prevent over-fitting)에 대하여 소개하도록 하겠습니다. 그것은 바로 'Validation Set'을 활용하는 방법(Cross-Validation)입니다.

 

기계학습, 데이터마이닝 초심자라면 과적합(Over-fitting)을 정확히 이해하기 힘들 수도 있구요, 과적합을 이해했다고 하더라도 Training set vs. Validation set vs. Test set 으로 데이터셋을 나누어서 훈련시키는 과정에서 검증하고, 마지막 모형 결과를 테스트하는 구조, 절차를 이해하는게 처음에는 좀 힘들 수도 있을 것 같습니다.  (제가 처음 배울 때에 이걸 잘 이해를 못했었어요... ^^;;) 

 

이걸 제대로 이해하지 못하면 분석가가 가지고 있는 데이터셋을 몽땅 집어넣어서 예측이나 분류 모델을 만들다가 과적합(over-fitting)의 함정에 빠지는 위험에 맞닥뜨리게 됩니다. 

 

 

 

 

 

1) Training with all original data set

 

가지고 있는 데이터셋을 몽땅 넣어서 예측 혹은 분류 모델을 훈련 시키면 이게 과소적합(under-fitting)인지, 적정적합(generalized-fitting)인지, 과적합(over-fitting)인지를 가늠하기가 힘듭니다. 

 

아래의 그림에 나오는 것처럼 training model의 error rate이 낮으면 낮을 수록 더 좋은 모델인 것일까요?

 

문제는 훈련을 시키면 시킬 수록 Error rate는 계속 줄어드는 경향이 있으므로 결국은 과적합(over-fitting)으로 귀결된다는 점입니다.  중간에 적정적합 구간에서 훈련을 중단시키지 않으면 말이지요.  그런데 가지고 있는 모든 데이터를 Training set 으로만 활용하면 어디서 훈련을 중단시켜야 할지 도무지 알 수가 없답니다.  바로 이 문제의식에서 Validation set의 필요성이 시작합니다.

 

 

 

 

 

 

2) Training Set vs. Validation Set

 

과적합을 탐지하고 방지하기 위해서, 보유하고 있는 데이터셋을 Training set (50%~60%), Validation set (20%~25%), Test set (20%~25%) 의 3개의 set으로 구분을 한 후에, (저는 보통 Training : Validation : Test set = 60% : 20% : 20% 로 분할)

 

 - (1) Training set 을 가지고 예측 혹은 분류 모델을 훈련시키고

 

 - (2) Validation set을 가지고서 (1)번의 Training set을 가지고 훈련 중인 모델이 혹시 과적합(over-fitting)의 유혹에 빠지고 있는 건 아닌지, 아니면 훈련 더해야 하는데 농땡이 치다가 과소적합(under-fitting)인 것은 아닌지 검증, 감시를 하면서 최적의 적정적합(generalized-fitting) 구간을 찾아 모델을 선택한 후 (즉, 모델의 coefficients, weights 결정)

 

 - (3) Test set을 사용해서 (1)번과 (2)번의 협동작업으로 도출한 최종 모델(final model)에 대해서 성적을 매기는 작업을 하게 됩니다.

 

Validation set과 Test set을 혼동하는 분도 있을 것 같습니다.  (제가 그랬습니다....  ^^;)  Validation set은 과적합 방지용, Test set은 최종 모델 평가용도 입니다.

 

아래 그림은 Training set으로 만든 예측 혹은 분류 모델에 Validation set 데이터를 적용해서 예측 혹은 분류 error 를 측정한 그래프입니다.  Training set으로 모델을 만들면 반복(iterarion)을 계속할 수록 error rate은 계속 줄어드는데요, 이 모델을 처음 보는 데이터셋인 Validation set 에 적용을 하게 되면 error rate이 처음에는 줄어들다가 어느 순간 부터는 방향을 바꾸어서 증가하게 됩니다(보통은 Training set의 error보다 Validation set의 error가 조금씩 높음).  바로 이 변곡점이 과적합(over-fitting)이 시작되는 지점으로 합리적으로 의심을 할 수 있습니다

 

이 변곡점을 지나서도 계속 훈련을 시키게 되면 '데이터에 내재한 구조, 관계, 패턴'을 학습해서 '일반화(generalization)'하는 것이 아니라 training set을 통째로 외우게 됨에 따라 --> 처음 보는 데이터셋인 Validation set에 대해서는 자꾸 틀린 답을 내놓게 되어 Validation set의 error rate은 거꾸로 올라가게(나빠지게) 되는 것입니다.

 

 

 

 

3) k-fold Cross Validation

 

데이터셋을  Training set (50%~60%), Validation set (20%~30%), Test set (20%~30%)으로 나누게 되면 모델 훈련에는 Training set (50%~60%)만이 사용이 됩니다.  나머지 Validation set과 Test set으로 빼놓은 데이터가 아깝다는 생각이 들지요? 

 

특히, 확보한 데이터의 개수가 작은 경우에는 문제가 심각해질 수 있습니다.  데이터가 충분하지 못한 상태에서 그걸 3개의 훈련, 검증, 테스트 셋으로 나누면 분할된 데이터셋에 무슨 데이터가 들어갔느냐에 따라 모형이 심하게 영향을 받을 수가 있습니다. 

 

이런 경우에 k-fold Cross Validation 기법을 사용하면 좋습니다. k-flod Cross Validation기법은 Traning set을 k 등분한 후에 --> (k-1) 개의 fold (= (k-1)/k 구성비) 는 Training set으로 사용하고, 나머지 1개의 fold (1/k 구성비)은 validation set으로 사용하며, --> Validation set 에 해당하는 fold를 round를 거듭하면서 바꿔주게 됩니다.  말로 설명하면 좀 이해하기 어려울 수도 있는데요, 아래의 5-fold Cross Validation 예시 그림을 참고하시기 바랍니다.  4개 fold의 Training set 과 1개 fold의 Validation set을 이용해서 모형 훈련을 시키는 것을 5 round 시행하여 분류 모형(classifier)을 선택하고, Test set을 가지고 이 최종모형을 평가하는 data flow 예시입니다.

 

 

 

k-fold Cross Validation을 극단으로 가져가면 k를 데이터 관측치 수 n 만큼 하는 경우도 있는데요, 이를 leave-one-out Cross Validation (LOOCV) 이라고 합니다.  보유하고 있는 데이터를 fully 활용할 수 있는 장점이 있고, 특히 데이터 샘플 수가 작을 경우 유용하겠지요.  다만, leave-one-out Cross Validation은 연산 비용이 높다는 점은 염두에 두어야 하며, 샘플 사이즈가 크다면 보통은 10-fold Cross Validation을 많이 사용하는 편입니다.

 

 

참고로, re-sampling methods 를 tree 형식으로 정리해놓은 자료가 있어서 소개합니다.  아래 구분 tree에서 색깔 칠해놓은 부분이 이번 포스팅에서 소개한 방법이 되겠습니다.  색 안칠해진 부분도 많고, 공부해야 할 것이 참 많지요? ^^"

 

* Source : “Performance Evaluation for Learning Algorithms”, Nathalie Japkowicz, School of Electrical Engineering & Computer Science University of Ottawa

 

 

다음번 포스팅에서는 이번 포스팅과 직접 관련된 bias-variance trade-off 에 대해서 소개하겠습니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡'를 꾸욱 ~ 눌러주세요. ^^

 

728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 기계학습(machine learning)의 정의와 3가지 유형 (supervised learning, unsupervised learning, reinforcement learning)에 대해서 알아보았습니다.

 

이번 포스팅에서는 학습의 일반화(generalization)와 과적합(overfitting), 혹은 과잉적합에 대해서 알아보도록 하겠습니다.  이번 포스팅은 기계학습의 3가지 유형 중에서 지도학습(supervised learning)에 대해 한정한 내용이긴 합니다만, 기계(컴퓨터)가 학습한다고 했을 때의 핵심이 되는 아주 아주 중요한 개념이므로 분석 기법/알고리즘으로 들어가기 전에 짚어보고 넘어가고자 합니다.

(기계학습 공부하는 대학원생이라면 '과(잉)적합(Over-fitting)에 대해서 논하시오'라는 문제가 중간고사에 무조건 나온다에 500원 걸겠습니다. ㅎㅎ)

 

기계학습의 정의에서 보면 과거의 대량의 data인 Experience (E) 로 부터 예측/추정이나 분류 등의 Task(T)를 어느 수준 이상의 정확도(Performance, P)로 향상시킬 수 있다면 기계(컴퓨터)가 해낼 수 있다면 컴퓨터가 학습을 하고 있다고 말할 수 있다고 했었습니다.  이때 중요한게 하나 있는데요, 훈련 데이터셋(Training Data Set)에서 뿐만이 아니라 컴퓨터가 본적이 없는 새로운 데이터 셋(Test Data Set, or New Data Set)에 대해서도 예측/추정이나 분류 모델이 잘 working 하느냐가 오늘의 포스팅의 주제입니다.

 

가령, 훈련 데이터(Training Data Set)를 가지고 지난 학기 기계학습 수업의 Pass와 Fail한 학생을 분류하는 모형을 만들었는데요, 그게 훈련 데이터에 너무나도 과도하게 적합이 된 나머지, 올해 신입생을 대상으로 한 새로운 데이터 셋(Test Data Set)에 대해서는 분류가 잘 맞지가 않는 경우 과(잉)적합(Overfitting)이 되었을 가능성이 아주 많다고 의심해볼 수 있습니다. .

 

아래 그림에 과소적합(Under-fitting), 적정적합, 과(잉)적합(Over-fitting) 분류 예를 가상으로 만들어서 들어보았습니다.   상단의 그림은 훈련 데이터셋(Training set)을 가지고 분류 모델을 만든 것이구요, 하단 그림은 새로운 데이터인 테스트 데이터셋(Test set)에 다가 훈련 데이터셋으로 만든 분류 모델을 적용해 본 그림입니다.

 

(1) 상단 좌측의 과소적합(Under-fitting)의 경우 훈련 데이터셋을 대상으로 훈련이 부족하여 파란점과 빨간점을 잘 분류를 못하고 있습니다. (정확도 65%). 

 

중간고사 앞두고 시험공부 하라고 했더니 기계학습 서문 서너페이지 읽다 말고는 태양의 후예 재방송 보느라 농땡이 친 학생이 여기에 해당이 되겠습니다.  이런 학생은 하단 좌측의 테스트 데이터셋에 보면 아시겠지만 처음보는 새로운 시험문제가 나오는 중간고사에서 좋은 점수를 받을리가 없겠지요. (정확도 60%)

 

(2) 상단 가운데의 적정적합(Generalized-fitting)의 경우 훈련 데이터셋을 대상으로 파란점과 빨간점을 분류하라고 시겼더니 비록 일부 오분류가 있기는 합니다만 전반적으로 적절하게 제법 분류를 해냈습니다.(정확도 90%)  그리고 훈련데이터로 만든 분류 모델을 하단의 가운데에 신규 데이터셋인 테스트 셋에 적용해 보았더니 역시 약간 오분류가 늘어나기는 했지만 그래도 85%의 정확도로 꽤 높은 분류 성과를 냈습니다. 

 

수업시간에 선생님께서 문제풀이를 하면서 '이론'과 '원리'를 가르쳐주실 때 정신 바짝 차리고 공부 잘하고 복습도 잘한 학생이 여기에 해당이 됩니다. '원리'를 깨우쳐서 '일반화(generalization)'을 했기 때문에 중간고사에서 응용문제가 나와도 그걸 풀 수 있는 힘이 있는 것입니다.

 

(3) 상단의 오른쪽에 있는 과(잉)적합(Over-fitting)은 훈련 데이터셋(Training Set)을 대상으로 파란점과 빨간점을 100% 정확하게 기가 막히게 잘 분류를 해놨습니다.  모델이 삐뚤빼뚤 비선형으로 해서 아주 복잡하게 생겼지요?  이 분류 모델을 새로운 데이터셋, 즉 테스트 셋(Test set)에 적용해서 분류를 시켜봤더니, 글쎄 정확도가 65%로 곤두박질을 쳤습니다.

 

중간고사 이틀 남겨놓고 코피 터지게 벼락치기로 '달달 외워서' 공부한 학생이 여기에 해당되겠습니다.  공부를 하면서 '원리'에 대해서도 생각을 해보고 음미도 해봤어야 하는건데요, 너무 의욕이 앞선 나머지, 아니면 공부하는 전략이 부족하고 미련해서 인지, 예제 문제 자체를 토씨하나 안틀리고 달달 외워버린 경우입니다 (아마 자신감 100% 만땅 이었겠죠?).  이렇게 교과서 문제를 너무나 과하게 통째로 외워버리다 보니 중간고사에 약간 문제를 비튼 '응용문제'가 나오자 당황하고 문제를 잘 못푼 학생을 생각하시면 됩니다. (성적은 중하위권...?) 

 

 

[ 과소적합(Under-fitting) vs. 적정적합(Generalized-fitting) vs. 과잉적합(Over-fitted) ]

 

 

 

 

기계학습이 지향하는 학습 수준은 당연히 일반화(generalization)가 된 적정수준의 학습 입니다.  과소적합(under-fitting)도, 과(잉)적합(over-fitting)도 아니구요.  특히 과적합(over-fitting)은 기계학습 분석가가 조심해야 합니다.  왜냐하면 훈련 데이터를 가지고 모형을 만들 때 과적합(over-fitting)을 하게 되면 성과(정확도)가 아주 좋게 나오거든요.  그러면 이 분석가는 자기가 대단한 일, 큰 일을 한 줄로 알고 착각하게 됩니다.  과적합(over-fitting)이 아마추어 분석가만 저지르는 실수로 생각할 수도 있습니다만, 지진을 예측하는 과학자도 실수하고, 일본 후쿠시마의 핵 원자로가 폭발한 원인 제공자가 바로 과적합이라는 사실을 아시나요? Nate Silver의 신호와 소음(The Signal and The Noise)에 실린 내용을 아래에 인용해 봅니다.

 

"그러나 자료의 이상적 관계를 알지 못할 때 우리는 탐욕에 사로잡히기도 한다. 이런 탐욕의 결과로 나타난 과잉적합 사례를 보면, 모든 측정점을 연결하는 복잡한 함수를 만들었다. 그러다 보니 아래위로 마구 오르내리는, 현실에서 있음직하지 않은 곡선이 나타났다. 이렇게 될 때 우리는 측정점들에 내재된 진정한 관계에서 한참 멀어지고 말며, 결국 우리 예측은 한층 엉뚱한 곳을 향하고 만다.

 

(중략)... 우리는 우리가 접할 수 있는 증거에서 그 구조를 추론해내야 한다. 이 과정에서, 자료가 한정되어 있고 소음이 많을 때 그리고 자료 안에 내재하는 근본 관계에 대해 이해가 부족할 때, 사람들은 대개 과잉적합의 오류를 범한다

 

(중략)... 과잉적합은 이중적 불운을 나타낸다. 이 모델은 연구논문에서는 '더 나은 것'으로 보이지만 실제 현실에서는 '더 나쁜' 성적을 거둔다. 과잉적합 모델은 후자의 특성 때문에 결국 실제 현실에서 예측하는데 동원될 경우 호된 대가를 치룬다. 이 모델은 또한 전자 때문에 겉보기에는 더 인상적이다. 매우 정확하고 또 뉴스 가치가 있는 예측을 할 수 있으며 과거에 사용된 여러 기법보다 훨씬 나은 듯 보인다. 그렇기에 이런 모델은 학술지에도 좀 더 쉽게 발표가 되고 또 고객들에게 환영을 받는다. 반면 좀 더 정직한 모델은 시장에서 내몰린다. 그러나 과잉적합 모델은 신호가 아닌 소음에 적합하도록 만들어진 만큼 결국 정확성, 다시 말해 과학성을 훼손할 수 밖에 없다.

 

- 출처 : 신호와 소음(The Signal and The Noise), Nate Silver

 

지진을 예측하는데 최고난이도의 수학으로 어마무시하게 복잡하고 정교한 모델을 만든 케일리스-보르크 지진학자가 있었다고 합니다.  '신호와 소음'에 소개된 성적표에 의하면, "이 모델은 믿을 수 없을 만큼 복잡한 방정식들을 동원해 소음에 물든 자료들에까지 적합하게 만들어졌다. 그리고 결국은 대가를 치러야 했다. 스물여섯 개 예측을 했지만 세 개 밖에 적중하지 못했다. 데이비드 보먼은 자기도 비슷한 문제를 안고 있다는 사실을 인식하고, 결국은 자신의 모델을 폐기하고 만다". 라고 하는군요.  케일리스-보르크든 데이비드 보먼이든, 훈련 데이터로는 아마 기가 막히게 정확하게 예측을 했었을 것이고 흥분을 했을 겁니다.  나중에 현실 세계에서 초라한 성적표를 받고 나서야 과적합(over-fitting)이었다는 걸 알기 전까지는 말이죠.

 

과적합은 소음(Over-fitting due to Noise), 부족한 사례(Over-fitting due to Insufficient example), 과도하게 복잡한 모형 개발(unnecesarily complex model)로 인해서 생기는데요, 기계학습 분석가에게는 참 조심하고 주의를 기울여야할 주제입니다.

 

오컴의 면도날(Occam's Razor )에 의하면 복잡한 모델보다는 단순한 모델을 선택(선호)하라고 합니다.  Variable, Feature를 있는 것 모두 때려 집어넣고 모델 만들지 말고 똘똘한 Variable, Feature를 선별해서 가능한 단순하게 만들라는 것입니다. 오컴의 면도날은 과적합(over-fitting)을 아주 싫어한다고 말할 수 있겠습니다.

 

다음번 포스팅에서는 과적합을 어떻게 피할 수 있나에 대해서 알아보도록 하겠습니다. 

(Training Set vs. Test Set error rate, cross-validation, Prunning, Sample size up)

 

많은 도움이 되었기를 바랍니다.

 

도움이 되었다면 아래의 '공감 ♡'를 꾸욱~ 눌러주세요. ^^

 

728x90
반응형
Posted by Rfriend
,

기계학습(Machine Learning)에 대한 최근의 관심이 뜨겁습니다.  R을 활용해서 기계학습 하는 방법을 블로그에 연재해보려고 합니다. 


저는 예전에 데이터마이닝(Data Mining) 책에서 k-NN (k Nearest Neighbor), Decision Tree, ANN (Artificial Neural Network), Association Rules, k-Means Clustering 등을 배웠었습니다.  그때와 비교하면... 최근에는 데이터마이닝이라는 용어 대신에 기계학습(Machine Learning)이라는 용어를 더 선호하는것 같고(유행?), 앙상블(Ensemble), 특히 Random Forest!!!, SVM(Support Vector Machine)!!, (이세돌과 알파고의 대국 이후) Deep Learning!!!!! 등이 많이 회자되고 있으며, 상용툴 SAS나 SPSS 사용하던걸 오픈소스 R, Python, 더 나아가서는 Big Data 시스템에서 분산병렬처리 적용(Spark MLlib, H2O, Tensor flow 등) 도 활발하게 활용 중이네요.  ANN(Artificial Neural Network)은 블랙박스 모델이어서 설명력이 부족하여 저는 실전에서는 안써봤는데요, 구글이 고양이, 개 이미지를 인식하는데 성공한거라든지(feature selection, feature extraction 없이 지가 알아서 학습을 척척...헐...), 알파고가 이세돌 이겼다든지 해서 최근에 기계학습, 인공지능 한다하는 커뮤니티에서는 Deep learning이 정말 Hot 한거 같아요. 


기계학습으로 할 수 있는 것들이 무척 많습니다. 상품/컨텐츠 추천, 신용카드 사기거래 탐지, 암 유발 DNA 패턴 탐지, 음성/영상/이미지 인식, 스팸 이메일 분류, 주가 예측, 날씨 예측, 구매행동 기반 고객세분화, 제조업 불량 패턴 분류 및 원인 자동 분석, 최근 뉴스에 종종 나오는 자율주행 자동차....등 이미 우리 실생활에 헤아리기 힘들 만큼 깊숙이 스며들어 기계학습이 사용되고 있습니다. 



서두가 길었는데요, 기계학습이 무엇인지부터 얘기를 시작해보겠습니다. 

위키피디아에서 좀 찾아보니 Arthur Samuel과 Tom M. Mitchell 이 정의해놓은 것이 있네요. 


Arthur Samuel 은 기계학습을 정의하기를 "컴퓨터에게 명시적으로 프로그래밍 하는 것 없이 배울 수 있는 능력을 주는 학문 분야"라고 했네요. 

(In 1959, Arthur Samuel defined machine learning as a "Field of study that gives computers the ability to learn without being explicitly programmed".)


Tom M. Mitchell 은 기계학습을 정의하기를 "컴퓨터 프로그램이 어떤 유형의 과업(T, Task)들에 대해 성과평가 지표(P, Performance measure)의 관점에서 경험(E, Experience)으로 부터 배워서, 만약 성과평가 지표(P)의 값이 향상이 된다면 컴퓨터 프로그램은 학습을 할 수 있다"고 말할 수 있다고 합니다. 

(Tom M. Mitchell provided a widely quoted, more formal definition: "A computer program is said to learn from experience E with respect to some class of tasks T and performance measure P if its performance at tasks in T, as measured by P, improves with experience E".)


- from Wikipedia -



좀더 부언설명을 하자면, Arthur Samuel 이 말한 것 중에 보면 기계학습은 명시적으로 프로그래밍하는 것이 아니라고 했는데요, 명시적으로 프로그래밍하는 것을 들라면 전문가 시스템(Expert System)을 있겠습니다.  전문가 시스템 하나 만들려면 업 전문가(domain expert)와 프로그래머가 긴 시간을 들여 협업해야 하므로 비용이 많이 드는 한계가 있지요. 


Tom M. Mitchell 은 Experience, Task, Performance measure를 가지고 기계학습을 정의했는데요, Arthur Samuel의 정의보다는 기계학습에 필요한 요소에 대해서 좀더 자세하게 설명하였습니다. Experience는 Data 로 보면 되겠습니다. 예전엔 데이터가 귀했지만 요즘은 데이터가 넘쳐나서 그걸 어떻게 제 시간에 처리하느냐가 문제가 되어버렸습니다.  Task 는 예측, 분류, 패턴 발견, 그룹핑 등을 들 수 있겠네요.  Performance measure 는 컴퓨터가 학습을 잘 하고 있는지 아닌지 평가, 판단, 제어할 때 사용하는 지표들인데요, 정확도, 민감도, 오분류율, recall rate ... 등을 훈련 집단, 테스트 집단과 비교해가면서 훈련을 진행하게 됩니다. 


컴퓨터의 아버지, 2차 세계 대전 시 독일군의 암호 이니그마를 풀었던 천재 수학자 Alan Turing은 제안하기를 "기계가 생각을 할 수 있는가?"라는 질문을 "우리가 할 수 있는 일들을 기계가 할 수 있는가?"라는 질문으로 바꾸어야 한다고 했는데요, Tom M. Mitchell의 기계학습 정의와도 일맥상통하는 면이 있습니다. 

(Alan Turing's proposal in his paper "Computing Machinery and Intelligence" that the question "Can machines think?" be replaced with the question "Can machines do what we (as thinking entities) can do?", from Wikipedia)



기계학습은 과업을 학습하는데 필요한 신호와 피드백(signal and feedback)에 따라서 크게 지도학습(Supervised Learning), 비지도학습(Unsupervised Learning), 강화학습(Reinforcement Learning)의 3개 유형으로 구분할 수 있습니다. 





지도학습(Supervised Learning)은 훈련 데이터(Training Data)로 부터 예측/추정(prediction, estimation), 분류(classification) 함수를 만들어 내는 기계학습 방법입니다.  독립변수(x1, x2, ...)들과 종속변수(y)를 가지고 있고, 선생님의 지도 하에 독립변수와 종속변수 간에 관계를 일반화하는 학습을 하게 됩니다.  Y값을 가지고 있으니 학습이 끝나고 나면 성적표가 적나라하게 나옵니다.  과거의 데이터를 가지고 학습을 시키고 나면, 학습 모델에 새로운 데이터에 적용해서 예측/추정, 분류 등의 과업을 수행합니다. 



반면에 비지도학습(Unsupervised Learning)은 관찰한 데이터로 부터 숨겨진 패턴/규칙을 탐색, 찾아내는 기계학습 방법입니다.  비지도학습에서는 종속변수(y) 값이 없습니다. 선생님도 없습니다.  그냥 Input 변수 (x1, x2, ...) 만 주고 컴퓨터보고 수많은 데이터 속에 숨겨져 있는 패턴을 찾으라고 합니다. 연관/순차규칙 분석(association rule, sequence analysis), 군집화(clustering, affinity grouping), 차원 축소(dimension reduction), 네트워크 분석(network analysis, link analysis) 등이 비지도학습에 속합니다.  비지도학습은 Y값이 없으니 학습이 끝나고 나서 몇 점을 받았는지 객관적으로 평가하기가 애매하며 분석가의 주관이 들어갑니다.  비지도학습은 데이터로 숨겨진 패턴/규칙을 발견하고 나면 그걸로 끝납니다. 비지도학습은 지도학습처럼 새로운 데이터에 학습모델을 적용하는거 없습니다. 

(영상, 이미지 처리/분석을 비지도학습에 넣기는 했는데요, 데이터마이닝이나 머신러닝 책들에서는 보통 언급을 안하더군요. feature extraction 하는데 유용하게 쓰곤 하는데요, 성격상 비지도학습에 넣어도 괜찮은거 같아서 일단 넣어봤습니다) 

 


비지도학습은 분석의 초기에 탐색적분석(EDA, Exploratory Data Analysis) 단계에서 많이 사용되곤 합니다.  비즈니스 과업의 많은 경우 비지도학습과 지도학습을 서로 연계해서 사용하는 경우가 많습니다. 




* 그림 출처 : http://prooffreaderswhimsy.blogspot.kr/2014/11/machine-learning.html




과업의 종류별로 지도학습과 비지도학습의 대표적인 알고리즘을 소개하면 아래와 같습니다 (통계기법도 포함함).  분석기법/알고리즘은 과업의 종류와 데이터의 특성에 맞게 적합한 것을 선별하면 됩니다.  앞으로 R 기계학습 패키지를 가지고 하나씩 예제를 들어가면서 소개하도록 하겠습니다. 


 


강화학습(Reinforcement Learning)은 위키피디아에서 소개하고 있는 내용을 번역해서 소개하는 걸로 하겠습니다.  이세돌과 바둑 대결했던 알파고와 구글의 무인자동차에 적용된 기계학습 기법이 강화학습인만큼 소위 뜨고 있는 핫한 분야인거 같습니다.  위키피디아에서 소개하길, 


강화학습(Reinforcement Learning)은 명시적으로 선생님이 가르치는 것 없이도 동적으로 변화하는 환경과 상호작용하면서 특정 목적(예: 자동차 운전)을 수행할 수 있는 컴퓨터 프로그램을 말합니다. 

(Reinforcement learning: A computer program interacts with a dynamic environment in which it must perform a certain goal (such as driving a vehicle), without a teacher explicitly telling it whether it has come close to its goal.)   


또다른 예로는 대전 게임하는 방법을 배우는 것을 들 수 있습니다. 강화학습은 장기관점의 보상(long-term reward)을 최대화하기 위해서 agent가 변화하는 환경 속에서 무슨 행동을 취해야 하는지에 대해서 주목합니다. (Another example is learning to play a game by playing against an opponent. Reinforcement learning is concerned with how an agent ought to take actions in an environment so as to maximize some notion of long-term reward.). 


강화학습 알고리즘은 세상(환경)의 상태(변화)에 따라 agent가 취해야 할 행동을 매핑(선택)하는 정책을 찾는 시도를 합니다.  강화학습은 지도학습과는 달리 정확한 input/output 쌍의 데이터라든지 최적의 행동 집합을 필요로 하지 않습니다. (Reinforcement learning algorithms attempt to find a policy that maps states of the world to the actions the agent ought to take in those states. Reinforcement learning differs from the supervised learning problem in that correct input/output pairs are never presented, nor sub-optimal actions explicitly corrected.)


* 출처 : 위키피디아(https://en.wikipedia.org/wiki/Machine_learning)



우리가 보통 (강한) 인공지능(AI, Artificial Intelligence) 이라고 말할 때 생각하는 기계학습은 강화학습(Reinforcement Learning)과 많이 관련이 있어보이지요?  Deep Learning이 Feature selection을 사람이 개입해서 해주지 않아도 알아서 해주니 Deep Learning + 강화학습(Reinforcement Learning)이 강한 인공지능의 핵심으로 부상하고 있는거 같습니다.  제약조건(constraints) 을 만족하는 하에서 최대화(maximization) 혹은 최소화(minimization)하는 최적화(optimization)가 역동적으로 변화하는 환경에 대응해서 실시간으로 계산해서 적용하고 실시간으로 피드백 받는 동적인 시스템을 생각하면 되겠습니다. 


많은 도움 되었기를 바랍니다. 


다음번 포스팅에서는 일반화(Generalization)과 과적합(Over-fitting)에 대해서 알아보겠습니다. 


이번 포스팅이 도움이 되었다면 아래의 '공감 ♡'를 꾸욱~ 눌러주세요. 



728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 행과 열의 개수가 같은 정방행렬(square matrix)에 대해 고유값 분해(eigenvalue decompositon)를 활용한 대각화(diagonalization)와, 이를 마아코프 과정(Markov Process)의 안정상태확률 계산에 적용한 사례에 대해서 소개하였습니다.

 

복습하는 차원에서 고유값 분해에 대해서 정리해보면 아래와 같습니다. 

 

  • 고유값 분해 (eigenvalue decomposition)

 

고유값 분해는 n*n 정방행렬 (n by n square matrix)에 대해서만 적용 가능하다는 점과 가운데에 D 행렬에 고유값이 들어가 있다는 점은 다시 한번 상기하시기 바랍니다.  m*n 직사각행렬(m by n rectangular matrix)에 대해서는 고유값 분해는 사용할 수 없다는 뜻입니다.

 

 

 

 

이번 포스팅에서는 실수(real number)나 복소수(complex number)로 이루어진 공간의 원소로 이루어진 m개의 행과 n개의 열을 가진 모든 직사각행렬 (rectangular matrix)에 폭넓게 사용 가능한 특이값 분해 (SVD, singular value decomposition)에 대해서 알아보겠습니다.

 

특이값 분해는 행렬의 스펙트럼 이론을 임의의 직사각행렬에 대해 일반화한 것으로 볼 수 있습니다. 스펙트럼 이론을 이용하면 직교 정사각행렬을 고유값을 기저로 하여 대각행렬로 분해할 수 있습니다. (* 위키피디아) 

  • 스펙트럼 분해 (spectral decomposition)

p*p 대칭행렬 A에 대한 스펙트럼 분해(spectral decomposition)는 다음과 같습니다.  p*p 대칭행렬 A는 직교행렬 P에 의해 대각화(diagonalization)된다고 합니다.

 

 

이때 를 만족하는 직교행렬 P는 로 이루어지며, (람다, lambda)는 A의 고유값(eigenvalue)들로만 이루어진 대각행렬(diagonal matrix)인

 입니다.  대각행렬 이 성립합니다.

 

 

 

위의 스펙트럼 분해 (혹은 분광분해)를 일반화한 특이값 분해는 아래와 같습니다. 

 

 

 

  • 특이값 분해 (SVD, Singular Value Decomposition)

m*n 직사각행렬 A에 대한 특이값 분해(SVD, Singular Value Decomposition)는 아래와 같이 나타낼 수 있습니다.

 

 

 

행렬 A의 계수(rank)가 k 라고 할 때,

 

를 고유값분해(eigenvalue decomposition)로 직교대각화하여 얻은 m*m 직교행렬 (orthogonal matrix)이며, 특히를 좌특이벡터(left singular vectors, gene coefficient vectors) 라고 합니다.

 

 

는  를 고유값분해로 직교대각화하여 얻은 n*n 직교행렬이며, 특히 를 우특이벡터(right singular vectors, expression level vectors)라고 합니다.

 

 

는 (의 0이 아닌 고유값이 일 때)  를 대각성분으로 가지고 나머지 성분은 0을 가지는 m*n 직사각 대각행렬(diagonal matrix) 입니다.

 

 

 

 

m*n 직사각행렬 A의 특이값 분해 를 다시 한번 풀어서 쓰면 아래와 같습니다.

 

 

 

 

위의 식에서 특이값(singular value)는 가 됩니다.

 

 

참고로,

U, V가 직교행렬(orthogonal matrix)이면 가 성립합니다. 

직교행렬(orthogonal matrix) Q는 다음을 만족하는 정방행렬이기 때문입니다.

 

 

 

 

서두에서 정방행렬에 국한된 고유값 분해보다 모든 m*n 행렬에 적용가능한 특이값 분해가 일반화면에서 활용성이 더 넓다고 했는데요, 이 둘이 사실은 서로 관련이 되어 있습니다.

 

 

 

  • 특이값 분해와 고유값 분해의 관계

아래의 수식 전개를 보면 확인할 수 있는데요, 서두에서 소개했던 고유값 분해 형식()과 같아졌습니다.  m*n 행렬 A의 특이값 분해의 U는  의 고유벡터(eigenvector)이고, V는의 고유벡터(eigenvector) 이며, A의 0이 아닌 특이값들의 제곱() 은 , 의 고유값과 같음을 알 수 있습니다.

 

결국 SVD를 계산한다는 것은 의 고유벡터와 고유값을 구하는 것이라는 것을 알 수 있습니다.

 

 

 

다음으로, 특이값 분해의 기하학적인 의미를 살펴보겠습니다.

  • 특이값 분해의 기하학적인 의미 (visualization of SVD)

아래의 그림을 가지고 의 특이값 분해가 가지는 선형변환의 의미를 기하학적으로 설명하자면, 먼저 직교행렬 에 의해서 원 행렬 M이 회전(방향 변환)을 하게 되며, 에 의해서 크기가 달라졌고 (scale 변환), 다시 직교행렬 에 의해서 에 의한 회전과는 반대로 회전(방향 변환)하였습니다.

 

* 그림 출처 : https://en.wikipedia.org/wiki/Singular_value_decomposition

 

위의 설명을 애니메이션을 넣어서 설명해주는 그림은 아래와 같습니다.

 

Singular value decomposition

* 출처 : By Kieff (Own work) [Public domain], via Wikimedia Commons

 

 

고유값 분해를 통한 대각화의 경우 고유벡터의 방향은 변화가 없고, 크기(scale 변환)만 고유값(eigenvalue) 만큼 변한다고 설명드렸었습니다.  반면, 특이값 분해는 위의 그림 결과를 보면 처음의 행렬 U, V^T에 의해 M이 방향이 변하고, Σ 특이값(singular values)들 만큼의 크기(scale)가 변했음을 알 수 있습니다.

 

 

  • Redeced SVD (Singular Value Decomposition)

위에서 SVD(Singular Value Decomposition)를 설명할 때 full SVD를 설명해 드렸는데요차원 축소할 때 아래 그림에서 소개드린 것처럼 reduced SVD를 합니다. full SVD 대비 reduced SVD는 특이값(singular value) 들 중에서 0인 것들을 제외하고 SVD를 한다는 점이 서로 다릅니다.

 

 

 

아래의 그림을 보면 조금 더 이해하기가 쉬울텐데요, 빨간색 점선으로 표시한 부분을 제외하고 행렬 A의 계수(rank) k 개 만큼의 특이값들을 가지고 SVD를 진행하는 것이 reduced SVD 입니다.

 

 

  • 특이값 분해 예제 (example of full SVD)

이해를 돕기 위해서 4 by 2 직사각행렬 (rectacgular matrix) A를 가지고 (full) SVD 계산 예를 들어보겠습니다.  아래 예에서의 고유값과 고유벡터 계산은 R 분석툴을 사용했습니다.  손으로 푸는 방법은 ☞ [선형대수] 고유값, 고유벡터 구하기 (calculation of eigenvalue and eigenvector) 를 참조하시기 바랍니다.

 

 

 

4 by 2 행렬 을 가지고 해보겠습니다.

 

특이값 분해가  라고 했는데요,

 

(1) 먼저 의 고유벡터(eigenvectors)인 U를 구해보겠습니다.

 

 

 

 

위의 풀이에서 사용한, R로 의 고유벡터를 구해서 U를 구하는 방법은 아래와 같습니다.

 

> A <- matrix(c(3, 2, 0, 0,  6, 3, 0, 0), nc=2, byrow = FALSE)
> A
     [,1] [,2]
[1,]    3    6
[2,]    2    3
[3,]    0    0
[4,]    0    0
> t(A)
     [,1] [,2] [,3] [,4]
[1,]    3    2    0    0
[2,]    6    3    0    0
> ##--- (1) calculation of U
> # A%*%t(A)
> W_1 <- A%*%t(A)
> W_1
     [,1] [,2] [,3] [,4]
[1,]   45   24    0    0
[2,]   24   13    0    0
[3,]    0    0    0    0
[4,]    0    0    0    0
> 
> 
> # eigenvalue, eigenvector of W
> eigen(W_1)
$values
[1] 57.8444102  0.1555898  0.0000000  0.0000000

$vectors
          [,1]       [,2] [,3] [,4]
[1,] 0.8816746 -0.4718579    0    0
[2,] 0.4718579  0.8816746    0    0
[3,] 0.0000000  0.0000000    0    1
[4,] 0.0000000  0.0000000    1    0

> 
> # U
> U <- eigen(W_1)[[2]] # eigenvectors
> U
          [,1]       [,2] [,3] [,4]
[1,] 0.8816746 -0.4718579    0    0
[2,] 0.4718579  0.8816746    0    0
[3,] 0.0000000  0.0000000    0    1
[4,] 0.0000000  0.0000000    1    0

 

 

 

 

(2) 다음으로,  의 고유벡터(eigenvectors of A^T*A)  를 구해보겠습니다.  위의 (1)번 풀이 과정과 동일합니다.

 

 

R로 풀이한 것은 아래와 같습니다.

 

> > ##---- (2) calculation of V^T > # t(A)%*%A > W_2 <- t(A)%*%A > W_2 [,1] [,2] [1,] 13 24 [2,] 24 45 > > # eigenvalue of W > eigen(W_2) $values [1] 57.8444102 0.1555898 $vectors [,1] [,2] [1,] 0.4718579 -0.8816746 [2,] 0.8816746 0.4718579 > > # V > V <- eigen(W_2)[[2]] # eigenvectors > V [,1] [,2] [1,] 0.4718579 -0.8816746 [2,] 0.8816746 0.4718579 

 

 

 

(3) 다음으로, 의 고유값(eigenvalue)의 제곱근(square root)을 특이값(singular value) 대각원소로 가지고 나머지는 '0'인 대각행렬 Σ 를 구해보겠습니다.

 

 

R로 고유값에 square root를 취해서 특이값(singular value) 구하는 절차는 아래와 같습니다.

 

> ##--- (3) calculation of Σ
> # square root of eigenvalues
> W_2_eigenvalue_sqrt <- sqrt(eigen(W_2)[[1]])
> W_2_eigenvalue_sqrt
[1] 7.6055513 0.3944487
> 
> S <- matrix(rep(0, 8), nc=2, byrow=F) # all zeros, temp matrix
> S
     [,1] [,2]
[1,]    0    0
[2,]    0    0
[3,]    0    0
[4,]    0    0
> 
> S[1,1] <- W_2_eigenvalue_sqrt[1] 
> S[2,2] <- W_2_eigenvalue_sqrt[2]
> S
         [,1]      [,2]
[1,] 7.605551 0.0000000
[2,] 0.000000 0.3944487
[3,] 0.000000 0.0000000
[4,] 0.000000 0.0000000 

 

 

 

(4) 위에서 구한 U, V^T, Σ 를 종합하면 끝이네요.

 

 

 

위에서 R로 풀었던 것을 다시 한번 불러와 정리해보면 아래와 같습니다.

 

> # overall (aggregation)

> > A # 4 by 2 rectacgular matrix [,1] [,2] [1,] 3 6 [2,] 2 3 [3,] 0 0 [4,] 0 0 >

> U # eigenvectors of A*t(A) [,1] [,2] [,3] [,4] [1,] 0.8816746 -0.4718579 0 0 [2,] 0.4718579 0.8816746 0 0 [3,] 0.0000000 0.0000000 0 1 [4,] 0.0000000 0.0000000 1 0 >

> S # square root of eigenvalues of t(A)*A [,1] [,2] [1,] 7.605551 0.0000000 [2,] 0.000000 0.3944487 [3,] 0.000000 0.0000000 [4,] 0.000000 0.0000000 >

> V # eigenvectors of t(A)*A [,1] [,2] [1,] 0.4718579 -0.8816746 [2,] 0.8816746 0.4718579 > > SVD_of_A <- U %*% S %*% t(V) > SVD_of_A [,1] [,2] [1,] 3.328201 5.824352 [2,] 1.386750 3.328201 [3,] 0.000000 0.000000 [4,] 0.000000 0.000000 

 

 


많은 도움이 되었기를 바랍니다.

 

도움이 되었다면 아래의 '공감 ♡'를 꾸욱~ 눌러주세요. ^^

 

728x90
반응형
Posted by Rfriend
,