1. 程式人生 > >【Python】尋找電影品味相似的使用者並推薦相關電影

【Python】尋找電影品味相似的使用者並推薦相關電影

過程:

  • 用爬蟲抓取豆瓣電影使用者資訊
  • 用多重分類法,定義電影評價等級
  • 計算自己與使用者的皮爾遜相關度
  • 以人為主體分析相似度:找出志同道合的人,可以發現潛在喜歡的商品
  • 以商品為主體分析相似度:找出相似的商品,可以發現潛在的客戶(如亞馬遜的‘買了該商品的使用者還買了’)

電影評價多重分類:


使用者資訊錄入:

#-*- coding: utf-8 -*-
import json
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )

user_info = {}

#爬取到的資料
user_dict = {
             'ns2250225':[4,3,4,5,4],
             'justin':[3,4,3,4,2],
             'totox':[2,3,5,1,4],
             'fabrice':[4,1,3,4,5],
             'doreen':[3,4,2,5,3]
             }

#錄入使用者資料
def user_data(user_dict):
    for name in user_dict:
        user_info[name] = {u'消失的愛人' : user_dict[name][0]}
        user_info[name][u'霍位元人3'] = user_dict[name][1]
        user_info[name][u'神去村'] = user_dict[name][2]
        user_info[name][u'泰坦尼克號'] = user_dict[name][3]
        user_info[name][u'這個殺手不太冷'] = user_dict[name][4]
        

user_data(user_dict)    

#存放使用者資料
try:
    with open('user_data.txt', 'w') as data:
        for key in user_info:
            data.write(key)
            for key2 in user_info[key]:
                data.write('\t')
                data.write(key2)
                data.write('\t')
                data.write('\t')
                data.write(str(user_info[key][key2]))
                data.write('\n')
            data.write('\n')
except IOError as err:
    print('File error: ' + str(err))


計算皮爾遜相關係數,找出興趣相投的使用者:(插入自己的資料)

from math import sqrt 

#計算皮爾遜相關度(1為完全正相關,-1為完成負相關)
def sim_pearson(prefs, p1, p2):  
    # Get the list of mutually rated items  
    si = {}  
    for item in prefs[p1]:  
        if item in prefs[p2]:  
            si[item] = 1  
  
    # if they are no ratings in common, return 0  
    if len(si) == 0:  
        return 0  
  
    # Sum calculations  
    n = len(si)  
  
    # Sums of all the preferences  
    sum1 = sum([prefs[p1][it] for it in si])  
    sum2 = sum([prefs[p2][it] for it in si])  
  
    # Sums of the squares  
    sum1Sq = sum([pow(prefs[p1][it], 2) for it in si])  
    sum2Sq = sum([pow(prefs[p2][it], 2) for it in si])  
  
    # Sum of the products  
    pSum = sum([prefs[p1][it] * prefs[p2][it] for it in si])  
  
    # Calculate r (Pearson score)  
    num = pSum - (sum1 * sum2 / n)  
    den = sqrt((sum1Sq - pow(sum1, 2) / n) * (sum2Sq - pow(sum2, 2) / n))  

    if den == 0:  
        return 0  
    r = num / den
    
    return r


#插入自己的資料
user_info['me'] = {u'消失的愛人' : 5,
                   u'神去村' : 3,
                   u'炸裂鼓手' : 5}


          
#找出皮爾遜相關係數>0的使用者,說明該使用者與自己的電影品味比較相近
for user in user_info:
    res = sim_pearson(user_info, 'me', user)
    if res > 0:
        print('the user like %s is : %s' % ('me', user))
        print('result :%f\n' % res)

向某使用者推薦電影(加權平均所有人的評價)

#向某個使用者推薦電影(加權平均所有人的評價值)
def getRecommendations(prefs,person,similarity=sim_pearson):
  totals={}
  simSums={}
  for other in prefs:
    # don't compare me to myself
    if other==person: continue
    sim=similarity(prefs,person,other)

    # ignore scores of zero or lower
    if sim<=0: continue
    for item in prefs[other]:
	    
      # only score movies I haven't seen yet
      if item not in prefs[person] or prefs[person][item]==0:
        # Similarity * Score
        totals.setdefault(item,0)
        totals[item]+=prefs[other][item]*sim
        # Sum of similarities
        simSums.setdefault(item,0)
        simSums[item]+=sim

  # Create the normalized list
  rankings=[(total/simSums[item],item) for item,total in totals.items()]

  # Return the sorted list
  rankings.sort()
  rankings.reverse()
  return rankings


#向我推薦電影
res = getRecommendations(user_info, "me")
print('Recommand watching the movie:')
print json.dumps(res, encoding='UTF-8', ensure_ascii=False)

結果與分析:

  • 與我電影口味相近的使用者有:doreen, fabrice 
  • 推薦我看的電影有:泰坦尼克號,這個殺手不太冷
  • 以人為主體分析, 找出有相似愛好的人, 並向這些人推薦商品,可以發現潛在喜歡的商品
  • 而若以商品為主體分析, 找出相似的商品, 找出喜歡這個產品的人, 可以發現商品潛在的客戶