Recommendation PoC

Recommendation PoC

2023-05-24 06:20

687 views

안녕하세요? 플러스제로 엔지니어팀 입니다.

이번에 공유 드릴 내용은 이전 포스팅에서 소개드렸던 [Recommendation System ]과 관련하여 플러스제로 파트너사의 데이터를 기반으로 진행한 PoC를 소개드리려 합니다.

PoC의 컨셉은 플러스제로와 함께하는 파트너사인 유니세프의 데이터를 사용하여 세션별 후원 가능성이 높은 유저를 분류하는 목표를 가지고 있습니다. 분류 결과는 추후 저희 솔루션을 통해 Personalized Advertising를 적용 할 수 있습니다.

pluszero_personalization

이전에도 소개드렸듯이, 플러스제로와 파트너사 분들의 데이터는 Google Cloud의 BigQuery에 데이터가 적재되어 있습니다.

간단하게 사용자의 웹 로그 데이터는 GA4 (Google Analytics 4)의 파라미터를 통해 수집되어 BigQuery에 저장되는 형태입니다.

각 유저별 접속한 세션마다 해당 유저의 이벤트들이 기록되기 때문에 저희는 “Session Based Recommendation”의 컨셉을 사용하여 한 세션에서 발생한 이벤트만을 사용하여 후원 가능성 여부를 확인해 보았습니다.

PoC의 순서는 데이터의 전처리 (Preprocessing)와 반복적인 실험과 검증을 거쳐, 최근 데이터를 통해서 테스트를 진행하였습니다.

실제 고객사의 데이터를 사용하였기 때문에 자세한 내용은 포함하지 못하는 점 양해 부탁드립니다.

PoC에 사용할 데이터 범위

  • 학습과 검증을 위한 데이터는 2022년 11월 19일 부터 2022년 12월 31일까지의 데이터를 통해 모델 학습과 검증을 진행하였습니다.
  • 시간 도메인이 포함된 데이터이기 때문에, 검증을 위한 데이터는 12월의 마지막 주차를 검증을 위해 분리 하였습니다.
    • Train: 2022.11.19 ~ 2022.12.24
    • Validation: 2022.12.25 ~ 2022.12.31
  • 최종 테스트를 위한 데이터는 2023년 1월, 2월의 데이터를 사용하였으며, 월별로 분리하여 테스트 하였습니다.
    • Testset-1: 2023.01.01 ~ 2023.01.31
    • Testset-2: 2023.02.01 ~ 2023.02.28

Data Preprocessing Strategy

  • BigQuery는 다양한 타입의 데이터를 저장 할 수 있습니다. 그러나, 파이썬을 통해 데이터셋을 만들고 분석하기에는 약간의 문제사항이 있습니다 (Nested Record Type)

# Python의 Dict구조와 비슷합니다.
event_params = {
    key='event_name',
    values = {
        'string_value': 'value_name',
        'int_value': int,
        'float_value': float,
        'double_value': float
     }
}
  • 데이터 분석을 위해 BigQuery에 저장된 모든 Record형식을 Unnest를 하여 정형데이터 형식으로 변경 후 분석을 진행하였습니다.

[How to use the UNNEST function in BigQuery to analyze event parameters in Analytics - Medium]

  • Unnest된 데이터를 기반으로 데이터를 분석해보니, 학습 데이터 기간동안에 약 xx만개의 세션이 발생하였으나, 후원이 발생한 세션은 많지 않았습니다. 그래서 저희는 Imbalanced 데이터 셋이라는 점을 염두하고 PoC를 진행 하였습니다.
  • 데이터셋을 구성하기 위해서는 데이터의 모든 값을 학습이 가능한 수치 형태로 변경이 필요하여 URL을 포함한 다양한 문자열의 처리를 진행하였습니다.
    • 이때 사용한 방법은 Label Encoding 방식과, NLP에서 주로 사용하는 Tokenizer를 사용하였습니다.

## Dataset

  • 초기 데이터 분석을 통해 원천 데이터는 Imbalanced데이터셋이기에 클래스별 동일한 Observation을 가질수 있도록 Down-Sampling을 진행하였습니다.
    • 보다 정확한 샘플링을 위해 세션 길이별로 동일한 데이터 수를 가질수 있도록 하였습니다.
  • 저희 엔지니어팀은 PoC를 위해 2가지 형태로 진행하였습니다.
    • 1. Sequential Problem (MS)
    • 2. Graph Problem (MG)

