Python 根據打分數據對某用戶進行推薦 電影推薦機制


Python 根據打分數據對某用戶進行推薦

代碼倉庫:https://github.com/SKPrimin/PythonCrawler/tree/master/%E7%94%B5%E5%BD%B1%E6%8E%A8%E8%8D%90

編寫程序,生成數據模擬(也可以使用網上爬取的真實數據)多人對多部定影的打分(1~5分),然后根據這些數據對某用戶A進行推薦。

推薦規則為:在已有的數據中選擇與該用戶A的愛好最相似的用戶B,然后從最相似的用戶B已看過但用戶A還沒看過的電影中選擇B打分最高的電影推薦給用戶A。其中,相似度的計算標准:

(1)兩個用戶共同打分過的電影越多,越相似;

(2)兩個用戶對共同打分的電影的打分越接近,越相似。

實現

生成數據模擬

import random

from openpyxl import Workbook

user = ['用戶1', '用戶2', '用戶3', '用戶4', '用戶5', '用戶6', '用戶7', '用戶8',
        '用戶9', '用戶10', '用戶11', '用戶12', '用戶13', '用戶14', '用戶15']
# 實例化
wb = Workbook()
# 激活 worksheet
ws = wb.active
# 設置表頭

ws.append(['用戶', '電影1', '電影2', '電影3', '電影4', '電影5', '電影6', '電影7', '電影8', '電影9', '電影10'])

# i 為用戶數 j為電影數
for i in range(15):
    numscore = []
    numscore.append(user[i])
    for j in range(10):
        # 生成電影j的分數
        numscore.append(random.randint(0, 5))
    # 生成第i行數據
    ws.append(numscore)

wb.save('電影用戶評價信息.xlsx')

通過這種方式,我們可以一個隨機出來的打分表

用戶 電影1 電影2 電影3 電影4 電影5 電影6 電影7 電影8 電影9 電影10
用戶1 0 4 4 0 5 2 0 3 1 5
用戶2 1 1 1 4 5 4 1 3 3 0
用戶3 3 4 2 3 2 4 5 2 2 2
用戶4 3 5 5 0 4 2 2 1 2 2
用戶5 2 0 1 2 1 3 0 5 5 1
用戶6 1 0 0 0 0 1 5 1 4 5
用戶7 5 1 0 0 4 3 1 2 1 1
用戶8 0 5 2 1 3 2 4 5 5 4
用戶9 3 3 2 3 0 0 0 4 5 3
用戶10 2 2 3 1 0 5 3 4 3 4
用戶11 2 0 1 1 5 3 1 0 5 3
用戶12 5 1 2 1 3 3 4 4 3 4
用戶13 5 2 5 5 4 3 3 1 0 3
用戶14 2 4 5 0 3 2 0 2 4 0
用戶15 2 1 4 2 5 1 0 5 4 4

數據分析推薦

讀取數據

  • 讀取excel表格數據,並存放於一個字典中
from openpyxl import load_workbook

# 打開文件及表
wb = load_workbook('電影用戶評價信息.xlsx')
ws = wb["Sheet"]

'''使用演員作為鍵,使用包含該演員參演電影名稱的集合作為“值”'''
fimeDict = dict()
i = 0
# 遍歷Excel文件中的所有行
for index, row in enumerate(ws.rows):
    # 跳過表頭,對於每一行有效數據,獲取每一行的電影名稱和演員清單,
    if index == 0:
        continue
    # 獲取電影名稱和演員列表
    user = row[0].value
    fimescore = [row[i].value for i in range(1, 11)]
    # 得到評分字典,評價用戶作為鍵,評分列表作為值
    fimeDict[user] = fimescore

print("評分字典:{}".format(fimeDict))

