본문 바로가기
R

27. 정형 데이터마이닝 - 연관성 분석(Association Analysis)

by #Glacier 2018. 11. 21.
반응형

안녕하세요.

오늘은 연관성 분석에 대해서 알아볼게요!


#연관성 분석

연관성 분석은 동시 또는 순차적으로 발생하는 이벤트 패턴을 파악하는 방법으로 구매나 사건의 발생에 대한 

패턴분석을 하는 데 사용됩니다. 이를 이용해서 상품추천에 사용할 수 있습니다. 

요즘 실시간이 중요하다고 하는데, 사실 실시간 추천엔진이 실시간으로 분석을 해서 유의미한 변화를 감지할 정도로

추천의 변화가 매우 짧은 초단위, 분단위로 이루어지지 않는다고 합니다. 

따라서 모델링과 결과값을 비즈니스적인 업무주기에 맞추어 일, 주, 월단위로 실행해도 된다고 합니다. 

이제 연관성 분석이 무엇인지 알아볼게요~


#연관성 분석이란?


-데이터 간의 관계에서 조건과 반응을 연결하는 분석으로 장바구니 분석(Market Basket Analysis), 혹은 서열분석(Sequence Analysis)이라고도 한다.


#활용 분야?


-마트의 특정 상품 간의 연관성을 통한 상품 디스플레이 방안 도출, 여행지 간 연관성을 이용한 특정 상품의 마케팅 대상 고객 선정, 제조 설비의 품질 분석 등이 있다.


#용어 정의?


(1) 지지도(Support) = (item1과 item2가 동시에 포함된 거래 건수) / 전체 거래 건수

-분석하고자 하는 전체 거래 건수 중 관심대상인 item이 어느 정도 있는지 보기 위한 측도로 사전적으로 분석의 대상이 의미가 있는지 가늠할 수 있다.

 따라서 일정 수준 이상이 팔리는 상품이어야 분석의 의미가 있다.


(2) 신뢰도(Confidence) = (item1과 item2가 동시에 포함된 거래 건수) / (item1이 포함된 거래 건수)

-item1을 사는 사람이 item2를 산다는 규칙이 어느 정도 확률도 존재하는지에 대한 측도이다.


(3) 향상도(Lift) = (item1을 포함한 거래 중 item2도 포함된 거래의 비율) / item2를 포함한 거래의 비율

                   = {(item1과 item2가 동시에 포함된 거래 건수) / item1을 포함한 거래 건수} / item2를 포함한 거래 건수

                   = (item1과 item2가 동시에 포함된 거래 건수) / (item1을 포함한 거래 건수 X item2를 포함한 거래 건수)

-item1을 구매한 거래에 대해 item2도 구매한 거래의 비율이, 단순히 item2만 거래한 비율에 대해 어느 정도 배율인지를 나타내는 측도다. 즉, 단순히

 item2 구매하는 확률보다는 item1을 구매했을 때 item2를 구매하는 확률이 어느 정도로 높은지를 나타낸다.


#조금 복잡하죠? 제 머릿속은 더 복잡합니다. 한 번 썼는데 다 날라가서 ㅠㅠ다시써요.ㅠ.ㅠ

 어쨌든 여기서 item1을 선행사건(antecedent), item2를 후행사건(consequent)이라 한다.


#알고리즘 : R패키지 apriori에 3세대 알고리즘이 포함되어 있다.


#R을 이용한 연관 분석


install.packages("arules")
library(arules)
data(Groceries)


str(Groceries)

Formal class 'transactions' [package "arules"] with 3 slots
  ..@ data       :Formal class 'ngCMatrix' [package "Matrix"] with 5 slots
  .. .. ..@ i       : int [1:43367] 13 60 69 78 14 29 98 24 15 29 ...
  .. .. ..@ p       : int [1:9836] 0 4 7 8 12 16 21 22 27 28 ...
  .. .. ..@ Dim     : int [1:2] 169 9835
  .. .. ..@ Dimnames:List of 2
  .. .. .. ..$ : NULL
  .. .. .. ..$ : NULL
  .. .. ..@ factors : list()
  ..@ itemInfo   :'data.frame': 169 obs. of  3 variables:
  .. ..$ labels: chr [1:169] "frankfurter" "sausage" "liver loaf" "ham" ...
  .. ..$ level2: Factor w/ 55 levels "baby food","bags",..: 44 44 44 44 44 44 44 42 42 41 ...
  .. ..$ level1: Factor w/ 10 levels "canned food",..: 6 6 6 6 6 6 6 6 6 6 ...
  ..@ itemsetInfo:'data.frame': 0 obs. of  0 variables

