🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

차원 축소와 연관 규칙 완벽 가이드 - 슬라이드 1/8
A

AI Generated

2025. 12. 4. · 13 Views

차원 축소와 연관 규칙 완벽 가이드

고차원 데이터를 효율적으로 다루는 차원 축소 기법과 데이터 사이의 숨겨진 패턴을 찾아내는 연관 규칙 마이닝을 초급자도 이해할 수 있도록 쉽게 설명합니다. PCA부터 Apriori 알고리즘까지 실무에서 바로 활용할 수 있는 예제와 함께 배워봅니다.


목차

  1. 차원_축소의_필요성
  2. 주성분_분석_PCA_원리
  3. PCA_구현하기
  4. 연관_규칙_마이닝_개요
  5. 지지도_신뢰도_향상도
  6. Apriori_알고리즘
  7. 연관_규칙_활용_사례

1. 차원 축소의 필요성

김개발 씨는 고객 데이터를 분석하는 프로젝트를 맡게 되었습니다. 데이터를 열어보니 컬럼이 무려 500개나 되었습니다.

"이걸 어떻게 다 분석하지?" 막막해하던 김개발 씨에게 선배 박시니어 씨가 다가왔습니다. "차원 축소에 대해 들어본 적 있어요?"

차원 축소는 한마디로 데이터의 핵심만 남기고 불필요한 정보를 줄이는 기술입니다. 마치 두꺼운 책의 핵심 내용만 요약하는 것과 같습니다.

이를 통해 계산 속도를 높이고, 시각화를 가능하게 하며, 모델의 성능까지 향상시킬 수 있습니다.

다음 코드를 살펴봅시다.

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris

# 아이리스 데이터셋 로드 - 4개의 특성을 가진 데이터
iris = load_iris()
data = pd.DataFrame(iris.data, columns=iris.feature_names)

# 데이터의 차원 확인
print(f"원본 데이터 shape: {data.shape}")
# 출력: (150, 4) - 150개 샘플, 4개 특성

# 고차원 데이터의 문제점 시뮬레이션
high_dim_data = np.random.rand(1000, 500)
print(f"고차원 데이터 shape: {high_dim_data.shape}")
# 500개의 특성 - 분석과 시각화가 어려움

김개발 씨는 입사 6개월 차 데이터 분석가입니다. 오늘 새로운 프로젝트를 배정받았는데, 고객 행동 데이터를 분석해서 인사이트를 도출하라는 미션이었습니다.

의욕에 차서 데이터를 열어본 김개발 씨는 그만 당황하고 말았습니다. 컬럼이 500개나 되는 거대한 데이터셋이 눈앞에 펼쳐져 있었습니다.

나이, 성별 같은 기본 정보부터 시작해서 클릭 횟수, 체류 시간, 구매 이력, 검색 키워드까지 온갖 정보가 담겨 있었습니다. 선배 박시니어 씨가 김개발 씨의 모니터를 힐끗 보더니 말했습니다.

"500개 컬럼을 다 쓸 필요 없어요. 차원 축소를 해보는 게 어때요?" 그렇다면 차원이란 정확히 무엇일까요?

쉽게 비유하자면, 차원은 마치 데이터를 설명하는 관점의 개수와 같습니다. 사람을 설명할 때 키, 몸무게, 나이라는 세 가지 관점을 사용하면 3차원 데이터가 됩니다.

관점이 많아질수록 더 자세히 설명할 수 있지만, 그만큼 복잡해지기도 합니다. 고차원 데이터가 왜 문제가 될까요?

첫째, 차원의 저주라는 현상이 발생합니다. 차원이 높아질수록 데이터 포인트 사이의 거리가 비슷해져서 의미 있는 패턴을 찾기 어려워집니다.

마치 모든 사람이 비슷비슷해 보여서 구분이 안 되는 것과 같습니다. 둘째, 계산 비용이 기하급수적으로 증가합니다.

500개의 특성을 모두 사용하면 모델 학습에 엄청난 시간과 메모리가 필요합니다. 간단한 분석도 몇 시간씩 걸릴 수 있습니다.

셋째, 시각화가 불가능해집니다. 우리가 눈으로 볼 수 있는 것은 2차원 또는 3차원까지입니다.

500차원 데이터를 그래프로 그려볼 방법이 없습니다. 바로 이런 문제를 해결하기 위해 차원 축소 기술이 등장했습니다.

