본문 바로가기

DM ML AD

딥 개인화 Deep Personalization

워드임베딩과 팩토라제이션을 설명한 지난 글에서 http://bahnsville.tistory.com/1139 저는 그 기술들을 크고 다양한 데이터 기반의 개인화 추천 data-rich personalization에 적용하는 것에 관심있다고 밝혔습니다. 이번에는 어떻게 개인화 추천에 활용할 수 있을 것인가?에 대해서 아이디어 차원의 글을 적습니다. 좀 naive할 수도 있음을 미리 밝힙니다.

불가능한 것은 아니지만 word2vec같은 워드임베딩 기술이나 SVD, NMF같은 팩토라이제이션 기술을 바로 개인화 추천에 이용하는 데는 한계가 있습니다. 유저별로 조회했던 아이템을 시간순으로 나열하고, 아이템을 word/vocabulary로 가정해서 아이템의 벡터를 만들 수 있습니다. 아이템 벡터의 cosine 유사도를 구해서 관련 아이템을 찾아내는 식으로 아이템 기반의 개인화 추천에 이용할 수가 있습니다. 또는 유저-아이템 행렬을 바로 팩토라즈해서 유저간, 아이템간, 또는 유저-아이템간의 연관도를 측정해서 추천하는 방식이 (추천 알고리즘 중에서) MF방식으로 알려져있습니다. 단순히 유저-아이템 sequence 또는 co-occurrence를 이용해서 추천에 사용할 수 있지만, 한정된 정보를 이용하는 데서 오는 한계가 명확히 존재합니다.

아래 그림은 워드임베딩과 딥러닝 기술을 이용해서 개인화 추천에 어떻게 적용할지를 설명하는 모델입니다. 그림에는 표시하지 않았지만 레이어 사이에 여러 은닉층이 있을 수도 있습니다. 이 모델의 핵심은 사용자와 아이템의 정보를 수치 벡터로 우선 표현하고, 다시 공통의 Latent Vector로 만드는 것입니다. 그렇게 만들어진 LV를 이용해서 유저간, 아이템간, 또는 유저-아이템간의 연관성을 계산합니다. 

유저 및 아이템 정보를 같은 체계인 Latent 벡터로 표현하는 네트워크 모델

** OUV/OIV, CUV/CIV, LUV/LIV: Original/Compressed/Latent + User/Item + Vector