head(Groceries)

transactions in sparse format with
 6 transactions (rows) and
 169 items (columns)


#이렇게 도출되었는데 오랜만에 데이터를 보니까 머리가 아프네요. 일단 여기까지만 생각하고 음 그렇구나 하고 넘어가죠~

 이제 조금 더 세밀하게 볼까요?


head(Groceries@itemInfo)

             labels  level2           level1
1       frankfurter sausage meat and sausage
2           sausage sausage meat and sausage
3        liver loaf sausage meat and sausage
4               ham sausage meat and sausage
5              meat sausage meat and sausage
6 finished products sausage meat and sausage


# 어휴 머리아퍼..;;


summary(Groceries)


transactions as itemMatrix in sparse format with
 9835 rows (elements/itemsets/transactions) and
 169 columns (items) and a density of 0.02609146

most frequent items:
      whole milk other vegetables       rolls/buns             soda 
            2513             1903             1809             1715 
          yogurt          (Other) 
            1372            34055

element (itemset/transaction) length distribution:
sizes
   1    2    3    4    5    6    7    8    9   10   11   12   13   14   15   16 
2159 1643 1299 1005  855  645  545  438  350  246  182  117   78   77   55   46 
  17   18   19   20   21   22   23   24   26   27   28   29   32 
  29   14   14    9   11    4    6    1    1    1    1    3    1

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   2.000   3.000   4.409   6.000  32.000

includes extended item information - examples:
       labels  level2           level1
1 frankfurter sausage meat and sausage
2     sausage sausage meat and sausage
3  liver loaf sausage meat and sausage


# 한 번 쓱 훑어보았는데도 썩 한 번에 와닿지 않고, 뭐지? 이런 생각이 많이 들죠??

  이러한 Transaction format의 데이터를 보기 위해서는 inspect()를 사용한다. 가끔 inspect가 작동하지 않는 경우는 다른 패키지의 inspect가

  작동해서 그런 경우이므로 arules를 다시 library로 로딩하거나 session restart를 해서 library로 다시 arules를 구동시키면 제대로 작동된다.

  inspect() 함수를 사용해서 봐볼까요?


inspect(head(Groceries))


  items                     
1 {citrus fruit,            
   semi-finished bread,     
   margarine,               
   ready soups}             
2 {tropical fruit,          
   yogurt,                  
   coffee}                  
3 {whole milk}              
4 {pip fruit,               
   yogurt,                  
   cream cheese ,           
   meat spreads}            
5 {other vegetables,        
   whole milk,              
   condensed milk,          
   long life bakery product}
6 {whole milk,              
   butter,                  
   yogurt,                  
   rice,                    
   abrasive cleaner}       


# 이제 조금 볼만해졌습니다. 이제 여기서 apriori함수를 적용하여 규칙을 도출하는데 최소 support와 최소 confidence를 지정하여 도출할 규칙이 비즈니스적으로

   의미 없는 내용이 산출되지 않도록 합니다.. 간혹 support를 0에 가까운 값으로 지정하는 사례들을 보았는데 그런 경우는 모든 거래정보를 이용해서 모든 조합의

   규칙을 도출하겠다는 것이므로 의미 없는 작업을 하는 것입니다.


G_arules <- apriori(Groceries, parameter = list(support = 0.01, confidence = 0.3))


Apriori

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

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

Absolute minimum support count: 98

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


# 자 이렇게 됐습니다.  또 이상하죠 뭔가 done 이라는 말만 뜨고?? summary를 통해 볼까요?


 summary(G_arules)


set of 125 rules

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

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

summary of quality measures:
    support          confidence          lift      
 Min.   :0.01007   Min.   :0.3079   Min.   :1.205  
 1st Qu.:0.01149   1st Qu.:0.3454   1st Qu.:1.608  
 Median :0.01454   Median :0.3978   Median :1.789  
 Mean   :0.01859   Mean   :0.4058   Mean   :1.906  
 3rd Qu.:0.02217   3rd Qu.:0.4496   3rd Qu.:2.155  
 Max.   :0.07483   Max.   :0.5862   Max.   :3.295 

mining info:
      data ntransactions support confidence
 Groceries          9835    0.01        0.3


# 125개의 규칙이 생겼다고 뜨고, 여러가지 사분위수 등이 나오네요. 그래도 썩 한번에 보기는 좋지 않습니다.

  이번에도 역시 inspect()함수를 써서 보면?


 inspect(G_arules)

    lhs                           rhs                         support confidence     lift
