ADP 실기 15장 Association Analysis
본 게시물은 연관분석에 대해 소개한다.
1. Run-Test
1.1 Concept
연관규칙을 찾기 전, 연속적인 binary 관측 값들이 임의적으로 나타난 값인지 임의적이 아닌지(=연관이 있는지)를 먼저 검정하는 기법
- H0: 연속적인 관측값이 임의적이다.
- H1: 연속적인 관측값이 임의적이 아니다. (=연관이 있다.)
1.2 Parameters
runstest_1samp(x, cutoff=‘mean’, correction=True)
- x: 2개의 관측값으로 이루어진 binary data (관측값은 정수)
- cutoff: data를 큰 값과 작은 값으로 나누기 위한 기준
- correction: 50 미만의 샘플사이즈일 경우 사건이 일어날 확률을 정의하기 어려우므로 0.5로 할당
1.3 Returns
- z-stat: 정규분포를 사용하므로 z 통계량 사용
- p-value
1.4 Implementation
import pandas as pd
data = ['a','a','b','b','a','a','a','a','b','b','b','b','b','a','a','b','b','a','b','b']
test_df = pd.DataFrame(data,columns=["product"])
test_df.head()
from statsmodels.sandbox.stats.runs import runstest_1samp
#Run-test를 위한 데이터 변환
test_df.loc[test_df['product']=='a','product'] =1
test_df.loc[test_df['product']=='b','product'] =0
#Perform Runs test
# - run-test의 귀무가설 : 연속적인 관측값이 임의적이다.
# - run-test의 대립가설 : 연속적인 관측값이 임의적이 아니다.
runstest_1samp(test_df['product'],cutoff =0.5 , correction=True)
(-1.1144881152070183, 0.26506984027306035)
2. Association analysis
2.1 Concept
사건의 연관규칙을 찾는 방법으로, A 후에 B라는 사건을 시행할 확률을 구함
- 장바구니 분석: 장바구니에 무엇이 같이 들어갈 것인지 분석
- 서열분석: A를 산 다음에 B를 살 것
2.2 Metric
- 지지도
- 전체 거래 중 항목 A와 B를 동시에 포함하는 거래의 비율
- A와 B가 동시에 포함된 거래수 / 전체 거래수
- 신뢰도
- 항목 A를 포함한느 거래 중에서 항목 A와 항목 B가 같이 포함될 확률로 연관성 정도 파악
- A와 B가 동시에 포함된 거래수 / A를 포함하는 거래수
- 향상도
- A가 구매되지 않았을 때 품목 B의 구매 확률에 비해 A가 구매되었을 때 품목 B의 구매 확률 증가비
- 품목 A와 B의 구매가 서로 관련이 없는 경우에 향상도가 1
- A와 B가 동시에 포함된 거래수 / A를 포함하는 거래수 * B를 포함하는 거래수
- A가 구매되지 않았을 때 품목 B의 구매 확률에 비해 A가 구매되었을 때 품목 B의 구매 확률 증가비
2.3 Aprori Algorithm
가능한 모든 경우의 수를 탐색하여 지지도, 신뢰도, 향상도가 높은 규칙들을 찾아내는 방식
- 아이템이 n개일 때, 탐색해야 할 모든 경우의 수: n*(n-1)
- 빈발집합: 최소 지지도보다 큰 지지도 값을 갖는 품목의 집합
- 계산방법
- 모든 품목 집합에 대한 지지도를 전부 계산하는 것이 아님
- 최소 지지도 이상의 빈발항목을 찾은 후 그것들에 대해서만 연관규칙 계산
- 장단점
- 장점: 구현과 이해가 쉬움
- 단점: 아이템의 개수가 많아지면 계산 복잡도가 증가
2.4 Parameters
-
apriori
from mlxtend.frequent_patterns import apriori
- df: 값이 0/1 또는 T/F인 dataframe
- min_support: 최소 지지도
- use_colnames: True이면 열 인덱스 대신 반환된 DataFrame의 열 이름을 사용
- max_len: 생성된 항목 세트의 최대 길이로 None인 경우 모든 항목 세트 길이를 평가
- low_memory: 메모리 리소스가 제한된 경우에 사용, 속도가 느림
-
association_rules
from mlxtend.frequent_patterns import association_rules association_rules(df, metric=‘confidence’, min_threshold=0.8, support_only=False)
- df: 값이 0/1 또는 T/F인 dataframe
- metric: support_only=True인 경우 자동으로 support로 설정
- min_threshold: metric에 지정된 rule의 최소값
- support_only: support만 계산하고 다른 메트릭의 열을 NaN으로 출력
2.5 Implementation1
import pandas as pd
from mlxtend.preprocessing import TransactionEncoder
dataset = [['Apple', 'Beer', 'Rice', 'Chicken'],
['Apple', 'Beer', 'Rice'],
['Apple', 'Beer'],
['Apple', 'Bananas'],
['Milk', 'Beer', 'Rice', 'Chicken'],
['Milk', 'Beer', 'Rice'],
['Milk', 'Beer'],
['Apple', 'Bananas']]
te = TransactionEncoder()
te_ary = te.fit_transform(dataset)
print(te.columns_)
te_ary
['Apple', 'Bananas', 'Beer', 'Chicken', 'Milk', 'Rice']
array([[ True, False, True, True, False, True],
[ True, False, True, False, False, True],
[ True, False, True, False, False, False],
[ True, True, False, False, False, False],
[False, False, True, True, True, True],
[False, False, True, False, True, True],
[False, False, True, False, True, False],
[ True, True, False, False, False, False]])
- TransactionEncoder를 통해 데이터세트를 트랜잭션 형태로 변경
- 원본 데이터의 unique 값을 컬럼으로 지정하고 True/False로 변환
df = pd.DataFrame(te_ary,columns = te.columns_)
df
## 지지도 60% 이상인 품목만 추출
from mlxtend.frequent_patterns import apriori
apriori(df, min_support=0.6, use_colnames=True)
- 최소 지지도가 0.6 이상인 품목
## 규칙의 길이를 추출하는 방법
frequent_itemsets = apriori(df, min_support=0.3, use_colnames=True)
frequent_itemsets['length'] = frequent_itemsets['itemsets'].apply(lambda x: len(x))
frequent_itemsets
- 최소 지지도가 0.3 이상인 규칙만 추출하고 규칙의 길이 파악
2.6 Implementation2
df= pd.read_csv("https://raw.githubusercontent.com/ADPclass/ADP_book_ver01/main/data/groceries.csv",)
df
df_split = df.iloc[:,0].str.split(',',expand=True)
df_split.values
array([['tropical fruit', 'yogurt', 'coffee', ..., None, None, None],
['whole milk', None, None, ..., None, None, None],
['pip fruit', 'yogurt', 'cream cheese', ..., None, None, None],
...,
['chicken', 'citrus fruit', 'other vegetables', ..., None, None,
None],
['semi-finished bread', 'bottled water', 'soda', ..., None, None,
None],
['chicken', 'tropical fruit', 'other vegetables', ..., None, None,
None]], dtype=object)
- 전처리
df_split_ary = df_split.values
groceries = []
for i in range(len(df_split_ary)) :
temp = list(filter(None,df_split_ary[i]))
groceries.append(temp)
groceries
[['tropical fruit', 'yogurt', 'coffee'],
['whole milk'],
['pip fruit', 'yogurt', 'cream cheese', 'meat spreads'],
['other vegetables',
'whole milk',
'condensed milk',
'long life bakery product'],
...]
- None을 지우고 트랜잭션 형태로 바꿈
from mlxtend.preprocessing import TransactionEncoder
import pandas as pd
te = TransactionEncoder()
groceries_tr = te.fit(groceries).transform(groceries)
groceries_tr = pd.DataFrame(groceries_tr, columns=te.columns_)
groceries_tr
from mlxtend.frequent_patterns import apriori
# 지지도가 5% 이상인 빈번항목집합 탐색
groceries_ap = apriori(groceries_tr, min_support=0.01,
use_colnames=True)
groceries_ap
- 지지도가 5% 이상인 빈번항목 집합
from mlxtend.frequent_patterns import association_rules
# 신뢰도가 0.3 이상인 빈번항목집합 탐색
association_rules(groceries_ap, metric="confidence", min_threshold=0.3)
- assoication_rules를 통해 규칙 파악
rules = association_rules(groceries_ap, metric="lift", min_threshold=1)
# 규칙의 길이 컬럼 생성
rules["antecedent_len"] = rules["antecedents"].apply(lambda x: len(x))
rules[ (rules['antecedent_len'] >=2) &
(rules['confidence'] >=0.4) &
(rules['lift'] >=3) ]
- 규칙 길이가 2 이상, 신뢰도가 0.4 이상, 향상도가 3이상인 규칙 추출
댓글남기기