비전공자도 이해할 수 있는 AI지식 -잠재요인을 찾아내는 추천시스템-

1. 은둔의 고수가 찾아낸 획기적인 추천 알고리즘

 

이번에는 협업 필터링 기법 중에 하나인 행렬 인수분해(matrix factorization)를 살펴보겠습니다. 

 

고객/영화 살인의 추억 겨울왕국 부산행 건축학개론 추격자
태연 4 1 - - -
아이유 2 2 1 ? -
수지 2 3 1 5 -
민경 - 5 3 - 1

 

아이유와 수지는 마침 비슷한 평점을 주었고 어렵지 않게 유사한 고객임을 확인할 수 있었지만, 

 

만약 평점이 한두개 영화가 아니라 수천개쯤 되고 점수 또한 제각각이라면 취향이 비슷한 고객을 찾는 일이 쉽지 않을 거에요.

 

행렬 인수분해는 제각각인 평점 정보를 이용해 고객의 특징을 자동으로 추출하고 뿐만 아니라

 

영화의 특징도 자동으로 추출해내서 이 정보를 바탕으로 고객의 평점을 예측합니다

 

이렇게 하면 좋은 평점을 줄 것같은 영화를 자동으로 추천할 수 있죠. 평점 정보를 활용하는 협업 필터링을 확장한 버전이라고 할 수 있습니다.

 

무엇보다 성능 또한 매우 좋습니다.

 

이 방식은 앞서 소개한 넷플릭스 프라이즈에 처음으로 등장했습니다. 당시 사이먼 펑크라는 가명을 사용한 참가자가 고안한 알고리즘으로 

 

다른 참가자들이 팀을 이뤄 대학이나 연구소 소속으로 출전한 것과 달리 그는 친구와 함께 뉴질랜드 여행 중에 참가하여 획기적인 알고리즘을 고안해냈고, 3위까지 올라갔습니다.

 

"평점 정보는 고객이 영화에서 좋아하는 것과 좋아하지 않는 것에 대한 선호도에 따른 결과이다"

 

평점 정보는 단순한 추측이 아니라 고객이 영화에서 좋아하는 것과 좋아하지 않는 것에 대한 선호도에 따른 결과라고 판단한 그의 직관이 적중한 것입니다.

 

핵심 원리는 단순합니다.

 

한쪽에서는 "이 영화는 액션이 얼마나 있나요?"라고 질문하고 다른 한쪽에서는 "이 고객은 액션 영화를 얼마나 좋아하나요?"라고 질문한 다음, 그 결과를 합산하는 방식이죠.

 

그리고 이 방식이 좋은 성과를 내던 어느 날, 대회에 관심이 없어진 그는 더 이상 참가하지 않겠다고 선언하고 2006년에 자신이 발명한 알고리즘을 블로그에 모두 공개한 후 홀연히 떠났습니다.

 

가명을 쓰던 은둔의 고수가 모든 것을 공개하고 미련 없이 떠나는 인상적인 퇴장이었죠.

 

이후 이 방식은 큰 인기를 끌게 되고 참가팀 대부분이 블로그에 공개된 그의 알고리즘을 채택하여 획기적으로 성능을 올립니다.

 

이 방식을 "펑크의 행렬 인수분해" 혹은 줄여서 "행렬 인수분해"라고 부릅니다.

 

2. 행렬 인수분해, 잠재요인을 찾아내는 방법

 

행렬 인수분해는 그 이름에 걸맞게 하나의 행렬을 2개의 행렬로 인수분해하여 예측하는 기법입니다. 

 

우리는 "인수분해"라고 하면 6이라는 수를 2와 3이라는 두 인수의 곱으로 나타낼 수 있습니다.

 

행렬 인수분해는 이처럼 고객이 영화에 평점을 매긴 점수 정보를 하나의 큰 행렬로 보고 이를 2개의 다른 행렬로 분해해서 예측 정보를 얻어 내는 거죠

 

 

 

위 그림에서 행렬의 한 축인 K는 특징의 개수입니다.

 

K개만큼 영화의 특징을 추출하고 고객 행렬과 영화 행렬, 이렇게 2개의 행렬로 분해하는데, 이 과정은 평점 정보를 기반으로 모두 자동으로 진행합니다.

 

여기서는 이해하기 쉽도록 2가지 특징만 추출하고 진행 과정 또한 수동으로 미리 정한 값을 사용합니다.

 

K=2이고 미리 정한 2가지 특징은 앞서 살펴본 것처럼 "공포 또는 드라마", "판타지 또는 현실"의 두 장르를 -1점에서 1점까지 표현한 수치로 하겠습니다.

 