차원 축소는 데이터의 핵심 정보는 최대한 보존하면서 차원 수를 줄이는 기술입니다. 500개의 특성 중에서 정말 중요한 10개나 20개만 남기는 것입니다.

물론 아무렇게나 고르는 것이 아니라, 수학적으로 가장 중요한 정보를 담고 있는 새로운 특성을 만들어냅니다. 실제 현업에서는 어떻게 활용할까요?

이미지 처리 분야에서는 수만 개의 픽셀로 이루어진 이미지를 몇백 개의 특성으로 압축합니다. 추천 시스템에서는 수천 개의 상품 특성을 축소해서 유사한 상품을 빠르게 찾아냅니다.

유전자 분석에서는 수만 개의 유전자 데이터를 핵심 패턴으로 요약합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

박시니어 씨의 조언을 듣고 차원 축소를 적용해보기로 했습니다. 500개의 특성을 20개로 줄였더니 분석 속도가 10배 이상 빨라졌고, 2차원으로 시각화해보니 고객 그룹이 명확하게 구분되는 것을 볼 수 있었습니다.

실전 팁

💡 - 차원 축소 전에 데이터 정규화를 먼저 수행하세요

  • 축소할 차원 수는 설명된 분산 비율을 보고 결정합니다

2. 주성분 분석 PCA 원리

김개발 씨는 차원 축소가 필요하다는 것은 알겠는데, 구체적으로 어떻게 하는지 궁금해졌습니다. 박시니어 씨가 말했습니다.

"가장 기본이 되는 방법이 PCA야. 주성분 분석이라고 하지.

이것부터 이해하면 다른 방법도 쉬워져요."

**PCA(Principal Component Analysis)**는 데이터의 분산이 가장 큰 방향을 찾아 새로운 축을 만드는 기법입니다. 마치 사진을 찍을 때 가장 특징이 잘 드러나는 각도를 찾는 것과 같습니다.

원본 데이터의 정보를 최대한 보존하면서 차원을 줄일 수 있습니다.

다음 코드를 살펴봅시다.

import numpy as np
import matplotlib.pyplot as plt

# 2차원 데이터 생성 - 상관관계가 있는 데이터
np.random.seed(42)
x = np.random.randn(100)
y = 0.8 * x + 0.2 * np.random.randn(100)
data = np.column_stack([x, y])

# 데이터 중심화 (평균을 0으로)
data_centered = data - data.mean(axis=0)

# 공분산 행렬 계산
cov_matrix = np.cov(data_centered.T)
print(f"공분산 행렬:\n{cov_matrix}")

# 고유값과 고유벡터 계산 - PCA의 핵심!
eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
print(f"고유값: {eigenvalues}")
print(f"첫 번째 주성분 방향: {eigenvectors[:, 0]}")

김개발 씨는 PCA라는 용어를 처음 들었습니다. Principal Component Analysis, 한국어로 주성분 분석이라고 합니다.

이름만 들으면 어려워 보이지만, 원리를 이해하면 의외로 직관적입니다. 박시니어 씨가 비유를 들어 설명해주었습니다.

"김개발 씨, 혹시 구름 사진 찍어본 적 있어요? 구름을 찍을 때 어떤 각도에서 찍으면 가장 예쁘게 나올까요?" 김개발 씨가 고개를 갸우뚱합니다.

"글쎄요, 구름의 모양이 가장 잘 드러나는 각도요?" "맞아요! PCA도 똑같아요.

데이터를 가장 잘 설명하는 각도, 즉 분산이 가장 큰 방향을 찾는 거예요." 분산이란 데이터가 얼마나 퍼져 있는지를 나타내는 지표입니다. 분산이 크다는 것은 데이터 포인트들이 넓게 분포되어 있다는 뜻입니다.

PCA는 이 분산이 가장 큰 방향을 첫 번째 주성분으로 선택합니다. 왜 분산이 큰 방향이 중요할까요?

데이터가 넓게 퍼진 방향에 정보가 많이 담겨 있기 때문입니다. 반대로 데이터가 좁게 모여 있는 방향은 모든 데이터가 비슷비슷하다는 뜻이므로 정보가 적습니다.

PCA의 작동 원리를 단계별로 살펴보겠습니다. 첫째, 데이터 중심화를 수행합니다.

모든 데이터에서 평균을 빼서 데이터의 중심을 원점으로 옮깁니다. 이렇게 하면 계산이 훨씬 간편해집니다.

둘째, 공분산 행렬을 계산합니다. 공분산 행렬은 각 특성들이 서로 어떻게 관련되어 있는지를 담고 있습니다.

