///
Search
Duplicate
🖇️

1강 - 추천시스템의 이해 (연관분석, Apriori, FP-Growth)

추천시스템의 개요

1) 추천시스템이란? (feat. 정의, 중요성, 목표)

추천시스템은 사용자에게 상품을 제안하는 소프트웨어 도구이자 기술이다. 수십만 데이터 속에서 자신에게 관심있는 아이템을 수많은 사용자들이 직접 찾기는 굉장히 어렵다. 또한 기업 입장에서도 추천시스템을 이용한다면, 그들이 직접 사용자에게 추천을 통해 제안하므로 매출 및 플랫폼 이용 증대에 유의미한 영향을 가져올 수 있다. 그렇기 때문에, 사용자를 정하여 그 사용자에게 상품을 어떻게 추천할지에 대해 이해하는 것이 추천시스템의 목표이다. 이때, 기업은 사용자인 타겟 집단을 먼저 정하게 되는데, 전체 사용자를 pool로 할 수도 있으나 사업부나 마케팅팀의 입장에 따라 집중할 사용자 pool을 특정지을 수도 있다.

2) 기업에서의 추천시스템

당근마켓 ‘이 상품과 함께 봤어요’를 통해 한 상품을 본 다른 사용자들이 어떤 상품을 함께 보았는지 나타내 준다.
카카오(브런치) 해당 글과 유사한 글을 모델을 통해 비교하며 관련된 글을 추천해 준다.
유튜브 스케일이 크다 보니 굉장히 많은 영상들을 딥러닝 모델을 통해 추천하는데, 특히 최근에는 대부분의 영상이 추천으로 인한 클릭수로 추정된다고 한다.

3) 파레토와 롱테일의 법칙

파레토의 법칙 상위 20%가 전체의 80% 가치를 창출한다는 법칙으로, 완두콩 예시로부터 출발하였다. 상위 20%의 완두콩에서 전체 80%의 완두콩이 발화되었다는 내용의 예시를 통해 전개되으며, 현재까지도 기업 경영에 필요한 법칙이다. 기업에서는 주로 매출의 80%는 20%의 핵심 고객 및 주력 상품에서 나오므로 그 핵심 고객 20%를 찾아내 그들에게 역량을 집중할 필요가 있다는 의미로 활용된다.
롱테일의 법칙 하위 80%의 가치가 상위 20%의 가치보다 크다는 의미로, 앞에 나온 파레토의 법칙과 정반대인 법칙이다. 즉, 파레토의 법칙에서 소외된 80%의 고객에게서도 상당한 영업기회가 존재한다는 의미이다. 최근 발달한 인터넷은 파레토의 법칙이 적용되는 오프라인과 상황이 다르기에 이러한 법칙이 적용될 수 있었다. 특히 아마존이나 넷플릭스 등에서 잘 활용된 롱테일의 법칙은, 오프라인보다 온라인에서 적용하기 쉬우며 아마존이 오프라인 서점에서 잘 팔리지 않던 책을 온라인 추천을 통해 많이 판매하게 되었다는 것을 일례로 들 수 있다.

4) 추천시스템의 역사

2005 ~ 2010년
과거에는 Apriori 연관상품추천 알고리즘으로 출발하였다. Apriori 연관상품추천 알고리즘은 소비자가 같이 구매하는 상품을 추천하는 방식으로, 이를 통해 사람들이 추천시스템을 마케팅에서 어떻게 적용할지에 대해서 고민하는 계기가 되었다고 한다.
2010 ~ 2015년 2006 ~ 2009년에 넷플릭스에서 어떤 식으로 컨텐츠를 추천할 수 있을지 이에 대한 모델을 개발하는 대회가 열렸는데, 이때 우승자의 알고리즘이 바로 SVD를 활용하는 협업 필터링 모델이다.
2013 ~ 2017년
2013년부터 많은 사람들이 데이터의 중요성을 인식하기 시작했고, DataBase에 데이터를 축적함으로써 데이터가 점점 빅데이터로 변화해 갔다. 이전에 있던 모델들로는 빅데이터를 다루기 어려웠기에 이런 빅데이터들을 어떻게 다룰지에 대한 연구가 활발하게 진행되었으며, 이때 나온 것이 Spark를 이용한 빅데이터 모델이다.
2015 ~ 2017년
현재는 딥러닝의 발달에 힘입어 협업 필터링을 딥러닝으로 어떻게 소화할지, 대규모의 데이터 속에서 어떻게 딥러닝을 잘 활용해서 추천할지에 대한 연구가 활발히 진행되고 있다.
2017년 ~
2017년 이후로는 강화학습이나 Factorization Machine과 같은 머신러닝 알고리즘, Hierarchical RNN 등으로 초개인화 추천시스템에 대한 연구가 진행되고 있다.

연관분석 (Association Analysis)

1) 연관분석이란? (feat. 정의, 예시)