고객/특징 공포-드라마 판타지-현실
태연 -0.57 0.83
아이유 0.77 0.65
수지 0.91 0.49
민경 0.33 -0.82

 

4명의 고객이 선호하는 특징을 정리했습니다.

 

다시 한번 얘기하지만 원래 이 과정은 평점 정보를 기반으로 자동으로 추출합니다. 하지만 여기서는 이해하기 쉽도록 미리 정리해봤습니다.

 

민경의 경우를 예로 들면 공포-드라마 점수가 0.33으로 좀 더 드라마에 가까운 영화를 좋아하고

 

판타지-현실 점수는 -0.82로 판타지에 매우 가까운 영화를 좋아합니다.

 

이제 고객의 특징을 정리했으므로 영화의 특징을 정리해봅니다.

 

영화/특징 공포-드라마 판타지-현실
살인의 추억 -0.56 0.33
겨울왕국 0.74 -0.95
부산행 -0.81 -0.66
건축학개론 0.84 0.77
추격자 -0.64 0.49

 

콘텐츠 기반 필터링을 설명할 때 살펴봤던 영화의 특징 정보입니다. 비교하기 쉽도록 점수를 동일하게 했습니다.

 

특징도 동일하게 정의했는데, 예를 들어 <겨울왕국>의 경우 공포-드라마 점수가 0.74로 무섭지 않은 영화이고

 

판타지-현실은 -0.95로 현실에서는 일어날 수 없는 판타지 영화입니다.

 

이렇게 각각의 특징을 나열해보니 고객이 선호하는 특징과 영화의 특징을 연결하면 어렵지 않게 예측할 수 있을 것 같습니다.

 

드라마면서 판타지 영화를 좋아하는 민경은 비슷한 특징을 지닌 영화 <겨울왕국>을 좋아할 것 같습니다.

 

보다 직관적으로 이해할 수 있도록 2차원 좌표계에 표현해보았습니다.

 

 

이렇게 보니 고객 각자가 선호하는 영화가 무엇인지 쉽게 짐작이 됩니다. 

 

마찬가지로 코사인 거리를 활용하여 가장 가까운 위치에 놓여 있는 영화를 선호하는 영화로 볼 수 있겠죠

 

태연은 <추격자> 또는 <살인의 추억>을 선호하고 아이유와 수지는 <건축학개론>을 선호할 것 같습니다.

 

반면 <부산행>은 안타깝게도 이 중에서 좋아할 만한 사람이 없습니다.

 

그렇다면 행렬 인수분해를 해서 어떤 값이 나오는지 확인해봅시다. 

 

이 행렬 인수분해의 결과는 각 고객의 영화에 대한 예상 선호도 입니다. 이 값이 높을수록 태연, 아이유, 수지, 민경은 각각 해당 영화에 더 높은 평점을 부여할 것입니다.

 

구하는 방식은 고객 행렬과 영화 행렬의 전치 행렬을 구한 다음에 서로 내적을 구하면 됩니다.

 

결과는 다음과 같습니다

 

고객/영화 살인의 추억 겨울왕국 부산행 건축학개론 추격자
태연 0.5931 -1.2103 -0.0861 0.1603 0.7715
아이유 -0.2167 -0.0477 -1.0527 1.1473 -0.1743
수지 -0.3479 0.2079 -1.0605 1.1417 -0.3423
민경 -0.4554 1.0232 0.2739 -0.3542 -0.613

 

 

복잡해보여도 각 값이 가지는 의미는 분명합니다. 값이 높을수록 평점이 높을 것이고, 값이 낮을수록 평점은 낮을 것입니다.

 

밑줄 친 부분은 우리가 예측해야할 평점에 해당하는 점수입니다

 

그렇다면 이번에는 고객이 평가한 점수를 다시 살펴보겠습니다.

 

고객/영화 살인의 추억 겨울왕국 부산행 건축학개론 추격자
태연 4 1 ?(2) - ?(4+)
아이유 2 2 1 ?(5) -
수지 2 3 1 5 -
민경 - 5 3 - 1

 

 

물음표로 표시한 부분에 행렬 인수분해의 결과로 예측한 평점을 밑줄로 표시했습니다.

 

괜찮은 결과가 나온 것 같나요? 하나씩 살펴보면, 먼저 아이유의 <건축학개론> 예상 평점은 몇 점이 돼야 할까요?

 

행렬 인수분해 결과에서 바로 아래 1.1417인 수지는 5점을 주었으니까, 1.1473인 아이유도 5점을 줄 것으로 보입니다.

 