두 특성이 함께 증가하는 경향이 있는지, 반대로 움직이는지 등의 정보가 들어 있습니다. 셋째, 고유값 분해를 수행합니다.

여기서 수학이 등장합니다. 공분산 행렬을 고유값 분해하면 고유벡터고유값을 얻을 수 있습니다.

고유벡터는 새로운 축의 방향을, 고유값은 그 방향의 중요도를 나타냅니다. 넷째, 고유값이 큰 순서대로 고유벡터를 정렬하고, 원하는 개수만큼 선택합니다.

이것이 바로 주성분입니다. 위의 코드에서 공분산 행렬을 계산하고 고유값 분해를 수행하는 부분을 볼 수 있습니다.

numpy의 linalg.eig 함수가 이 계산을 자동으로 처리해줍니다. 고유값이 큰 주성분일수록 원본 데이터의 정보를 많이 담고 있습니다.

보통 전체 분산의 95%나 99%를 설명하는 만큼의 주성분만 선택합니다. 김개발 씨가 물었습니다.

"그러면 원본 데이터는 어떻게 되는 건가요?" 박시니어 씨가 답했습니다. "원본 데이터를 새로운 축에 투영하는 거예요.

3차원 물체의 그림자를 2차원 바닥에 비추는 것처럼요. 정보 손실은 약간 있지만, 핵심은 보존됩니다."

실전 팁

💡 - PCA는 선형 관계만 잡아낼 수 있으므로 비선형 데이터에는 다른 방법을 고려하세요

  • 특성들의 스케일이 다르면 반드시 정규화를 먼저 수행해야 합니다

3. PCA 구현하기

이론을 이해한 김개발 씨는 이제 직접 코드로 구현해보고 싶어졌습니다. 박시니어 씨가 말했습니다.

"scikit-learn을 사용하면 PCA를 아주 쉽게 적용할 수 있어요. 직접 해보면서 감을 잡아봐요."

scikit-learn의 PCA 클래스를 사용하면 몇 줄의 코드로 차원 축소를 수행할 수 있습니다. fit_transform 메서드로 데이터를 변환하고, explained_variance_ratio로 각 주성분이 설명하는 분산 비율을 확인할 수 있습니다.

다음 코드를 살펴봅시다.

from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris

# 데이터 로드 및 정규화
iris = load_iris()
scaler = StandardScaler()
X_scaled = scaler.fit_transform(iris.data)

# PCA 적용 - 4차원을 2차원으로 축소
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)

# 결과 확인
print(f"원본 shape: {iris.data.shape}")
print(f"축소 후 shape: {X_pca.shape}")
print(f"설명된 분산 비율: {pca.explained_variance_ratio_}")
print(f"누적 설명 분산: {sum(pca.explained_variance_ratio_):.2%}")

김개발 씨는 노트북을 열고 직접 코드를 작성하기 시작했습니다. 먼저 유명한 아이리스 데이터셋을 사용하기로 했습니다.

붓꽃의 꽃받침 길이, 꽃받침 너비, 꽃잎 길이, 꽃잎 너비 총 4개의 특성으로 이루어진 데이터입니다. 첫 번째로 해야 할 일은 데이터 정규화입니다.

왜 정규화가 필요할까요? 특성마다 단위와 범위가 다르기 때문입니다.

키는 150190cm 범위이고, 몸무게는 50100kg 범위라면, 단순히 숫자만 비교하면 범위가 큰 특성에 PCA가 치우치게 됩니다. StandardScaler는 각 특성의 평균을 0으로, 표준편차를 1로 만들어줍니다.

이렇게 하면 모든 특성이 동등한 조건에서 비교됩니다. 두 번째로 PCA 객체를 생성합니다.

n_components 파라미터로 원하는 차원 수를 지정합니다. 위 코드에서는 4차원 데이터를 2차원으로 줄이기 위해 2를 지정했습니다.

만약 0과 1 사이의 소수를 넣으면 그 비율만큼의 분산을 설명하는 주성분 개수가 자동으로 결정됩니다. 세 번째로 fit_transform 메서드를 호출합니다.

이 메서드는 두 가지 일을 합니다. fit은 데이터를 분석해서 주성분을 찾고, transform은 원본 데이터를 새로운 축으로 변환합니다.

한 번에 처리하기 위해 fit_transform을 사용합니다. 결과를 확인해보면 원본 데이터는 (150, 4) 형태였는데, 변환 후에는 (150, 2)가 되었습니다.

150개의 샘플은 그대로이고, 특성 수만 4개에서 2개로 줄었습니다. explained_variance_ratio_ 속성은 매우 중요합니다.

이 값은 각 주성분이 전체 분산 중 얼마나 설명하는지를 보여줍니다. 예를 들어 첫 번째 주성분이 0.72, 두 번째가 0.23이라면, 2개의 주성분으로 전체 정보의 95%를 설명할 수 있다는 뜻입니다.

나머지 5%의 정보만 손실된 것입니다. 김개발 씨가 결과를 보고 감탄했습니다.

"4개의 특성을 2개로 줄였는데 95%나 보존되네요!" 박시니어 씨가 고개를 끄덕였습니다. "원래 4개의 특성이 서로 상관관계가 높았던 거예요.

그래서 적은 주성분으로도 충분히 설명할 수 있는 거죠." 이제 2차원으로 축소된 데이터는 산점도로 시각화할 수 있습니다. matplotlib을 사용해서 그래프를 그려보면 세 종류의 붓꽃이 어떻게 분포되어 있는지 한눈에 볼 수 있습니다.

주의할 점이 있습니다. PCA로 만들어진 새로운 특성은 원본 특성과 다릅니다.

첫 번째 주성분은 꽃받침 길이도 아니고 꽃잎 너비도 아닌, 여러 특성이 조합된 새로운 값입니다. 해석이 어려워질 수 있다는 단점이 있습니다.

실전 팁

💡 - n_components에 소수(예: 0.95)를 넣으면 해당 분산 비율을 만족하는 주성분 수가 자동 결정됩니다

  • pca.components_로 각 주성분이 원본 특성과 어떤 관계인지 확인할 수 있습니다

4. 연관 규칙 마이닝 개요

차원 축소를 마스터한 김개발 씨에게 새로운 과제가 주어졌습니다. "고객들의 구매 패턴을 분석해서 함께 자주 팔리는 상품을 찾아주세요." 박시니어 씨가 말했습니다.

"이건 연관 규칙 마이닝으로 풀 수 있어요. 마트에서 맥주와 기저귀를 같이 진열하는 이유, 들어본 적 있죠?"

연관 규칙 마이닝은 데이터에서 함께 발생하는 패턴을 찾아내는 기법입니다. 마치 탐정이 사건의 연결고리를 찾아내는 것처럼, 아이템 간의 숨겨진 관계를 발견합니다.

마케팅, 추천 시스템, 웹 분석 등 다양한 분야에서 활용됩니다.

다음 코드를 살펴봅시다.

# 장바구니 데이터 예시
transactions = [
    ['빵', '우유', '기저귀'],
    ['빵', '기저귀', '맥주', '계란'],
    ['우유', '기저귀', '맥주', '콜라'],
    ['빵', '우유', '기저귀', '맥주'],
    ['빵', '우유', '기저귀', '콜라']
]

# 아이템 빈도 계산
from collections import Counter
all_items = [item for trans in transactions for item in trans]
item_counts = Counter(all_items)

print("아이템별 출현 횟수:")
for item, count in item_counts.most_common():
    print(f"  {item}: {count}회 ({count/len(transactions)*100:.0f}%)")

# 연관 규칙의 기본 아이디어
# {기저귀} -> {맥주} : 기저귀를 사면 맥주도 살까?

김개발 씨는 새로운 미션에 대해 생각해보았습니다. 고객들이 어떤 상품을 함께 구매하는지 알아내는 것, 이것을 장바구니 분석이라고 합니다.

유명한 일화가 있습니다. 1990년대 미국의 한 대형 마트에서 데이터를 분석했더니 놀라운 사실을 발견했습니다.

금요일 저녁에 기저귀와 맥주가 함께 팔리는 경우가 많다는 것이었습니다. 처음에는 관련 없어 보이는 두 상품이지만, 이유를 생각해보면 납득이 됩니다.

금요일 저녁, 아이가 있는 아빠들이 퇴근 후 기저귀를 사러 마트에 들렀다가 주말에 마실 맥주도 함께 구매한 것입니다. 이처럼 연관 규칙 마이닝은 데이터에서 숨겨진 패턴을 찾아냅니다.

연관 규칙은 "A를 사면 B도 산다"라는 형태로 표현됩니다. 수학적으로는 A → B라고 씁니다.

A를 선행 항목(antecedent), B를 **결과 항목(consequent)**이라고 부릅니다. 위의 코드에서 장바구니 데이터를 정의했습니다.