評分字典:{'用戶1': [0, 4, 4, 0, 5, 2, 0, 3, 1, 5], '用戶2': [1, 1, 1, 4, 5, 4, 1, 3, 3, 0],...

用戶A讀入
# 假設來了個新用戶
username = "用戶A"
user = [4, 0, 4, 4, 0, 0, 2, 0, 0, 5]
print(f"新來的用戶為{username}:{user}")

共同打分過的電影多的用戶

  • 先找出第一個最高分用戶

filmSamenum = 0  # 共同打分的數目
filmSameNumDict = {}
for key, value in fimeDict.items():
    # 共同打分的電影分析
    filmiswatch = []
    for i in range(len(user)):
        # 如果雙方都看了 ,便為True
        filmiswatch.append(bool(value[i]) & bool(user[i]))
    # 統計True的個數,即雙方都看的個數
    filmSamenum = filmiswatch.count(True)
    # 將此用戶名用戶名與共同觀看個數放入字典
    filmSameNumDict[key] = filmSamenum
print(filmSameNumDict)
# 調用max函數找出最大值對應的鍵 但此方法只會找到返回一個值
keyName = max(filmSameNumDict, key=filmSameNumDict.get)
print("第一個最高匹配人為:{}".format(keyName))

# 再次遍歷查看有沒有其他的用戶觀看次數一樣
userSame = []
maxScore = filmSameNumDict[keyName]
for key, value in filmSameNumDict.items():
    # 如果觀看次與最大值相同添加進列表
    if value == maxScore:
        userSame.append(key)
print("共同打分過的電影多的用戶為:{}".format(userSame))

第一個最高匹配人為:用戶3

  • 根據最高分找出其他觀看次數一樣的用戶
# 再次遍歷查看有沒有其他的用戶觀看次數一樣
userSame = []
maxScore = filmSameNumDict[keyName]
for key, value in filmSameNumDict.items():
    # 如果觀看次與最大值相同添加進列表
    if value == maxScore:
        userSame.append(key)
print("共同打分過的電影多的用戶為:{}".format(userSame))

共同打分過的電影多的用戶為:['用戶3', '用戶10', '用戶11', '用戶12', '用戶13']

打分越接近的用戶

# 開始對相同次數的用戶進行第二輪推薦
userScoreDifferentDict = {}
for username in userSame:
    score = 0
    for index, userscore in enumerate(fimeDict[username]):
        # 計算兩個用戶的打分差距
        if userscore != 0 and user[index] != 0:
            score += abs(userscore - user[index])
    # 將計算出的
    userScoreDifferentDict[username] = score
print("相似用戶的得分字典為:{}".format(userScoreDifferentDict))

相似用戶的得分字典為:{'用戶3': 10, '用戶10': 8, '用戶11': 11, '用戶12': 9, '用戶13': 6}

轉換出電影名

# 統計出其觀看電影的清單fimeName = ['電影1', '電影2', '電影3', '電影4', '電影5', '電影6', '電影7', '電影8', '電影9', '電影10']
selectefimeName = []
selecteName = min(userScoreDifferentDict, key=userScoreDifferentDict.get)
for index, fime in enumerate(fimeDict[selecteName]):
    if fime != 0:
        selectefimeName.append(fimeName[index])
print("最高匹配人為:{0},他所觀看的電影為{1}".format(selecteName, selectefimeName))

最高匹配人為:用戶13,他所觀看的電影為['電影1', '電影2', '電影3', '電影4', '電影5', '電影6', '電影7', '電影8', '電影10']

找出用戶未看過的電影

# 求出用戶觀看的電影列表
userfimeName = []
for index, fime in enumerate(user):
    if fime != 0:
        userfimeName.append(fimeName[index])

# 轉成集合求差集
selectefimeName = set(selectefimeName)
userfimeName = set(userfimeName)
finallFimeName = selectefimeName.difference(userfimeName)
print("推薦的電影如下:{}".format(finallFimeName))

推薦的電影如下:{'電影6', '電影5', '電影8', '電影2'}

推薦評分最高電影

# 求出這些電影中評分最高的一個
finallScore = 0
finallFime = ""
for fime in finallFimeName:
    # 找到這個電影的索引
    index = fimeName.index(fime)
    # 根據索引找到分數
    score = fimeDict[selecteName][index]
    # 比較哪那個高
    if finallScore < score:
        finallScore = score
        finallFime = fime
    # 如果是最高評分則無需繼續查找了
    if score == 5:
        break
print("最終推薦的電影為:{}".format(finallFime))

最終推薦的電影為:電影5

本次模擬的推薦算法是當今社會常見的算法應用,平台的大數據推薦在我們生活中屢見不鮮。本次我在計算標准的指引下,也親身實際設計了一次大數據推薦算法,本次生成的數據先保存至excel表格,用戶作為行,電影名稱作為列,實現了評分的存儲。在數據讀取時,通過同樣的方式,以用戶名作為鍵,評分列表作為值進行讀取,這也與我們實際應用中的表單傳值使用的json數據有異曲同工之處,都是字典搭配列表。讀取時首先要統計其他用戶與用戶A共同打分過的電影數,這里我采用的bool的方式,進行&運算,便得到了一個是否都打過分的布爾列表,然后統計True的個數便可以得出。接下來第二輪比較評分差異時,便通過雙循環算出各用戶與用戶A打分之差,統計時需要將有人未看的電影去除。在最后的找出要推薦的電影階段,先是通過索引找出對應的電影名稱,再將列表轉為集合求出差集,最后再次根據索引去查找分數,找出其打分最高的那個電影。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM