基於協同過濾演算法構建推薦系統
阿新 • • 發佈:2018-12-30
一 推薦系統介紹
- 推薦系統是資訊過濾系統的一個子類,它根據使用者的偏好和行為,來向用戶呈現他(或她)可能感興趣的物品。推薦系統會嘗試去預測你對一個物品的喜好,以此向你推薦一個你很有可能會喜歡的物品。我們組設計的系統是一個購物系統,主要包括主頁,商品頁和推薦頁。
- 完整專案效果點選此處檢視(此專案為Web應用,暫未對PC端進行介面適配,如無法開啟請用移動端瀏覽器進入139.199.59.246:8081瀏覽)
- GitHub地址:https://github.com/KingsleyChung/Blockchain_Market
- 主頁
主頁向用戶展現了能夠購買的物品的圖片、價格以及庫存。點選商品圖片可以進入商品頁,點選主頁右下角的推薦圖示可以進入推薦頁。 - 商品頁
商品頁能看到商品簡介、價格、瀏覽量等資訊,以及出現購買量與購買圖示。 - 推薦頁
系統根據使用者對某個商品的瀏覽次數、購買記錄以及該商品的總訪問量和銷量而對使用者進行的相關推薦。上圖是在已經購買了主頁的2種網球之後生成的,可以看到推薦系統基於我們的偏好,向我們推薦了可能會喜歡的Wilson護腕
二 協同過濾演算法介紹
- 協同過濾的過程分為這三步:一開始,收集使用者資訊,然後以此生成矩陣來計算使用者關聯,最後作出高可信度的推薦。這種技術分為兩大類:一種是基於使用者的協同過濾,一種則是基於物品的協同過濾。我們的系統採用的是基於物品的協同過濾方法。
- 基於物品的協同過濾演算法核心思想是:給使用者推薦那些和他們之前喜歡的物品相似的物品,值得注意的是,這裡所說的物品A和物品B具有很大的相似度是因為喜歡物品A的使用者大都也喜歡B。
- 計算物品之間的相似度:
我們使用如下的公式定義物品的相似度:
- 其中, N(i) 是喜歡物品 i 的使用者數, N(j) 是喜歡物品 j 的使用者數, N(i) N(j) 是同時喜歡物品i和物品j的使用者數。
- 這裡面有個假設,就是每個使用者的興趣都侷限在某幾個方面。如果使用者之間的興趣廣泛且不相交,那麼即使存在同時喜歡物品i和物品j的使用者數多,那也不能代表物品i和物品j的相似度大,因為很可能兩種物品所屬領域非常不同。
- 根據物品的相似度和使用者的歷史行為給使用者生成推薦列表:
- 其中, p(u,i)表示使用者 u 對物品 j 的興趣, N(i)表示使用者喜歡的物品集合(u是該使用者喜歡的某一個物品), S(u,K)表示和物品 u 最相似的 K 個物品集合(i 是這個集合中的某一個物品), wuv 表示物品 u 和物品 v 的相似度,rvi 表示使用者 v 對物品 i 的興趣(這裡簡化rvi都等於1)。
- 該公式的含義可以理解為:和使用者歷史上感興趣的物品越相似的物品,越有可能在使用者的推薦列表中獲得比較高的排名。
三 演算法實現
- 連線資料庫
def connectMongo(host, port, username, password, db):
if username and password:
mongo_url = "mongodb://%s:%[email protected]%s:%s/%s" % (username, password, host, port, db)
connection = MongoClient(mongo_url)
else:
connection = MongoClient(host, port)
return connection[db]
- 構建一個二維陣列,根據商品的瀏覽記錄,購買記錄,總瀏覽量等計算相關性
def getMatrix(db):
matrix = list()
goods = list(db.goods.find())
goodsTitle = list(['username'])
for good in goods:
goodsTitle.append(str(good['_id']))
users = list(db.users.find())
for user in users:
userRow = list([user['username']])
for i in range(len(goods)):
userRow.append(goods[i]['sale'] * 0.3 + goods[i]['view'] * 0.1)
for key in user['goods']:
for i in range(len(goods)):
if str(goods[i]['_id']) == str(key):
userRow[i + 1] = user['goods'][key]['bought'] * 3 + user['goods'][key]['view'] * 0.5 + goods[i]['sale'] * 0.3 + goods[i]['view'] * 0.1
break
matrix.append(userRow)
return (goodsTitle, matrix)
- 將得到的矩陣傳給getRecommand函式,根據矩陣計算其他商品對於客戶的推薦分,最後將得分最高的商品進行推薦
def getRecommand(header, matrix): # 推薦演算法
data = pd.DataFrame(matrix)
data.columns = header
data.set_index('username', inplace = True)
corrMatrix = data.corr(method = 'pearson')
recommandResult = list()
for row in matrix:
username = row[0]
myRatings = data.loc[username].dropna()
simCandidates = pd.Series()
for i in range(0, len(myRatings.index)):
sims = corrMatrix[myRatings.index[i]].dropna()
sims = sims.map( lambda x: x * myRatings[i])
simCandidates = simCandidates.append(sims)
simCandidates.sort_values(inplace = True, ascending = False)
simCandidates = simCandidates.groupby(simCandidates.index).sum()
simCandidates.sort_values(inplace = True, ascending = False)
recommands = list()
for i in range(0, len(simCandidates.index)):
if i < 4:
recommands.append(simCandidates.index[i])
elif i < 10 and i * 3 <= len(simCandidates.index):
recommands.append(simCandidates.index[i])
result = {}
result['username'] = username
result['recommands'] = recommands
recommandResult.append(result)
return recommandResult
- 將得到的資料寫入資料庫
def updateRecommandToDB(db, recommandForEachUser):
for recommand in recommandForEachUser:
db.users.update_one({'username': recommand['username']}, {'$set': {'recommands': recommand['recommands']}})
四 小組成員
姓名 | 學號 | 貢獻度 |
---|---|---|
鍾文傑 | 15331429 | 50% |
周銳 | 15331434 | 25% |
朱薇薇 | 15331442 | 25% |