다섯 명의 고객이 각각 어떤 상품을 구매했는지 리스트로 표현되어 있습니다. 이런 형태의 데이터를 트랜잭션 데이터라고 합니다.

먼저 각 아이템이 얼마나 자주 등장하는지 세어봅니다. 기저귀는 5번 모두 등장하고, 맥주는 3번 등장합니다.

이 빈도 정보가 연관 규칙을 찾는 기초가 됩니다. 연관 규칙은 어디에 활용될까요?

첫째, 추천 시스템입니다. 아마존의 "이 상품을 구매한 고객이 함께 구매한 상품"이 바로 연관 규칙을 활용한 것입니다.

둘째, 매장 진열입니다. 함께 구매되는 상품을 가까이 배치하면 매출을 높일 수 있습니다.

셋째, 교차 판매입니다. 고객이 특정 상품을 장바구니에 담으면 관련 상품을 추천합니다.

넷째, 웹 분석입니다. 사용자가 특정 페이지를 보면 어떤 페이지를 다음에 볼지 예측할 수 있습니다.

박시니어 씨가 말했습니다. "연관 규칙을 찾는 건 쉬워 보이지만, 아이템 조합이 많아지면 계산량이 폭발적으로 늘어나요.

그래서 효율적인 알고리즘이 필요한 거죠." 김개발 씨가 고개를 끄덕였습니다. 상품이 1000개라면 가능한 조합은 어마어마하게 많을 것입니다.

모든 조합을 다 검사하는 것은 불가능에 가깝습니다. 다음에 배울 지지도, 신뢰도, 향상도라는 지표와 Apriori 알고리즘이 바로 이 문제를 해결하는 열쇠입니다.

실전 팁

💡 - 트랜잭션 데이터는 고객 ID나 주문 번호로 그룹화된 구매 내역입니다

  • 연관 규칙은 인과관계가 아닌 상관관계를 나타낸다는 점을 기억하세요

5. 지지도 신뢰도 향상도

김개발 씨가 물었습니다. "기저귀와 맥주가 함께 팔린다는 건 알겠는데, 이 규칙이 얼마나 믿을 만한지 어떻게 판단하나요?" 박시니어 씨가 대답했습니다.

"좋은 질문이에요! 연관 규칙의 품질을 평가하는 세 가지 핵심 지표가 있어요.

지지도, 신뢰도, 향상도예요."

**지지도(Support)**는 해당 아이템 조합이 전체 거래에서 얼마나 자주 나타나는지, **신뢰도(Confidence)**는 A를 샀을 때 B도 살 확률이 얼마인지, **향상도(Lift)**는 우연히 함께 살 확률 대비 얼마나 더 자주 함께 사는지를 나타냅니다.

다음 코드를 살펴봅시다.

# 예시 데이터: 5개의 거래
transactions = [
    {'빵', '우유', '기저귀'},
    {'빵', '기저귀', '맥주'},
    {'우유', '기저귀', '맥주'},
    {'빵', '우유', '기저귀', '맥주'},
    {'빵', '우유', '기저귀'}
]
total = len(transactions)

# 지지도(Support): 해당 조합이 나타나는 비율
# {기저귀, 맥주}가 함께 나타나는 거래 수
diaper_beer = sum(1 for t in transactions if {'기저귀', '맥주'}.issubset(t))
support = diaper_beer / total
print(f"지지도(기저귀, 맥주): {support:.0%}")

# 신뢰도(Confidence): 기저귀를 샀을 때 맥주도 살 확률
diaper_count = sum(1 for t in transactions if '기저귀' in t)
confidence = diaper_beer / diaper_count
print(f"신뢰도(기저귀->맥주): {confidence:.0%}")

# 향상도(Lift): 독립일 때 대비 함께 살 확률의 비율
beer_count = sum(1 for t in transactions if '맥주' in t)
lift = confidence / (beer_count / total)
print(f"향상도(기저귀->맥주): {lift:.2f}")

김개발 씨는 연관 규칙을 평가하는 방법이 궁금해졌습니다. 단순히 "기저귀를 사면 맥주를 산다"는 규칙만으로는 부족합니다.

이 규칙이 얼마나 자주 적용되는지, 얼마나 정확한지 알아야 실제로 활용할 수 있습니다. 박시니어 씨가 화이트보드에 세 가지 지표를 적었습니다.

첫 번째는 **지지도(Support)**입니다. 지지도는 해당 아이템 조합이 전체 거래에서 얼마나 자주 나타나는지를 나타냅니다.

