Learning/Recommendation System

03-2. Best Recommendation

눈떠보니 월요일 2022. 6. 2. 12:56
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;

cmc_product_click_best

- 어떤 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;

cmc_product_purchase_best

 

- 어떤 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;

cmc_product_best

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

cmc_category1_best

- 의류 카테고리에 대한 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)

의류(243100100)

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;

cmc_category2_best

- 상의 카테고리에 대한  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)

상의(243102100)


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;

cmc_product_gender_best

- 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 이동주

링크 : https://fastcampus.app/course-detail/205535