첫번째 단계는 일단 사용자의 정보와 활동 이력 User History나 아이템의 설명 Item Description을 숫자 벡터 Original Vector로 표현하고, 다시 정형화한 Compressed Vector로 정제하는 것입니다. 먼저 사용자 정보는 사용자의 성별이나 연령, 거주지 등의 부가정보나 서비스에서의 행동 이력 (검색쿼리, 봤던 글이나 사진, 댓글, 좋아요활동, 구매 등)을 포함합니다. 텍스트나 ID로 표현되는 정보는 워드임베딩 기술로 벡터화, 사진/이미지는 CNN으로 벡터화 (또는 이미지에서 객체를 인식한 후 워드임베딩할 수도...), 또는 다른 형태의 정보도 수치벡터화 합니다. 아이템 정보도 비슷한 과정으로 Origina Vector를 만듭니다. 단순히 짧은 광고나 상품정보 뿐만 아니라, 장문의 컨텐츠나 관련 이미지 등을 벡터로 만든다면 벡터의 길이가 천차만별일 것입니다. 그래서 모든 유저 벡터 또는 모든 아이템 벡터의 길이를 맞춰주기 위해서 Original Vector를 Compressed Vector로 정형화할 필요가 있습니다. 압축된 CUV나 CIV의 길이가 같을 필요는 없지만 data loss가 크지 않다면 같게 만들어주는 것이 좋고, CV는 수백차원 이상으로 적당히 길어도 무관합니다. 짧을수록 실시간 연산에 용이하겠지만 정보 손실 information loss는 감내해야 합니다. 유저의 이력에서 시간이 중요한 요소라면 RNN을 사용하는 것도 괜찮고, 그저 전체를 스냅샷처럼 요약하는 것이라면 CNN으로 압축하는 것도 고려할 수 있습니다. (참고. 텍스트 convolution 방법: http://www.jmlr.org/papers/volume12/collobert11a/collobert11a.pdf Compressed Vector/Layer를 Convolution Vector/Layer로 불러도 될 듯.)
솔질히 말씀드리면, 이 부분에 대해서 구체적으로 어떤 기술을 어떻게 사용하면 좋을지를 고민/연구하지 못했습니다. 어쨌든 비수치형 데이터인 유저 및 아이템 정보를 간결한 수치벡터 CV로 표현합니다. 이번 글은 다음 단계에 초점을 맞췄지만 대부분의 기계학습에서 인풋을 어떻게 잘 정의/표현하느냐 (knowledge representation)는 기계학습의 성패에 결정적인 부분입니다.

위에서 CUV와 CIV의 길이를 같게 만들었만, CUV와 CIV의 내적 또는 코사인 유사도로 유저-아이템의 관계를 파악할 수 없습니다. 각 CV는 unsupervised로 구축했기 때문에 서로 간의 (CV벡터의 각 엘리먼트 간의) 연관성이 없습니다. 유저-아이템 행렬을 MF한 경우라면 사용자벡터와 아이템벡터의 내적이 곧 사용자와 아이템의 관계를 암시하지만, 위의 관계에서는 그렇지 않습니다. 즉, 사용자와 아이템을 표현하는 벡터의 길이만 같지 벡터의 각 element를 이루는 구성요소/방식이 서로 다릅니다. Bi-linear regression 모델을 이용해서 모든 '유저x아이템'의 계수를 측정할 수도 있지만, 앞서 말했듯이 CV는 수백차원의 벡터이기 때문에 데이터 차원 폭발 dimension explosion이 발생합니다. CUV과 CIV가 각각 100차원이라 하더라도 10,000개의 계수를 예측해야하는 문제가 됩니다. (처음에 유저 및 아이템 벡터를 만들려고 생각했을 때는 bi-linear regression을 고려했었지만 차원 폭발 문제가 우려돼서 포기함) 그래서, CUV와 CIV를 같은 조건으로 표현한 Latent Vector로 만드는 것이 다음 단계입니다.

CV는 여느 차원축소 dimension reduction 기술이 그렇듯이 unsupervised로 만들면 됩니다. 단 새로운 정보가 들어왔을 때도 기존의 변환 구조/결과를 크게 훼손하면 안 됩니다. 비슷한 정보를 가진 사용자는 결과 CUV가 비슷해야 합니다. A라는 사용자의 현재 CUV와 며칠 후 (행동 이력이 조금 추가/변경된)의 CUV가 크게 달라지면 안 됩니다. 데이터가 업데이트되면서 CV가 달라지겠지만 일관적이어야 한다는 것입니다. 한편, CV를 LV로 만드는 것은 이미 확보한 유저-아이템 관계를 이용한 supervised 방식으로 학습시킵니다. 즉, 어떤 사용자 U가 아이템 I를 구매했다는 정보를 이용해서 U의 CV를 LV로 변환 encoding하고 그 LV를 다시 CIV로 변환 decoding한 결과가 I의 CV가 되도록 학습시킵니다. word2vec처럼 LV가 유일한 은닉층일 수도 있고, 통상의 auto-encoder처럼 은닉층이 여러 겹일 수도 있습니다. word2vec의 skip-gram에서 입력 단어 벡터는 CUV가 되고 출력 맥락(단어) 벡터는 CIV가 되는 형태, 또는 번역할 언어의 문장을 CUV로 보고 번역될 언어의 문장을 CIV로 가정했을 때는 번역 시스템의 구조와 같습니다. 유저-아이템 네트워크를 처음 생각했을 때 NMT (Neural Machine Translation)과 개념상 구조가 같다고 봤습니다. NMT의 구조는 auto-encoder나 word2vec의 그것도 개념적으로 같습니다. 앞의 설명에서는 CUV-LV-CIV 순으로 학습시켰지만, 역순(CIV-LV-CUV)으로도 함께 학습시켜서 유저와 아이템이 동일한 LV체계를 갖도록 학습시킵니다. 그래서 CUV와 CIV의 차원을 같게 만들어야 한다고 적었습니다. (굳이 따를 필요는 없음)

중간을 많이 생략했지만, 사용자의 정보 및 이력을 LUV로 만들고, 아이템의 정보를 LIV로 표현했다면 추천 및 개인화에 필요한 모든 것이 끝났습니다. LUV1과 LUV2의 유사도를 구하면 사용자 U1과 U2의 유사도가 나옵니다. 즉, 나와 비슷한 취향의 사용자를 바로 확인할 수 있습니다. 비슷하게 LIV1과 LIV2의 유사도를 구해서 유사 아이템도 구할 수 있습니다. (유저-유저 또는 아이템-아이템 유사도는 그냥 CV의 연산으로 처리해도 됨) LUV와 LIV을 같은 식으로 표현했기 때문에 LUV와 LIV의 유사도를 이용해서 유저에게 가장 적합한 아이템들을 바로 선별할 수 있습니다. 그리고 한 가지 더 장점이 있습니다. 이제껏 단순히 유저-아이템 관계라고 설명을 했지만, 종류가 다른 아이템을 한꺼번에 학습시킬 수가 있습니다. 즉, 사용자 U는 컨텐츠 C도 봤고 광고 A를 봤다면 U-C, U-A의 관계로 학습시켜서 C와 A의 유사도도 측정할 수 있습니다. (설명을 많이 생략했지만...) 그래서 컨텐츠 C가 노출되는 화면에 다른 종류의 컨텐츠인 광고 A를 함께 노출시켜줍니다. 기존에는 단순히 사용자 U가 어떤 페이지에 접속했을 때 'U'의 정보만 고려해서 컨텐츠 C의 추천과 광고 A의 노출이 독립적으로 이뤄졌는데, 새로운 scheme에서는 C와 A가 같은 공간에서 LV로 만들어져서 LVc와 LVa의 유사도를 계산해서 문맥(현재 보는 컨텐츠)에 맞는 광고나 관련 상품 등을 노출할 수 있습니다. (유저와 무관한 맥락 광고를 제공. 물론 사용자를 고려했을 때 효과가 더 높겠지만...)

학습 Training
위에서 설명한 프레임워크가 제대로 작동한다는 것을 증명하기 위해서 어쨌든 CV-LV-CV (CLC)로 이어지는 네트워크를 supervised 방법으로 학습시켜야 합니다. OV에서 CV로 차원을 축소해서 정형화하는 바른 방법은 존재한다고 일단 가정합니다. CLC 네트워크의 구조나 가중치W 업데이트 방법 등은 보통의 ANN (MLP, auto-encoder, word2vec 등)과 동일해서 별도의 설명은 생략합니다. 관건은 어떤 데이터로 학습시키느냐입니다. 번역에서는 번역할 문장과 (인간이 번역한) 정답 문장이 존재하기 때문에 입력층에 번역할 문장을 넣고 출력층에 정답문장을 넣어서 W를 업데이트합니다. 추천에서는 이런 매핑 관계는 결국 유저-아이템 간의 interaction 유무를 정답세트로 봐야합니다. 예를 들어, 유저 U가 컨텐츠 A, B, C를 조회했다면 (U, A), (U, B), (U, C) [그리고, (A, U), (B, U), (C, U)]를 학습데이터로 보는 것입니다. 기존의 추천에서 사용하던 유저-아이템 행렬과 동일한 데이터입니다.

하지만 우려되는 점은 도메인마다 어느 수준까지를 유저-아이템 사이에 관계가 있다고 볼 것인가입니다. 광고를 예로 들면, 사용자 U가 광고 A, B를 클릭해서 광고주 페이지로 이동했을 때, 그 중에서 광고 B와 연결된 상품만을 구매(전환발생)했습니다. 광고를 클릭한 것만으로도 유저-광고를 연결해도 되는가 아니면 전환이 발생한 B만이 U에게 유효한 광고인가의 문제가 있습니다. 몇 년전까지만해도 트래킹 이슈가 있어서 클릭을 광고의 주요 지표로 봤지만 최근에는 실제 전환을 더 중시하기 시작했고 또 그에 따라서 다양한 트래킹 업체들이 등장했습니다. 하지만 전환 데이터는 여전히 수집의 어렵고 또 실제 전환 발생 빈도가 낮아서 데이터 양이 부족한 경우가 많습니다. 정답세트가 부족하다면 아무리 우수한 모델이 있더라도 제대로 학습시키지 못해서 좋은 성능을 기대하기 어렵습니다. 역으로 클릭 정보는 다소 많이 있지만 어뷰징을 포함해서 실제 매핑 관계가 아닐 가능성이 높습니다. ... 현실적으로 클릭과 전환을 모두 정답 세트로 사용하는 것입니다. 전환이 발생했다는 것은 이전에 클릭이 존재한다는 의미입니다. 그래서 클릭은 가중치가 1이 되고, 전환은 (클릭 1 + 전환 1) 가중치가 2가 됩니다. 전환에 더 fit한 모델을 만들면서 부족한 부분은 클릭으로 어느 정도 커버하는 형태입니다.

(바라건대 제대로 작동한다고 가정하고...) 일반적인 상품이나 컨텐츠 추천에서는 위에서 설명한 방법이 별로 문제될 것이 없는데 (제대로 동작한다면), 제가 지금 맡고 있는 광고는 추천과 결이 조금 다릅니다. 추천에서는 그저 1등 또는 상위 N개의 아이템만 선별해서 순서에 맞게 노출시켜주면 되는데, 광고에서는 예상CTR (Clickthrough rate)를 계산해야 합니다. 유저-아이템의 연관도가 높을수록 pCTR이 높게 나옵니다. 이는 보통 광고는 ecpm (expected cost per mille) 순으로 랭킹하는데, ecpm = pCTR * BA (Bidding Amount)로 계산되기 때문입니다 (보통 CPC광고에 한함). 즉, 유저와 아이템 (광고)의 연관도가 높거나 광고주가 높은 값으로 광고기회를 구매한 광고를 우선 노출시켜줘서 광고 플랫폼의 기대 수익을 높이는 방식입니다. 그리고 보통 과금액을 정할 때 Dutch auction으로 알려진 second-price로 과금합니다. 그래서 정확한 기대 CTR을 예측하는 것이 광고 사업에서 매우 중요합니다. (기대수익 계산과 과금액 산정이 일반 추천과 조금 상이할 수 있음) 그런데 앞서 설명한 방식에서는 CTR 수치를 얻지 못해서 기존 광고 시스템과 어긋나는 부분이 있습니다. 그런데 CTR이 유저와 아이템 간의 연관도 (즉 순서와 정도)를 나타내는 지표라면, 그냥 Sim(LUV, LIV)를 CTR의 대체제로 사용해도 크게 문제될 소지가 없지 않을까?라는 확신이 강하게 듭니다.

요즘은 기-승-전-딥러닝입니다. 이미지 객체 인식, 음성 인식, 자연어처리 등의 분야에서 딥러닝이 괄목할만한 성과를 냈습니다. 세계의 어딘가에선 딥러닝을 이용한 추천 시스템도 개발해서 활용하고 있으리라 봅니다. 논문이나 연구결과를 별로 못 봤는데, 글을 적으면서 좀 찾아보니 논문이 전혀없는 것은 아닙니다. 기존의 여러 알고리즘을 딥러닝에 맞게 변형한 것이나 딥러닝의 구조에 입력층만 잘 끼워맞춘 것 등의 논문들이 눈에 띕니다. 제가 구상한 것과 비슷한 구조의 논문도 눈에 띕니다. (참고. https://arxiv.org/pdf/1701.04783.pdf CV를 만드는 것까지는 유사하나 유저와 아이템 관계를 학습하는 부분에서 상이함) 직접 구현해서 테스트해보기 전까지는... 학교 다니면서 ANN을 야매로 공부했고, 3년 전에 딥러닝을 주목했고, 2년 전에 서베이 수준에서 딥러닝을 공부했는데, 추천에 딥러닝을 활용하는 방안에 대한 고민은 있었지만 팀을 옮기고 생각의 발전이 별로 없었습니다. 올해는 다시 공부하는 해로 정하고 이것저것 훑어보면서 다시 오래된 고민을 정리하고 있습니다. 실마리는 거의 다 찾았고 이젠 구현해서 테스트만 해보면...

... 직접 코딩해서 테스트해보기가 참 싫다. 내가 프로그래밍을 조금만 더 좋아하고 소질이 있었더라면 세상이 약간은 더 바뀌지 않았을까? 이게 글의 결론은 아닌데...

===


반응형