Yes24 책 추천 알고리즘 분석 대회 후기

Reading time ~18 minutes

얼마전 한국 정보화 진흥원이 관리하는 개방형 문제해결 플랫폼에 올라온 Yes24 도서 추천 알고리즘 대회가 종료되었다.

총 230여명이 참여하였고, 25팀에 최종 결과물을 제출한 대회였다. 이 대회에서 친구와 같이 참여했으며, 입상은 아니지만 우수한 알고리즘 혹은 분석결과를 제시한 팀에 뽑혔다. 결과

이 포스트에서는 어떤 과정으로 대회에 참여 하였으며, 어떤 알고리즘을 이용하였는지 설명할 것이다. 또한, 다음 과정들은 혼자 진행한 것이 아니라 팀원과 함께 진행하였다.


0. 문제

다음과 같은 문제를 해결하는 것이 이 대회의 목적이었다.

  • 문제

YES24에서 제공하는 Training Data Set를 활용하여, 추천구매에 대한 예측력을 제고할 수 있는 도서추천 알고리즘을 만들어 주시기 바랍니다. (Test Data Set은 이미 별도로 가지고 있으나 공개하지 않고 이는 사후적으로 제출된 솔루션 결과를 평가하는 목적으로 사용하게 됩니다.)

이 도서추천 알고리즘은 Hardware, Computing Time 등의 여러 가지 이유로 5개 카테고리에 한정하여 진행됩니다. "인문/자기계발/국내문학/해외문학/종교" 카테고리 중 한 개 또는 여러 개의 카테고리를 선정하여 도서추천 알고리즘을 만들어 주시기 바랍니다.

  • 평가방법

제출된 추천 알고리즘은 다음의 2가지 평가기준에 의해 평가됩니다.

  1. 예측결과 (Test Data Set에 기반한 제출된 알고리즘의 예측결과)
  2. 창의성/창의적 모델링 접근방법

이 두 가지 기준에 의해 3명의 평가위원이 제출된 알고리즘을 평가를 하게 됩니다.

--

하지만, 문제가 너무 러프하였다. 어떤 식으로 예측 결과를 내야하는지에 대한 세부적인 정보도 없었으며, 창의적 모델링 접근법을 어떻게 평가할 것인지에 대한 정보 역시 없어서 처음 문제를 접한 후에 이것을 어떻게 해석해야 하나 고민을 많이 하였다. 결론은 주최측에서 러프하게 냈으니 그냥 제시 기준에만 맞춰 내자는 결론이 나왔다.


1. 데이터

주최측에서 제공한 데이터는 사용자가 어떤 책을 구매하였는지에 대한 정보가 약 53만개 정도 들어있는 데이터였으며, 다음과 같은 컬럼들로 구성되어 있었다. 아쉽게도 대회의 규정상 데이터는 다른 목적으로 사용이 불가능하여 공개하지는 못한다.

"date","state","uid","title","category","author","isbn","company","pub_day","time","amount","cart","cart_date","mobile","addr1","addr2"

처음 문제와 데이터를 봤을 때 데이터가 생각보다 적다는 생각이 들었다. 실제 문제에서 요구한 카테고리는 인문/자연/자기계발/국내문학/해외문학/종교에 한정되어 있었으며, 이 카테고리에 대한 데이터만 추렸을 때는 10만건이 약간 넘는(정확하게 기억이 나지 않는다.) 정도였으며, 게다가 각 카테고리별로 추천을 수행하게 된다고 가정하면 그 수는 더욱 줄어들 것이기 때문이었다.


2. 알고리즘 고민

앞서 설명하였듯 데이터가 적은 편이었기 때문에 기본 CF 모델 혹은 ALS를 그대로 적용하기에는 적절하지 않을 것이라 생각하였다. 또한 이런 모델만 적용하였을 때는 입상권에 들기 어려울 것이라 판단하여 좀 더 복잡한 추천 알고리즘을 구성할 필요가 있었다.

그래서 혹시 다른 정보를 같이 활용할 수 있을까 하였는데 제공된 데이터에서는 추가적으로 가지고 올 수 있는 정보가 많지 않았다. 기껏해야 구매한 시간, 구매한 위치, 구매한 시간과 카트에 넣은 시간의 차이 정도였고 이 정보를 따로 분류하거나 파싱하기에는 노력 대비 효율이 좋지 않을 것이라 예상하여 이 정보들을 추가적으로 활용할 수 없었다.

물론 평가 방법중 단순히 창의적인 모델링에 집중한다면 위치기반의 추천과 같은 추천이 가능할 수 있겠지만 데이터가 많지 않아 실제 좋은 성능을 내기는 어려울 것이라 판단하였다. 따라서 제시된 데이터가 아닌 다른 데이터를 수집하여 활용하여야 했다. 주최측에서도 모델링을 위해 외부변수를 추가적으로 사용한 경우에 대해 언급하였으므로 추가 데이터를 사용할 수 있을 것이라 생각했다.

