본문 바로가기
machine learning

word2vec으로 영화 추천 하기

by 유주원 2016. 11. 18.

word2vec을 검색 엔진에 포팅했는데 이제 이걸 가지고 무엇을 해야 하나 고민을 하던 찰나에 아래의 링크를 발견했다.


http://www.slideshare.net/ssuser2fe594/2015-py-con-word2vec


word2vec을 이용해서 영화 추천을 해봤다는 발표자료인데 word2vec에 학습시킬 corpus만 잘 조합하면 가능할 것 같아서 나도 한번 해보기로 했다.


movieLens 라는 사이트에 들어가게 되면 사용자들이 각 영화에 대해 평점이나 tag를 매겨놓은 데이터를 다운 받을 수가 있다.


나같은 경우엔 다운 받은 파일들 중 movies.csv, ratings.csv 만 가지고 word2vec으로 만들 corpus를 만들어 보기로 했다.


movies.csv 같은 경우에는 영화 id와 해당 영화 title 그리고 장르가 담겨져 있고, ratings.csv 같은 경우에는 user id와 그 유저가 본 movieid 그리고 평점과 timestamp가 명시되어 있다.


movies.csv


1,Toy Story (1995),Adventure|Animation|Children|Comedy|Fantasy

2,Jumanji (1995),Adventure|Children|Fantasy

3,Grumpier Old Men (1995),Comedy|Romance

4,Waiting to Exhale (1995),Comedy|Drama|Romance

5,Father of the Bride Part II (1995),Comedy

.....


ratings.csv


1,2,3.5,1112486027

1,29,3.5,1112484676

1,32,3.5,1112484819

1,47,3.5,1112484727



우선 위에 slide에서 시키는 대로 사용자 id별로 movie id를 나열해서 한 문장을 만들어 보기로 했다.


2539 2571 2496 2587 1213 260 2108 1210 1374 541 1196 1682 110 1701 1291 318 2401 1639 2136 1653 2150 1721 2291 296 1356 1584 1748 2174 628 1080 589 1197 1967 1246 38 2046 47 1120 1136 150 2000 1243 32 1279 1500 356 802 1240 2144 2470 2406 21 10 1676 1287 1552 1580 2528 1275 2001 2006 2370 380 2167 1376 1127 

....


1번 사용자가 본 영화 리스트는 첫 번째 문장, 2번 사용자는 두번째 문장.. 이런 식으로 corpus가 구성된다.

여기서 추가로 필터링을 적용한 것은 영화 리스트에 추가할 때 평점이 3.0 이하인 영화들은 영화 리스트에서 제외시켰다. 왜냐하면 3점 이하는 추천할만한 영화라고 설명하기엔 충분하지 못하기 때문이다.


위에 슬라이드에서는 이런식으로 하고 word2vec을 돌리면 제법 그럴싸한 영화가 추천된다고 설명되어져 있었는데, 나같은 경우에는 만족할만한 결과가 나타나지 않았다.


여기서 사실 만족할만한 결과가 나올 수가 없는게, 1번 영화를 본 사람들이 많이 본게 2번 영화라는 건데 2번 영화는 성격이 완전 다를 수도 있는 것이고, 정답이라는게 있을 수가 없기 때문인 것도 같다.


어쨌든 추천으로 나온 영화들이.. "어?? 왜 이 영화가 추천됐지??" 하는 의구심이 많이 드는 결과가 나오기는 했다.


그리고 또 의구심이 든게 위 방식대로 저렇게 나열했을 때에 주변 인접 movie에 어떤 장르의 영화가 오느냐에 따라 값이 확 달라질 것 같은데 그것에 대한 처리도 없는 게 의심이 들었고 (슬라이드 코드 상에는 단지 timestamp로 영화 리스트를 sorting 했음), 또 해당 인접 movie를 처리하기 위한 window size도 큰 관건이 될 것 같았다.

word2vec에서는 context 사이즈(window size) 가 가장 중요한 요소가 되기 때문에 단순히 timestamp로 sorting 하기에는 너무 리스크가 커 보였다.


그래서 추가로 같은 사람이 본 영화 중 성격이 비슷한 영화들은 또 따로 모아서 corpus를 만들어 보자란 생각을 하게 됐고, 그래서 같은 사람이 본 영화 중 같은 장르끼리 같이 분류해서 문장을 만들어 보기로 했다.




587 595 596 919 953 2115 2174 2997 3052 4890 27706

899

150 595 1797 8636 62081

60 364 588 595

589 924 1019 1097 1240 2117 2311 6502 72378

3671


1번 사용자가 본 adventure 영화는 1번째 문장에 , 범죄 영화는 두 번째 문장에, 이런 식으로 사용자 별 장르별로 문장을 구분지어서 corpus를 만들어서 word2vec을 학습 시켰다.



Lion King이란 영화를 입력으로 해서 유사한 영화들을 찾아 봤는데, 제법 그럴싸한 결과가 나타났다. 

(similarity는 대부분 낮게 나타났는데, 이건 내 코드 문제일까 -_-??)


James and the Giant Peach, Secret Garden The는 어릴 때 부모님을 일찍 여의고 집을 떠난 후에 펼쳐지는 내용이 Lion King이랑 매우 흡사하며, Aristocats The 같은 경우에도 어떤 음모에 당해 집을 떠나게 되지만 다시 집으로 돌아오는 이야기를 담고 있다.


아래의 그림은 2000개의 영화만 따로 학습해서 clustering을 해본 것인데, 아래 쪽에는 히어로물 , 그리고 왼쪽 영역은 정치 쪽 이야기, 오른 쪽은 판타지, 중간 지점엔 가족 애니메이션.. 이런 식으로 군집화되서 표현되는 것을 확인하였다.



word2vec의 무궁무진함을 확인해 볼 수 있었다. 해당 corpus가 쇼핑 로그이면 쇼핑 추천도 가능할 듯 보였고, 문서 id가 corpus로 주어지면 문서 추천도 충분히 가능한 이야기가 된다는 것을 확인해 볼 수 있었다.