Recommender System
추천 시스템의 종류와 동작 방식에 대해 알아봅니다.읽는데 15분 정도 걸려요.사람이 손수 작성한 추천목록, 플레이리스트 등 기존의 추천엔 한계가 있습니다.
따라서 개인화된 추천 시스템을 만들어야 하는데, 이를 개발할 때 여러 문제점들이 있습니다.
- 훈련 데이터를 얻기 힘듦
- 입력 안된 데이터를 채우기 힘듦 (평가 안된 항목 예측이 힘듦)
- 추천 방식의 성능을 평가할 방식을 찾기 힘듦
그렇기에 이러한 요소를 염두해두고 아래의 소개되는 추천 시스템을 비교하며 알아보도록 합시다.
Content-based
기본적인 아이디어는 추천 대상을 여러가지 키워드의 벡터로 표현하고, 유저의 추천 대상에 대한 평점을 기반으로 벡터의 값을 계산해 비슷한 아이템을 추천하는 것입니다.
따라서, 우선 영화라고 한다면 감독, 배우, 장르 등등의 키워드로서 영화를 표현해야 하는데요, 특징을 추출하는데는 TF-IDF 휴리스틱 알고리즘이 사용됩니다.
TF-IDF
IF-IDF score는 아래와 같은 수식으로 계산합니다.
j: 문서, i: 단어
여기서 TF는 i-단어가 j-문서에 얼마나 많이 등장하는지에 대한 척도로, 아래와 같이 계산됩니다.
i-단어의 등장횟수를 한 문서에 대해 가장 많이 등장하는 단어의 등장횟수로 나눠줌으로서 문서의 길이에 비해 많이 나오는 정도(normalize)를 캐치합니다.
하지만, 모든 문서에 대해 빈번하게 등장하는 단어의 경우에는 키워드로서 부적절 할 것입니다.
따라서 이런 단어들에 대한 페널티를 부과하기 위해 IDF 항이 존재하며, 식은 아래와 같습니다.
전체 문서의 개수를 i-단어가 나온 문서의 수로 나눠줍니다.
즉, 단어가 특이하게 많이 등장할수록 큰 점수를 부여하는 방식입니다.
User Profiles
TF-IDF를 이용해서 item을 프로파일링 했으니, 이제 user를 프로파일링 해보겠습니다.
예로 들어 아래와 같이 프로파일링된 item들이 있다고 가정해보겠습니다.
TF-IDF에서 선택된 키워드는 1, 아닌 키워드는 0으로 표기됩니다.
keywordA | keywordB | keywordC | keywordD | keywordE | |
---|---|---|---|---|---|
itemA | 1 | 1 | 0 | 0 | 0 |
itemB | 1 | 0 | 1 | 0 | 0 |
itemC | 0 | 0 | 0 | 1 | 1 |
그리고 user들이 이런 item에 평점을 매겼다고 가정해보겠습니다.
itemA | itemB | itemC | average | |
---|---|---|---|---|
user1 | 5(1) | 3(-1) | 0 | 4 |
user2 | 3(0) | 1(-2) | 2(-1) | 3 |
user3 | 3(0) | 0 | 3(0) | 3 |
rate(diff) |
user 프로파일링은 item profile에 대한 평점을 이용한 가중평균을 사용합니다.
user1 | keywordA | keywordB | keywordC | keywordD | keywordE |
---|---|---|---|---|---|
itemA | 5 | 5 | 0 | 0 | 0 |
itemB | 4 | 0 | 4 | 0 | 0 |
itemC | 0 | 0 | 0 | 0 | 0 |
average | 3 | 5/3 | 4/3 | 0 | 0 |
하지만, 이렇게되면 유저가 평가하지 않은 항목에 대해서는 반드시 부정적인 평가가 이루어지게 되는 문제가 있습니다.
따라서, 유저의 평점에서 평점의 평균 뺀 값 (diff) 을 사용해서 가중평균을 구하는 것이 좋습니다.
user1 | keywordA | keywordB | keywordC | keywordD | keywordE |
---|---|---|---|---|---|
itemA | 1 | 1 | 0 | 0 | 0 |
itemB | -1 | 0 | -1 | 0 | 0 |
itemC | 0 | 0 | 0 | 0 | 0 |
average | 0 | 1/3 | -1/3 | 0 | 0 |
같은 방식으로 user를 모두 프로파일링 하면 다음과 같은 profile을 얻을 수 있습니다.
keywordA | keywordB | keywordC | keywordD | keywordE | |
---|---|---|---|---|---|
user1 | 0 | 1/3 | -1/3 | 0 | 0 |
user2 | -2/3 | 0 | -2/3 | -1/3 | -1/3 |
user3 | 0 | 0 | 0 | 0 | 0 |
user profile를 이용해서 비슷한 사용자를 찾을 때는 cosine 유사도, L1-norm 유사도의 방법을 사용하곤 합니다.
cosine 유사도(방향)는 취향 유사도를 판단할 때 쓰이고, L1-norm(차원별 거리)는 구매력 유사도를 판단할 때 사용하면 좋습니다.
user profile를 이용해서 비슷한 item을 찾을 때는 LSH
를 사용하면 됩니다.
Pros & Cons
장점
- 다른 유저가 없어도 item을 추천할 수 있다(cold start 문제가 없다)
(물론, user profiling은 cold start 문제가 있다) - 독특한 취향의 사람에게도 추천할 수 있다
- 새로운 item이나, 독특한 item의 경우에도 잘 동작한다
- 추천에 대한 설명도 제공할 수 있다
단점
- 분야에 따라 추출해야 하는 keyword를 찾아야 한다
- 새로운 user에 대한 추천은 어렵다
- 너무 사용자 전용 추천이 되어버린다
(관심 밖은 추천이 아예 안되고, 다른 사람의 취향(트렌드)를 따르지 않음)
Collaborative Filtering
위에서는 item을 프로파일링 했다면, Collaborative Filtering 방식은 그런 프로파일을 작성하지 않습니다.
이 방식은 단순히 utility matrix(위에 user의 item에 대한 평점 matrix)를 사용합니다.
User-User C.F.
나와 비슷한 유저를 추천해주는 시스템을 만들기 위해 User-User Collaborative Filtering을 사용합니다.
빠르게 LSH로 찾을 수도 있겠지만, 정밀한 추천을 위해 예시와 함께 다른 추천방법을 알아봅시다.
우선, 유저 A~D의 item에 대한 평점정보가 아래와 같이 있다고 가정해봅시다.
item1 | item2 | item3 | item4 | item5 | item6 | item7 | avg | |
---|---|---|---|---|---|---|---|---|
A | 4 | 5 | 1 | 10/3 | ||||
B | 5 | 5 | 4 | 14/3 | ||||
C | 2 | 4 | 5 | 11/3 | ||||
D | 3 | 3 | 3 |
만약 Jaccard 유사도를 기준으로 측정한다면 어떻게 될까요?
A-B 유사도는 1/5, A-C 유사도는 1/2가 나올 것입니다.
Jaccard 유사도는 영화의 평점을 반영하지 못하기 때문에 여기서 사용하는 것은 부적절해 보입니다.
이번엔 Cosine 유사도를 기준으로 측정해봅시다.
A-B 유사도는 0.380, A-C 유사도는 0.322가 나올 것입니다.
B가 C보다 A와 비슷하다는 점은 잘 캐치하는 것을 볼 수 있습니다.
하지만, C가 A와 비슷한게 아니라 취향이 다르다는 점은 캐치하지 못합니다.
Negative도 캐치할 수 있도록 피어슨 상관계수를 기준으로 측정해봅시다.
피어슨 상관계수는 평점을 평점의 평균으로 뺀 값을을 코사인 유사도를 측정한 것입니다.
피어슨 상관계수를 사용하면 좋은게, 부정적인 정도도 나타낼 수 있을 뿐만 아니라,
사용자가 평가하지 않은 항목은 0으로 출력한다는 점에서 좋습니다.
A-B 유사도는 0.092, A-C 유사도는 -0.559가 나올 것입니다.
이제는 얼마나 다른지도 [-1, 1] 범위로 잘 측정할 수 있습니다.
이렇게 나온 필터를 이용해서 유저에게 영화를 추천할 수 있습니다.
위에서 나온 가중평균을 이용하면 되는데요, 여기서는 소개하지 않겠습니다.
왜냐하면, Item-Item 필터로 추천하는 것이 성능이 더 좋기 때문입니다.
(user의 취향은 여러개가 동시에 존재할 수 있지만, item은 일정하고 간단하기 때문)
Item-Item C.F.
이제 Item-Item Collaborative Filtering 을 이용해서 item의 평점을 예측하고, 그 평점을 바탕으로 user에게 추천을 주도록 해봅시다.
위의 예시를 그대로 사용하겠습니다.
여기서 item2을 userA에게 추천할만한지 판단하기 위해 userA의 item2에 대한 평점을 예측해보겠습니다.
item1 | item2 | item3 | item4 | item5 | item6 | item7 | |
---|---|---|---|---|---|---|---|
A | 4(2/3) | [!] | 5(5/3) | 1(-7/3) | |||
B | 5(1/3) | 5(1/3) | 4(-2/3) | ||||
C | 2(-5/3) | 4(1/3) | 5(4/3) | ||||
D | 3(0) | 3(0) | |||||
0.45 | 1.00 | -1.00 | 0 | 0 | 0 | 0 |
여기서 는 item2에 대한 각 item의 피어슨 상관계수를 구한 것입니다.
이제 item2의 가중평균을 아래와 같은 계산식으로 구해줍니다.
즉, item2에 대한 userA의 평점을 4로 예측하였고, 이는 userA 평균평점 이상이기에 추천할만한 item이라 판단할 수 있겠습니다.
지금은 가중 평균 계산시 모든 item을 다 사용했지만,
일반적으로는 Sim(유사도)이 높은 k개의 item만을 가지고 평점을 예측합니다.
장단점은 Content-based와 정 반대입니다.
추가로, 유사한 k개를 찾을 때, 그 k를 구하는 것이 어렵다는 단점도 있습니다.
그럴때는 그냥 LSH, 클러스터링, 차원축소 등을 사용하는 것도 하나의 방법입니다.
추천 알고리즘의 정답은 없으니까요!
추천 시스템을 개발할 때는 일반적으로 복잡한 알고리즘을 쓰는 것 보다,
단순한 알고리즘을 쓰되, 데이터를 많이 집어넣는게 좋습니다.
Evaluating Prediction
마지막으로 추천 시스템을 평가하는 방법을 알아봅시다.
대표적으로 아래의 평가 방법이 있습니다.
- RMSE
오차의 제곱근(큰 오차에 대한 페널티 부여)의 평균을 이용합니다.
- MAE
오차의 절댓값의 평균을 이용합니다.
예시로 알아봅시다.
MAE | RMSE | ||
---|---|---|---|
실제 평점 | 2 2 2 | - | - |
예측 A | 3 3 3 | 1 | 1 |
예측 B | 2 2 5 | 1 |
물론 이 측정 방법의 한계도 존재합니다.
바로, 아래의 상황을 반영하지 못하는 것이죠..
- 추천 다양성
e.g. 어떤 영화를 많이 봤는데, 이와 다른 장르는 추천하지 않는 현상 - 추천 문맥
e.g. 여행 당시에 사놓은 여행 서적의 기록을 갖고, 평상시에도 여행 서적을 추천하는 현상 - 추천의 순서
e.g. 시리즈물은 순서별로 추천해야 하는데 그렇지 않은 현상