機器學習(六)推薦引擎之構建電影推薦引擎
阿新 • • 發佈:2020-12-19
構建電影推薦引擎
簡介
推薦引擎是一個能預測使用者興趣點的模型。將推薦引擎應用於電影語境時,便成了一個電影 推薦引擎。我們通過預測當前使用者可能會喜歡的內容,將相應的東西從資料庫中篩選出來,這樣的推薦引擎可以有助於將使用者和資料集中的合適內容連線起來。
為什麼推薦引擎這麼重要?設想 你有一個很龐大的商品目錄,而使用者可能或者不可能查詢所有的相關內容。通過推薦合適的內容, 可以增加使用者消費。
推薦引擎通常用協同過濾(collaborative filtering)或基於內容的過濾(content-based filtering)來產生一組推薦。兩種過濾方法的不同之處在於挖掘推薦的方式。協同過濾從當前使用者過去的行 為和其他使用者對當前使用者的評分來構建模型,然後使用這個模型來預測這個使用者可能感興趣的內容;而基於內容的過濾用商品本身的特徵來給使用者推薦更多的商品,商品間的相似度是模型主要的關注點。本章將重點介紹協同過濾。
主要步驟
編寫一個程式用來計算歐式距離分數
# 建立一個Python檔案,匯入以下程式包:
import json
import numpy as np
# 計算user1和user2的歐氏距離分數,第一步先判斷使用者是否在資料
# 庫中出現:
def euclidean_score(dataset, user1, user2):
if user1 not in dataset:
raise TypeError('User ' + user1 + ' not present in the dataset')
if user2 not in dataset:
raise TypeError('User ' + user2 + ' not present in the dataset')
# 提取兩個使用者均評過分的電影
rated_by_both = {}
for item in dataset[user1]:
if item in dataset[user2]:
rated_by_both[item] = 1
# 如果兩個使用者都沒評分過,得分為0,則說明這兩個使用者之間沒有相似度
if len(rated_by_both) == 0:
return 0
# 對於每個共同評分,只計算平方和的平方根,並將該值歸一化,使得評分取值在0到1之間:
squared_differences = []
for item in dataset[user1]:
if item in dataset[user2]:
squared_differences.append(np.square(dataset[user1][item] - dataset[user2][item]))
return 1 / (1 + np.sqrt(np.sum(squared_differences)))
# 如果評分相似,那麼平方和的差別就會很小,因此評分就會變得很高,這也是我們希望指標
# 達到的效果。
# if __name__ == '__main__':
# # 載入資料檔案中的movie_ratings.json檔案:
# data_file = 'movie_ratings.json'
#
# with open(data_file, 'r') as f:
# data = json.loads(f.read())
#
# # 假定兩個隨機使用者,計算其歐氏距離分數:
# user1 = 'John Carson'
# user2 = 'Michelle Peterson'
#
# # 執行該程式碼,可以看到歐氏距離分數顯示在命令列工具中
# print("\nEuclidean score:")
# print(euclidean_score(data, user1, user2))
編寫一個程式用來計算皮爾遜相關係數
import numpy as np
# 計算user1和user2的皮爾遜相關係數
def pearson_score(dataset, user1, user2):
if user1 not in dataset:
raise TypeError('User ' + user1 + ' not present in the dataset')
if user2 not in dataset:
raise TypeError('User ' + user2 + ' not present in the dataset')
# 提取兩個使用者均評過分的電影
rated_by_both = {}
for item in dataset[user1]:
if item in dataset[user2]:
rated_by_both[item] = 1
num_ratings = len(rated_by_both)
# 如果兩個使用者都沒有評分,得分為0
if num_ratings == 0:
return 0
# 計算相同評分電影的平方值之和
user1_sum = np.sum([dataset[user1][item] for item in rated_by_both])
user2_sum = np.sum([dataset[user2][item] for item in rated_by_both])
# 計算所有相同評分電影的評分的平方和
user1_squared_sum = np.sum([np.square(dataset[user1][item]) for item in rated_by_both])
user2_squared_sum = np.sum([np.square(dataset[user2][item]) for item in rated_by_both])
# 計算資料集的乘積之和
product_sum = np.sum([dataset[user1][item] * dataset[user2][item] for item in rated_by_both])
# 計算皮爾遜相關度
Sxy = product_sum - (user1_sum * user2_sum / num_ratings)
Sxx = user1_squared_sum - np.square(user1_sum) / num_ratings
Syy = user2_squared_sum - np.square(user2_sum) / num_ratings
# 考慮分母為0的情況:
if Sxx * Syy == 0:
return 0
# 如果一切正常,返回皮爾遜相關係數:
return Sxy / np.sqrt(Sxx * Syy)
# 定義main函式並計算兩個使用者之間的皮爾遜相關係數
# if __name__ == '__main__':
# data_file = 'movie_ratings.json'
#
# with open(data_file, 'r') as f:
# data = json.loads(f.read())
#
# user1 = 'John Carson'
# user2 = 'Michelle Peterson'
#
# print("\nPearson score:")
# print(pearson_score(data, user1, user2))
編寫一個程式用來尋找資料集中的相似使用者
# import json
import numpy as np
from TestsOfPythonBook.Chapter05.movie_recomm.pearson_score import pearson_score
# 尋找特定數量的與輸入使用者相似的使用者
def find_similar_users(dataset, user, num_users):
if user not in dataset:
raise TypeError('User ' + user + ' not present in the dataset')
# 計算所有使用者的皮爾遜相關度
scores = np.array([[x, pearson_score(dataset, user, x)] for x in dataset if user != x])
# 評分按照第二列排序
scores_sorted = np.argsort(scores[:, 1])
# 評分按照降序排列
scored_sorted_dec = scores_sorted[::-1]
# 提取出k個最高分
top_k = scored_sorted_dec[0:num_users]
return scores[top_k]
# if __name__=='__main__':
# data_file = 'movie_ratings.json'
#
# with open(data_file, 'r') as f:
# data = json.loads(f.read())
#
# user = 'John Carson'
# print("\nUsers similar to " + user + ":\n")
# similar_users = find_similar_users(data, user, 3)
# print("User\t\t\tSimilarity score\n")
# for item in similar_users:
# print(item[0], '\t\t', round(float(item[1]), 2))
結合上述三個程式構建電影推薦引擎
import json
import numpy as np
from TestsOfPythonBook.Chapter05.movie_recomm.pearson_score import pearson_score
# 為給定使用者生成電影推薦
def generate_recommendations(dataset, user):
if user not in dataset:
raise TypeError('User ' + user + ' not present in the dataset')
# 計算該使用者與資料庫中其他使用者的皮爾遜相關係數:
total_scores = {}
similarity_sums = {}
for u in [x for x in dataset if x != user]:
similarity_score = pearson_score(dataset, user, u)
if similarity_score <= 0:
continue
# 找到還未被該使用者評分的電影
for item in [x for x in dataset[u] if x not in dataset[user] or dataset[user][x] == 0]:
total_scores.update({item: dataset[u][item] * similarity_score})
similarity_sums.update({item: similarity_score})
# 如果該使用者看過資料庫中所有的電影,那就不能為使用者推薦電影。對該條件做如下處理:
if len(total_scores) == 0:
return ['No recommendations possible']
# 生成一個電影評分標準化列表
movie_ranks = np.array([[total / similarity_sums[item], item]
for item, total in total_scores.items()])
# 根據第一列對皮爾遜相關係數進行降序排列
movie_ranks = movie_ranks[np.argsort(movie_ranks[:, 0])[::-1]]
# 提取出推薦的電影
recommendations = [movie for _, movie in movie_ranks]
return recommendations
if __name__ == '__main__':
data_file = 'movie_ratings.json'
with open(data_file, 'r') as f:
data = json.loads(f.read())
user = 'Michael Henry'
print("\nRecommendations for " + user + ":")
movies = generate_recommendations(data, user)
for i, movie in enumerate(movies):
print(str(i + 1) + '. ' + movie)
user = 'John Carson'
print("\nRecommendations for " + user + ":")
movies = generate_recommendations(data, user)
for i, movie in enumerate(movies):
print(str(i + 1) + '. ' + movie)
原始碼+資料集
連結:https://pan.baidu.com/s/1rQRPW9zX4v7J3wBMwYE0Ug
提取碼:na93
複製這段內容後開啟百度網盤手機App,操作更方便哦
實驗結果
結果分析
在為Michael Henry生成推薦時,通過計算皮爾遜係數,根據相關性進行排序,最終返回3個相關性最高的電影。
使用者John Carson看過所有電影,因此在為他推薦電影時,應該顯示0推薦。