태연이 <추격자>를 선호할 것이라 했는데, 태연의 <추격자> 행렬 인수분해 결과는 0.7715이므로 아마 4점 이상을 줄 것으로 보입니다.

 

태연에게 <추격자>를 추천해준다면 분명 좋아할 것 같습니다. 

 

반면 <부산행>은 모두 3점 넘게는 주지 않았습니다. 유일하게 <부산행>을 평가하지 않은 태연의 행렬 인수분해 결과도 -0.0861임로 아마 2점 정도밖에 주지 않을 것 같습니다.

 

모두 우리가 예상했던 결과 그대로입니다.

 

행렬 인수분해로 평점을 예측해봤습니다. 그렇다면 행렬 인수분해를 활용하기 위해 고객과 영화에 대해 일일이 특징을 추출하고 값을 정의해야 할까요?

 

3. 특징은 몇개가 적절한가

 

예제는 K=2, 즉 2가지 특징만 선정했기 때문에 어렵지 않았지만, 만약 특징을 25가지 즉 K=25로 정의한다면 어떨까요?

 

이렇게 많은 특징을 일일이 추출하고 매번 값을 수동으로 정할 수 있을까요?

 

당연히 수동으로 정의하는 일은 매우 어려울 것입니다. 실제로 이 과정은 평점 정보를 기반으로 모두 자동으로 진행됩니다.

 

행렬 인수분해는 숨어 있는 특징을 자동으로 추출하기 때문에 이를 두고 잠재요인(Latent Factor)을 발굴해낸다고 표현합니다.

 

예제는 K=2이므로 2가지 잠재요인을 발굴해낸거죠. 실제로 쓰일 때는 K=25, 적어도 25개 이상의 잠재요인을 발굴해내며 이 과정에는 사람이 개입하지 않고 컴퓨터가 자동으로 찾아냅니다.

 

계산에 필요한 데이터는 평점 정보입니다. 평점 정보가 많을수록 이들의 관계를 컴퓨터가 정교하게 찾아낼 수 있죠

 

유사한 평점을 받은 영화 데이터를 학습하다 보면 비슷한 장르끼리 비슷한 점수를 부여받는 경우를 자동으로 발견해냅니다.

 

자동으로 계산하기 때문에 25개가 아니라 100개도 문제가 없습니다.

 

다만 특징의 개수를 크게 지정하려면 그만큼 훨씬 더 많은 데이터가 필요합니다.

 

머신러닝에서는 이를 차원의 저주(Curse of Dimensionality)라고 표현합니다. 

 

특징 하나 정도 더 추가하는 게 뭐가 어려운 일이냐고 반문할 수 있겠지만,

 

사실 특징이 하나 늘어날 때마다 한 차원이 더 추가되는 것이고 그렇게 되면 데이터가 훨씬 더 많이 있어야 겨우 비슷한 성능을 낼 수 있습니다.

 

https://medium.com/diogo-menezes-borges/give-me-the-antidote-for-the-curse-of-dimensionality-b14bce4bf4d2

 

위 그림에서 이런 부분이 잘 나타나고 있습니다.

 

1차원을 가득 채우는 데는 5개만 있으면 되지만, 2차원이라면 25개, 3차원이라면 무려 125개나 필요합니다.

 

K=25라는 것은 결국 25차원이라는 이야기이고 제대로 성능을 낼려면 K=2일때 비해 엄청나게 많은 데이터가 필요합니다.

 

그래서 무작정 특징의 개수를 늘리는 게 능사는 아닙니다.

 

데이터가 부족하면 오히려 특징을 제대로 추출해내지 못하고 성능이 더 떨어지는 저주를 받을 수 있기 때문입니다.

 

그렇다면 왜 하필 25개냐라고 물을 수 있는데, 행렬 인수분해를 처음 고안한 사이먼 펑크가 맨 처음 설정한 값이 K=25라고 합니다.

 

그래서 특별한 이유 없이 관례상 K=25라고 쓰는 경우가 많습니다. 만약 데이터를 아주 많이 구할 수 있다면 당연히 특징의 수를 좀 더 크게 지정하는 편이 좋습니다.

 

데이터가 부족하다면 더 작은 값으로 설정하는 게 좋겠죠. 어떤 값이 가장 적절한 지 정답은 없습니다.

 

모델과 데이터에 따라 그때그때 값을 설정할 수도 있습니다. 

 

그래서 현업에서는 경우에 따라 다양한 값을 모두 실험해보고 그 중 가장 좋은 성능을 내는 값을 채택하기도 합니다.

 

TAGS.

Comments