마치 인기도와 비슷합니다. "기저귀와 맥주를 함께 산 거래가 전체의 몇 퍼센트인가?"라는 질문에 답합니다.

위 코드에서 5개의 거래 중 기저귀와 맥주가 함께 등장하는 거래는 3개입니다. 따라서 지지도는 3/5 = 60%입니다.

지지도가 너무 낮으면 그 규칙은 신뢰하기 어렵습니다. 아무리 신뢰도가 높아도 한두 건의 거래에서만 나타난 패턴은 우연일 가능성이 높습니다.

두 번째는 **신뢰도(Confidence)**입니다. 신뢰도는 "A를 샀을 때 B도 살 확률"입니다.

조건부 확률이라고도 합니다. "기저귀를 산 사람 중에서 맥주도 산 사람은 몇 퍼센트인가?"라는 질문에 답합니다.

기저귀가 등장하는 거래는 5개 모두이고, 그중 맥주도 함께 등장하는 거래는 3개입니다. 따라서 신뢰도는 3/5 = 60%입니다.

신뢰도가 높다는 것은 A를 사면 B도 살 가능성이 높다는 뜻입니다. 하지만 신뢰도만으로는 부족합니다.

왜일까요? 만약 맥주가 원래 모든 사람이 사는 인기 상품이라면, 기저귀와 관계없이 맥주를 사는 것일 수 있습니다.

이런 함정을 피하기 위해 세 번째 지표가 필요합니다. 세 번째는 **향상도(Lift)**입니다.

향상도는 "우연히 함께 살 확률 대비 실제로 함께 사는 비율"입니다. 기저귀와 맥주가 정말로 연관이 있는지, 아니면 둘 다 인기 상품이라 우연히 함께 팔리는 것인지를 구분합니다.

향상도가 1이면 두 아이템은 독립적입니다. 서로 영향을 주지 않습니다.

향상도가 1보다 크면 양의 상관관계가 있습니다. A를 사면 B를 살 확률이 높아집니다.

향상도가 1보다 작으면 음의 상관관계가 있습니다. A를 사면 오히려 B를 살 확률이 낮아집니다.

위 코드에서 맥주의 전체 지지도는 3/5 = 60%입니다. 기저귀를 샀을 때 맥주를 살 확률(신뢰도)도 60%이므로, 향상도는 0.6/0.6 = 1입니다.

이 경우 기저귀와 맥주는 특별한 연관이 없다고 볼 수 있습니다. 실제 데이터에서는 향상도가 1.5 이상이면 의미 있는 연관관계로 보는 경우가 많습니다.

김개발 씨가 정리했습니다. "지지도로 빈도를 확인하고, 신뢰도로 조건부 확률을 보고, 향상도로 진짜 연관인지 확인하는 거군요!"

실전 팁

💡 - 세 지표를 종합적으로 고려해야 합니다. 지지도가 낮으면 신뢰도가 높아도 의미 없을 수 있습니다

  • 향상도가 1에 가까우면 두 아이템은 독립적이므로 규칙으로 활용하기 어렵습니다

6. Apriori 알고리즘

김개발 씨가 고민에 빠졌습니다. "상품이 1000개면 가능한 조합이 엄청나게 많잖아요.

이걸 다 계산하려면..." 박시니어 씨가 웃으며 말했습니다. "그래서 Apriori 알고리즘이 있는 거예요.

똑똑하게 불필요한 계산을 건너뛰는 방법이죠."

Apriori 알고리즘은 빈발 아이템 집합을 효율적으로 찾는 알고리즘입니다. 핵심 아이디어는 "빈발하지 않은 아이템을 포함하는 조합은 절대 빈발할 수 없다"는 원리입니다.

이를 통해 탐색 공간을 대폭 줄여 계산 효율을 높입니다.

다음 코드를 살펴봅시다.

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

# 거래 데이터 정의
transactions = [
    ['빵', '우유', '기저귀'],
    ['빵', '기저귀', '맥주', '계란'],
    ['우유', '기저귀', '맥주', '콜라'],
    ['빵', '우유', '기저귀', '맥주'],
    ['빵', '우유', '기저귀', '콜라']
]

# 원-핫 인코딩으로 변환
te = TransactionEncoder()
te_array = te.fit_transform(transactions)
df = pd.DataFrame(te_array, columns=te.columns_)

# Apriori 알고리즘으로 빈발 아이템 집합 찾기
frequent_itemsets = apriori(df, min_support=0.4, use_colnames=True)
print("빈발 아이템 집합:")
print(frequent_itemsets)