1   {hard cheese}              => {whole milk}       0.01006609  0.4107884 1.607682
2   {butter milk}              => {other vegetables} 0.01037112  0.3709091 1.916916
3   {butter milk}              => {whole milk}         0.01159126  0.4145455 1.622385
4   {ham}                      => {whole milk}         0.01148958  0.4414062 1.727509
5   {sliced cheese}            => {whole milk}       0.01077783  0.4398340 1.721356
6   {oil}                      => {whole milk}           0.01128622  0.4021739 1.573968
7   {onions}                   => {other vegetables} 0.01423488  0.4590164 2.372268
(중략)---125개까지 나옵니다.


#자 이제 볼만해졌죠? 지지도 신뢰도 향상도 등이 나오고 이제 좀 해석이 될 것 같습니다.

 즉, 도출된 규칙을 출력하는데도 inspect()함수를 이용합니다. 그렇지만, support&confidence가 높은 값이라도 너무 당연한 규칙은 아닌지,

 confidence는 매우 높더라도 support가 너무 낮으면 실제 적용될 수 있는지 고민해봐야 합니다.

 이제, 이 도출된 125개의 규칙 중 특정 조건에 만족하는 규칙을 뽑거나, 내림차순 등으로 정리하는 방법을 알아볼게요.


(G_arules_yogurt <- subset(G_arules, subset=rhs %in% "yogurt"&lift>2))
set of 9 rules 
(G_arules_root_vegetables <- subset(G_arules, subset=rhs %in% "root vegetables"& lift >2))
set of 4 rules


#역시 inspect()로 봅니다.

inspect(G_arules_yogurt)

    lhs                                                 rhs      support    confidence
9   {berries}                                         => {yogurt} 0.01057448 0.3180428 
21  {cream cheese }                               => {yogurt} 0.01240468 0.3128205 
35  {curd}                                            => {yogurt} 0.01728521 0.3244275 
71  {whole milk,curd}                               => {yogurt} 0.01006609 0.3852140 
81  {other vegetables,whipped/sour cream} => {yogurt} 0.01016777 0.3521127 
83  {whole milk,whipped/sour cream}          => {yogurt} 0.01087951 0.3375394 
93  {citrus fruit,whole milk}                      => {yogurt} 0.01026945 0.3366667 
104 {tropical fruit,other vegetables}          => {yogurt} 0.01230300 0.3427762 
106 {tropical fruit,whole milk}                    => {yogurt} 0.01514997 0.3581731 
    lift    
9   2.279848
21  2.242412
35  2.325615
71  2.761356
81  2.524073
83  2.419607
93  2.413350
104 2.457146
106 2.567516


#위를 통해서 볼 수 있는 활용 방안은 무엇일까요?

  -설정 : lhs에 해당하는 제품을 구매하고, yogurt를 구매하지 않는 고객에 대해 yogurt 할인 쿠폰이 영수증과 함께 인쇄

  -효과 : G_arules_yogurt 규칙에 언급된 상품을 구매하는 1%(Support)의 고객 중 약 70%(1-confidence) 고객에게 할인권 발행 ->

           할인권을 이용해 yogurt를 구매할 가능성이 일반적인 경우보다 2배 (Lift>2) 높음.


이렇게 보면 됩니다 ^^ 이제 confidence를 중심으로 큰 순으로 보여주는 결과값을 추출해보겠습니다.


inspect(head(sort(G_arules_yogurt, by="confidence"), n=3))

    lhs                                                         rhs      support    confidence
71  {whole milk,curd}                               => {yogurt} 0.01006609 0.3852140 
106 {tropical fruit,whole milk}                    => {yogurt} 0.01514997 0.3581731 
81  {other vegetables,whipped/sour cream} => {yogurt} 0.01016777 0.3521127 
       lift    
71  2.761356
106 2.567516
81  2.524073


#이렇게 하면, confidence 중심으로 높은 순으로 볼 수도 있습니다.

 대부분 이런 식으로 전체 규칙 중에서 관심 있는 특정규칙을 조건으로 추출해서 해당규칙을 inspect()로 보거나 csv 또는 RDBMS에   저장하여 활용합니다.

 오늘은 이렇게 연관성 분석을 알아봤는데요~

 한 번 날아가서 두 번이나 쓰고 ㅠㅠ 교육 중에 쓰느라 제가 제대로 쓰는지도 모르겠고 ㅎㅎ;; 눈이 아프다..

 다음 포스팅은요, 연관성분석 2번째 파트, 순차연관성분석과 시각화에 대해 알아보도록 하겠습니다.



 

반응형