그래서 고민후에 생각한 방법은 각 사용자들이 주로 어떤 토픽의 책을 구매하였는지에 대해 모델링을 수행하는 방법이었다. 예를 들면 단순히

"이 사람은 국내문학에 관련된 책을 많이 구매했네"가 아닌

"이 사람은 국내문학 중에서도 사랑에 관련된 책을 많이 구매했네" 혹은 "이 사람은 국내문학 중에서도 사랑에 관련된 책에 관심이 있네"와 같은

정도의 모델링을 수행하여, 이것을 CF 혹은 ALS와 결합한다면 좀 더 좋은 성능을 내지 않을까 생각하였다. 이 과정에서 LDA를 이용한 토픽 모델링을 사용할 수 있을 것이라고 판단하였다. LDA를 이용하여 토픽 모델링을 수행하게 되면 각 Document 별로 생성된 Topic에 대한 Probability 를 알 수 있다. 때문에 각 사용자를 하나의 Document로 하여 LDA를 수행하게 된다면 각 사용자별로 관심있는 Topic에 대해 알 수 있고, 역으로 각 토픽별로 사용자를 클러스터링 할 수 있을 것이다.

Topic Modeling을 수행하기 위한 데이터는 책의 소개문구를 이용하기로 하였다.


3. 알고리즘 디자인

다음 과정은 생각한 방법들을 기반으로 하여 어떻게 추출한 토픽과 ALS를 연관시킬지에 대한 디자인을 하는 것이었다. 고민의 결론은 각 사용자별로 LDA를 기반으로 한 Topic Modeling을 수행하고, 생성된 Topic을 기반으로 사용자를 클러스터링 한 후, 각 클러스터별로 ALS기반의 추천을 수행하고, 가중평균을 이용하여 각 사용자에게 최종 추천을 수행하는 것이었다.

다음과 같은 과정으로 추천이 수행된다.

  1. 각 사용자별로 구매한 책들의 소개글을 합하여 하나의 Document라 가정한 후, 각 사용자를 하나의 Document, 각 단어를 Word로 하는 LDA를 수행한다.
  2. 각 Document(사용자) 별로 높은 상위 3 개의 Topic에 해당 사용자를 할당한다.
  3. 각 클러스터(Topic)별로 User-Item Matrix를 생성한다. 이 Matrix를 생성할 때, 해당 클러스터에 속하는 사용자만을 이용하여 구성한다.
  4. 각 클러스터별로 생성한 User-Item matrix를 이용하여 ALS를 수행한다. ALS의 수행 결과로 각 사용자별 아이템에 대한 예상 수치를 얻을 수 있다.
  5. 모든 사용자별로 각 사용자가 속하는 3 개의 클러스터에서 각 클러스터별 유사도와, 각 클러스터의 ALS에서 추천된 N개의 아이템의 아이템과 그 예상 수치를 이용하여 각 아이템별로 가중평균을 구한다. 같은 아이템이 양쪽 클러스터에서 같이 등장한다면 추가 가중치를 부여한다.
  6. 계산된 가중평균을 기준으로 내림차순 정렬하여 최대 N 개를 추천한다.


4. 데이터 크롤링

앞서 디자인한 알고리즘을 수행하기 위해선 추가적인 데이터의 수집이 필요했다. 따라서 Yes24 홈페이지에서 각 책별로 존재하는 책 소개 내용을 수집하였으며, 책 소개가 없는 경우에는 책 제목으로 대체하였다.

이 과정은 같이 대회에 참여하였던 박치완님이 도와주었다.


5. 구현

알고리즘의 구현체는 Github Repository에 업로드 하였다.

초기 계획은 비교 대조군을 몇개 만들어 놓고, 그 중에 가장 성능이 좋은 것을 선택하여 제출하려 했으나.... 짧은 개발 기간(3일)로 인해 꿈으로만 남았다.

아직 코드가 제대로 정리되어 있지 않다. 코드 정리가 필요한 상황이다.

Maven 기반의 Scala 프로젝트이며, 동작 환경은 Spark 1.5.x 이다.


6. 중간 결과

LDA를 이용하여 각 토픽별로 어떠한 단어들이 등장하는지에 대한 중간 결과를 확인할 수 있었다. 다음과 같다.

TOPIC0:                                                                         
사랑      0.038950771399064034
인생      0.03515207672645974
이야기     0.025418685837176613
감각      0.025245626823315444
마음      0.020893368477979433
현장      0.01642261966657828
사람      0.01481647339996354
자신      0.013958826369854944
스님      0.011214607773803646
가지      0.009985940266383107