# 연관 규칙 생성
rules = association_rules(frequent_itemsets, metric="lift", min_threshold=1.0)
print("\n연관 규칙 (향상도 >= 1.0):")
print(rules[['antecedents', 'consequents', 'support', 'confidence', 'lift']])

김개발 씨는 조합 폭발 문제에 대해 생각해보았습니다. 상품이 n개일 때 가능한 부분집합의 수는 2의 n제곱입니다.

상품이 100개만 되어도 조합의 수는 우주의 원자 수보다 많습니다. 박시니어 씨가 Apriori 알고리즘의 핵심 아이디어를 설명했습니다.

"Apriori는 '하향 폐쇄 성질'을 이용해요. 어떤 아이템 집합이 빈발하지 않으면, 그 집합을 포함하는 더 큰 집합도 절대 빈발할 수 없다는 거죠." 예를 들어 {맥주}의 지지도가 3%로 기준에 미달한다면, {맥주, 기저귀}나 {맥주, 빵}처럼 맥주를 포함하는 모든 조합은 검사할 필요가 없습니다.

더 큰 집합의 지지도는 항상 부분집합보다 작거나 같기 때문입니다. Apriori 알고리즘의 동작 과정을 단계별로 살펴보겠습니다.

첫째, 모든 개별 아이템의 지지도를 계산합니다. 최소 지지도 기준을 충족하는 아이템만 남깁니다.

둘째, 남은 아이템들로 2개짜리 조합을 만들고 지지도를 계산합니다. 다시 기준을 충족하는 조합만 남깁니다.

셋째, 2개짜리 조합에서 3개짜리 조합을 만들고 같은 과정을 반복합니다. 넷째, 더 이상 기준을 충족하는 조합이 없을 때까지 반복합니다.

이렇게 단계별로 올라가면서 탐색하기 때문에 불필요한 조합을 대폭 줄일 수 있습니다. 위의 코드에서 mlxtend 라이브러리를 사용했습니다.

이 라이브러리는 Apriori 알고리즘을 쉽게 사용할 수 있게 해줍니다. 먼저 TransactionEncoder로 거래 데이터를 원-핫 인코딩 형태로 변환합니다.

각 아이템이 해당 거래에 포함되어 있으면 True, 없으면 False인 테이블이 만들어집니다. 그 다음 apriori 함수를 호출합니다.

min_support 파라미터로 최소 지지도를 지정합니다. 0.4는 전체 거래의 40% 이상에서 나타나는 조합만 찾겠다는 뜻입니다.

마지막으로 association_rules 함수로 연관 규칙을 생성합니다. 빈발 아이템 집합에서 가능한 모든 규칙을 만들고, 지표를 계산합니다.

min_threshold로 향상도 기준을 설정하여 의미 있는 규칙만 필터링합니다. 결과를 보면 antecedents(선행 항목), consequents(결과 항목), 그리고 세 가지 지표가 표시됩니다.

이 정보를 바탕으로 비즈니스에 활용할 규칙을 선택하면 됩니다. 김개발 씨가 코드를 실행해보고 감탄했습니다.

"생각보다 간단하네요! 몇 줄 만에 연관 규칙이 나오다니."

실전 팁

💡 - min_support 값이 너무 낮으면 무의미한 규칙이 많아지고, 너무 높으면 규칙을 찾기 어렵습니다

  • mlxtend 설치: pip install mlxtend

7. 연관 규칙 활용 사례

모든 이론과 구현을 마친 김개발 씨가 물었습니다. "이제 실제로 어디에 쓸 수 있을까요?" 박시니어 씨가 미소를 지었습니다.

"생각보다 많은 곳에서 쓰이고 있어요. 지금 당장 여러분의 스마트폰에서도 이 기술이 작동하고 있죠."

연관 규칙 마이닝은 이커머스 추천, 교차 판매, 재고 관리, 의료 진단, 웹 사용자 분석 등 다양한 분야에서 활용됩니다. 데이터에서 숨겨진 패턴을 찾아 비즈니스 가치를 창출하는 핵심 기술입니다.

다음 코드를 살펴봅시다.

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

# 실제 이커머스 시나리오: 고객별 구매 내역
customer_purchases = [
    ['노트북', '마우스', '키보드', '모니터'],
    ['노트북', '마우스', '노트북가방'],
    ['스마트폰', '케이스', '충전기', '이어폰'],
    ['노트북', '마우스', '키보드', '외장하드'],
    ['스마트폰', '케이스', '충전기'],
    ['노트북', '마우스', '모니터', '웹캠'],
    ['태블릿', '케이스', '펜슬', '충전기'],
    ['노트북', '마우스', '키보드', '모니터', '외장하드']
]

