아이템 간 연관성을 파악하는 Apriori 알고리즘

연관 분석의 기본 개념

연관 분석은 대규모 데이터에서 항목들 사이의 의미 있는 관계를 찾아내는 기법으로, 주로 소매업이나 추천 시스템에서 활용된다. 예를 들어, 고객이 특정 상품을 구매할 때 함께 구매하는 다른 상품을 발견함으로써 크로스셀링 전략을 수립할 수 있다.

기본 용어는 다음과 같다:

  • 트랜잭션(Transaction): 하나의 거래 내역, 즉 데이터셋의 한 행을 의미한다.
  • 아이템 집합(Itemset): 하나의 트랜잭션에 포함된 항목들의 모임. {양파}, {감자}는 각각 1-항목 집합이며, {양파, 감자}는 2-항목 집합이다.
  • 지원도(Support): 전체 트랜잭션 중에서 특정 아이템 집합이 나타나는 비율. 예를 들어, 100건의 거래 중 30건에서 양파와 감자가 동시에 구매되었다면 지원도는 0.3이다.
  • 신뢰도(Confidence): X가 구매되었을 때 Y도 함께 구매될 확률. 수식으로는 P(Y|X) = support(X ∪ Y) / support(X).
  • 향상도(Lift): X의 존재가 Y의 출현 확률에 미치는 영향을 나타낸다. lift(X→Y) = confidence(X→Y) / support(Y). 값이 1보다 클수록 두 항목 간의 양의 연관성이 강하다고 판단할 수 있다.

연관 규칙 도출 과정

연관 규칙을 찾는 작업은 일반적으로 다음 두 단계로 나뉜다:

  1. 빈번한 아이템 집합 생성: 최소 지원도(min_support) 이상을 만족하는 모든 아이템 집합을 탐색.
  2. 강한 규칙 생성: 빈번한 아이템 집합을 바탕으로 최소 신뢰도(min_confidence)를 넘는 규칙들을 추출.

Apriori 알고리즘의 핵심 원리

Apriori는 "부모 집합이 빈번하지 않으면 그 슈퍼셋도 빈번하지 않다"는 선결 조건 원리(Apriori Property)를 활용하여 탐색 공간을 줄인다. 이는 다음과 같은 의미를 갖는다:

  • 항목 집합 {A, B}가 빈번하지 않다면, 이를 포함하는 {A, B, C} 역시 빈번하지 않다.
  • 따라서 후보군을 생성할 때, 이전 단계에서 빈번하지 않은 집합을 기반으로 조합을 만들지 않음으로써 계산량을 크게 줄일 수 있다.

Python을 이용한 구현 예제

mlxtend 라이브러리를 사용해 실제 데이터에서 연관 규칙을 도출하는 예시를 살펴보자.

import pandas as pd
from mlxtend.frequent_patterns import apriori, association_rules

# 샘플 데이터 구성
raw_data = {
    "ID": [1, 2, 3, 4, 5, 6],
    "onion": [1, 0, 0, 1, 1, 1],
    "potato": [1, 1, 0, 1, 1, 1],
    "burger": [1, 1, 0, 0, 1, 1],
    "cabbage": [0, 1, 1, 1, 0, 1],
    "carrot": [0, 0, 1, 0, 1, 0]
}

df = pd.DataFrame(raw_data)
item_columns = ["onion", "potato", "burger", "cabbage", "carrot"]
binary_df = df[item_columns].astype(bool)

# 빈번한 아이템 집합 추출 (최소 지원도 50%)
frequent_sets = apriori(binary_df, min_support=0.5, use_colnames=True)

# 연관 규칙 생성 (Lift 기준, 최소 임계값 1)
association_ruleset = association_rules(frequent_sets, metric="lift", min_threshold=1)

# 신뢰도와 향상도 조건을 만족하는 규칙 필터링
filtered_rules = association_ruleset[
    (association_ruleset['lift'] > 1.125) & 
    (association_ruleset['confidence'] > 0.8)
]
print(filtered_rules)

출력 결과에서 (onion → potato), (burger → potato) 등의 규칙이 발견된다면, 해당 상품들을 함께 진열하거나 추천하는 전략이 효과적일 수 있다.

영화 장르 데이터 분석 사례

영화 데이터셋에서 장르 간 연관성을 분석해보자. 장르 정보는 다중 레이블 형태이므로 원-핫 인코딩을 통해 이진 속성으로 변환해야 한다.

movie_df = pd.read_csv("movies.csv")
genre_encoded = movie_df['genres'].str.get_dummies(sep='|')
movie_features = movie_df[['movieId', 'title']].join(genre_encoded)
movie_features.set_index(['movieId', 'title'], inplace=True)

# 빈번한 장르 조합 탐색
frequent_genres = apriori(movie_features, min_support=0.025, use_colnames=True)

# 연관 규칙 생성 및 정렬
rules_genre = association_rules(frequent_genres, metric="lift", min_threshold=1.25)
high_lift_rules = rules_genre[rules_genre['lift'] > 4].sort_values('lift', ascending=False)
print(high_lift_rules.head())

예를 들어, "Children"과 "Animation" 장르가 자주 함께 나타난다면, 이러한 영화들이 유사한 타겟층을 가진다는 것을 시사하며, 추천 시스템에 활용할 수 있다.

범주형 및 연속형 변수 처리

1. 범주형 변수의 이진화

성별, 교육 수준 등 범주형 변수는 각 카테고리 값을 별도의 이진 항목으로 변환해야 한다. 예를 들어:

  • 교육 수준: 고졸, 대졸, 석사 이상 → 세 개의 독립된 불리언 항목
  • 지역: 각 주를 지리적 지역(예: 동부, 서부)으로 그룹화하여 드물게 나타나는 값을 통합

2. 연속형 변수의 처리

소득, 나이 등의 연속형 변수는 직접 사용하기 어려우므로 다음과 같은 방법을 사용한다:

  • 이산화(Discretization): 구간으로 나누어 범주화. 예: 나이[20-30), [30-40) 등.
  • 통계 기반 접근: 평균, 분산 등의 통계량을 규칙 결과로 도출. 예: {소득 > 100000, 온라인쇼핑=yes} → 평균 나이=38세.

후자의 경우, 해당 규칙이 적용되는 그룹과 전체 평균 간의 차이가 통계적으로 유의미한지 검정(t-test 등)을 통해 확인해야 한다.

태그: Apriori 연관 규칙 지지도 신뢰도 향상도

7월 9일 20:22에 게시됨