룰기반의 모델로서, 상품과 상품 사이에 어떠한 연관이 있는지를 찾아내는 알고리즘이다. 여기에서 의미하는 ‘연관’은 두 가지인데, 첫 번째는 얼마나(frequent) 같이 구매되느냐는 것으로 단순하게 같이 구매하는가의 여부를 중점으로 본다. 두 번째는 A 아이템을 구매하는 사람이 B 아이템을 같이 구매하느냐의 여부로, A 아이템 구매 조건에 따라 B 아이템을 구매하느냐 아니냐가 결정되므로 선후 관계가 형성된다. 그렇기 때문에 연관분석은 장바구니 분석이라고도 불린다.
월마트의 맥주와 기저귀 사례가 가장 유명하다. 월마트에서 구매한 사람들의 영수증을 통계내어본 결과, 맥주를 구매했을 때 기저귀를 구매하는 경향이 크다는 것을 알게 되었고 맥주 옆에 기저귀를 같이 진열함으로써 매출의 상승을 도모하였다. 이렇게 관련이 없어 보이는 두 물건의 접근 편의성을 높여 사람들이 실질적으로 구매를 이어서 할 수 있도록 도왔다.

2) 규칙평가지표

1.
지지도 support
A 상품을 구매했을 때, 이것이 B 상품의 구매로 이어지는 것을 의미하며, 조건절 A에 따라 B가 이어지는 현상을 의미한다.
For the rule A → B, support(A) = P(A)
2.
신뢰도 confidence
A 상품을 구매했을 때, 이것이 B 상품의 구매로 이어지는 확률 지표를 의미한다.
confidence(AB)=P(A,B)/P(A)confidence(A→B) = P(A, B) / P(A)
보통 위의 두 가지, 지지도와 신뢰도를 규칙평가지표로 자주 사용한다.
3.
향상도 lift
두 사건이 동시에 얼마나 발생하는지에 관한 비율에 따른 독립성을 측정하는 지표이다.
lift(AB)=P(A,B)/P(A)P(B)lift(A→B) = P(A, B) / P(A)▪P(B)

3) 규칙 생성

순열과 조합으로 전체 경우의 수를 구하는 것처럼, 가능한 모든 경우의 수를 탐색하여 규칙평가지표인 지지도, 신뢰도, 향상도가 높은 규칙들을 찾아내는 방식이다.

4) 연관분석의 문제점

아이템의 증가에 따라 규칙의 수가 기하급수적으로 증가한다. 아이템이 100개만 되더라도 규칙의 수가 (1.26*10^30)개로, 약 1경 가까운 경우의 수가 나온다. 그렇기에 아이템의 수가 많은 분야에서는 활용성이 떨어진다.

Apriori 알고리즘

1) Apriori 알고리즘 개념
item set의 증가를 줄이기 위한 방법
“빈번하지 않은 item set은 하위 item set 또한 빈번하지 않다”라는 아이디어에서 출발한 알고리즘
2) Apriori 알고리즘 원리
1.
k개의 item을 가지고 단일항목집단 생성(one-item frequent set)
2.
단일항목집단에서 최소 지지도(support) 이상의 항목만 선택
3.
2에서 선택된 항목만을 대상으로 2개항목집단 생성
4.
2개항목집단에서 최소 지지도 혹은 신뢰도 이상의 항목만 선택
5.
위의 과정을 k개의 k-item frequent set을 생성할 때까지 반복
3) Apriori 알고리즘 데이터
Implicit Feedback dataset 사용(ex. 상품을 구매 후 고객이 만족했는지, 만족하지 않았는지 피드백이 없는 데이터)
Sparse Matrix(희소 행렬)로 변형
4) Apriori 알고리즘 과정
1.
5개의 item을 이용해 단일항목집단 생성(one-item frequent set) 생성
➜ 우유, 양상추, 기저귀, 맥주, 쥬스
2.
단일항목집단에서 최소 지지도(support) 이상인 항목만 선택(ex. 최소지지도를 0.5로 가정)
➜ P(우유) = 0.5 / P(양상추) = 0.75 / P(기저귀) = 0.75 / P(쥬스) = 0.25(0.5 미만이라 삭제) / P(맥주) = 0.75
3.
2번에서 선택된 항목만을 대상으로 2개항목집단 생성
➜ {우유, 양상추}, {우유, 기저귀}, {우유, 맥주}, {양상추, 기저귀}, {양상추, 맥주}, {기저귀, 맥주}
4.
2개항목집단에서 최소 지지도 이상인 항목만을 선택(ex. 최소지지도를 0.5로 가정)
{우유, 양상추} = 0.25 / {우유, 기저귀} = 0.5 / {우유, 맥주} = 0.25 / {양상추, 기저귀} = 0.5 / {양상추, 맥주} = 0.75 / {기저귀, 맥주} = 0.5
5.
1~4번의 과정을 k개의 k-item frequent set을 생성할 때까지 반복
5) Apriori 알고리즘 과정 그래프 표현
위 예시는 지지도를 기준으로 진행하며 최소지지도 0.5 이상인 item들만 선택
Confidence와 Lift를 기준으로도 가능
6) Apriori 알고리즘의 장점과 단점
장점
원리가 간단하여 사용자가 쉽게 이해하고 의미 파악이 가능함
유의미한 연관성을 가지는 구매 패턴을 찾아줌
단점
데이터가 클 경우 속도가 느리고 연산량이 많음
실제 적용을 해보면 많은 연관 상품들이 제시됨

