ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Recommendation] 추천 알고리즘 Python 구현 : Collaborative Filtering w/ 유클리디안 유사도
    ML/Recommendation 2020. 3. 6. 13:14

     

     

     

     

    넷플릭스를 한창 보는 중인데, 도대체 넷플릭스는 어떤 방식으로 나한테 추천을 해주는 건지가 궁금해졌다.

     

    추천 알고리즘을 좀 알아봐야겠다!

     

    먼저 제일 기초적인 [1. 사용자 간의 유사도를 구하는 방식 + 2. 그 유사도로 추천하는 기본 방식]을 알아보고,

     

    넷플릭스는 그걸 어떻게 사용하는지 알아보자.

     

     

     

     

     

    Popularity, High Rated Based


    가장 단순한 방법 → 평점이 높은 것을 추천

    모두에게 같은 item 추천하게 됨.

     

    ratings = {
         'doky':{'Anne_with_an_E':5,'Strange_Things':3,'The_Escape':3},
         'steve':{'Anne_with_an_E':5,'Strange_Things':1,'The_Escape':4},
         'jamie':{'Anne_with_an_E':0,'Strange_Things':4,'The_Escape':5},
         'bobby':{'Anne_with_an_E':2,'Strange_Things':1,'The_Escape':5}
    }
    recmd_movielist = dict()
    
    # (A)
    for name in ratings:
        for title in ratings[name]:
            score = ratings[name][title]
            
            if title not in recmd_movielist:
                recmd_movielist[title] = score
            else:
                recmd_movielist[title] += score
    
    #
    # (B)
    for recmd_movietitle in recmd_movielist:
        recmd_movielist[recmd_movietitle] /= 4
    #
    # (C)
    from operator import itemgetter
    recmd_movielist = sorted(recmd_movielist.items(), reverse=True, key=itemgetter(1))
    #
    
    recmd_movielist
    Out:    [('The_Escape', 4.25), ('Anne_with_an_E', 3.0), ('Strange_Things', 2.25)]

     

    네 사람이 같은 영화에 준 평점들을 각각 더한 다음 (A)
    4로 나눠서 각 영화가 받은 평점의 평균을 낸다 (B)
    그 평균으로 내림차순 정렬해서 추천 리스트를 만든다 (C)

     

     

     

     

    Collaborative Filtering


    • 사용자가 입력한 선호도(평점)를 사용하여 사용자-항목 선호도(평점) 행렬 계산
    • 그 행렬을 사용하여 사용자들 간의 유사도를 계산
    • 사용자들 간의 유사도를 바탕으로 모든 항목에 대해 예측 값을 계산하고, 높은 예측 값을 갖는 상위 N개의 추천 목록을 생성

     

    ratings = {
         'doky':{'Anne_with_an_E':5,'Strange_Things':3,'The_Escape':3},
         'steve':{'Anne_with_an_E':5,'Strange_Things':1,'The_Escape':4},
         'jamie':{'Strange_Things':4,'The_Escape':5},
         'bobby':{'Anne_with_an_E':2,'Strange_Things':1,'The_Escape':5}
    }
    import math
    
    def sim_w_dist(i, j):
        return math.sqrt(pow(i,2) + pow(j,2))

     

    유클리디안 거리 유사도 측정

     

     

    max_sim_w_dist = sim_w_dist(5, 5)
    min_sim_w_dist = sim_w_dist(0, 0)
    print(min_sim_w_dist, ',', max_sim_w_dist)

     

    sim_w_dist로 구한 sim의

    최대값=루트50, 최소값=0

     

     

    for name in ratings:
        if name != 'jamie':
            v1 = ratings['jamie']['Strange_Things'] - ratings[name]['Strange_Things']
            v2 = ratings['jamie']['The_Escape'] - ratings[name]['The_Escape']
            sim = sim_w_dist(v1, v2)
            norm_sim = (sim-min_sim_w_dist)/(max_sim_w_dist-min_sim_w_dist)
            print('similarity with', name, ':', sim, '->', norm_sim)
    Out:    similarity with doky : 2.23606797749979 -> 0.31622776601683794
               similarity with steve : 3.1622776601683795 -> 0.4472135954999579
               similarity with bobby : 3.0 -> 0.4242640687119285

     

    jamie가 평가한 Strange_Things, The_Escape를 모두 평가한 사용자와의 유사도 구하기
        ● sim_w_dist 함수 사용
        ● sim을 0과 1 사이로 정규화한 norm_sim 계산 => 1에 가까운 값일수록 유사도 높음

     

     

    다음 포스팅(#2)에서는 오늘 구현한 유클리디안 유사도 말고 다른 유사도들을 알아보겠다.

     

     

     

     

     

     

     


    reference: https://www.fun-coding.org/recommend_basic2.html

    댓글

dokylee's Tech Blog