# 분석 수행
te = TransactionEncoder()
df = pd.DataFrame(te.fit_transform(customer_purchases), columns=te.columns_)
frequent = apriori(df, min_support=0.3, use_colnames=True)
rules = association_rules(frequent, metric="confidence", min_threshold=0.7)

# 추천 시스템에 활용할 규칙 출력
print("=== 추천 규칙 (신뢰도 70% 이상) ===")
for _, rule in rules.iterrows():
    ant = ', '.join(list(rule['antecedents']))
    con = ', '.join(list(rule['consequents']))
    print(f"{ant} 구매 시 -> {con} 추천 (신뢰도: {rule['confidence']:.0%})")

김개발 씨는 연관 규칙을 실제로 어떻게 활용하는지 알고 싶어졌습니다. 박시니어 씨는 몇 가지 실제 사례를 들려주었습니다.

가장 대표적인 활용처는 이커머스 추천 시스템입니다. 아마존의 "이 상품을 구매한 고객이 함께 구매한 상품" 섹션을 본 적 있을 것입니다.

이것이 바로 연관 규칙을 활용한 것입니다. 노트북을 사면 마우스를 추천하고, 스마트폰을 사면 케이스를 추천합니다.

위의 코드에서 전자제품 구매 데이터를 분석했습니다. 결과를 보면 노트북을 구매한 고객에게 마우스를 추천하는 규칙이 높은 신뢰도로 나타날 것입니다.

두 번째 활용처는 매장 진열입니다. 대형 마트에서는 연관 규칙 분석 결과를 바탕으로 상품 배치를 결정합니다.

파스타와 토마토 소스, 빵과 버터처럼 함께 구매되는 상품을 가까이 배치하면 매출이 증가합니다. 반대로 기저귀와 맥주처럼 의외의 조합은 동선 끝에 배치해서 고객이 매장을 더 많이 둘러보게 만들기도 합니다.

세 번째 활용처는 교차 판매와 번들 상품입니다. "이 상품과 함께 구매하면 10% 할인" 같은 프로모션도 연관 규칙을 기반으로 설계됩니다.

함께 구매될 가능성이 높은 상품을 묶어서 판매하면 고객 만족도와 매출을 동시에 높일 수 있습니다. 네 번째 활용처는 의료 분야입니다.

특정 증상들이 함께 나타나는 패턴을 분석해서 질병을 진단하는 데 도움을 줍니다. "두통과 구역질과 어지러움이 함께 나타나면 편두통 가능성이 높다"와 같은 규칙을 찾아낼 수 있습니다.

다섯 번째 활용처는 웹 분석입니다. 사용자가 어떤 페이지를 본 후에 어떤 페이지로 이동하는지 분석합니다.

"상품 상세 페이지를 본 사용자가 리뷰 페이지도 본다"는 패턴을 발견하면 UI를 개선할 수 있습니다. 김개발 씨가 감탄했습니다.

"정말 다양하게 쓰이네요!" 하지만 박시니어 씨는 주의사항도 알려주었습니다. "연관 규칙은 상관관계를 보여주는 것이지 인과관계를 증명하는 게 아니에요.

기저귀를 샀다고 해서 맥주를 사게 되는 건 아니죠. 둘 다 살 가능성이 높은 고객군이 있는 거예요." 또한 시간에 따라 패턴이 변할 수 있습니다.

정기적으로 분석을 업데이트해야 합니다. 계절, 트렌드, 프로모션에 따라 구매 패턴이 달라지기 때문입니다.

김개발 씨는 오늘 배운 내용을 정리했습니다. 차원 축소로 복잡한 데이터를 단순화하고, 연관 규칙으로 숨겨진 패턴을 찾아내는 것.

이 두 가지 기술을 활용하면 데이터에서 가치 있는 인사이트를 발견할 수 있습니다.

실전 팁

💡 - 연관 규칙은 정기적으로 재분석하여 최신 패턴을 반영해야 합니다

  • 비즈니스 맥락을 고려해서 규칙을 해석하고 활용하세요
  • 상관관계와 인과관계를 혼동하지 않도록 주의해야 합니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Python#PCA#DimensionReduction#AssociationRules#Apriori#Python,ML,DimensionReduction

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.