03-2. Best Recommendation
Best Recommendation
☞ 다양한 그룹에서의 베스트
- 전체 베스트
- 시간대 별 베스트
- 브랜드 별 베스트
- 카테고리 별 베스트
- 성별에 따른 베스트......
☞ 스코어링 방법 별 베스트
- 구매 베스트
- 클릭 베스트
- 구매전환 베스트........
Step1. Best의 대상이 되는 그룹 정의
Step2. 각 그룹마다 특성화된 스코어링 방법 적용
※ 만약 전체 Best와 그룹별 Best의 결과가 다르게 나올 경우, 새로운 인사이트를 추출하여 활용도가 높아진다.
Case Study
전체 베스트 추출
Click 이력을 이용한 Best Product 추출
- 단순히 Click 이력을 사용하면 여러번 클릭하는 경우를 포함하기 때문에 session_id를 중복 제거 후 count
- timestamp를 확인해서 장시간 움직임이 없는 session에 대해 처리하는 방법도 있음.(지금은 처리 안함)
%%sql
drop table if exists cmc_product_click_best;
create table cmc_product_click_best as
select t.item_no, t.score, row_number() over (order by score desc) rank
from (
select item_no, count(distinct session_id) score
from cmc_event a
where event_name = 'click_item'
and a.event_timestamp between '2021-07-18' and '2021-07-25'
group by a.item_no
) t
order by score desc;
- 어떤 item들이 클릭이 많이 일어난 상품인지 확인
query = '''
select a.rank, a.score, b.*
from cmc_product_click_best a
join cmc_product b on a.item_no = b.item_no
order by score desc
limit 10
'''
result1 = executeQuery(query)
displayItemInRows(result1)
구매 이력을 이용한 Best Product 추출
- 구매가 이루어진 상품들 중 비싼 상품 1건과 싼 상품 1건은 차이가 있기 때문에 이를 반영
- 구매 이력과 상품 정보를 함께 봐야하기 때문에 Table join
- 가격의 편차를 줄이기 위해 log 사용(0인 상품도 있을 수 있기 때문에 +1/소수점 무시(int)) --> score로 사용
%%sql
drop table if exists cmc_product_purchase_best;
create table cmc_product_purchase_best as
select t.item_no, t.score, row_number() over (order by score desc) rank
from (
select a.item_no, sum(log(b.price::float + 1)::int) score
from cmc_event a
join cmc_product b on b.item_no = a.item_no
where a.event_name = 'purchase_success'
and a.event_timestamp between '2021-07-18' and '2021-07-25'
group by a.item_no
) t
order by score desc;
- 어떤 item들이 구매가 많이 일어난 상품인지 확인
query = '''
select a.rank, a.score, b.*
from cmc_product_purchase_best a
join cmc_product b on a.item_no = b.item_no
order by score desc
limit 10
'''
result2 = executeQuery(query)
displayItemInRows(result2)
클릭이력과 구매이력을 활용한 Best Product 추출
- w1 * click + w2 * purchase
- 구매가 더 중요한 행위라고 생각하기 떄문에 임의로 가중치 3을 줌
- 아이템별로 두 가지 score를 sum 하기
%%sql
drop table if exists cmc_product_best;
create table cmc_product_best as
select t.item_no, t.score, row_number() over (order by score desc) rank
from (
select item_no, sum(score) score
from (
select item_no, score
from cmc_product_click_best
union all
select item_no, score * 3
from cmc_product_purchase_best ) t
group by item_no
) t
order by score desc;
query = '''
select a.rank, a.score, b.*
from cmc_product_best a
join cmc_product b on a.item_no = b.item_no
order by score desc
limit 10
'''
result3 = executeQuery(query)
displayItemInRows(result3)
Category별 베스트
Category1별 Best Product
- score 데이터와 상품 테이블을 join
- 카테고리에 따라 row_number() 적용
%%sql
drop table if exists cmc_category1_best;
create table cmc_category1_best as
select b.category1_code, b.item_no, a.score, row_number() over (partition by b.category1_code order by a.score desc) rank
from cmc_product_best a
join cmc_product b on b.item_no = a.item_no
- 의류 카테고리에 대한 Best Product 추출
query = '''
select a.rank, a.score, b.*
from cmc_category1_best a
join cmc_product b on a.item_no = b.item_no
where a.category1_code = '243100100'
order by score desc
limit 10
'''
result4 = executeQuery(query)
displayItemInRows(result4)
Category2별 Best Product
- 더 하위 카테고리로 구분
%%sql
drop table if exists cmc_category2_best;
create table cmc_category2_best as
select b.category2_code, b.item_no, a.score, row_number() over (partition by b.category2_code order by a.score desc) rank
from cmc_product_best a
join cmc_product b on b.item_no = a.item_no;
- 상의 카테고리에 대한 best product 추출
query = '''
select a.rank, a.score, b.*
from cmc_category2_best a
join cmc_product b on a.item_no = b.item_no
where a.category2_code = '243102100'
order by score desc
limit 10
'''
result7 = executeQuery(query)
displayItemInRows(result7)
Gender별 베스트
- 기존 Category별 베스트는 각 아이템이 하나의 카테고리에만 속하기 때문에 Score 접오 자체가 달라지지 않고 활용 방법만 달라진다. 하지만 Gender의 경우에는 각 아이템이 여러 성별에게 구매와 클릭이이 이루어질 수 있기 때문에 Best 정보를 만들 때 다르게 만들어야 한다.
- user(gender)정보를 join해서 테이블을 만듬.
- with as 구문을 통해 테이블로 활용 가능(subquary로 해도 무방)
%%sql
drop table if exists cmc_product_gender_best;
create table cmc_product_gender_best as
-- click best
with click_best as (
-- click best + gender 정보 추가
select b.gender, item_no, count(distinct session_id) score
from cmc_event a
join cmc_user b
on b.user_no = a.user_no
where event_name = 'click_item'
and a.event_timestamp between '2021-07-18' and '2021-07-25'
group by b.gender, a.item_no),
-- purchase best
purchase_best as (
-- 구매 정보
select c.gender, a.item_no, sum(log(b.price::float + 1)::int) score
from cmc_event a
join cmc_product b on b.item_no = a.item_no
join cmc_user c on c.user_no = a.user_no
where a.event_name = 'purchase_success'
and a.event_timestamp between '2021-07-18' and '2021-07-25'
group by c.gender, a.item_no )
select t.gender, t.item_no, t.score, row_number() over (order by score desc) rank
from (
select gender, item_no, sum(score) score
from (
select gender, item_no, score
from click_best
union all
select gender, item_no, score * 3
from purchase_best ) t
group by gender, item_no
) t
order by gender, score desc;
- Female Best Product 추출
query = '''
select a.rank, a.score, b.*
from cmc_product_gender_best a
join cmc_product b on a.item_no = b.item_no
where a.gender = 'F'
order by score desc
limit 10
'''
result9 = executeQuery(query)
displayItemInRows(result9)
출처 : The RED : 현실 데이터를 활용한 추천시스템 구현 A to Z by 번개장터 CTO 이동주