TOPIC1:
세계      0.04994877001062086
경제      0.034433078200563016
우리      0.03254562163029728
한국      0.01958911018319702
미래      0.01692410713112926
통해      0.01682498169768221
독자      0.01671768092723129
지금      0.01665981297149608
작가      0.016495697094411226
중국      0.01644162358505943

TOPIC2:
소설      0.038058091178287554
작가      0.03164151030320994
사랑      0.014982771499678716
작품      0.013980950020051253
여자      0.011241435352324514
시인      0.010293643455372868
이번      0.009588547443499656
문학      0.009384890941094364
남자      0.009172136669658392
세계      0.00875815649112367

TOPIC3:
철학      0.027872185181795257
고전      0.01899458579086188
사상      0.009970794191175998
역사      0.009145088267109771
이해      0.009090435616220563
대한      0.00891559440526876
증명      0.007949637931088908
저자      0.007737877329008972
시대      0.007504918744110347
지식      0.007190884930254014

TOPIC4:
세계      0.024141657195419507
확신      0.023254790478907144
무엇      0.020561955505817603
작품      0.01796548295193048
정치      0.015422368617599365
역사      0.013493955309093881
이야기     0.013344052090964226
사건      0.012988721657737918
인생      0.01289824138631931
가장      0.011198337930209776

TOPIC5:
작품      0.020456171283759938
독자      0.015376050675311888
작가      0.015130099763268453
이야기     0.014561306081437523
시리즈     0.013887056794027141
소설      0.01234213886292947
아이디어            0.011188108952049788
세계      0.010898025197746665
고전      0.008525176136316384
사랑      0.00786297203438913

TOPIC6:
사건      0.02103824609772385
작품      0.017807257180762197
소설      0.017457953856403502
작가      0.01712331329720654
살인      0.008785026764247469
이야기     0.0072546581159950805
독자      0.006984216038646738
시리즈     0.006544779598922323
일본      0.006095210735821216
시작      0.00534694833892813

TOPIC7:
인생      0.04574771191525166
우리      0.0331295665851022
마음      0.02600983683922045
사람      0.02263497670866045
시간      0.018730727114082156
독서      0.017798183470428906
세상      0.01485754375840436
통해      0.01416859840332696
대해      0.013191241858221675
저자      0.013101317163704397

TOPIC8:
사람      0.024483916096268845
강의      0.020224518288395794
대화      0.016782886277784723
교수      0.015770886259112514
최고      0.010996576573475025
사회      0.010535599207417902
방법      0.009966624687028717
성공      0.009807661545913731
상대      0.009222202033299464
습관      0.009121246755516243

TOPIC9:
사랑      0.02213784197615728
이야기     0.01772322621102953
대한      0.017309430909218677
여행      0.01465205015939723
사람      0.01456699329694893
우리      0.013797265937478648
자신      0.01166775423889618
통해      0.011017462627371669
일상      0.009267416924552943
사회      0.009213923922705928

TOPIC10:
이야기     0.020616023081828375
편지      0.013932305666324857
소설      0.013669690497313864
과거      0.01076967158824421
자신      0.009807666523129583
소년      0.009688170650006968
고민      0.009565007212529605
작품      0.009468309454259458
기억      0.009393742898172668
작가      0.009387598027138165

TOPIC11:
하나님     0.028877801631496967
성경      0.026571636427607372
교회      0.016071591478662054
우리      0.013651128335939367
기도      0.01190310850373663
저자      0.011412814240508724
기독교     0.009753764891267266
말씀      0.008998065889125427
사람      0.008869120816531921
예수      0.008501843457410042

TOPIC12:
사람      0.028783455203289957
공부      0.01789677322548907
저자      0.01758348460534456
마음      0.016980841060103936
심리학     0.015450609696654164
자신      0.015426573857353887
방법      0.014921197551560475
생각      0.013316907130197864
심리      0.012283333703454424
글쓰기     0.011017951281154943

TOPIC13:
사랑      0.01629699122010116
세상      0.014119800121617326
자신      0.008852907628560024
남자      0.008599152420418884
시인      0.008096688544342551
사람      0.007591992606568243
작가      0.007224683357099236
이야기     0.007044728358115589
조선      0.006744395180701537
여자      0.006657011146982586

TOPIC14:
감정      0.041194666696242735
우리      0.029147186160630938
사랑      0.027256701576788202
이야기     0.019030340353812132
자신      0.016117387258532154
용기      0.015257783215476176
철학자     0.015150579463710349
하나      0.01503732449961679
저자      0.012974779070331585
독자      0.012641342715594273

