본문 바로가기
Programming_Collective Intelligence/2.추천시스템 만들기

항목 기반 필터링/추천 생성

by 볼록티 2019. 12. 29.
728x90
반응형

모든 사용자들이 평가한 랭킹 정보 데이터가 있어야 추천 엔진을 구현할 수 있었다. 이는 수천 명의 사람이나 항목이 있을 땐 잘 동작할 것이다. 하지만 아마존과 같은 매우 큰 사이트의 경우에는 수백만의 고객과 제품이 있어서 연산량도 많아지고 느려지게 될 것이다. 그리고 사람 간의 중첩도 거의 없어서 어떤 사람들이 유사한지 결정하기가 까다로워 진다.

 지금까지 알아본 것은 '사용자 기반 협력 필터링(user-based collaborative filtering)이다. 이밖에 항목 기반 협력 필터링(item-based collaborative filtering)이라는 방법도 있다. 

 매우 큰 데이터 셋을 다룰 때 항목 기반 협력 필터링 방법이 더 좋은 결과를 낼 것이다. 이 기법은 추천이 필요한 사용자에게 더욱 빠르게 추천하기 위해 미리 계산을 한다.

 항목들 간의 비교는 사람들 간의 비교에 비해 자주 바뀌지 않는다는 점이 중요하다. 이는 결국 계속 계산하지 않아도 되기 때문이다.

 

항목 기반 데이터 셋 생성

 

 항목간 비교를 위해서 데이터 셋을 한번 구축해본다.

 

def calculateSimilarItems(prefs, n=10):
    #가장 유사한 항목들을 가진 항목 딕셔너리를 생성.
    result={}
    
    #선호도 행렬을 뒤집어 항목 중심 행렬로 변환.
    itemPrefs=transformPrefs(prefs)
    c=0
    for item in itemPrefs:
        #큰 데이터셋을 위해 진척 상태를 갱신
        c+=1
        if c%100==0: print("%d / %d" % (c,len(itemPrefs)))
        #각 항목과 가장 유사한 항목들을 구함
        scores = topMatches(itemPrefs, item, n=n, similarity=sim_distance)
        result[item] = scores
    return result

함수 실행 결과

itemsim=rating.calculateSimilarItems(rating.critics)

항목간 유사도 점수

 

각 항목들이 공통으로 가진 사람에 대한 평점을 기준으로 거리를 구하고 이를 이용하여 점수까지 구하고, 순차적으로 나타낸 것이다. 이를 통해서 우리는 항목별로 유사한 것들이 무엇인지 정량적으로 알아볼 수 있게 되었다.

 

 

 

 

추천 생성

 

이제 전체 데이터를 다루지 않고 항목 유사도 딕셔너리만을 사용해서 추천할 준비가 끝났다. 사용자가 평가한 항목을 얻고 유사항목을 찾은다음에 그들 사이의 유사 점수를 통해 가중치를 계산한다. 항목 딕셔너리를 이용해서 항목간 유사도를 쉽게 구할 수 있다.

 

 

def getRecommendedItems(prefs, itemMatch, user):
    userRatings = prefs[user]
    scores={}
    totalSim={}
    
    #이 사용자가 평가한 모든 항목마다 루프를 돔
    for (item, rating) in userRatings.items():
        
        #이 항목과 유사한 모든 항목마다 루프를 돔
        for (similarity, item2) in itemMatch[item]:
            
            #이 사용자가 이 항목을 이미 평가했다면 무시함
            if item2 in userRatings: continue
                
            #유사도와 평가점수 곱의 가중치 합을 계산
            scores.setdefault(item2,0)
            scores[item2] += similarity*rating
            
            #모든 유사도 합을 계산
            totalSim.setdefault(item2,0)
            totalSim[item2]+=similarity
            
        #평균값을 얻기 위해 합계를 가중치 합계로 나눔
        rankings=[(score/totalSim[item],item) for item, score in scores.items()]
        
        #최고값에서 최저값 순으로 랭킹을 리턴함
        rankings.sort()
        rankings.reverse()
        return rankings

수정필요.

기입한 사람에게 이제 영화를 추천해주게 된다.

728x90
반응형

댓글