session_based_methods

  • MS의 방식은 세션이 시작한 순간부터 세션이 종료되는 순간까지의 모든 이벤트를 시계열 형태로 나열하여 사용자가 방문한 페이지를 순차적으로 나열하는 방식으로 데이터셋을 구성하였습니다.
  • MG의 방식은 MS와 비슷하지만, 중복되는 페이지가 있는 경우에 같은 노드를 통해서 연결되는 Directional Graph 데이터셋을 구성하였습니다.

MS 데이터셋 예시

'user_id': '100004****.**********’,,
'page_referrer': 9568.0,
'page_source': 32.0,
'page_medium': 3.0,
'page_term': 273.0,
'page_campaign': 29.0,
'page_content': 650.0,
'page_intraffic_source': 314.0,
'page_intraffic_medium': 28.0,
'seq_event_time_norm': '[0.03536977491961415,
0.028938906752411574, 0.022508038585209004, 0.0, 0.04823151125401929,
0.0, 0.022508038585209004, 0.0, 0.1414790996784566, 0.01607717041800643,
0.0, 0.1382636655948553, 0.0, 0.1157556270096463, 0.01929260450160772, 0.0,
0.01607717041800643, 0.07717041800643087, 0.0, 0.1157556270096463, 0.0, 0.0,
0.01607717041800643, 0.0, 0.0, 0.0, 0.02572347266881029, 0.0, 0.01607717041800643,
0.0, 0.0, 0.0, 0.0, 0.01607717041800643, 0.0, 0.0, 0.10289389067524116, 0.01607717041800643, 0.0, 0.0, 0.01929260450160772, 0.0, 1.0, 0.0, 0.0]’,
'seq_page_location': '[1181.0,
1186.0, 1482.0, 1194.0, 1194.0, 827.0, 827.0, 814.0, 814.0, 816.0,
817.0, 817.0, 820.0, 820.0, 827.0, 827.0, 43.0, 43.0, 1858.0, 1858.0, 1875.0,
1875.0, 1876.0, 1877.0, 1875.0, 1876.0, 1875.0, 1194.0, 1194.0, 1858.0, 1875.0,
1858.0, 43.0, 43.0, 1875.0, 1876.0, 1876.0, 1875.0, 1873.0, 1873.0, 1875.0, 1868.0, 1868.0, 1858.0, 1858.0]’,
'label': 0,
'page_datetime': 1672404045202997000,
…

MG 데이터셋 예시 (Pytorch Geometric Format)

x=[6],
edge_index=[2, 5],
y=1,
user_identifier='100004****.**********’,
label=1,
current_is_donator=[6],
history_is_donator=[6],
history_payment_method=[6],
event_params_video_percent_int_value=[6],
event_name_input_ids=[6, 128],
device_category_input_ids=[6, 128],
traffic_source_name_input_ids=[6, 128],
traffic_source_medium_input_ids=[6, 128],
traffic_source_source_input_ids=[6, 128],
event_params_page_referrer_string_value_input_ids=[6, 128],
…

page_graph_view

Model Architecture

General

  • URL과 같은 텍스트 데이터는 Embedding을 통해 각 페이지에 대한 정보를 가지도록 설계 하였습니다.

MS

  • MS 방법은 보편적으로 많이 알려져 있는 RNN과 Transformer를 이용하여 아키텍처를 구성하였습니다. [Attention Is All You Need]
  • 그러나 정형데이터이기에 Embedding은 컬럼별 Embedding 을 진행하였습니다.

MG

  • MG 방법은 Graph Convolution과 이전 블로그에서 소개드렸던 [ SR-GNN ] 을 이용하여 아키텍처를 구성하였습니다. [SR-GNN]
  • Shared Embedding을 구성하여 학습이 가능하도록 하였습니다.

Experiments

  • 실험관리를 위해 저희 엔지니어팀은 WandB를 활용하여 관련 메트릭스와 아티펙트를 저장하여 사용합니다. 특히 이번 실험은 아키텍처의 하이퍼 파라미터를 찾는 작업이 동반되어 Wandb-Sweep을 통해 다양한 실험을 진행 하였습니다.