TOPIC15:
인류      0.0498372102472762
인간      0.03379429042702267
소설      0.028014827738242452
작품      0.021200628208484628
과학      0.01794840144695439
만남      0.01641915725242832
시작      0.014654742183719486
상상력     0.01445620734844426
사회      0.010700420329539783
창조      0.01057772568162761

TOPIC16:
성공      0.02660171637591407
사람      0.022367799493907953
자신      0.01505699603653131
저자      0.014896546653713778
인생      0.013526588119255934
시간      0.010959792605428396
당신      0.009557989569069886
생각      0.008127274061635938
가지      0.007727816536524141
방법      0.007410024004336087

TOPIC17:
이야기     0.023695377724228722
인간      0.01946201361094322
역사      0.016362912320875042
우리      0.015870888389808404
시대      0.013738434081786773
사회      0.013643307625891594
세계      0.010892085337965499
신화      0.010808663879575329
지식      0.010749682143135467
저자      0.00957354797979392

TOPIC18:
우리      0.0378256076523149
사람      0.029814703470588417
가장      0.0277431062535585
이야기     0.027134071365245132
행복      0.020619528174727907
인생      0.01857040565668168
당신      0.016352557769813394
죽음      0.016078070887595428
가족      0.01538197357160221
자신      0.015314170280887558

TOPIC19:
작품      0.029106267733493736
인간      0.016823144261245
문학      0.012818792642740058
사회      0.012617625920241113
대한      0.01120908393427178
소설      0.011030423016008779
세기      0.0105561854448285
작가      0.010293366024680773
대표      0.009802885112187715
사랑      0.007696910129304892

각 토픽 별로 어떠한 단어들이 구분되는지 추측할 수 있다. 예를 들면 Topic 0은 사랑과 인생에 관한 이야기, Topic 1은 경제에 관련된 것들, Topic 11은 종교에 관련된 것들로 말이다.

이 결과는 LDA의 수행 결과중 일부인데, 어떤 새로운 Document가 갖고 있는 단어의 분포를 이용하여 위에서 보이는 것과 같은 각 Topic 별 단어의 분포를 이용해 새 Document가 어떤 Topic에 가까운지에 대한 분포를 추론할 수 있다. 물론, 트레이닝에 사용된 Document 역시 추론할 수 있으며 그 결과는 LDA의 수행 결과중 하나로 이미 존재한다.


7. 최종 결과

최종 결과는 링크에서 다운로드 할 수 있다. 해당 링크는 모든 카테고리(6개)에 속하는 데이터들 안에서 추천을 수행한 경우이다.

사용자 ID[Delimiter]책 제목[Delimiter]추천 Score

형태로 저장이 되어있다.


8. 부족한 부분

  1. 정말 한심하게도 성능평가가 수행되어 있지 않다. 단순히 추천 결과만 내어놓았다. 초기 예상으로는 3일정도의 개발 기간이라면 추천 결과를 평가하는 Metric도 정의하여 다양한 알고리즘의 성능을 평가해 볼 수 있을 것이라 예상하였지만, Spark에서 RDD 연산을 반복하여 수행하는 과정에서 여러 문제점들이 발생하는 바람에, 그 부분을 다른 방법으로 해결하는 과정에서 시간이 많이 소비되었다. 심지어 파라미터 최적화도 수행하지 못하였다..;;

  2. 부족한 알고리즘의 구성. 실제 알고리즘을 개발하거나, 수정한 것이 아닌 단순히 두 개의 알고리즘을 잘 연결시킨 것일 뿐이다. 좀 더 좋은 성능을 이끌어내려면 깊은 레벨에서의 개선이 필요할 것이다.

  3. 코드가 지저분하다. 대회에 제출하였던 코드 그 상태이므로 주석도 제대로 달려있지 않고, 코드가 깔끔하지 않다. 게다가 검증을 못하였으므로 정상적으로 작성한 코드인지도 검증이 안되어있다. 한심하다. 다음 포스트를 작성할 때는 개선된 코드를 이용해 설명할 것이다.

  4. 상을 못탔다. 상을 못탔다.... 시간투자를 좀 더 해서 결과 더 다듬고 했으면 괜찮은 결과가 나왔을 것 같은데 그러지 못했다. 어디 이력서에 한줄 넣기도 애매한 결과다.

Yes24 책 추천 알고리즘, 어떻게 구현했나

얼마전 한국 정보화 진흥원이 관리하는 [개방형 문제해결 플랫폼](http://crowd.kbig.kr)에 올라온 Yes24 도서 추천 알고리즘 대회가 종료되었다.총 230여명이 참여하였고, 25팀이 최종 결과물을 제출한 대회였다. 이 대회에서 친...… Continue reading