TITLE : [토크ON세미나] 추천시스템 분석 입문하기 6강 - Goodbooks-10k 데이터를 이용한 추천시스템 실습
YOUTUBE LINK : https://youtu.be/apbTjHEhZeg PRESENTER : SKplanet Tacademy DURATION : 00:49:48 PUBLISHED : 2021-01-25
Table of contents
FULL SCRIPT
인테리어 시스템을 만들 수 있는지 그 부분에 대해서 진행하도록 하겠습니다.
그래서 좀 중요한 평가 지표는 이렇게 Accrush라든지 NDCG, MAP 많이 사용해가지고 이렇게 3개 봤고요.
한번 이제 실제 실제 코드 넘어가서 어떤 식으로 이제 추천 시스템 만들 수 있는지 그 부분에 대해서 진행하도록 하겠습니다.
그래서 먼저 GoodBooks라는 10K 한번 데이터에서 이거 데이터 탐색이라고 적힌 노트북부터 한번 같이 진행을 시작하겠습니다.
그래서 다른 분들도 여기 노트북 들어와 주시고요.
그리고 포인트 포인트로 딱 중요한 부분만 설명을 드릴게요.
이 데이터 탐색을 이제 베이스 릴라인 만들어주기 전에 꼭 해보면서 해주는 게 중요한 게 이게 아까 말했듯이 처음 추천 시스템 만들다 보면 어떤 사용자를 사용자의 타겟군을 정해줘야 되고 이 사용자에게 어떤 상품을 추천해줄지 상품의 특성과 사용자의 특성을 잘 파악해주는 게 중요한데 이 데이터 탐색 과정을 통해서 그 과정을 수행한다고 생각하시면 될 것 같아요.
그래서 먼저 패키지 간단하게 로드해주고 데이터를 불러와 주도록 하겠습니다.
그래서 간단하게 국수의 메타 정보 한번 살펴보면 이렇게 보면 메타 정보가 이렇게 나와져 있는데 컬럼이 길어서 컬럼부터 한번 살펴볼게요.
그래서 컬럼 보면 북 아이디에 대해서 어떤 저자가 언제 이 책을 출판했는지 그리고 출판된 책의 제목은 무엇이고 어떤 언어로 쓰여졌고 어떤 사람들이 평점을 얼마나 내렸는지 그리고 1점부터 5점까지 각 평점의 개수 이미지 같은 경우도 이렇게 나와있습니다.
그래서 북수의 이미지 간단하게 보면 아래는 Hunger Games이라는 영화에 대해서 Hunger Games의 표지가 어떻게 나왔는지 이미지 이렇게 바로 따올 수 있는데 책 같은 경우 추천할 때 중요한 게 사실 글의 내용이 유사한 것을 추천해줄 수도 있지만 사실 처음 봤을 때 저희 사용자 입장에서는 글의 내용을 먼저 보지 않고 표지부터 먼저 보게 되잖아요.
그래서 이런 이미지를 통한 유사도 계산하고 자연어 처리를 통한 유사도 계산해서 둘을 가중치 내서 추천을 해주는 것도 하나의 방법인 거죠.
책 추천해서.
저희는 거기까지는 할 요약이 없으니까 그런 콘텐츠 기반에서만 사용할 거기 때문에 이 부분은 빼도록 하겠습니다.
그래서 일단 필요한 변수들만 먼저 추출을 해볼게요.
변수 추출할 때는 이렇게 리스트 이거 두 개 씌워가지고 각각의 내용에 사용할 변수들만 뽑아서 사용하시면 됩니다.
저는 이제 author와 title 그리고 얼마만큼의 사용자들이 평점을 내렸는지 그리고 평균 평점과 그리고 언어 코드는 뭐라고 되어 있는지를 통해서 한번 데이터 탐색을 진행해볼게요.
그리고 이거는 그 Python 같은 경우 보통 Matplotlib 많이 사용하는데 저는 원래 R 유저여가지고 ggplot이 많이 익숙하더라고요.
그래서 Python에서는 flatline이라고 아래 있는 ggplot을 사용해줄 수 있는 도구인데 한번 이거 토대로 코드 작성해서 그래프 보여드리도록 하겠습니다.
아래 그래프는 이제 저자마다 몇 개의 책을 썼는지 넘버스를 찍은 거고요.
평균적으로 저자 같은 경우 한 권 부터 60권까지 가장 많이 쓴 사람 60권까지 많이 쓴 거를 볼 수가 있습니다.
이렇게 히스토그램을 그렸는데 어떤 식으로 ggplot 형성하냐 하면 ggplot 같은 경우에 되게 데이터 구조가 명확하거든요.
그래서 ggplot으로 데이터 어떤 거를 사용하겠다?
를
입력을 받고 히스토그램으로 어떤 컬럼을 이렇게 그리겠다?
를 받습니다.
여기에서는 ages라고 만든 항목이 각 저자별로 책을 몇 권이 썼는지를 카운트로 이렇게 만든 거기 때문에 이 데이터 같은 경우 저자가 몇 권의 책을 썼는지 그리고 x축의 카운트를 몇 권이 썼는지에 대한 빈도수를 개선할 거고 색깔은 49BB7이라는 색을 사용하겠다.
그리고 제목하고 x축, y축은 어떤 변수명을 사용할 거고 그리고 테마 같은 경우 그냥 꾸며주는 거기 때문에 그냥 검정색과 회색깔 적절하게 사용했다고 보시면 됩니다.
그래서 제일 중요한 이제 그런 책 메타 데이터 의미 좀만 더 보면 책의 숫자는 만 개로 되게 적어요.
이게 실습용도로 만들어진 데이터이기 때문에 원래 책이 수백 이렇게 많은데 그 중에서 만 개만 임의로 샘플링 된 거고 그래서 메타 정보에 없는 정보도 있어가지고 실제 결과값이 예상한 것보다 많이 낮을 수도 있는데 그거는 참고하시기 바랍니다.
일단 책의 숫자는 만 개고 저자의 숫자는 4664명 그리고 각 저자당 평균적으로 책 두 권 쓴 사람이 있고 어떤 저자는 60권의 책을 썼더라고요.
그래서 이 저자가 누군지 궁금해서 한번 살펴보려고 했는데 어떻게 살펴보냐?
아까 봤던 함수 중에 Salt values라는 함수가 있잖아요.
이 Salt values로 이렇게 카운트를 해주게 되면 순서를 정렬해줄 수가 있어요.
근데 저희는 이제 카운트가 큰 거를 순서대로 봐야 이제 맨 위에 가장 큰 값이 나올 테니까 Salt values에 카운트를 기준으로 정렬을 해주는데 Auth sending은 false로 하겠다.
이렇게 하면 정렬이 잘 되고 첫 번째로 스티븐 킹 같은 저자가 60권 책 쓴 것을 볼 수가 있습니다.
한 권씩 쓴 사람도 굉장히 많죠.
한 번 이제 다음에는 책의 평균 평점이 어떻게 되는지를 한번 살펴볼게요.
평균 평점 같은 경우 대부분의 책이 4점에서 4.5점으로 되게 높은 걸 볼 수 있어요.
평균이 4고 4를 기준으로 약간 정규범포 형태의 모습을 보이고 있죠.
근데 3 이하의 책들도 많잖아요.
메타 정보에서는 약간 이런 식으로 전처리를 좀 더 도와줄 수 있는 것 같아요.
예를 들어 3 이하의 책들 같은 경우 이렇게 14권으로 좀 몇 개 있는데 굳이 이런 책도 추천을 해줄 이유가 있을까?
여러분 어떻게 생각하시나요?
유사도 계산했을 때 글 간의 유사도가 얘 14권의 책은 비슷한데 평점이 매우 낮아요.
그럼 추천을 해줄 이유가 있을까요?
저 같은 경우는 굳이 안 해줘도 될 것 같거든요.
그러니까 이런 거는 기존에 학습하기 전에 미리 제거해준다든지 하는 것을 거치면 더 좋은 추천 품질을 성능을 보장할 수가 있죠.
그리고 위에처럼 평점이 높은 순서대로 정렬을 했어요.
그래서 평점을 높은 순서대로 책을 추천해주는 게 좋긴 하잖아요.
근데 높은 순서대로만 추천해주는 게 꼭 답일까요?
예를 들어서 아래를 보면 이거는 평점이 높은데 레이팅 카운트라고 사람들이 얼마만큼 평점을 줬는지에 대한 정보거든요.
보면 어벌리지 레이팅이 높은데 이 값들 보면 28,000, 30,000, 9,000, 8,000 이렇게 값이 되게 작아요.
그러니까 이거는 진짜 평점을 높게 주는 사람들은 많지만 애초에 모수 자체가 많이 적은 경우죠.
실제 가장 많은 책 같은 경우는 만 10만, 100만, 500만 이상이 레이팅을 줬는데 쟤는 많으면 되게 적잖아요.
그러니까 이런 평가 지표를 여러 개를 뽑은 다음에 적절하게 잘 조화를 해주는 것도 필요하죠.
그래서 보면 이 부분에 보면 대부분이 25만 이하이긴 하지만 어떤 경우는 25만 이상에서 많은 사람들이 평가를 해준 책이 있다.
이런 경우는 콜드 스타트 유저들에 대해서 추천해주면 되게 좋을 거라고 저는 생각합니다.
그리고 이 과정을 통해서 예를 들어서 트와인 라이크 같은 경우는 이게 380명이 읽었지만 평점은 3.57로 굉장히 낮은 거로 볼 수 있죠.
이런 거를 잘 데이터 탐색 과정에서 해가지고 평가 지표를 추출해야 될 것 같고요.
그리고 책에 보면 아까 랭기지 코드 같은 게 있었잖아요.
근데 랭기지 코드 내용 보면 영어부터 시작해가지고 인디언인 것 같고 절맨이 독일어인 것 같고 이렇게 여러 가지가 있는데 만약 추천 상황에서 저는 한국 사람인데 영어 책 같은 경우는 영어 공부 오래 했으니까 읽을 수 있겠지만 영어 책이 아니라 중국어나 독일어 이런 책을 추천해주면 제가 과연 그 책을 들어가서 볼까요?
그렇진 않겠죠.
그래서 이런 부분에 대해서도 일단 잘 철회해주는 게 여기서 살펴보고 철회해주는 게 되게 중요합니다.
이런 부분 어떤 정보들 있는지 살펴봐야 되고요.
근데 이게 어차피 영어권 사람들을 위한 데이터여가지고 대부분의 데이터가 이미 영어권이고 이런 책들만 좀 주의해서 추천해주면 좋을 것 같아요.
근데 이런 거는 보통 후처리단에서 이 사람이 한국 사람이면 한국 사람 책이나 영어 기존에 책을 읽은 게 있으면 그런 거를 추천해주고 그리고 만약에 영어권 사람이면 영어권 사람의 책을 우선적으로 추천해주고 근데 아쉬운 게 이거 결즉치가 되게 많은데 이게 어쩔 수 없는 한계인 것 같아요.
메타데이터 같은 경우는 진짜 데이터 수집하고 만드는 게 어렵기 때문에 결즉치라든지 이런 좀 부정확한 정보들이 많더라고요.
그래서 국적에 맞는 책을 추천해주는 것도 필요하고 결즉치도 만 권 중에 1084권으로 굉장히 적다.
그리고 레이팅스가 아까 그 영화 추천 평점 내린 것처럼 사용자가 어떤 책에 대해서 평점을 내린 건데 여기 있는 책 중에서 메타데이터에는 과연 몇 권이나 있을지를 한번 살펴봤을 때 이게 함수가 set의 difference라는 게 차집합을 계산하는 거거든요.
그래서 레이팅스에는 있지만 북스에는 없는 책의 id의 수를 계산하는 게 이 함수입니다.
그래서 set과 set 간의 difference를 계산하는데 그 length를 여기서 계산하겠다.
그러니까 차집합의 전체의 길이를 계산하는 코드인데요.
보면 만 개 중에 9088개가 메타데이터에 없어가지고 실제 이런 경우에는 컨텐츠 기반의 유사도 추천을 하게 되면 조금 어려운 면이 있겠죠.
정확도나 이런 거 계산했을 때.
왜냐하면 9200개는 정보가 없으니까 컨텐츠 기반에 추천을 해줄 수가 없고 남은 800개에 대해서만 적용할 수밖에 없으니까.
그래서 아마 이런 경우에는 협업 필터링 기반의 모델이 조금 더 정확하지 않을까 생각합니다.
협업 필터링이라든지 아니면 통계 기반의 룰 기반의 모델들도 괜찮고요.
그래서 태그 정보들도 있었는데 태그 정보 한번 살펴보면 이제 각각의 책에 대해서 어떤 태그가 달렸고 이 태그가 총 전체 책에 대해서 몇 번이나 카운터가 됐는지 알 수 있습니다.
근데 이 태그에 대해서 이 태그가 무엇을 의미하는지 모르기 때문에 같이 있는 데이터 중에 하나가 태그스인데 태그스 같은 경우 각각의 태그 아이디와 맵핑되는 태그 네임에 대한 정보를 담고 있는 테이블이라고 보시면 됩니다.
근데 이제 두 개 보기가 불편하니까 둘을 잘 멀지를 해가지고 한번 사용을 할게요.
그래서 멀지를 하게 되면 이제 태그 아이디라는 컬럼을 기준으로 얘와 얘를 맵핑을 하게 되잖아요.
그래서 보게 되면 태그 아이디를 기준으로 맵핑을 했기 때문에 여기서 국북스와 카운터가 이렇게 조임된 거를 볼 수가 있죠.
그래서 32482 같은 경우는 favorite을 가지고 있고 이런 정보들을 확인할 수가 있습니다.
보면 이게 둘 다 같은 의미인데 이렇게 조금 스펠링 철자 차이에 따라서도 이렇게 표시가 태그 다를 수도 있어서 이런 것도 데이터 탐색해주면서 확인해주는 과정이 필요하고요.
한번 태그 중에서도 많이 나온 태그 뭐 있는지 보면 to read라든지 favorite, fiction, 소설 그리고 fantasy, fantasy 같은 소설책들 의미하는 거겠죠.
상위 태그에 대해서 한번 카운트를 찍어볼게요.
바플라로 상위 태그에 대해서 어떤 식으로 태그들 나왔는지 찍어봤는데 보면 to read라는 태그가 압도적으로 많은 걸 볼 수 있습니다.
이게 다 상위 태그인데도 하나가 압도적으로 많으니까 얘 같은 경우 사실 모든 책에서 이렇게 많이 결합되는 태그니까 얘 같은 경우 조금 많이 안 좋을 거다.
KF, IDF 기준에서 보면 많이 나오는 게 중요한데 모든 책에 다 나오면 안 좋다라고 그런 걸 표현했잖아요, DF에서.
그런 식으로 생각해서 to read 같은 경우는 제거해주고 태그 유사도 계산해도 괜찮은 추천 모델이 될 수 있고요.
그래서 한번 태그 카운트 몇 번 나왔는지 그런 서메이션에 대해서 기술 동계값 제공해주면 평균적으로 태그 하나당, 태그 총 3만 4천 개 있는데 태그 하나당 평균적으로 6천 명 정도가 책에서 달리지만 편차는 76만으로 태그 간의 편차가 되게 큰 걸 볼 수가 있고요.
그래서 좀 이거를 잘 처리를 해줘야 되겠다.
그리고 태그 카운트 된 게 마이너스 1로 희한한 값들도 있죠, 여기 보면.
그리고 맥스 값은 셀 수도 없이 되게 크고요.
그 이후에 이제 사실 가장 중요한 정보인 레이팅스 사용자들이 어떻게 전체 책과 사용자에 대해서 어떻게 평점을 때리고 했는지에 대한 기술 통계에 대해서 한번 살펴볼게요.
한번 레이팅스 그룹 바이를 통해서 어그리게이션을 하면 이 그룹 바이라는 함수가 유저 아이디를 기준으로 북을 몇 권이나 읽었는지를 카운트로 세주는 함수거든요.
그래서 사용자 1 같은 경우는 총 서로 다른 책을 3권이나 읽은 거고 사용자 2는 책을 마찬가지로 3권, 사용자 5만 3천 4백 22는 책을 18권 읽었다.
이런 식으로 정보를 볼 수가 있습니다.
그래서 이렇게 본 정보로 실제 사용자마다 얼만큼의 평균적으로 읽은 횟수를 가지는지를 보면 보면 이런 식으로 이제 함수꼴을 가지는 걸 볼 수 있고요.
가장 많이 읽은 사용자 같은 경우는 한 사람당 200권이나 읽었지만 어떤 사용자 같은 경우는 이제 한 두 권, 열 권 이하로 이렇게 구성된 것도 볼 수 있죠.
좀 더 자세하게 보면 평균적으로는 18권을 읽는데 50% 중위수로 보면 한 사람당은 8권을 책 읽는 거를 볼 수가 있습니다.
그리고 이제 북에 대해서도 한 번 그런 레이팅 평점 매겨진 책들이 사람들이 몇 명이나 읽었는지 그런 카운트에 대해서 보면 평균적으로 이게 샘플링 된 그런 데이터라고 했었잖아요.
이게 좀 사용자들이 그런 거 실습하는 용도로 그 원본 데이터에서 책 만 것만 샘플링한 결과인데 보면 대부분의 책이 사용자 100명에 대해서 읽어진 것들만 있는 거를 볼 수가 있습니다.
그래서 이건 조금 샘플링을 통해서 만들어진 결과이기 때문에 실제 상황이랑 좀 다르고요.
실제는 보통 많이 읽혀진 것부터 그리고 어떤 것들은 되게 소수는 한 두 명만 읽은 거 그리고 아예 안 읽은 정보들에 대해서도 있을 수가 있겠죠.
그래서 기술 통계 마찬가지로 보면 한 사람당 평균적으로 책당 평균적으로 읽힌 횟수는 98로 좀 비정상적인 수가 나오는데 이거는 샘플링 결과를 어쩔 수 없다는 거를 미리 말씀드리고요.
책의 경우 최소 읽혀도 8명 이상은 한 책을 읽었다는 거를 알 수가 있습니다.
그리고 보면 이게 북 아이디 12345에 대해서 보시면 사실 얘네가 의미하는 게 해리포터 시리즈거든요.
근데 해리포터 시리즈같이 이렇게 글 간에 연속성이 있는 글들이 있잖아요.
드라마 같은 경우는 드라마 1화부터 16화까지 이렇게 이어지는 연속성이 있다라든지 반지의 제왕 123편 이렇게 시리즈 책들 이런 시리즈 책들 같은 경우 당연히 읽는 순서들 간에 연관성이 있지 않을까요?
실제 사용자 전체에 대해서 한번 이거를 같이 읽는지 안 읽는지에 대한 정보를 한번 살펴볼게요.
예를 들어 314 같은 유저에 대해서 보면 314 유저 같은 경우 해리포터 북아이디 1, 3, 5, 6 이 빼고 이 5개에서 다 본 거를 알 수가 있어요.
이 유저가 그랬으니까 다른 유저들도 그런 성향을 보이지 않을까요?
해가지고 전체 유저에 대해서 얼만큼 그런 거 읽는지를 봤을 때 1부터 8이 해리포터 시리즈 총 8건에 대해서 몇 명이나 사람들이 8건을 같이 읽었는지 얘는 8건 중에서 7건 읽었는지 얘는 8건 중에서 한 건만 읽은 사람은 몇 명인지를 살펴봤을 때 총 약 200이 넘는 한 300명 가까이 되는 수중에서 이 100명 정도만 한 건만 읽었고 그 외에 나머지 사용자들은 그 시리즈물을 같이 읽은 걸 볼 수가 있습니다.
그래서 비율로 치면 36%만 한 건을 읽고 64% 같은 경우는 시리즈물을 같이 읽는 경향을 보인다고 저희가 판단할 수 있고 이런 추천 시스템 설계할 때도 이런 시즈 같은 책들은 같이 추천이 될 수 있도록 내가 직접 모델링을 해줘야겠다라는 걸 여기서 생각하고 넘어갈 수가 있는 거죠.
이거 이따가 실습해서 보여주겠지만 이러한 순서 같은 걸 잘 잡아내는 게 Word2Vec이 이런 순서 같은 걸 되게 잘 잡아내더라고요.
그래서 데이터 삼색은 여기까지 마치고 그 다음에 실제 베이스라인 모델부터 컨텐츠 기반의 모델 그리고 허버 필터링 기반의 모델 차근차근 적용해보면서 한번 추천 시스템 구성을 해볼게요.
그리고 시간이 30분밖에 남지 않아가지고 실제 돌려진 결과를 가지고 제가 코드 설명하고 결과가 어떻게 나왔는지에 대한 설명 위주로 진행하도록 하겠습니다.
그리고 참고로 이게 원래는 전체 데이터셋이 이렇게 전체 사용자에 대해서 98만 개의 평점 정보를 가지고 사용자 같은 경우는 53,424에 대해서 총 만 건의 책에 대해서 이렇게 평점이 매겨진 거거든요.
근데 저희가 아까 말했듯이 초반에 그런 알고리즘 같은 걸 적용하거나 하이퍼 파라미터를 적용할 때 내 방법론이 좋은지에 대해서 평가를 스스로 매겨야 된다고 했었잖아요.
그래서 이거를 평가셋을 만들어주기 위해서 저는 임의로 사용자마다 임의로 절반씩 랜덤 샘플링을 진행했어요.
그래서 유저 1 같은 경우 책 총 3권을 봤는데 그 중에서 임의로 절반 정도는 트레인셋으로 임의로 절반 정도는 테스트셋으로 만들어서 오프라인 그런 메트릭 평가를 진행했다고 생각하시면 됩니다.
그래서 실제 이 다음부터 어떻게 그런 거 모델 만들고 그리고 평가 진행했는지 한번 살펴볼게요.
살펴볼게요.
첫 번째로는 베이스라인을 만드는 부분입니다.
아까 같은 경우 이론에서는 첫 번째 설명으로 에이프리오리와 FP-Gross를 봤지만 사실 가장 기본적으로 처음에 생각하는 모델들은 통계 기반의 모델들이거든요.
이 책을 얼마만큼 많이 사용자들이 봤냐.
그런 인기 순으로 100권을 추천해줄 수도 있고 추천 그런 스코어 순으로 예를 들어서 가장 평점이 높은 책 100권을 이렇게 추천해줄 수도 있고 그런 통계 기반의 추천들이 기본적으로 베이스라인 만들어서 비교하기는 가장 괜찮은 것 같아요.
그래가지고 데이터셋을 한번 만들어서 진행을 해보도록 하겠습니다.
그래서 일단 한 사람당 100권 책 추천해주는 게 아니라 이거 잘못 썼는데 200권 책 추천해주는 상황이고요.
추천 모델은 사용자마다 얼마큼의 사용자마다 많이 읽은 책을 기준으로 추천을 해주는 걸로 생각을 할게요.
그래서 메타 정보에 보면 북스 카운트라고 사용자가 얼마만큼의 많은 책을 읽었는지 그에 대한 피처 정보가 있습니다.
그래서 이거를 기준으로 지금 소울트를 해주고 얘가 높은 순서대로 단순하게 200권 이렇게 추천을 해주는 상황을 고려할게요.
그래서 북스에 소울트를 북스 카운트로 해주는데 어스선딩은 어스선딩은 first로 북스 카운트가 높은 순서대로 이렇게 추천이 진행되고 그 중에서 500권만 뽑고 나중에는 추후에 200권을 추천을 진행해 줄 거예요.
그래서 저희가 전체 사용자에 대해서 추천을 해줘야 되니까 이제 전체 사용자에 대해서 똑같이 포문 함수를 도는데 저희가 만든 퍼플럴 랙이라는 모델 단순하게 인기 순서대로 200권 추천해주는 함수 순서대로 이렇게 추천을 진행해주고 평가를 진행해주게 됩니다.
평가 함수 같은 경우는 이거 같은 경우는 카카오 아레나에서 예전에 진행했던 평가 함수 그대로 사용했고요.
평가 지표로는 MAP와 NDCG 그리고 다이버전스라는 새로운 평가 지표가 하나가 더 있는데 다이버전스 같은 경우는 얼마만큼의 다양한 책들이 추천됐는지를 의미하는 정보입니다.
그래가지고 200권의 책이 사용자들마다 다 동일하면 다이버전스 값이 매우 낮고 다이버시티 값이 매우 낮고 사용자들마다의 추천 정보가 매우 다르다면 이거가 개인화가 가장 잘 됐다는 의미겠죠.
그래서 개인화 정도가 얼마나 잘 됐는지를 측정하는 지표로 생각하시면 됩니다.
그래서 단순하게 200권을 사용자들에게 동일하게 인기 순서대로 추천했을 때는 MAP와 NDCG가 굉장히 낮습니다.
보면 NDC는 0.0001이고 MAP는 0.0001이죠.
200권을 솔직히 많이 추천했는데도 이렇게 결과가 맞는데 이제 이거를 기준으로 각각의 아까 봤던 데이터 탐색을 통해서 본 정보들을 적용할 수도 있고 협업 필터링이나 콘텐츠 기반의 모델들을 하나씩 적용해보면서 점수를 비교해 갈 겁니다.
그래서 첫 번째로 생각할 수 있는 게 저희가 방금은 글 많이 읽은 순서대로 그냥 추천을 해줬었잖아요.
근데 여기서 하나 더 생각할 수 있는 게 글 많이 읽은 순서도 중요하지만 아까 평점이라는 게 중요하다고 했었는데 글 읽은 순서 플러스 평점이 높은 순서를 같이 결합해서 단순하게 추천을 해주면 어떨까?
그러면 더 좋지 않을까?
이런 생각도 할 수가 있고요.
그리고 장바구니에 담긴 글을 좀 더 정보를 활용해서 추천을 해줄 수도 있고 아까 봤던 시리즈의 글들, 해리포터 1을 읽었을 때 해리포터 2를 자연스럽게 추천해주면 더 좋지 않을까?
그리고 최신의 글들, 이렇게 그냥 예전에 나온 책들이 되게 자연스럽게 사람들한테 많이 노출됐을 테니까 읽은 양이 많을 수밖에 없는데 최신의 글 같은 경우 좀 더 가중치를 둬서 추천을 해주면 더 좋지 않을까?
이런 생각을 할 수 있습니다.
저는 그중에서도 좋아하는 작가의 글들만을 추천해주는 상황을 생각해볼게요.
그래서 책의 메타 정보에 보면은 어써라는 정보가 있었는데 이 어써 정보를 활용해서 유저마다 이 어써를, 어써의 책을 몇 권 읽었는지 그리고 만약에 이 어써의 책 중에서 안 읽은 책이 있다면 이 책을 추천해주는 그런 알고리즘을 만들었을 때 얼마만큼의 정확도와 MAPI, MDCG, 그리고 다이버시티 그 다양성에 대해서 나오는지 한번 살펴볼게요.
그래서 코드 짜는 건 되게 간단합니다.
그래서 유저 아이디에서 어써를 이렇게 맵핑을 통해서 각각의 유저 아이디가 읽은 북 카운트가, 북 아이디가 어떤 어써를 어써와 맵핑되는지에 대한 정보를 한번 만들어주시고요.
그 다음에 트레인의 그룹 바이를 어써를 통해서 함으로써 각 사용자가 어써에 대해서 얼마큼의 많은 책을 읽었는지를 계산하면 됩니다.
그래서 아래에 지금 헤드 찍힌 거 보시면 30944라는 사용자는 빌 브리슨이라는 저자의 책을 총 7권이나 읽은 거고 그리고 20845는 토마스의 책을 6권이나 읽은 건데 이렇게 보면 이 두 사용자는 각각의 저자에 대해서 굉장히 좋아하는 걸 알 수가 있죠.
그럼 이제 추천 시스템 만들 때도 30944한테는 빌 브리슨의 신권이라든지 아니면 안 읽은 책들이 있으면 그걸 우선적으로 추천해 준다거나 20845는 토마스의 책을 추천해 주거나 하는 걸 한번 만들어 볼게요.
그리고 참고로 아까 말했던 그 저자의 책을 추천해 주는데 그 저자의 책도 한 권이 아니라 굉장히 많을 거잖아요.
그 추천의 순서를 정했을 때 레이팅 카운트가 많은 순서대로 추천을 해 준다든지 이 어버리지 평점이 높은 순서대로 추천을 해 준다든지 그런 추천에 대한 기준은 여러분 스스로가 한번 더 탐색해 보면서 더 좋은 값을 찾으면 됩니다.
그래서 저는 이 레이팅스 카운트가 많이 나오는 순서대로 한번 기준을 세워서 추천을 해 볼게요.
그래서 추천 모델을 이제 AuthorRack이라는 모델을 만들고 이 각 Author별로 이제 이 레이팅 카운트가 높은 순서대로 추천을 진행해 줄 겁니다.
그래서 보면 단순하게 이렇게 멀지 한 다음에 딱 200권만 이렇게 뽑으면 나오는 거 볼 수 있는데 이 AuthorRack에서 이제 각 사용자별로 북 아이디 뭐 추천됐는지 뽑아서 200권 그냥 추천해 주는 부분이 여기고요.
그리고 저자가 쓴 책이 200권이 안 될 수가 있잖아요.
그래서 그 모자란 부분은 그냥 단순하게 인기 기반에 추천해서 모자란 부분 채우도록 했습니다.
그랬을 때 결과가 0.01로 아까보다 한 10배 정도 상승된 거 볼 수 있죠.
여기서는 0.0001이었는데 10배가 아니라 100배 정도 상승했네요.
이런 식으로 단순하게 하나 정도 이렇게 수정해 줌으로써 결과가 많이 좋아진 거 볼 수 있고 사실 여기가 끝이 아닌 게 이게 추천해 줬을 때 이미 봤던 책을 또 추천해 줬을 수도 있잖아요.
그런 것도 이제 후처리 작업에서 처리를 해 주는 게 필요하죠.
내가 읽은 책은 추천해 주면 안 된다든지 내가 읽은 언어와 맞는 책을 추천해 줘야 된다든지 그래서 한번 내가 읽은 책을 추천 목록을 트레인의 GroupByUser에서 북 아이디만 유니크가 뽑으면 내가 읽은 목록들이 이렇게 유저별로 이렇게 값이 저장이 되고 만일 어떤 책이 유니크에 포함되는 항목이라면 추천을 하지 않겠다라는 항목 하나만 이렇게 입력을 해 주도록 하겠습니다.
그래서 아까 봤던 이 ReadList라는 항목이 읽은 책에 대한 목록이고 여기서 사용자별로 이 ReadList에서 내 읽은 목록을 뽑았을 때 추천해 주는 책이 이 씬에 들어가지 않은 경우에 대해서만 추천을 진행하도록 하면 아까 점수 대비 아까 점수가 이건데 아까 MAP 같은 경우는 0.0108이었는데 이번에는 0.0118로 조금 소량의 상승이 있는 걸 볼 수가 있습니다.
NDCG 같은 건 이게 0이었는데 5로 좀 더 많이 상승했죠.
그래서 이런 식으로 해 줄 수도 있고 아까 봤던 언어 관련해 가지고 좀 더 후처리로 활용해 줄 수도 있어가지고 이렇게 좀 다양한 정보들을 데이터 탐색 과정에서 활용을 해 주는 다양한 데이터 탐색 과정에서 찾은 다음에 추천 시스템 만들 때 전처리라든지 후처리라든지 그런 과정 속에서 활용해 주는 게 되게 중요합니다.
그래서 이런 방법들이 되게 속도가 빨라 가지고 많이 사용하고요.
한번 이렇게 베이스라인 모델 만들었으니까 실제 저희가 배운 모델들에 대해서도 한번 적용을 해 봐야죠.
그래서 한번 협업 필터링 모델부터 한번 출발해 볼게요.
그래서 일단 퍼플럴 랭 모델 같은 경우 만들어주는 건 그냥 동일하고요.
매트리스 팩토라이제이션 아까 만든 코드 이용해서 바로 그냥 SGD랑 ALS 적용을 해 볼게요.
그리고 아까 말했듯이 저희 트레인의 유저 아이디와 트레인의 북 아이디 같은 경우 기존에 데이터와 맵핑이 잘 그런가 안 되는 문제가 있어가지고 바로 변환해 주는 작업이 먼저 필요하거든요.
그래서 그리고 이거 매트리스 만들 때 인덱스가 정확히 0부터 랭스까지 순서대로 맵핑이 돼야 그런 거 매트리스 만들고 나중에 그런 거 인덱스 추출할 때 문제가 없기 때문에 딕셔너리 만들어가지고 이렇게 탐색해 주는 딕셔너리 만들어서 아이디 한번 변형해 주는 작업은 꼭 필요합니다.
근데 이거는 아까 설명해 준 거기 때문에 넘어가고 레이팅 매트리스 만들 때 보통 어떻게 만드냐면 SCPI에 sparse에서 CSR 매트리스라는 함수 부분 이용해가지고 만들면 돼요.
그래가지고 여기서 순서대로 보면은 쉐이프는 유저 아이디의 길이는 얼마나 가지고 책의 아이디는 전체 얼마나 길이는 가지는지 그 쉐이프에 대해서 각각의 입력 값을 이제 레이팅 평점과 그리고 유저 아이디의 IDX 번호, 책의 IDX 번호 이렇게 통해서 매트리스를 만들 수가 있고요.
그 매트리스의 크기를 출력했을 때 요 53,382명의 사용자에 대해서 만 권의 책을 가지고 지금 sparse 매트리스를 만들었다는 걸 이렇게 볼 수가 있습니다.
그리고 아까 봤듯이.toArray라는 함수를 이용하면 레이팅 매트리스를 numpy로 바꿀 수 있고요.
간단하게 아까 말했던 매트리스의 팩토라이제이션 함수에 그냥 이렇게 넣어서 돌리게 되면 이제 제가 설정해 준 hyperparameter 기준을 가지고 학습을 진행하게 되는데 얘 같은 경우 좀 도는데 40분이나 걸려서 아까 문제점으로 봤을 때 얘 같은 경우는 numpy로 짜서 지금 CPU로 계산하는 거거든요.
그래서 수련 속도가 좀 느려요.
GPU로 짜면은 더 빨라질 수 있는 장점이 있고요.
이렇게 추천된 결과를 보면 0.00으로 아까 그냥 단순하게 100권 추천해 주는 베이스라인 모델보다는 좋아졌지만 그 어서 기반의 모델보다는 사실 조금 낮은 그런 거 볼 수 있죠.
그래서 아까 결과 한번 다시 비교해 보면 아까 같은 경우는 0.001과 0.001 값을 가졌는데 지금 같은 경우는 이거는 0.000으로 이거에 비해서는 좀 더 올라졌고 NDCG도 이거는 많이 상승한 걸 보면 NDCG가 좀 더 앞에 순서 오는 거에 대해서 가중치를 많이 받아서 지금 협업 필터링 기반의 SGD 모델이 좀 우선적으로 추천해 주는 게 많이 맞았지만 전체적으로는 조금 많이 못 맞췄다를 MAP 점수를 보면서 알 수 있고요.
그리고 다이버시티 같이 이제 얼마만큼 개인화가 많이 반영되느냐에 평가 지표에서는 굉장히 좋아진 걸 볼 수 있죠.
그리고 SGD 말고 아까 ALS에 대해서도 언급했었는데 ALS 아까 그냥 넘피 형태로 클래스 짤 수도 있지만 인플리시시라고 이거 패키지를 제공해 주거든요.
그래서 패키지 사용법도 되게 간단해서 아까 실습 부분에서 다시 언급한다고 했었는데 ALS에 그거 여기 인플리시시의 ALS 부분에서 리스트 스퀘어스를 함수를 받아서 바로 호출을 하면 됩니다.
ALS 같은 건 논문에서 20이 조금 괜찮았고 이거 더 이상 키우거나 해도 별로 큰 차이 없다라는 좀 연구가 있어가지고 20 사용했고요.
레귤라이제이션은 0.01로 이터레이션은 0.01로 이터레이션은 100번 반복했을 때 결과 어떻게 되는지 한번 살펴보겠습니다.
그리고 얘는 조금 만들어둔 거기 때문에 리코멘드 그냥 인덱스 하면 0번 인덱스와 유사한 상품을 200개 이렇게 자동으로 추출을 해줘요.
그래서 이거 기반으로 추천을 해줬을 때 MAP와 NDCG 보면 기존 모델에 비해서 가장 괜찮아진 거 한번 확인할 수가 있죠.
어서 기반의 모델도 아까 0.01에서 5.8에 0.004였는데 이 0.004가 아예 10배나 됐을 정도로 모델의 상승폭이 되게 컸고요.
이런 식으로 협업 필터링 기반 모델 만들 수도 있고요.
그리고 마지막으로 한번 컨텐츠 기반에서 아까 TF-IDF랑 그리고 Word2vec 했을 때 결과 어떻게 되는지 한번 살펴볼게요.
근데 이거는 Word2vec하고 TF-IDF 통해서 컨텐츠 기반 모델 사용하는 건 아마 점수가 그렇게 높지는 않을 거예요.
왜냐하면 이게 아까 봤듯이 메타 정보가 책이 만 권 중에서 정보가 있는 게 800권밖에 없어가지고 메타 정보 활용해서 추천해주는 게 그렇게 큰 의미가 없는데 여기서 이따가 보시겠지만 Word2vec 이용해서 순서 기반에 추천해주는 거 아까 실습에서 잠깐 봤었잖아요.
근데 그거 결과가 괜찮아서 한번 소개를 같이 드릴게요.
데이터 패스 블러어와서 읽어드린 것까지는 동일하고요.
TF-IDF 이용한 코드 아까 봤으니까 간단하게 설명만 하고 넘어갈게요.
TF-IDF 벡터라이저 이용해서 불용어 잉글리시로 받고 타이틀에 대해서 타이틀 유사한 거를 추출을 한 다음에 만 권에서 만 권 이제 유사도 매트릭스를 이렇게 계산할 수가 있고 이거를 통해서 추천을 해준다 했었잖아요.
그리고 기존에 타이틀과 아이디 같은 경우 맵핑 정보가 임덱스랑 많이 다르기 때문에 그거를 반영해줄 딕셔너리 함수 만들어주는 게 중요하고 그래서 트와일라이트에 대해서 어떤 식으로 책 유사도 가지는지 봤을 때 제목만 기준으로 유사도 뽑았을 때 되게 잘 나와요 생각보다.
트와일라이트 사과, 트와일라이트 컬렉션, 사과 컴플리트 컬렉션 이런 식으로.
근데 이게 실제 결과 계산해보면 TF-IDF 통해서 추천 결과 해준 거 결과 보면은 이 부분인데 많이 낮거든요.
이제까지 기존에 본 것 중에 가장 많이 낮은데 이게 왜 발생했냐면 아까 말했듯이 메타 정보에 조금 트레인이 없는 정보들이 너무 많아서 그래가지고 실제 컨텐츠 기반 추천해주면 내부적으로는 있는 정보들에 대해서는 괜찮지만 없는 거에 대해서는 결과가 안 좋아가지고 이렇게 조금 문제점이 있습니다.
그래서 활용 방안을 메타 정보 있는 거는 메타 정보 이용해가지고 컨텐츠 기반에 추천 시스템 적용해 주는 것도 하나의 방법이고요.
좀 상황에 맞게 아까 말했던 상황에 맞게 조금 모델을 다르게 적용해 줄 필요가 있습니다.
워드투백을 이용한 모델, 여기서 워드투백을 이용한 것도 이제 여러 가지 방식으로 유사도를 만들 수가 있어요.
워드투백 이용한 거, 제목 간의 유사도를 만들 수도 있고 태그 간의 유사도를 만들 수도 있고 그리고 책을 읽은 순서를 통한 유사도를 만들 수도 있는데 이 태그 간의 유사도를 해가지고 이전에 카카오, RN에서 작년에 브런치 책 추천대회 열렸을 때 1등 분이 워드투백으로 태그 간의 유사도를 잘 해가지고 솔루션으로 만들었더라고요.
그래서 이런 것도 되게 한번 적용해 보시면 좋고 저는 여기서 간단하게 책을 읽은 순서를 통해서 유사도 만드는 거 소개해드리고 소개해드리겠습니다.
그래서 일단 트레인의 그룹 바이의 유저 아이디에서 유저 아이디를 기준으로 어떤 책을 읽었는지 북 아이디에 대해서 유니크 값을 계산해보면 사용자마다 책을 읽은 정보를 계산할 수가 있어요.
그리고 이 값을 센텐스로 받아서 내 양옆의 주변 단어에 어떤 영화들이 나왔는지 어떤 순서들을 읽었는지를 한번 볼게요.
그걸 해주는 게 이게 센텐스에 넣어주는 거고 아까 잠깐 말했듯이 워드투백은 인트 형식을 잘 받지 않아서 얘를 스트링으로 바꿔주는 게 필요한데 맵이라는 함수가 리스트 내부에 있는 전체 원소에 대해서 한 번에 스트링으로 이렇게 함수 적용해주라는 명령어이기 때문에 맵의 스트링으로 유저 센텐스를 감싸게 되면 유저 센텐스의 모든 원소에 대해서 스트링을 적용해주고 그 다음에 이 값을 리스트로 반환해주세요 라고 이해하시면 됩니다.
그 다음에 워드투백으로 이렇게 학습을 진행하게 되고요.
그 다음에 4893이라는 책에 대해서 내 양옆에 어떤 책들이 나왔는지를 통해서 유사도를 계산해보면 이렇게 10건의 책의 유사도 이렇게 높은 걸 볼 수가 있고 실제 이거를 가지고 모델을 만들어서 평점을 내렸을 때 기존의 MVP, NDCG, 다이버전시 계산했을 때보다 되게 많이 상승된 걸 볼 수 있어요.
아까 ALS 같은 경우 이게 0.01이었고 NDCG도 0.06 정도인가 그랬고 다이버시티도 굉장히 낮았는데 워드투백으로 이렇게 단순하게 순서 관련해서 전부 유사도 뽑았을 때 적용했을 때는 굉장히 좋아지는 걸 볼 수 있고 아마 이 원인이 이 도메인 자체가 책 같은 경우 순서 간에 상관성이 있기 때문에 아까 말했던 해리포터 시리즈 같은 걸 연속적으로 읽는다든지 반지의 장 이런 거 시리즈 연속적으로 읽을 수가 있고 그리고 브런치 같은 글 같은 경우는 좀 이런 게 있었는데 그런 거 웹툰이라든지 이런 거 보면 1화를 본 다음에 2화를 보고 3화를 보잖아요?
이렇게 책들 간에 좀 연속성이 있는 경우에 대해서 워드투백 이렇게 모델 만들어주는 게 굉장히 점수 잘 나오는 것 같았습니다.
그래서 좀 더 도메인 상황에 맞춰서 적용해주면 좋고요.
그래서 여기까지 하면 기본적으로 추천 시스템 이용해가지고 어떤 식으로 베이스라인 만들고 살펴는지 봤는데 시간이 급해가지고 되게 빠르게 설명한 감이 있는데 궁금하신 부분 카톡이라든지 이거 캐글 사이트 계속 열어둘 테니까 댓글로 코드 부분 질문 남겨주시면 제가 바로바로 답변을 드릴게요.
그래서 오늘 비록 설명은 많이 못 드렸지만 한번 직접 코드 쳐보면서 모르는 부분이 있으면 질문 남겨주시기 바랍니다.
그리고 마무리로 최근에 어떤 식의 모델들 연구하고 있는지 그리고 많이 사용하는지 간단하게 이야기를 드리고 마치겠습니다.
유튜브 같은 데에서는 16년도에 딥러닝 이용해서 유튜브에서는 딥뉴럴 네트워크스 유튜브 레코멘데이션 모델이 나왔는데 이거 같은 경우 기존에 딥러닝 관련된 연구들이 많이 없었고 그리고 유튜브 같은 경우는 되게 스케일이 많이 크거든요.
초당 몇 십만 건의 영상들이 새로 올라오니까 이런 영상들에서 추천해줄 필요가 있고 그리고 애초에 사용자가 10억 명이 넘어서 DB스탄에 쌓인 데이터도 너무 많으니까 단순한 방법으로 추천해주기가 힘들다.
그래서 이런 거를 스케일과 그런 걸 잘 고려해서 어떻게 추천해줄까 해서 만든 모델이고요.
그리고 아까 말했던 협업 필터링을 딥러닝을 통해서 만드는 모델들도 있어요.
얘는 베리에이션 오토 인코더라는 건데 베리에이션으로 이게 딥러닝의 웨이트 같은 경우는 평균과 세타 이런 걸 통해서 같이 하는 걸 의미하는 건데 이런 식으로 딥러닝과 협업 필터링을 같이 결합한 연구들도 있고요.
그리고 머신러닝에서 팩토라이제이션 머신이라고 그런 정보들 간의 상호작용들을 보기 위한 건데 이 팩토라이제이션 머신에 딥러닝을 달아서 딥 팩토라이제이션 머신 그런 연구도 있고 요새는 강학습을 통해서 어떤 식으로 잘 추천을 할지 그리고 그래프 기반의 사용자와 사용자를 노드로 봐가지고 사용자랑의 어떤 관계가 있는지를 그래프를 통해서 추천해주는 연구도 있습니다.
그 외에도 지금 되게 추천 시스템 관련해서 많은 연구가 있는데 뭐 이제 아까 말했던 챌린지 같은 경우 보면 이제 추천 시스템 관련해서 콜드 스타스도 있고 페어넷을 좀 공평하게 어떻게 추천을 해줄지 그런 UX나 어떤 편향 같은 게 책에 추천이 없어야 되는데 그런 것도 있고 에디셔널 인포메이션을 어떻게 달아야 될지 유사도 함수를 어떻게 사용해야 될지 그리고 메모리 아까 문제라고 엄청 많이 말했었는데 그런 메모리를 어떻게 잘 다룰지 그리고 아까 말했던 콜라보레이트 필터링과 그리고 컨텐츠 위안의 모델들 이런 게 여러 가지가 있는데 얘를 어떻게 잘 하이브리드 해가지고 사용할지 그리고 시간에 따라서 추천 시스템 같은 데이터도 새로 들어오고 사용자들의 선호도 바뀌는데 이런 선호 같은 걸 어떻게 계속해서 잘 추적해가면서 모델을 만들지 되게 많은 연구가 있어서 이제 요 부분은 직접 한번 관심 있는 거에 맞춰서 계속 공부해가면서 정보 맞춰가면 될 것 같습니다.
참고 자료는 다음에 링크들 사용해서 봤고요.
이상으로 여기까지 해가지고 발표 마치도록 하겠습니다.
5시간 듣느라 고생하셨습니다.
감사합니다.
SUMMARY
인테리어 시스템을 만들기 위해 평가 지표로 Accrush, NDCG, MAP을 사용하며, GoodBooks 10K 데이터를 분석하기 시작하였습니다.
북 아이디, 저자, 출판 날짜, 제목, 언어, 평점, 표지 이미지 등 컬럼을 분석하여 사용자의 타겟군과 상품의 특성을 잘 파악하는 것이 중요합니다.
그리고 표지부터 먼저 보게 되는 경우가 많기 때문에 이를 고려하여 사용자에게 추천해주는 시스템을 만들 수 있도록 합니다.
이미지 비교와 자연어 처리를 통한 유사도를 계산해 가중치를 두고 추천하는 방법이 있다.
책 추천을 위해 필요한 변수를 리스트로 추출하고, 각 변수를 통해 데이터 탐색을 진행한다.
이를 바탕으로 Matplotlib과 ggplot을 통해 그래프를 그려내고 히스토그램으로 저자별 책 수를 개선한다.
이를 위해 ggplot을 사용하고 데이터를 입력받고 히스토그램을 그리며 색깔은 49BB7색을 사용한다.
이 데이터는 실습용으로 만들어진 책 메타 데이터로, 원래 책의 수가 수백 개 이지만 만 개로 샘플링 되었다.
저자는 4664명이고, 평균적으로 각 저자는 두 권의 책을 쓴 것으로 나타났으며, Salt values 함수를 통해 카운트를 기준으로 정렬하여 가장 많은 책을 쓴 저자를 찾을 수 있었다.
그리고 평균 평점은 4점에서 4.5점 사이로 높게 나타났고, 3 이하의 책들도 많읤 나타났다.
메타 데이터를 통해 이런 책들을 추천할 이유가 있는지 궁금하게 만들었다.
본 문장은 추천 시스템의 성능을 높이기 위해 미리 제거해주는 것과 평점이 높은 순서대로 정렬하는 것을 거치면 더 좋은 품질의 추천이 가능하다고 하였다.
그러나 평점을 높은 순서대로만 추천해주는 것이 꼭 답일까?
가장 많은 책들의 경우 레이팅 카운트가 10만, 100만, 500만 이상이기 때문에 이를 여러 개의 평가 지표로 뽑고 적절하게 조화를 시켜야한다.
이 과정을 통해 트와인 라이크라는 책의 경우 380명이 읽었지만 평점이 3.57로 낮은 것을 발견하게 되었다.
따라서 이런 경우는 콜드 스타트 유저들에게 추천해주는 것이 좋다고 한다.
그런 부분에 대해서 적절한 추천 모델을 찾기 위해서는 일단 메타데이터가 있는 책의 수를 확인하고 차집합을 계산하여 정확한 추천을 할 수 있는 책의 수를 확인해야 합니다.
이러한 과정을 거쳐 차집합의 길이가 만 권 중에 9088개로 정보가 없어 컨텐츠 기반의 유사도 추천이 어려울 것으로 보여 협업 필터링 기반의 모델이나 통계 기반의 룰 기반의 모델을 사용하는 것이 적절합니다.
태그 정보를 살펴보면 각각의 책에 대해 달린 태그들과 그 태그가 총 전체 책에 몇 번 나왔는지를 알 수 있다.
태그스는 태그 아이디와 맵핑되는 태그 네임의 정보를 담고 있는 테이블이다.
멀지를 하게 되면 태그 아이디를 기준으로 맵핑이 되는데, 태그 중 많이 나온 것에는 to read, favorite, fiction, 소설, fantasy가 있다.
KF, IDF 기준에서 보면 to read가 압도적으로 많기 때문에 이 태그를 제거해주고 태그 유사도를 계산하면 추천 모델이 될 수 있다.
태그 카운트는 총 3만 4천 개로 편차가 76만으로 크고, 레이팅스 사용자들의 평점을 살펴보면 가장 많이 읽은 사람은 200권, 평균적으로는 8권을 읽는 것으로 나타났다.
이러한 기술 통계를 잘 처리해야 한다.
사용자들은 책 만 것만 샘플링한 결과를 보면 사용자 100명 중 대부분이 책을 읽었고, 최소 8명 이상이라는 것을 알 수 있습니다.
해리포터 시리즈와 같이 연속성이 있는 책들을 보면 사용자들이 연관성 있게 읽는 것을 알 수 있습니다.
사용자들은 샘플링 결과로 비정상적인 평균 읽힌 횟수를 가질 수 있지만, 책의 경우 최소 8명 이상이 읽었다는 것을 알 수 있습니다.
해리포터 시리즈를 통해 사용자들이 연관성 있게 읽는 것을 확인할 수 있습니다.
사용자들이 책을 샘플링한 결과로 대부분이 책을 읽었고, 최소 8명 이상이 읽었음을 알 수 있습니다.
해리포터 시리즈를 통해 사용자들이 연관성 있게 읽는 것을 확인할 수 있습니다.
저희는 전체 유저들이 Harry Potter 시리즈의 8권을 읽는 비율을 분석해보았다.
결과로 약 300명 중 100명 정도만 한 권만 읽었고, 나머지는 시리즈를 같이 읽었는데, 이는 약 36%로 나타났다.
이러한 결과를 바탕으로 추천 시스템을 설계하고, 실제로 시간이 없어서 바로 돌려보지는 못하였지만, 코드를 설명하고 결과를 살펴보는 것으로 진행하기로 했다.
이러한 분석을 위해 원래는 98만 개의 평점 정보를 가지고 있는 53,424명의 사용자들에 대해 만 권의 책에 대해 평점이 매겨졌다.
따라서 우리는 이를 통해 알고리즘과 하이퍼 파라미터를 적용할 때 자신의 방법론이 좋은지 평가할 수 있게 되었다.
사용자가 책을 읽는 것을 예로 들었을 때, 그 중 절반을 트레인셋, 절반을 테스트셋으로 나눠 메트릭 평가를 진행합니다.
기본적으로 통계 기반의 모델을 베이스라인으로 만들어 비교하고, 많이 읽은 책을 기준으로 사용자마다 추천해주는 추천 모델을 만들어 평가를 진행합니다.
이를 위해 메타 정보를 바탕으로 북스 카운트로 소울트를 해주고, 인기 순으로 추천하는 퍼플럴 랙 모델을 사용하여 전체 사용자에 대해 추천 및 평가를 진행합니다.
평가 함수로는 카카오 아레나에서 예전에 진행했던 함수와 MAP, NDCG, 다이버전스라는 새로운 평가 지표가 사용되었습니다.
다이버전스는 추천된 책들의 다양성을 측정하는 지표로, 개인화 정도가 잘 됐는지 측정할 수 있습니다.
단순하게 200권을 사용자들에게 동일하게 인기 순서대로 추천할 경우 MAP, NDCG 값이 매우 낮습니다.
또한 글 많이 읽은 순서도 중요하지만 평점과 같이 결합하여 추천하는 것도 고려할 수 있고, 장바구니에 담긴 글을 좀 더 정보를 활용해서 추천하거나 시리즈의 글들과 최신의 글들을 가중치를 두어 추천하는 방법도 있습니다.
좋아하는 작가의 글들만을 추천하는 상황도 고려할 수 있습니다.
사용자의 어써 정보를 활용해 추천 시스템을 만들 수 있습니다.
각각의 사용자가 어써의 책을 몇 권 읽었는지 맵핑하고, 각 저자의 책도 한 권이 아닌 많은 권을 추천해줄 수 있도록 레이팅 카운트가 많은 순서대로 추천해주는 AuthorRack 모델을 만들 수 있습니다.
AuthorRack은 사용자별로 북 아이디를 추천하고, 나머지 모자란 부분은 인기 기반으로 추천해 줌으로써 추천 점수가 0.0108에서 0.0118로 상승하고, NDCG는 0에서 5로 상승했다.
또한 이미 봤던 책을 또 추천하지 않도록 후처리 작업을 하고 있다.
데이터 탐색 과정에서 다양한 정보들을 활용하여 추천 시스템을 만들 수 있습니다.
보통 베이스라인 모델을 만들고 기존 모델들을 적용하는 것부터 시작합니다.
이때 유저 아이디와 북 아이디를 매핑해 주기 위해 딕셔너리를 만들고 레이팅 매트리스는 SCPI sparse의 CSR 매트리스 함수를 이용해 만들 수 있습니다.
53,382명의 사용자가 가진 17권의 책에 대해 sparse 매트리스를 만들었고, toArray 함수를 이용해 numpy로 바꿀 수 있었습니다.
간단한 매트리스 팩토라이제이션 함수를 이용해 hyperparameter 기준으로 학습했는데 40분이 걸렸고, GPU로 짜면 더 빨라질 수 있었습니다.
추천 결과는 단순한 베이스라인 모델보다 낫았으나 더 높은 수준이 되지는 못했습니다.
NDCG는 상승했고, 개인화가 많이 반영되는 다이버시티 같은 경우 좋아졌습니다.
결과 한번 비교해 보면 MAP 점수는 조금 낮았고, SGD 모델이 우선적으로 추천해 주는 것이 많았습니다.
ALS 패키지인 인플리시시를 이용해 간단하게 리스트 스퀘어스를 함수를 받아 호출할 수 있습니다.
우리는 ALS 논문에서 사용한 20이라는 숫자를 사용하여 레귤라이제이션과 이터레이션을 0.01과 100번 반복해서 협업 필터링 기반 모델을 만들었다.
이 모델은 기존 모델보다 MAP과 NDCG 점수가 높아졌고, 또한 TF-IDF와 Word2vec을 이용한 컨텐츠 기반 모델을 만들었으며, 이 모델은 메타 정보가 있는 책 800권 중에서 추천을 해주고, 순서 기반 모델을 만들어 추천해주는 것도 시도했다.
따라서 결과 점수가 높아진 것을 확인할 수 있었다.
기존의 제목과 아이디 맵핑 정보가 다르기 때문에 딕셔너리 함수를 만들어 줘야 하며, 트와일라이트 유사도를 뽑았을 때 생각보다 잘 나왔다.
TF-IDF를 이용한 추천 결과는 낮았고, 메타 정보가 부족하기 때문인 것으로 보았다.
메타 정보를 이용하거나 컨텐츠 기반 추천 시스템을 적용하거나, 워드투백을 이용한 모델을 다르게 적용하는 것이 필요하다.
사용자를 기준으로 책을 읽은 정보를 계산하는 것도 하나의 방법이다.
이를 통해 유사도를 만들 수 있다.
센텐스(sentence)를 받아 주변 단어에 나온 영화들과 순서를 확인하기 위해 스트링으로 바꾸는 맵 함수를 사용하여 리스트로 반환하고, 워드투백을 통해 학습하여 4893라는 책에 대해 유사도를 계산한 결과 10건의 책의 유사도가 높이 나왔다.
이 모델을 통해 평점을 내리면 기존의 MVP, NDCG, 다이버전시 계산했을 때 더 높은 점수가 나오고, 책의 경우 연속성이 있기 때문에 워드투백 모델이 좋은 점수를 나타낸다.
그러므로 도메인에 맞게 모델을 적용하면 더 나은 점수를 나타낼 수 있다.
요즘 추천 시스템은 딥러닝과 협업필터링, 그리고 딥 팩토라이제이션 머신과 강학습을 통해 발전하고 있습니다.
딥러닝은 유튜브 레코멘데이션 모델을 만들어 대규모 사용자와 영상들을 처리하고, 협업필터링은 베리에이션 오토 인코더를 사용해 사용자들 간 관계를 분석하고, 그래프 기반의 추천 시스템은 사용자 간 상호작용을 보고 추천합니다.
만약 추가적인 질문이 있다면 카톡 또는 코드 댓글로 남겨주시면 바로 답변해드리겠습니다.
지금 추천 시스템 관련해서 많은 연구가 있습니다.
콜드 스타트, 페어넷, UX, 편향, 에디셔널 인포메이션, 유사도 함수, 메모리, 콜라보레이트 필터링, 컨텐츠 위안과 하이브리드 모델들을 사용해 추천 시스템을 잘 다룰 수 있는 방법에 대한 연구들이 있습니다.
사용자들의 선호도가 바뀌는 것도 고려해야 합니다.
이러한 내용들을 자신이 관심 있는 부분에 맞춰 계속 공부해가면서 정보를 맞춰가면 될 것입니다.