推薦引擎
推薦引擎意在把最需要的推薦給用戶。
在不同的機器學習場景中通常需要分析相似樣本。而統計相似樣本的方式可以基於歐氏距離分數,也可基於皮氏距離分數。
歐氏距離分數
計算所得歐氏距離分數區間處於:[0, 1],越趨於0樣本間的歐氏距離越遠,樣本越不相似;越趨於1,樣本間的歐氏距離越近,越相似。
構建樣本之間的歐氏距離得分矩陣:
案例:解析ratings.json,根據每個用戶對已觀看電影的打分計算樣本間的歐氏距離,輸出歐氏距離得分矩陣。
import json
import numpy as np
with open('../data/ratings.json', 'r') as f:
ratings = json.loads(f.read())
users, scmat = list(ratings.keys()), []
for user1 in users:
scrow = []
for user2 in users:
movies = set()
for movie in ratings[user1]:
if movie in ratings[user2]:
movies.add(movie)
if len(movies) == 0:
score = 0
else:
x, y = [], []
for movie in movies:
x.append(ratings[user1][movie])
y.append(ratings[user2][movie])
x = np.array(x)
y = np.array(y)
score = 1 / (1 + np.sqrt(((x - y) ** 2).sum()))
scrow.append(score)
scmat.append(scrow)
users = np.array(users)
scmat = np.array(scmat)
for scrow in scmat:
print(' '.join('{:.2f}'.format(score) for score in scrow))
皮爾遜相關係數
A = [1,2,3,1,2]
B = [3,4,5,3,4]
m = np.corrcoef(A, B)
皮爾遜相關係數 = 協方差 / 標準差之積
相關係數處於[-1, 1]區間。越靠近-1代表兩組樣本反相關,越靠近1代表兩組樣本正相關。
案例:使用皮爾遜相關係數計算兩用戶對一組電影評分的相關性。
score = np.corrcoef(x, y)[0, 1]
按照相似度從高到低排列每個用戶的相似用戶
# scmat矩陣中每一行爲 每一個用戶對所有用戶的皮爾遜相關係數
for i, user in enumerate(users):
# 拿到所有相似用戶與相似用戶所對應的皮爾遜相關係數
sorted_indices = scmat[i].argsort()[::-1]
sorted_indices = sorted_indices[sorted_indices != i]
similar_users = users[sorted_indices]
similar_scores = scmat[i, sorted_indices]
print(user, similar_users, similar_scores, sep='\n')
生成推薦清單
- 找到所有皮爾遜係數正相關的用戶
- 遍歷當前用戶的每個相似用戶,拿到相似用戶看過但是當前用戶沒有看過的電影作爲推薦電影
- 多個相似用戶有可能推薦同一部電影,則取每個相似用戶對該電影的評分得均值作爲推薦度。
- 可以把相似用戶的皮爾遜係數作爲權重,皮爾遜係數越大,推薦度越高。
# 找到所有皮爾遜係數正相關的用戶
positive_mask = similar_scores > 0
similar_users = similar_users[positive_mask]
# 相似用戶對應的皮爾遜相關係數
similar_scores = similar_scores[positive_mask]
#存儲對於當前用戶所推薦的電影以及電影的推薦度(推薦電影的平均分)
recomm_movies = {}
#遍歷當前用戶的每個相似用戶
for i, similar_user in enumerate(similar_users):
#拿到相似用戶看過但是當前用戶沒有看過的電影
for movie, score in ratings[similar_user].items():
if (movie not in ratings[user].keys()):
if movie not in recomm_movies:
recomm_movies[movie] = []
else:
recomm_movies[movie].append(score)
print(user)
movie_list = sorted(recomm_movies.items(), key=lambda x:np.average(x[1]), reverse=True)
print(movie_list)