FP-Growth 알고리즘

1) FP-Growth 알고리즘 개념
Apriori 알고리즘의 속도 측면에서의 단점을 개선한 알고리즘
Apriori 알고리즘과 성능은 비슷하지만 FP Tree 구조를 이용해 속도가 조금 빨라졌음
frequent itemsets를 찾는것에는 좋지만 아이템간의 연관성을 찾기 어려움
2) FP-Growth 알고리즘 원리
1.
모든 거래를 확인하여, 각 아이템마다의 지지도를 계산하고 최소 지지도 이상의 아이템만 선택(앞선 Apriori 알고리즘과 동일한 단계)
2.
모든 거래에서 빈도가 높은 아이템 순서대로 순서를 정렬
3.
부모 노드를 중심으로 거래를 자식 노드로 추가하면서 tree를 형성
4.
새로운 아이템이 나올 경우 부모노드부터 시작하고 그렇지 않을 경우 기존의 노드에서 확장
5.
1~4번을 모든 거래에 대해 반복하고 FP Tree를 만들고 최소 지지도 이상의 패턴만을 추출
3) FP-Growth 알고리즘 과정
1.
모든 거래를 확인하여, 각 아이템마다의 지지도를 계산하고 최소 지지도 이상의 아이템만 선택(위와 같이 최소지지도는 0.5로 가정)
➜ P(우유) = 0.5 / P(양상추) = 0.75 / P(기저귀) = 0.75 / P(쥬스) = 0.25 / P(맥주) = 0.75
2.
모든 거래에서 빈도가 높은 아이템 순서대로 순서를 정렬
3.
부모 노드를 중심으로 거래를 자식 노드로 추가하면서 tree를 형성
➜ 거래번호 0번의 tree
4.
새로운 아이템이 나올 경우 부모노드부터 시작하고 그렇지 않을 경우 기존의 노드에서 확장
➜ 거래번호 1번의 tree(새로운 아이템의 경우)
➜ 거래번호 2번의 tree(기존의 노드에서 확장된 경우)
➜ 거래번호 3번의 tree(기존의 노드에서 확장된 경우)
5.
지지도가 낮은 순서부터 시작해 조건부 패턴 생성
➜ 우유의 경우, {양상추, 기저귀, 맥주} : 2 / {기저귀} : 1
6.
모든 아이템에 대해 위 과정 반복
4) FP-Growth 알고리즘의 장점과 단점
장점
Apriori 알고리즘 보다 빠르고 2번의 탐색으로 가능
후보 itemsets을 생성할 필요 없음
단점
대용량의 데이터셋에서 메모리 활용이 효율적이지 않음
Apriori 알고리즘에 비해 설계가 어려움
FP Tree가 모두 만들어진 후 지지도 계산을 할 수 있음

Apriori, FP-Growth 코드 구현

pip install mlxtend --upgrade
Python
복사
구글 코랩에서 코드구현을 진행하였는데 mlxtend를업그레이드 하지 않았을때 FP-Growth라이브러리가 import되지 않는 문제가 있었다. 따라서 먼저 mlxtend를 업그레이드한다.
import numpy as np import pandas as pd from mlxtend.preprocessing import TransactionEncoder from mlxtend.frequent_patterns import apriori from mlxtend.frequent_patterns import fpgrowth
Python
복사
데이터 프레임을 만들어 주기 위해 numpy와 pandas를 import해준다.
apriori와 fpgorwth 라이브러리를 사용하기 위해서는 TF행렬이 필요하기 때문에 transactionEncoder를 사용한다.
apriori알고리즘과 fpgorwth알고리즘을 사용하기 위해 이 두 가지 라이브러리를 import한다.
data = np.array([ ["우유","기저귀","쥬스"], ["양상추","기저귀","맥주"], ["우유","양상추","기저귀","맥주"], ["양상추","맥주"] ])
Python
복사
예시 데이터를 만들기 위해 numpy를 사용하여 넘파이 행렬을 생성한다.
te = TransactionEncoder() te_arr = te.fit(data).transform(data) df = pd.DataFrame(te_arr, columns = te.columns_)
Python
복사
TransactionEncoder를 사용하여 앞서 생성한 data를 TF행렬로 변환해 준다. 그 이후 판다스의 dataframe을 사용하여 TF로 이루어진 데이터 프레임을 생성한다.
%%time apriori(df, min_support=0.5, use_colnames=True)
Python
복사
apriori함수를 사용하여 지지도가 0.5.를 넘는 데이터셋을 출력한다.
%%time fpgrowth.fpgrowth(df, min_support = 0.5, use_colnames=True)
Python
복사
fpgrowth함수를 사용하여 지지도가 0.5를 넘는 데이터셋을 출력한다.
알고리즘의 차이로 데이터셋의 순서에는 차이가 있지만 동일한 결과라는 것을 확인할 수 있다. 소요 시간을 보면 apriori의 경우 7.69ms, fpgrowth의 경우 5.15ms로 fpgrowth가 더 빠르다는 것을 알 수 있다.