MS Sweep

MS_Sweep

MG Sweep

MG_Sweep

Results

결과를 확인하기 위해 저희 엔지니어팀은 F1-Score를 주요 메트릭스로 정하였고, 보조적으로 Accuracy, Precision, Recall을 함께 보며 실험 결과를 비교 하였습니다.

MS

MS_results

MG

MG_results

Compare

7
  • MS와 MG의 차이는 데이터셋의 구성을 최대한 비슷하게 하였으나, Test 데이터셋을 사용함에 있어 차이가 있었습니다. MS는 텍스트 데이터를 Label-Encoding방식으로 처리하였으나, MG는 Tokenizer를 통해 텍스트 데이터를 인코딩 하였습니다.
    • 인코딩 방법으로 인하여, Inference시 MS는 새로운 URL과 텍스트 데이터에 대해서는 OOV - (Out of Vocabulary) 문제를 야기시켰고, 이는 MS모델이 새로운 데이터에 대해서는 예외처리를 통해 해당 데이터를 바이패스 시키는 문제가 있었습니다. 즉, MS는 학습에 사용되었던 텍스트 데이터에 대해서는 Inference가 가능하나, 새로운 데이터에 대해서는 알지 못하는 모델이 되었습니다.
  • 모델의 성능은 시간에 지남에 따라 감소하는 것을 확인하였습니다.
    • 이렇게 모델의 성능이 감소하는 것은 어떻게 보면 당연하지만, 엔지니어팀 입장에서는 달갑지 않은 상황이 나오게 되었습니다. 초기에 저희가 소개드렸던 MLOPs와 관련된 글 을 보시면, 데이터 또는 컨셉 드리프트가 일어났다는 것을 의심해 볼 수 있었습니다.
  • 2022년 12월과 2023년 1월, 2월에 어떤 이유로 차이가 났는지 확인해 보기 위해 Error Analysis를 진행하였습니다.

Power of Error Analysis

  • 저희 엔지니어팀이 사용한 데이터는 유니세프 홈페이지의 데이터입니다. 강건한 모델을 만들기 위해 Tokenizer를 사용한 MG방법에서 검증데이터와 큰 차이를 보였던 2월달의 데이터를 우선 살펴보았습니다.
  • 데이터를 확인하던 중, 가장 큰 사건을 놓친것을 확인 하였습니다. 바로 2023년 2월 6일, 84년만의 최대 규모 지진이 튀르키예 에서 발생하여, 수많은 사망자와 부상자가 발생하였습니다. 대지진으로 인하여 많은 분들께서 튀르키예를 돕기 위해 많은 후원을 해주신것을 확인하게 되었습니다.
  • 따라서 학습에 사용되었던 11월과 12월달의 데이터만으로는 이러한 이벤트에 대해서는 강건하게 대응하지 못하는 것을 데이터를 통해 확인하여, 이러한 경우에는 PoC에 사용한 모델과 데이터 이외의 다른 방법이 추가적으로 필요해 보였습니다.

unicef_data

Operation?

  • 서비스 중심적인 관점으로 모델을 사용한다면, 모델의 재학습 주기(Cycle)에 대한 설정이 필요 할 것으로 판단하였습니다.
  • PoC의 특성상, 새로운 캠페인의 실행여부를 정확하게 모니터링을 못 하였지만, 파트너사와 함께 운영을 한다면, 새로운 캠페인의 실행후 10일 이후의 데이터를 사용하여 모델의 재학습을 진행하는 방법과, 모델의 성능이 떨어지는것을 모니터링 하며, 일정 수치가 넘어가면 재학습을 진행하는 트리거가 필요할 것으로 판단하였습니다.

Conclusion

이번 포스팅은 저희 엔지니어팀에서 진행한 Personalization을 위한 Session Based Classification을 진행하였습니다. 이번 PoC를 통해서 Google Analytics 4의 데이터를 통해 Session별 Personalize의 가능성을 확인해 보았습니다. 추후 이번 PoC결과를 통해 Personalized Advertising A/B 테스트를 진행해 볼 예정입니다.

[User Behavior Prediction with GA4]

[User Behavior Validation]



다음글 - PlusZero QA ChatBot
이전글 - Session based Recommendation